Fix possible evaluation order problems.
We should not allow handle dereference and GC inside the same expression because order of subexpression evalution are not defined. Review URL: http://codereview.chromium.org/3398014 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@5509 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
e69278a70c
commit
7c8bb52737
44
src/api.cc
44
src/api.cc
@ -767,6 +767,12 @@ int TypeSwitch::match(v8::Handle<Value> value) {
|
||||
}
|
||||
|
||||
|
||||
#define SET_FIELD_WRAPPED(obj, setter, cdata) do { \
|
||||
i::Handle<i::Object> proxy = FromCData(cdata); \
|
||||
(obj)->setter(*proxy); \
|
||||
} while (false)
|
||||
|
||||
|
||||
void FunctionTemplate::SetCallHandler(InvocationCallback callback,
|
||||
v8::Handle<Value> data) {
|
||||
if (IsDeadCheck("v8::FunctionTemplate::SetCallHandler()")) return;
|
||||
@ -776,7 +782,7 @@ void FunctionTemplate::SetCallHandler(InvocationCallback callback,
|
||||
i::Factory::NewStruct(i::CALL_HANDLER_INFO_TYPE);
|
||||
i::Handle<i::CallHandlerInfo> obj =
|
||||
i::Handle<i::CallHandlerInfo>::cast(struct_obj);
|
||||
obj->set_callback(*FromCData(callback));
|
||||
SET_FIELD_WRAPPED(obj, set_callback, callback);
|
||||
if (data.IsEmpty()) data = v8::Undefined();
|
||||
obj->set_data(*Utils::OpenHandle(*data));
|
||||
Utils::OpenHandle(this)->set_call_code(*obj);
|
||||
@ -792,8 +798,8 @@ static i::Handle<i::AccessorInfo> MakeAccessorInfo(
|
||||
v8::PropertyAttribute attributes) {
|
||||
i::Handle<i::AccessorInfo> obj = i::Factory::NewAccessorInfo();
|
||||
ASSERT(getter != NULL);
|
||||
obj->set_getter(*FromCData(getter));
|
||||
obj->set_setter(*FromCData(setter));
|
||||
SET_FIELD_WRAPPED(obj, set_getter, getter);
|
||||
SET_FIELD_WRAPPED(obj, set_setter, setter);
|
||||
if (data.IsEmpty()) data = v8::Undefined();
|
||||
obj->set_data(*Utils::OpenHandle(*data));
|
||||
obj->set_name(*Utils::OpenHandle(*name));
|
||||
@ -877,11 +883,13 @@ void FunctionTemplate::SetNamedInstancePropertyHandler(
|
||||
i::Factory::NewStruct(i::INTERCEPTOR_INFO_TYPE);
|
||||
i::Handle<i::InterceptorInfo> obj =
|
||||
i::Handle<i::InterceptorInfo>::cast(struct_obj);
|
||||
if (getter != 0) obj->set_getter(*FromCData(getter));
|
||||
if (setter != 0) obj->set_setter(*FromCData(setter));
|
||||
if (query != 0) obj->set_query(*FromCData(query));
|
||||
if (remover != 0) obj->set_deleter(*FromCData(remover));
|
||||
if (enumerator != 0) obj->set_enumerator(*FromCData(enumerator));
|
||||
|
||||
if (getter != 0) SET_FIELD_WRAPPED(obj, set_getter, getter);
|
||||
if (setter != 0) SET_FIELD_WRAPPED(obj, set_setter, setter);
|
||||
if (query != 0) SET_FIELD_WRAPPED(obj, set_query, query);
|
||||
if (remover != 0) SET_FIELD_WRAPPED(obj, set_deleter, remover);
|
||||
if (enumerator != 0) SET_FIELD_WRAPPED(obj, set_enumerator, enumerator);
|
||||
|
||||
if (data.IsEmpty()) data = v8::Undefined();
|
||||
obj->set_data(*Utils::OpenHandle(*data));
|
||||
Utils::OpenHandle(this)->set_named_property_handler(*obj);
|
||||
@ -905,11 +913,13 @@ void FunctionTemplate::SetIndexedInstancePropertyHandler(
|
||||
i::Factory::NewStruct(i::INTERCEPTOR_INFO_TYPE);
|
||||
i::Handle<i::InterceptorInfo> obj =
|
||||
i::Handle<i::InterceptorInfo>::cast(struct_obj);
|
||||
if (getter != 0) obj->set_getter(*FromCData(getter));
|
||||
if (setter != 0) obj->set_setter(*FromCData(setter));
|
||||
if (query != 0) obj->set_query(*FromCData(query));
|
||||
if (remover != 0) obj->set_deleter(*FromCData(remover));
|
||||
if (enumerator != 0) obj->set_enumerator(*FromCData(enumerator));
|
||||
|
||||
if (getter != 0) SET_FIELD_WRAPPED(obj, set_getter, getter);
|
||||
if (setter != 0) SET_FIELD_WRAPPED(obj, set_setter, setter);
|
||||
if (query != 0) SET_FIELD_WRAPPED(obj, set_query, query);
|
||||
if (remover != 0) SET_FIELD_WRAPPED(obj, set_deleter, remover);
|
||||
if (enumerator != 0) SET_FIELD_WRAPPED(obj, set_enumerator, enumerator);
|
||||
|
||||
if (data.IsEmpty()) data = v8::Undefined();
|
||||
obj->set_data(*Utils::OpenHandle(*data));
|
||||
Utils::OpenHandle(this)->set_indexed_property_handler(*obj);
|
||||
@ -928,7 +938,7 @@ void FunctionTemplate::SetInstanceCallAsFunctionHandler(
|
||||
i::Factory::NewStruct(i::CALL_HANDLER_INFO_TYPE);
|
||||
i::Handle<i::CallHandlerInfo> obj =
|
||||
i::Handle<i::CallHandlerInfo>::cast(struct_obj);
|
||||
obj->set_callback(*FromCData(callback));
|
||||
SET_FIELD_WRAPPED(obj, set_callback, callback);
|
||||
if (data.IsEmpty()) data = v8::Undefined();
|
||||
obj->set_data(*Utils::OpenHandle(*data));
|
||||
Utils::OpenHandle(this)->set_instance_call_handler(*obj);
|
||||
@ -1043,8 +1053,10 @@ void ObjectTemplate::SetAccessCheckCallbacks(
|
||||
i::Factory::NewStruct(i::ACCESS_CHECK_INFO_TYPE);
|
||||
i::Handle<i::AccessCheckInfo> info =
|
||||
i::Handle<i::AccessCheckInfo>::cast(struct_info);
|
||||
info->set_named_callback(*FromCData(named_callback));
|
||||
info->set_indexed_callback(*FromCData(indexed_callback));
|
||||
|
||||
SET_FIELD_WRAPPED(info, set_named_callback, named_callback);
|
||||
SET_FIELD_WRAPPED(info, set_indexed_callback, indexed_callback);
|
||||
|
||||
if (data.IsEmpty()) data = v8::Undefined();
|
||||
info->set_data(*Utils::OpenHandle(*data));
|
||||
|
||||
|
@ -1413,8 +1413,14 @@ void Genesis::InstallJSFunctionResultCaches() {
|
||||
Handle<FixedArray> caches = Factory::NewFixedArray(kNumberOfCaches, TENURED);
|
||||
|
||||
int index = 0;
|
||||
#define F(size, func) caches->set(index++, CreateCache(size, func));
|
||||
JSFUNCTION_RESULT_CACHE_LIST(F)
|
||||
|
||||
#define F(size, func) do { \
|
||||
FixedArray* cache = CreateCache((size), (func)); \
|
||||
caches->set(index++, cache); \
|
||||
} while (false)
|
||||
|
||||
JSFUNCTION_RESULT_CACHE_LIST(F);
|
||||
|
||||
#undef F
|
||||
|
||||
global_context()->set_jsfunction_result_caches(*caches);
|
||||
|
@ -110,6 +110,9 @@ class CompilationCacheScript : public CompilationSubCache {
|
||||
void Put(Handle<String> source, Handle<SharedFunctionInfo> function_info);
|
||||
|
||||
private:
|
||||
MUST_USE_RESULT Object* TryTablePut(
|
||||
Handle<String> source, Handle<SharedFunctionInfo> function_info);
|
||||
|
||||
// Note: Returns a new hash table if operation results in expansion.
|
||||
Handle<CompilationCacheTable> TablePut(
|
||||
Handle<String> source, Handle<SharedFunctionInfo> function_info);
|
||||
@ -137,6 +140,12 @@ class CompilationCacheEval: public CompilationSubCache {
|
||||
Handle<SharedFunctionInfo> function_info);
|
||||
|
||||
private:
|
||||
MUST_USE_RESULT Object* TryTablePut(
|
||||
Handle<String> source,
|
||||
Handle<Context> context,
|
||||
Handle<SharedFunctionInfo> function_info);
|
||||
|
||||
|
||||
// Note: Returns a new hash table if operation results in expansion.
|
||||
Handle<CompilationCacheTable> TablePut(
|
||||
Handle<String> source,
|
||||
@ -159,6 +168,10 @@ class CompilationCacheRegExp: public CompilationSubCache {
|
||||
JSRegExp::Flags flags,
|
||||
Handle<FixedArray> data);
|
||||
private:
|
||||
MUST_USE_RESULT Object* TryTablePut(Handle<String> source,
|
||||
JSRegExp::Flags flags,
|
||||
Handle<FixedArray> data);
|
||||
|
||||
// Note: Returns a new hash table if operation results in expansion.
|
||||
Handle<CompilationCacheTable> TablePut(Handle<String> source,
|
||||
JSRegExp::Flags flags,
|
||||
@ -320,11 +333,18 @@ Handle<SharedFunctionInfo> CompilationCacheScript::Lookup(Handle<String> source,
|
||||
}
|
||||
|
||||
|
||||
Object* CompilationCacheScript::TryTablePut(
|
||||
Handle<String> source,
|
||||
Handle<SharedFunctionInfo> function_info) {
|
||||
Handle<CompilationCacheTable> table = GetFirstTable();
|
||||
return table->Put(*source, *function_info);
|
||||
}
|
||||
|
||||
|
||||
Handle<CompilationCacheTable> CompilationCacheScript::TablePut(
|
||||
Handle<String> source,
|
||||
Handle<SharedFunctionInfo> function_info) {
|
||||
CALL_HEAP_FUNCTION(GetFirstTable()->Put(*source, *function_info),
|
||||
CompilationCacheTable);
|
||||
CALL_HEAP_FUNCTION(TryTablePut(source, function_info), CompilationCacheTable);
|
||||
}
|
||||
|
||||
|
||||
@ -366,13 +386,20 @@ Handle<SharedFunctionInfo> CompilationCacheEval::Lookup(
|
||||
}
|
||||
|
||||
|
||||
Object* CompilationCacheEval::TryTablePut(
|
||||
Handle<String> source,
|
||||
Handle<Context> context,
|
||||
Handle<SharedFunctionInfo> function_info) {
|
||||
Handle<CompilationCacheTable> table = GetFirstTable();
|
||||
return table->PutEval(*source, *context, *function_info);
|
||||
}
|
||||
|
||||
|
||||
Handle<CompilationCacheTable> CompilationCacheEval::TablePut(
|
||||
Handle<String> source,
|
||||
Handle<Context> context,
|
||||
Handle<SharedFunctionInfo> function_info) {
|
||||
CALL_HEAP_FUNCTION(GetFirstTable()->PutEval(*source,
|
||||
*context,
|
||||
*function_info),
|
||||
CALL_HEAP_FUNCTION(TryTablePut(source, context, function_info),
|
||||
CompilationCacheTable);
|
||||
}
|
||||
|
||||
@ -415,12 +442,20 @@ Handle<FixedArray> CompilationCacheRegExp::Lookup(Handle<String> source,
|
||||
}
|
||||
|
||||
|
||||
Object* CompilationCacheRegExp::TryTablePut(
|
||||
Handle<String> source,
|
||||
JSRegExp::Flags flags,
|
||||
Handle<FixedArray> data) {
|
||||
Handle<CompilationCacheTable> table = GetFirstTable();
|
||||
return table->PutRegExp(*source, flags, *data);
|
||||
}
|
||||
|
||||
|
||||
Handle<CompilationCacheTable> CompilationCacheRegExp::TablePut(
|
||||
Handle<String> source,
|
||||
JSRegExp::Flags flags,
|
||||
Handle<FixedArray> data) {
|
||||
CALL_HEAP_FUNCTION(GetFirstTable()->PutRegExp(*source, flags, *data),
|
||||
CompilationCacheTable);
|
||||
CALL_HEAP_FUNCTION(TryTablePut(source, flags, data), CompilationCacheTable);
|
||||
}
|
||||
|
||||
|
||||
|
@ -120,8 +120,9 @@ Handle<Code> MakeCodeForLiveEdit(CompilationInfo* info) {
|
||||
Handle<Context> context = Handle<Context>::null();
|
||||
Handle<Code> code = MakeCode(context, info);
|
||||
if (!info->shared_info().is_null()) {
|
||||
info->shared_info()->set_scope_info(
|
||||
*SerializedScopeInfo::Create(info->scope()));
|
||||
Handle<SerializedScopeInfo> scope_info =
|
||||
SerializedScopeInfo::Create(info->scope());
|
||||
info->shared_info()->set_scope_info(*scope_info);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
@ -420,10 +421,12 @@ bool Compiler::CompileLazy(CompilationInfo* info) {
|
||||
|
||||
// Update the shared function info with the compiled code and the scope info.
|
||||
// Please note, that the order of the sharedfunction initialization is
|
||||
// important since set_scope_info might trigger a GC, causing the ASSERT
|
||||
// below to be invalid if the code was flushed. By settting the code
|
||||
// important since SerializedScopeInfo::Create might trigger a GC, causing
|
||||
// the ASSERT below to be invalid if the code was flushed. By setting the code
|
||||
// object last we avoid this.
|
||||
shared->set_scope_info(*SerializedScopeInfo::Create(info->scope()));
|
||||
Handle<SerializedScopeInfo> scope_info =
|
||||
SerializedScopeInfo::Create(info->scope());
|
||||
shared->set_scope_info(*scope_info);
|
||||
shared->set_code(*code);
|
||||
if (!info->closure().is_null()) {
|
||||
info->closure()->set_code(*code);
|
||||
|
@ -466,7 +466,8 @@ void InitScriptLineEnds(Handle<Script> script) {
|
||||
|
||||
if (!script->source()->IsString()) {
|
||||
ASSERT(script->source()->IsUndefined());
|
||||
script->set_line_ends(*(Factory::NewFixedArray(0)));
|
||||
Handle<FixedArray> empty = Factory::NewFixedArray(0);
|
||||
script->set_line_ends(*empty);
|
||||
ASSERT(script->line_ends()->IsFixedArray());
|
||||
return;
|
||||
}
|
||||
|
@ -8721,11 +8721,11 @@ void DebugInfo::SetBreakPoint(Handle<DebugInfo> debug_info,
|
||||
// No free slot - extend break point info array.
|
||||
Handle<FixedArray> old_break_points =
|
||||
Handle<FixedArray>(FixedArray::cast(debug_info->break_points()));
|
||||
debug_info->set_break_points(*Factory::NewFixedArray(
|
||||
old_break_points->length() +
|
||||
Debug::kEstimatedNofBreakPointsInFunction));
|
||||
Handle<FixedArray> new_break_points =
|
||||
Handle<FixedArray>(FixedArray::cast(debug_info->break_points()));
|
||||
Factory::NewFixedArray(old_break_points->length() +
|
||||
Debug::kEstimatedNofBreakPointsInFunction);
|
||||
|
||||
debug_info->set_break_points(*new_break_points);
|
||||
for (int i = 0; i < old_break_points->length(); i++) {
|
||||
new_break_points->set(i, old_break_points->get(i));
|
||||
}
|
||||
|
@ -678,7 +678,8 @@ static Object* Runtime_GetOwnProperty(Arguments args) {
|
||||
// Elements that are stored as array elements always has:
|
||||
// writable: true, configurable: true, enumerable: true.
|
||||
elms->set(IS_ACCESSOR_INDEX, Heap::false_value());
|
||||
elms->set(VALUE_INDEX, obj->GetElement(index));
|
||||
Object* element = obj->GetElement(index);
|
||||
elms->set(VALUE_INDEX, element);
|
||||
elms->set(WRITABLE_INDEX, Heap::true_value());
|
||||
elms->set(ENUMERABLE_INDEX, Heap::true_value());
|
||||
elms->set(CONFIGURABLE_INDEX, Heap::true_value());
|
||||
@ -2837,7 +2838,8 @@ static Object* Runtime_StringMatch(Arguments args) {
|
||||
for (int i = 0; i < matches ; i++) {
|
||||
int from = offsets.at(i * 2);
|
||||
int to = offsets.at(i * 2 + 1);
|
||||
elements->set(i, *Factory::NewSubString(subject, from, to));
|
||||
Handle<String> match = Factory::NewSubString(subject, from, to);
|
||||
elements->set(i, *match);
|
||||
}
|
||||
Handle<JSArray> result = Factory::NewJSArrayWithElements(elements);
|
||||
result->set_length(Smi::FromInt(matches));
|
||||
@ -3105,9 +3107,10 @@ static RegExpImpl::IrregexpResult SearchRegExpMultiple(
|
||||
// Arguments array to replace function is match, captures, index and
|
||||
// subject, i.e., 3 + capture count in total.
|
||||
Handle<FixedArray> elements = Factory::NewFixedArray(3 + capture_count);
|
||||
elements->set(0, *Factory::NewSubString(subject,
|
||||
match_start,
|
||||
match_end));
|
||||
Handle<String> match = Factory::NewSubString(subject,
|
||||
match_start,
|
||||
match_end);
|
||||
elements->set(0, *match);
|
||||
for (int i = 1; i <= capture_count; i++) {
|
||||
int start = register_vector[i * 2];
|
||||
if (start >= 0) {
|
||||
@ -4953,12 +4956,14 @@ static Object* Runtime_StringToArray(Arguments args) {
|
||||
length);
|
||||
|
||||
for (int i = num_copied_from_cache; i < length; ++i) {
|
||||
elements->set(i, *LookupSingleCharacterStringFromCode(chars[i]));
|
||||
Handle<Object> str = LookupSingleCharacterStringFromCode(chars[i]);
|
||||
elements->set(i, *str);
|
||||
}
|
||||
} else {
|
||||
elements = Factory::NewFixedArray(length);
|
||||
for (int i = 0; i < length; ++i) {
|
||||
elements->set(i, *LookupSingleCharacterStringFromCode(s->Get(i)));
|
||||
Handle<Object> str = LookupSingleCharacterStringFromCode(s->Get(i));
|
||||
elements->set(i, *str);
|
||||
}
|
||||
}
|
||||
|
||||
@ -7826,7 +7831,8 @@ static Object* Runtime_DebugGetPropertyDetails(Arguments args) {
|
||||
uint32_t index;
|
||||
if (name->AsArrayIndex(&index)) {
|
||||
Handle<FixedArray> details = Factory::NewFixedArray(2);
|
||||
details->set(0, Runtime::GetElementOrCharAt(obj, index));
|
||||
Object* element_or_char = Runtime::GetElementOrCharAt(obj, index);
|
||||
details->set(0, element_or_char);
|
||||
details->set(1, PropertyDetails(NONE, NORMAL).AsSmi());
|
||||
return *Factory::NewJSArrayWithElements(details);
|
||||
}
|
||||
@ -8628,7 +8634,8 @@ static Object* Runtime_GetScopeDetails(Arguments args) {
|
||||
|
||||
// Fill in scope details.
|
||||
details->set(kScopeDetailsTypeIndex, Smi::FromInt(it.Type()));
|
||||
details->set(kScopeDetailsObjectIndex, *it.ScopeObject());
|
||||
Handle<JSObject> scope_object = it.ScopeObject();
|
||||
details->set(kScopeDetailsObjectIndex, *scope_object);
|
||||
|
||||
return *Factory::NewJSArrayWithElements(details);
|
||||
}
|
||||
@ -8673,10 +8680,10 @@ static Object* Runtime_GetCFrames(Arguments args) {
|
||||
Handle<FixedArray> frames_array = Factory::NewFixedArray(frames_count);
|
||||
for (int i = 0; i < frames_count; i++) {
|
||||
Handle<JSObject> frame_value = Factory::NewJSObject(Top::object_function());
|
||||
frame_value->SetProperty(
|
||||
*address_str,
|
||||
*Factory::NewNumberFromInt(reinterpret_cast<int>(frames[i].address)),
|
||||
NONE);
|
||||
Handle<Object> frame_address =
|
||||
Factory::NewNumberFromInt(reinterpret_cast<int>(frames[i].address));
|
||||
|
||||
frame_value->SetProperty(*address_str, *frame_address, NONE);
|
||||
|
||||
// Get the stack walk text for this frame.
|
||||
Handle<String> frame_text;
|
||||
|
Loading…
Reference in New Issue
Block a user