Commit 1040aef3 authored by Nico Hartmann's avatar Nico Hartmann Committed by Commit Bot

Check published FunctionTemplateInfo is immutable

This CL generalized the previous check that a FunctionTemplateInfo
instance is not changed after being instantiated to a check for
immutability after being published. A FTI is considered published once
it is instantiated (set in a SharedFunctionInfo) or set as an accessor
on a JSObject. The published state is tracked in the flags field.
TurboFan relies on this immutabilty for concurrent access.

The immutability requirement was already met before this CL, but this
change enforces this by adding necessary checks.

Change-Id: I4d214e7aed8e04339072c2870caef1c28c772ed5
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2718147Reviewed-by: 's avatarUlan Degenbaev <ulan@chromium.org>
Reviewed-by: 's avatarToon Verwaest <verwaest@chromium.org>
Commit-Queue: Nico Hartmann <nicohartmann@chromium.org>
Cr-Commit-Position: refs/heads/master@{#73221}
parent 7535b91f
...@@ -531,6 +531,7 @@ MaybeHandle<JSFunction> InstantiateFunction( ...@@ -531,6 +531,7 @@ MaybeHandle<JSFunction> InstantiateFunction(
} }
return MaybeHandle<JSFunction>(); return MaybeHandle<JSFunction>();
} }
data->set_published(true);
return function; return function;
} }
...@@ -626,6 +627,8 @@ void ApiNatives::AddAccessorProperty(Isolate* isolate, ...@@ -626,6 +627,8 @@ void ApiNatives::AddAccessorProperty(Isolate* isolate,
Handle<FunctionTemplateInfo> getter, Handle<FunctionTemplateInfo> getter,
Handle<FunctionTemplateInfo> setter, Handle<FunctionTemplateInfo> setter,
PropertyAttributes attributes) { PropertyAttributes attributes) {
if (!getter.is_null()) getter->set_published(true);
if (!setter.is_null()) setter->set_published(true);
PropertyDetails details(kAccessor, attributes, PropertyConstness::kMutable); PropertyDetails details(kAccessor, attributes, PropertyConstness::kMutable);
auto details_handle = handle(details.AsSmi(), isolate); auto details_handle = handle(details.AsSmi(), isolate);
Handle<Object> data[] = {name, details_handle, getter, setter}; Handle<Object> data[] = {name, details_handle, getter, setter};
......
...@@ -1180,15 +1180,16 @@ void FunctionTemplate::SetPrototypeProviderTemplate( ...@@ -1180,15 +1180,16 @@ void FunctionTemplate::SetPrototypeProviderTemplate(
result); result);
} }
static void EnsureNotInstantiated(i::Handle<i::FunctionTemplateInfo> info, static void EnsureNotPublished(i::Handle<i::FunctionTemplateInfo> info,
const char* func) { const char* func) {
Utils::ApiCheck(!info->instantiated(), func, DCHECK_IMPLIES(info->instantiated(), info->published());
Utils::ApiCheck(!info->published(), func,
"FunctionTemplate already instantiated"); "FunctionTemplate already instantiated");
} }
void FunctionTemplate::Inherit(v8::Local<FunctionTemplate> value) { void FunctionTemplate::Inherit(v8::Local<FunctionTemplate> value) {
auto info = Utils::OpenHandle(this); auto info = Utils::OpenHandle(this);
EnsureNotInstantiated(info, "v8::FunctionTemplate::Inherit"); EnsureNotPublished(info, "v8::FunctionTemplate::Inherit");
i::Isolate* i_isolate = info->GetIsolate(); i::Isolate* i_isolate = info->GetIsolate();
ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate); ENTER_V8_NO_SCRIPT_NO_EXCEPTION(i_isolate);
Utils::ApiCheck(info->GetPrototypeProviderTemplate().IsUndefined(i_isolate), Utils::ApiCheck(info->GetPrototypeProviderTemplate().IsUndefined(i_isolate),
...@@ -1288,7 +1289,7 @@ void FunctionTemplate::SetCallHandler(FunctionCallback callback, ...@@ -1288,7 +1289,7 @@ void FunctionTemplate::SetCallHandler(FunctionCallback callback,
SideEffectType side_effect_type, SideEffectType side_effect_type,
const CFunction* c_function) { const CFunction* c_function) {
auto info = Utils::OpenHandle(this); auto info = Utils::OpenHandle(this);
EnsureNotInstantiated(info, "v8::FunctionTemplate::SetCallHandler"); EnsureNotPublished(info, "v8::FunctionTemplate::SetCallHandler");
i::Isolate* isolate = info->GetIsolate(); i::Isolate* isolate = info->GetIsolate();
ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
i::HandleScope scope(isolate); i::HandleScope scope(isolate);
...@@ -1378,7 +1379,7 @@ Local<ObjectTemplate> FunctionTemplate::InstanceTemplate() { ...@@ -1378,7 +1379,7 @@ Local<ObjectTemplate> FunctionTemplate::InstanceTemplate() {
void FunctionTemplate::SetLength(int length) { void FunctionTemplate::SetLength(int length) {
auto info = Utils::OpenHandle(this); auto info = Utils::OpenHandle(this);
EnsureNotInstantiated(info, "v8::FunctionTemplate::SetLength"); EnsureNotPublished(info, "v8::FunctionTemplate::SetLength");
auto isolate = info->GetIsolate(); auto isolate = info->GetIsolate();
ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
info->set_length(length); info->set_length(length);
...@@ -1386,7 +1387,7 @@ void FunctionTemplate::SetLength(int length) { ...@@ -1386,7 +1387,7 @@ void FunctionTemplate::SetLength(int length) {
void FunctionTemplate::SetClassName(Local<String> name) { void FunctionTemplate::SetClassName(Local<String> name) {
auto info = Utils::OpenHandle(this); auto info = Utils::OpenHandle(this);
EnsureNotInstantiated(info, "v8::FunctionTemplate::SetClassName"); EnsureNotPublished(info, "v8::FunctionTemplate::SetClassName");
auto isolate = info->GetIsolate(); auto isolate = info->GetIsolate();
ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
info->set_class_name(*Utils::OpenHandle(*name)); info->set_class_name(*Utils::OpenHandle(*name));
...@@ -1394,7 +1395,7 @@ void FunctionTemplate::SetClassName(Local<String> name) { ...@@ -1394,7 +1395,7 @@ void FunctionTemplate::SetClassName(Local<String> name) {
void FunctionTemplate::SetAcceptAnyReceiver(bool value) { void FunctionTemplate::SetAcceptAnyReceiver(bool value) {
auto info = Utils::OpenHandle(this); auto info = Utils::OpenHandle(this);
EnsureNotInstantiated(info, "v8::FunctionTemplate::SetAcceptAnyReceiver"); EnsureNotPublished(info, "v8::FunctionTemplate::SetAcceptAnyReceiver");
auto isolate = info->GetIsolate(); auto isolate = info->GetIsolate();
ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
info->set_accept_any_receiver(value); info->set_accept_any_receiver(value);
...@@ -1402,7 +1403,7 @@ void FunctionTemplate::SetAcceptAnyReceiver(bool value) { ...@@ -1402,7 +1403,7 @@ void FunctionTemplate::SetAcceptAnyReceiver(bool value) {
void FunctionTemplate::ReadOnlyPrototype() { void FunctionTemplate::ReadOnlyPrototype() {
auto info = Utils::OpenHandle(this); auto info = Utils::OpenHandle(this);
EnsureNotInstantiated(info, "v8::FunctionTemplate::ReadOnlyPrototype"); EnsureNotPublished(info, "v8::FunctionTemplate::ReadOnlyPrototype");
auto isolate = info->GetIsolate(); auto isolate = info->GetIsolate();
ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
info->set_read_only_prototype(true); info->set_read_only_prototype(true);
...@@ -1410,7 +1411,7 @@ void FunctionTemplate::ReadOnlyPrototype() { ...@@ -1410,7 +1411,7 @@ void FunctionTemplate::ReadOnlyPrototype() {
void FunctionTemplate::RemovePrototype() { void FunctionTemplate::RemovePrototype() {
auto info = Utils::OpenHandle(this); auto info = Utils::OpenHandle(this);
EnsureNotInstantiated(info, "v8::FunctionTemplate::RemovePrototype"); EnsureNotPublished(info, "v8::FunctionTemplate::RemovePrototype");
auto isolate = info->GetIsolate(); auto isolate = info->GetIsolate();
ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
info->set_remove_prototype(true); info->set_remove_prototype(true);
...@@ -1638,7 +1639,7 @@ static void ObjectTemplateSetNamedPropertyHandler( ...@@ -1638,7 +1639,7 @@ static void ObjectTemplateSetNamedPropertyHandler(
ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
i::HandleScope scope(isolate); i::HandleScope scope(isolate);
auto cons = EnsureConstructor(isolate, templ); auto cons = EnsureConstructor(isolate, templ);
EnsureNotInstantiated(cons, "ObjectTemplateSetNamedPropertyHandler"); EnsureNotPublished(cons, "ObjectTemplateSetNamedPropertyHandler");
auto obj = auto obj =
CreateNamedInterceptorInfo(isolate, getter, setter, query, descriptor, CreateNamedInterceptorInfo(isolate, getter, setter, query, descriptor,
remover, enumerator, definer, data, flags); remover, enumerator, definer, data, flags);
...@@ -1658,7 +1659,7 @@ void ObjectTemplate::MarkAsUndetectable() { ...@@ -1658,7 +1659,7 @@ void ObjectTemplate::MarkAsUndetectable() {
ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
i::HandleScope scope(isolate); i::HandleScope scope(isolate);
auto cons = EnsureConstructor(isolate, this); auto cons = EnsureConstructor(isolate, this);
EnsureNotInstantiated(cons, "v8::ObjectTemplate::MarkAsUndetectable"); EnsureNotPublished(cons, "v8::ObjectTemplate::MarkAsUndetectable");
cons->set_undetectable(true); cons->set_undetectable(true);
} }
...@@ -1668,7 +1669,7 @@ void ObjectTemplate::SetAccessCheckCallback(AccessCheckCallback callback, ...@@ -1668,7 +1669,7 @@ void ObjectTemplate::SetAccessCheckCallback(AccessCheckCallback callback,
ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
i::HandleScope scope(isolate); i::HandleScope scope(isolate);
auto cons = EnsureConstructor(isolate, this); auto cons = EnsureConstructor(isolate, this);
EnsureNotInstantiated(cons, "v8::ObjectTemplate::SetAccessCheckCallback"); EnsureNotPublished(cons, "v8::ObjectTemplate::SetAccessCheckCallback");
i::Handle<i::Struct> struct_info = isolate->factory()->NewStruct( i::Handle<i::Struct> struct_info = isolate->factory()->NewStruct(
i::ACCESS_CHECK_INFO_TYPE, i::AllocationType::kOld); i::ACCESS_CHECK_INFO_TYPE, i::AllocationType::kOld);
...@@ -1697,8 +1698,8 @@ void ObjectTemplate::SetAccessCheckCallbackAndHandler( ...@@ -1697,8 +1698,8 @@ void ObjectTemplate::SetAccessCheckCallbackAndHandler(
ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
i::HandleScope scope(isolate); i::HandleScope scope(isolate);
auto cons = EnsureConstructor(isolate, this); auto cons = EnsureConstructor(isolate, this);
EnsureNotInstantiated( EnsureNotPublished(cons,
cons, "v8::ObjectTemplate::SetAccessCheckCallbackWithHandler"); "v8::ObjectTemplate::SetAccessCheckCallbackWithHandler");
i::Handle<i::Struct> struct_info = isolate->factory()->NewStruct( i::Handle<i::Struct> struct_info = isolate->factory()->NewStruct(
i::ACCESS_CHECK_INFO_TYPE, i::AllocationType::kOld); i::ACCESS_CHECK_INFO_TYPE, i::AllocationType::kOld);
...@@ -1733,7 +1734,7 @@ void ObjectTemplate::SetHandler( ...@@ -1733,7 +1734,7 @@ void ObjectTemplate::SetHandler(
ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
i::HandleScope scope(isolate); i::HandleScope scope(isolate);
auto cons = EnsureConstructor(isolate, this); auto cons = EnsureConstructor(isolate, this);
EnsureNotInstantiated(cons, "v8::ObjectTemplate::SetHandler"); EnsureNotPublished(cons, "v8::ObjectTemplate::SetHandler");
auto obj = CreateIndexedInterceptorInfo( auto obj = CreateIndexedInterceptorInfo(
isolate, config.getter, config.setter, config.query, config.descriptor, isolate, config.getter, config.setter, config.query, config.descriptor,
config.deleter, config.enumerator, config.definer, config.data, config.deleter, config.enumerator, config.definer, config.data,
...@@ -1747,7 +1748,7 @@ void ObjectTemplate::SetCallAsFunctionHandler(FunctionCallback callback, ...@@ -1747,7 +1748,7 @@ void ObjectTemplate::SetCallAsFunctionHandler(FunctionCallback callback,
ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
i::HandleScope scope(isolate); i::HandleScope scope(isolate);
auto cons = EnsureConstructor(isolate, this); auto cons = EnsureConstructor(isolate, this);
EnsureNotInstantiated(cons, "v8::ObjectTemplate::SetCallAsFunctionHandler"); EnsureNotPublished(cons, "v8::ObjectTemplate::SetCallAsFunctionHandler");
i::Handle<i::CallHandlerInfo> obj = isolate->factory()->NewCallHandlerInfo(); i::Handle<i::CallHandlerInfo> obj = isolate->factory()->NewCallHandlerInfo();
SET_FIELD_WRAPPED(isolate, obj, set_callback, callback); SET_FIELD_WRAPPED(isolate, obj, set_callback, callback);
SET_FIELD_WRAPPED(isolate, obj, set_js_callback, obj->redirected_callback()); SET_FIELD_WRAPPED(isolate, obj, set_js_callback, obj->redirected_callback());
......
...@@ -37,6 +37,7 @@ BOOL_ACCESSORS(FunctionTemplateInfo, flag, remove_prototype, ...@@ -37,6 +37,7 @@ BOOL_ACCESSORS(FunctionTemplateInfo, flag, remove_prototype,
BOOL_ACCESSORS(FunctionTemplateInfo, flag, do_not_cache, DoNotCacheBit::kShift) BOOL_ACCESSORS(FunctionTemplateInfo, flag, do_not_cache, DoNotCacheBit::kShift)
BOOL_ACCESSORS(FunctionTemplateInfo, flag, accept_any_receiver, BOOL_ACCESSORS(FunctionTemplateInfo, flag, accept_any_receiver,
AcceptAnyReceiverBit::kShift) AcceptAnyReceiverBit::kShift)
BOOL_ACCESSORS(FunctionTemplateInfo, flag, published, PublishedBit::kShift)
RELEASE_ACQUIRE_ACCESSORS(FunctionTemplateInfo, call_code, HeapObject, RELEASE_ACQUIRE_ACCESSORS(FunctionTemplateInfo, call_code, HeapObject,
kCallCodeOffset) kCallCodeOffset)
......
...@@ -109,6 +109,12 @@ class FunctionTemplateInfo ...@@ -109,6 +109,12 @@ class FunctionTemplateInfo
// If not set an access may be performed on calling the associated JSFunction. // If not set an access may be performed on calling the associated JSFunction.
DECL_BOOLEAN_ACCESSORS(accept_any_receiver) DECL_BOOLEAN_ACCESSORS(accept_any_receiver)
// This flag is used to check that the FunctionTemplateInfo instance is not
// changed after it became visible to TurboFan (either set in a
// SharedFunctionInfo or an accessor), because TF relies on immutability to
// safely read concurrently.
DECL_BOOLEAN_ACCESSORS(published)
// End flag bits --------------------- // End flag bits ---------------------
// Dispatched behavior. // Dispatched behavior.
......
...@@ -35,6 +35,7 @@ bitfield struct FunctionTemplateInfoFlags extends uint31 { ...@@ -35,6 +35,7 @@ bitfield struct FunctionTemplateInfoFlags extends uint31 {
remove_prototype: bool: 1 bit; remove_prototype: bool: 1 bit;
do_not_cache: bool: 1 bit; do_not_cache: bool: 1 bit;
accept_any_receiver: bool: 1 bit; accept_any_receiver: bool: 1 bit;
published: bool: 1 bit;
} }
@generateCppClass @generateCppClass
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment