From: vegorov@chromium.org Date: Thu, 23 Sep 2010 08:27:51 +0000 (+0000) Subject: Fix possible evaluation order problems. X-Git-Tag: upstream/4.7.83~21174 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=7c8bb5273759512797d816e67c7841db4c480c09;p=platform%2Fupstream%2Fv8.git 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 --- diff --git a/src/api.cc b/src/api.cc index d6ed8ae..91ecc41 100644 --- a/src/api.cc +++ b/src/api.cc @@ -767,6 +767,12 @@ int TypeSwitch::match(v8::Handle value) { } +#define SET_FIELD_WRAPPED(obj, setter, cdata) do { \ + i::Handle proxy = FromCData(cdata); \ + (obj)->setter(*proxy); \ + } while (false) + + void FunctionTemplate::SetCallHandler(InvocationCallback callback, v8::Handle 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 obj = i::Handle::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 MakeAccessorInfo( v8::PropertyAttribute attributes) { i::Handle 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 obj = i::Handle::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 obj = i::Handle::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 obj = i::Handle::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 info = i::Handle::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)); diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc index 1f12502..f2e31c0 100644 --- a/src/bootstrapper.cc +++ b/src/bootstrapper.cc @@ -1413,8 +1413,14 @@ void Genesis::InstallJSFunctionResultCaches() { Handle 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); diff --git a/src/compilation-cache.cc b/src/compilation-cache.cc index 7402e68..b0449c4 100644 --- a/src/compilation-cache.cc +++ b/src/compilation-cache.cc @@ -110,6 +110,9 @@ class CompilationCacheScript : public CompilationSubCache { void Put(Handle source, Handle function_info); private: + MUST_USE_RESULT Object* TryTablePut( + Handle source, Handle function_info); + // Note: Returns a new hash table if operation results in expansion. Handle TablePut( Handle source, Handle function_info); @@ -137,6 +140,12 @@ class CompilationCacheEval: public CompilationSubCache { Handle function_info); private: + MUST_USE_RESULT Object* TryTablePut( + Handle source, + Handle context, + Handle function_info); + + // Note: Returns a new hash table if operation results in expansion. Handle TablePut( Handle source, @@ -159,6 +168,10 @@ class CompilationCacheRegExp: public CompilationSubCache { JSRegExp::Flags flags, Handle data); private: + MUST_USE_RESULT Object* TryTablePut(Handle source, + JSRegExp::Flags flags, + Handle data); + // Note: Returns a new hash table if operation results in expansion. Handle TablePut(Handle source, JSRegExp::Flags flags, @@ -320,11 +333,18 @@ Handle CompilationCacheScript::Lookup(Handle source, } +Object* CompilationCacheScript::TryTablePut( + Handle source, + Handle function_info) { + Handle table = GetFirstTable(); + return table->Put(*source, *function_info); +} + + Handle CompilationCacheScript::TablePut( Handle source, Handle function_info) { - CALL_HEAP_FUNCTION(GetFirstTable()->Put(*source, *function_info), - CompilationCacheTable); + CALL_HEAP_FUNCTION(TryTablePut(source, function_info), CompilationCacheTable); } @@ -366,13 +386,20 @@ Handle CompilationCacheEval::Lookup( } +Object* CompilationCacheEval::TryTablePut( + Handle source, + Handle context, + Handle function_info) { + Handle table = GetFirstTable(); + return table->PutEval(*source, *context, *function_info); +} + + Handle CompilationCacheEval::TablePut( Handle source, Handle context, Handle 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 CompilationCacheRegExp::Lookup(Handle source, } +Object* CompilationCacheRegExp::TryTablePut( + Handle source, + JSRegExp::Flags flags, + Handle data) { + Handle table = GetFirstTable(); + return table->PutRegExp(*source, flags, *data); +} + + Handle CompilationCacheRegExp::TablePut( Handle source, JSRegExp::Flags flags, Handle data) { - CALL_HEAP_FUNCTION(GetFirstTable()->PutRegExp(*source, flags, *data), - CompilationCacheTable); + CALL_HEAP_FUNCTION(TryTablePut(source, flags, data), CompilationCacheTable); } diff --git a/src/compiler.cc b/src/compiler.cc index f65f941..825198e 100755 --- a/src/compiler.cc +++ b/src/compiler.cc @@ -120,8 +120,9 @@ Handle MakeCodeForLiveEdit(CompilationInfo* info) { Handle context = Handle::null(); Handle code = MakeCode(context, info); if (!info->shared_info().is_null()) { - info->shared_info()->set_scope_info( - *SerializedScopeInfo::Create(info->scope())); + Handle 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 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); diff --git a/src/handles.cc b/src/handles.cc index 655254c..80957c2 100644 --- a/src/handles.cc +++ b/src/handles.cc @@ -466,7 +466,8 @@ void InitScriptLineEnds(Handle