Commit 7df6678c authored by Sathya Gunasekaran's avatar Sathya Gunasekaran Committed by V8 LUCI CQ

[api] Implement signature checks using instance types

Rather than depending on slow signature checks, receiver type checks are
performed using fast numeric instance type checks.

This CL adds a instance type range for embedders to assign values and
uses these to perform type checks.

Bug: v8:11476
Change-Id: Ie8236ae47ca0ba93ae76a7e690b81aa0a2b0f3e2
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2883623Reviewed-by: 's avatarLeszek Swirski <leszeks@chromium.org>
Reviewed-by: 's avatarCamillo Bruni <cbruni@chromium.org>
Commit-Queue: Sathya Gunasekaran  <gsathya@chromium.org>
Cr-Commit-Position: refs/heads/master@{#76162}
parent f9627c11
...@@ -188,6 +188,8 @@ V8_EXPORT internal::Isolate* IsolateFromNeverReadOnlySpaceObject(Address obj); ...@@ -188,6 +188,8 @@ V8_EXPORT internal::Isolate* IsolateFromNeverReadOnlySpaceObject(Address obj);
// language mode is strict. // language mode is strict.
V8_EXPORT bool ShouldThrowOnError(v8::internal::Isolate* isolate); V8_EXPORT bool ShouldThrowOnError(v8::internal::Isolate* isolate);
V8_EXPORT bool CanHaveInternalField(int instance_type);
/** /**
* This class exports constants and functionality from within v8 that * This class exports constants and functionality from within v8 that
* is necessary to implement inline functions in the v8 api. Don't * is necessary to implement inline functions in the v8 api. Don't
...@@ -266,8 +268,9 @@ class Internals { ...@@ -266,8 +268,9 @@ class Internals {
static const int kOddballType = 0x43; static const int kOddballType = 0x43;
static const int kForeignType = 0x46; static const int kForeignType = 0x46;
static const int kJSSpecialApiObjectType = 0x410; static const int kJSSpecialApiObjectType = 0x410;
static const int kJSApiObjectType = 0x420;
static const int kJSObjectType = 0x421; static const int kJSObjectType = 0x421;
static const int kFirstJSApiObjectType = 0x422;
static const int kLastJSApiObjectType = 0x80A;
static const int kUndefinedOddballKind = 5; static const int kUndefinedOddballKind = 5;
static const int kNullOddballKind = 3; static const int kNullOddballKind = 3;
......
...@@ -6544,9 +6544,9 @@ class V8_EXPORT FunctionTemplate : public Template { ...@@ -6544,9 +6544,9 @@ class V8_EXPORT FunctionTemplate : public Template {
Local<Signature> signature = Local<Signature>(), int length = 0, Local<Signature> signature = Local<Signature>(), int length = 0,
ConstructorBehavior behavior = ConstructorBehavior::kAllow, ConstructorBehavior behavior = ConstructorBehavior::kAllow,
SideEffectType side_effect_type = SideEffectType::kHasSideEffect, SideEffectType side_effect_type = SideEffectType::kHasSideEffect,
const CFunction* c_function = nullptr, uint8_t instance_type = 0, const CFunction* c_function = nullptr, uint16_t instance_type = 0,
uint8_t allowed_receiver_range_start = 0, uint16_t allowed_receiver_instance_type_range_start = 0,
uint8_t allowed_receiver_range_end = 0); uint16_t allowed_receiver_instance_type_range_end = 0);
/** Creates a function template for multiple overloaded fast API calls.*/ /** Creates a function template for multiple overloaded fast API calls.*/
static Local<FunctionTemplate> NewWithCFunctionOverloads( static Local<FunctionTemplate> NewWithCFunctionOverloads(
...@@ -11684,10 +11684,8 @@ Local<Value> Object::GetInternalField(int index) { ...@@ -11684,10 +11684,8 @@ Local<Value> Object::GetInternalField(int index) {
A obj = *reinterpret_cast<A*>(this); A obj = *reinterpret_cast<A*>(this);
// Fast path: If the object is a plain JSObject, which is the common case, we // Fast path: If the object is a plain JSObject, which is the common case, we
// know where to find the internal fields and can return the value directly. // know where to find the internal fields and can return the value directly.
auto instance_type = I::GetInstanceType(obj); int instance_type = I::GetInstanceType(obj);
if (instance_type == I::kJSObjectType || if (v8::internal::CanHaveInternalField(instance_type)) {
instance_type == I::kJSApiObjectType ||
instance_type == I::kJSSpecialApiObjectType) {
int offset = I::kJSObjectHeaderSize + (I::kEmbedderDataSlotSize * index); int offset = I::kJSObjectHeaderSize + (I::kEmbedderDataSlotSize * index);
A value = I::ReadRawField<A>(obj, offset); A value = I::ReadRawField<A>(obj, offset);
#ifdef V8_COMPRESS_POINTERS #ifdef V8_COMPRESS_POINTERS
...@@ -11713,9 +11711,7 @@ void* Object::GetAlignedPointerFromInternalField(int index) { ...@@ -11713,9 +11711,7 @@ void* Object::GetAlignedPointerFromInternalField(int index) {
// Fast path: If the object is a plain JSObject, which is the common case, we // Fast path: If the object is a plain JSObject, which is the common case, we
// know where to find the internal fields and can return the value directly. // know where to find the internal fields and can return the value directly.
auto instance_type = I::GetInstanceType(obj); auto instance_type = I::GetInstanceType(obj);
if (V8_LIKELY(instance_type == I::kJSObjectType || if (v8::internal::CanHaveInternalField(instance_type)) {
instance_type == I::kJSApiObjectType ||
instance_type == I::kJSSpecialApiObjectType)) {
int offset = I::kJSObjectHeaderSize + (I::kEmbedderDataSlotSize * index); int offset = I::kJSObjectHeaderSize + (I::kEmbedderDataSlotSize * index);
#ifdef V8_HEAP_SANDBOX #ifdef V8_HEAP_SANDBOX
offset += I::kEmbedderDataSlotRawPayloadOffset; offset += I::kEmbedderDataSlotRawPayloadOffset;
......
...@@ -528,12 +528,14 @@ MaybeHandle<JSFunction> InstantiateFunction( ...@@ -528,12 +528,14 @@ MaybeHandle<JSFunction> InstantiateFunction(
Handle<HeapObject>::cast(parent_prototype)); Handle<HeapObject>::cast(parent_prototype));
} }
} }
InstanceType function_type = InstanceType function_type = JS_SPECIAL_API_OBJECT_TYPE;
(!data->needs_access_check() && if (!data->needs_access_check() &&
data->GetNamedPropertyHandler().IsUndefined(isolate) && data->GetNamedPropertyHandler().IsUndefined(isolate) &&
data->GetIndexedPropertyHandler().IsUndefined(isolate)) data->GetIndexedPropertyHandler().IsUndefined(isolate)) {
? JS_API_OBJECT_TYPE function_type = FLAG_embedder_instance_types && data->HasInstanceType()
: JS_SPECIAL_API_OBJECT_TYPE; ? static_cast<InstanceType>(data->InstanceType())
: JS_API_OBJECT_TYPE;
}
Handle<JSFunction> function = ApiNatives::CreateApiFunction( Handle<JSFunction> function = ApiNatives::CreateApiFunction(
isolate, native_context, data, prototype, function_type, maybe_name); isolate, native_context, data, prototype, function_type, maybe_name);
......
...@@ -1226,8 +1226,9 @@ static Local<FunctionTemplate> FunctionTemplateNew( ...@@ -1226,8 +1226,9 @@ static Local<FunctionTemplate> FunctionTemplateNew(
v8::Local<Private> cached_property_name = v8::Local<Private>(), v8::Local<Private> cached_property_name = v8::Local<Private>(),
SideEffectType side_effect_type = SideEffectType::kHasSideEffect, SideEffectType side_effect_type = SideEffectType::kHasSideEffect,
const MemorySpan<const CFunction>& c_function_overloads = {}, const MemorySpan<const CFunction>& c_function_overloads = {},
uint8_t instance_type = 0, uint8_t allowed_receiver_range_start = 0, uint8_t instance_type = 0,
uint8_t allowed_receiver_range_end = 0) { uint8_t allowed_receiver_instance_type_range_start = 0,
uint8_t allowed_receiver_instance_type_range_end = 0) {
i::Handle<i::Struct> struct_obj = isolate->factory()->NewStruct( i::Handle<i::Struct> struct_obj = isolate->factory()->NewStruct(
i::FUNCTION_TEMPLATE_INFO_TYPE, i::AllocationType::kOld); i::FUNCTION_TEMPLATE_INFO_TYPE, i::AllocationType::kOld);
i::Handle<i::FunctionTemplateInfo> obj = i::Handle<i::FunctionTemplateInfo> obj =
...@@ -1250,8 +1251,10 @@ static Local<FunctionTemplate> FunctionTemplateNew( ...@@ -1250,8 +1251,10 @@ static Local<FunctionTemplate> FunctionTemplateNew(
: *Utils::OpenHandle(*cached_property_name)); : *Utils::OpenHandle(*cached_property_name));
if (behavior == ConstructorBehavior::kThrow) raw.set_remove_prototype(true); if (behavior == ConstructorBehavior::kThrow) raw.set_remove_prototype(true);
raw.SetInstanceType(instance_type); raw.SetInstanceType(instance_type);
raw.set_allowed_receiver_range_start(allowed_receiver_range_start); raw.set_allowed_receiver_instance_type_range_start(
raw.set_allowed_receiver_range_end(allowed_receiver_range_end); allowed_receiver_instance_type_range_start);
raw.set_allowed_receiver_instance_type_range_end(
allowed_receiver_instance_type_range_end);
} }
if (callback != nullptr) { if (callback != nullptr) {
Utils::ToLocal(obj)->SetCallHandler(callback, data, side_effect_type, Utils::ToLocal(obj)->SetCallHandler(callback, data, side_effect_type,
...@@ -1264,8 +1267,8 @@ Local<FunctionTemplate> FunctionTemplate::New( ...@@ -1264,8 +1267,8 @@ Local<FunctionTemplate> FunctionTemplate::New(
Isolate* isolate, FunctionCallback callback, v8::Local<Value> data, Isolate* isolate, FunctionCallback callback, v8::Local<Value> data,
v8::Local<Signature> signature, int length, ConstructorBehavior behavior, v8::Local<Signature> signature, int length, ConstructorBehavior behavior,
SideEffectType side_effect_type, const CFunction* c_function, SideEffectType side_effect_type, const CFunction* c_function,
uint8_t instance_type, uint8_t allowed_receiver_range_start, uint16_t instance_type, uint16_t allowed_receiver_instance_type_range_start,
uint8_t allowed_receiver_range_end) { uint16_t allowed_receiver_instance_type_range_end) {
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
// Changes to the environment cannot be captured in the snapshot. Expect no // Changes to the environment cannot be captured in the snapshot. Expect no
// function templates when the isolate is created for serialization. // function templates when the isolate is created for serialization.
...@@ -1276,7 +1279,8 @@ Local<FunctionTemplate> FunctionTemplate::New( ...@@ -1276,7 +1279,8 @@ Local<FunctionTemplate> FunctionTemplate::New(
Local<Private>(), side_effect_type, Local<Private>(), side_effect_type,
c_function ? MemorySpan<const CFunction>{c_function, 1} c_function ? MemorySpan<const CFunction>{c_function, 1}
: MemorySpan<const CFunction>{}, : MemorySpan<const CFunction>{},
instance_type, allowed_receiver_range_start, allowed_receiver_range_end); instance_type, allowed_receiver_instance_type_range_start,
allowed_receiver_instance_type_range_end);
} }
Local<FunctionTemplate> FunctionTemplate::NewWithCFunctionOverloads( Local<FunctionTemplate> FunctionTemplate::NewWithCFunctionOverloads(
...@@ -3712,6 +3716,13 @@ bool i::ShouldThrowOnError(i::Isolate* isolate) { ...@@ -3712,6 +3716,13 @@ bool i::ShouldThrowOnError(i::Isolate* isolate) {
i::ShouldThrow::kThrowOnError; i::ShouldThrow::kThrowOnError;
} }
bool i::CanHaveInternalField(int instance_type) {
return instance_type == i::Internals::kJSObjectType ||
instance_type == i::Internals::kJSSpecialApiObjectType ||
v8::internal::InstanceTypeChecker::IsJSApiObject(
static_cast<v8::internal::InstanceType>(instance_type));
}
void i::Internals::CheckInitializedImpl(v8::Isolate* external_isolate) { void i::Internals::CheckInitializedImpl(v8::Isolate* external_isolate) {
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(external_isolate); i::Isolate* isolate = reinterpret_cast<i::Isolate*>(external_isolate);
Utils::ApiCheck(isolate != nullptr && !isolate->IsDead(), Utils::ApiCheck(isolate != nullptr && !isolate->IsDead(),
......
...@@ -552,8 +552,20 @@ extern class Filler extends HeapObject generates 'TNode<HeapObject>'; ...@@ -552,8 +552,20 @@ extern class Filler extends HeapObject generates 'TNode<HeapObject>';
// but not their own class definitions: // but not their own class definitions:
// Like JSObject, but created from API function. // Like JSObject, but created from API function.
@apiExposedInstanceTypeValue(0x420) @apiExposedInstanceTypeValue(0x422)
@doNotGenerateCast
@noVerifier
extern class JSApiObject extends JSObject generates 'TNode<JSObject>'; extern class JSApiObject extends JSObject generates 'TNode<JSObject>';
// TODO(gsathya): This only exists to make JSApiObject instance type into a
// range.
@apiExposedInstanceTypeValue(0x80A)
@doNotGenerateCast
@highestInstanceTypeWithinParentClassRange
@noVerifier
extern class JSLastDummyApiObject extends JSApiObject
generates 'TNode<JSObject>';
// Like JSApiObject, but requires access checks and/or has interceptors. // Like JSApiObject, but requires access checks and/or has interceptors.
@apiExposedInstanceTypeValue(0x410) @apiExposedInstanceTypeValue(0x410)
extern class JSSpecialApiObject extends JSSpecialObject extern class JSSpecialApiObject extends JSSpecialObject
......
...@@ -472,7 +472,8 @@ class FastCApiObject { ...@@ -472,7 +472,8 @@ class FastCApiObject {
static bool IsValidApiObject(Local<Object> object) { static bool IsValidApiObject(Local<Object> object) {
i::Address addr = *reinterpret_cast<i::Address*>(*object); i::Address addr = *reinterpret_cast<i::Address*>(*object);
auto instance_type = i::Internals::GetInstanceType(addr); auto instance_type = i::Internals::GetInstanceType(addr);
return (instance_type == i::Internals::kJSApiObjectType || return (base::IsInRange(instance_type, i::Internals::kFirstJSApiObjectType,
i::Internals::kLastJSApiObjectType) ||
instance_type == i::Internals::kJSSpecialApiObjectType); instance_type == i::Internals::kJSSpecialApiObjectType);
} }
static FastCApiObject* UnwrapObject(Local<Object> object) { static FastCApiObject* UnwrapObject(Local<Object> object) {
......
...@@ -302,6 +302,8 @@ void HeapObject::HeapObjectVerify(Isolate* isolate) { ...@@ -302,6 +302,8 @@ void HeapObject::HeapObjectVerify(Isolate* isolate) {
#undef TYPED_ARRAY_CONSTRUCTORS_SWITCH #undef TYPED_ARRAY_CONSTRUCTORS_SWITCH
JSFunction::cast(*this).JSFunctionVerify(isolate); JSFunction::cast(*this).JSFunctionVerify(isolate);
break; break;
case JS_LAST_DUMMY_API_OBJECT_TYPE:
UNREACHABLE();
} }
} }
......
...@@ -261,6 +261,7 @@ void HeapObject::HeapObjectPrint(std::ostream& os) { ...@@ -261,6 +261,7 @@ void HeapObject::HeapObjectPrint(std::ostream& os) {
case THIN_ONE_BYTE_STRING_TYPE: case THIN_ONE_BYTE_STRING_TYPE:
case UNCACHED_EXTERNAL_STRING_TYPE: case UNCACHED_EXTERNAL_STRING_TYPE:
case UNCACHED_EXTERNAL_ONE_BYTE_STRING_TYPE: case UNCACHED_EXTERNAL_ONE_BYTE_STRING_TYPE:
case JS_LAST_DUMMY_API_OBJECT_TYPE:
// TODO(all): Handle these types too. // TODO(all): Handle these types too.
os << "UNKNOWN TYPE " << map().instance_type(); os << "UNKNOWN TYPE " << map().instance_type();
UNREACHABLE(); UNREACHABLE();
......
...@@ -1394,6 +1394,9 @@ DEFINE_NEG_IMPLICATION(parallel_compile_tasks, finalize_streaming_on_background) ...@@ -1394,6 +1394,9 @@ DEFINE_NEG_IMPLICATION(parallel_compile_tasks, finalize_streaming_on_background)
DEFINE_BOOL(disable_old_api_accessors, false, DEFINE_BOOL(disable_old_api_accessors, false,
"Disable old-style API accessors whose setters trigger through the " "Disable old-style API accessors whose setters trigger through the "
"prototype chain") "prototype chain")
DEFINE_BOOL(
embedder_instance_types, false,
"enable type checks based on instance types provided by the embedder")
// bootstrapper.cc // bootstrapper.cc
DEFINE_BOOL(expose_gc, false, "expose gc extension") DEFINE_BOOL(expose_gc, false, "expose gc extension")
......
...@@ -1812,8 +1812,8 @@ Handle<JSObject> Factory::CopyJSObjectWithAllocationSite( ...@@ -1812,8 +1812,8 @@ Handle<JSObject> Factory::CopyJSObjectWithAllocationSite(
bool is_clonable_js_type = bool is_clonable_js_type =
instance_type == JS_REG_EXP_TYPE || instance_type == JS_OBJECT_TYPE || instance_type == JS_REG_EXP_TYPE || instance_type == JS_OBJECT_TYPE ||
instance_type == JS_ERROR_TYPE || instance_type == JS_ARRAY_TYPE || instance_type == JS_ERROR_TYPE || instance_type == JS_ARRAY_TYPE ||
instance_type == JS_API_OBJECT_TYPE || instance_type == JS_SPECIAL_API_OBJECT_TYPE ||
instance_type == JS_SPECIAL_API_OBJECT_TYPE; InstanceTypeChecker::IsJSApiObject(instance_type);
bool is_clonable_wasm_type = false; bool is_clonable_wasm_type = false;
#if V8_ENABLE_WEBASSEMBLY #if V8_ENABLE_WEBASSEMBLY
is_clonable_wasm_type = instance_type == WASM_GLOBAL_OBJECT_TYPE || is_clonable_wasm_type = instance_type == WASM_GLOBAL_OBJECT_TYPE ||
......
...@@ -149,7 +149,8 @@ constexpr InstanceType LAST_STRING_TYPE = ...@@ -149,7 +149,8 @@ constexpr InstanceType LAST_STRING_TYPE =
STATIC_ASSERT((FIRST_NONSTRING_TYPE & kIsNotStringMask) != kStringTag); STATIC_ASSERT((FIRST_NONSTRING_TYPE & kIsNotStringMask) != kStringTag);
STATIC_ASSERT(JS_OBJECT_TYPE == Internals::kJSObjectType); STATIC_ASSERT(JS_OBJECT_TYPE == Internals::kJSObjectType);
STATIC_ASSERT(JS_API_OBJECT_TYPE == Internals::kJSApiObjectType); STATIC_ASSERT(FIRST_JS_API_OBJECT_TYPE == Internals::kFirstJSApiObjectType);
STATIC_ASSERT(LAST_JS_API_OBJECT_TYPE == Internals::kLastJSApiObjectType);
STATIC_ASSERT(JS_SPECIAL_API_OBJECT_TYPE == Internals::kJSSpecialApiObjectType); STATIC_ASSERT(JS_SPECIAL_API_OBJECT_TYPE == Internals::kJSSpecialApiObjectType);
STATIC_ASSERT(FIRST_NONSTRING_TYPE == Internals::kFirstNonstringType); STATIC_ASSERT(FIRST_NONSTRING_TYPE == Internals::kFirstNonstringType);
STATIC_ASSERT(ODDBALL_TYPE == Internals::kOddballType); STATIC_ASSERT(ODDBALL_TYPE == Internals::kOddballType);
......
...@@ -2338,6 +2338,11 @@ int JSObject::GetHeaderSize(InstanceType type, ...@@ -2338,6 +2338,11 @@ int JSObject::GetHeaderSize(InstanceType type,
return WasmTagObject::kHeaderSize; return WasmTagObject::kHeaderSize;
#endif // V8_ENABLE_WEBASSEMBLY #endif // V8_ENABLE_WEBASSEMBLY
default: { default: {
// Special type check for API Objects because they are in a large variable
// instance type range.
if (InstanceTypeChecker::IsJSApiObject(type)) {
return JSObject::kHeaderSize;
}
std::stringstream ss; std::stringstream ss;
ss << type; ss << type;
FATAL("unexpected instance type: %s\n", ss.str().c_str()); FATAL("unexpected instance type: %s\n", ss.str().c_str());
...@@ -5143,18 +5148,18 @@ bool JSObject::IsApiWrapper() { ...@@ -5143,18 +5148,18 @@ bool JSObject::IsApiWrapper() {
// *_API_* types are generated through templates which can have embedder // *_API_* types are generated through templates which can have embedder
// fields. The other types have their embedder fields added at compile time. // fields. The other types have their embedder fields added at compile time.
auto instance_type = map().instance_type(); auto instance_type = map().instance_type();
return instance_type == JS_API_OBJECT_TYPE || return instance_type == JS_ARRAY_BUFFER_TYPE ||
instance_type == JS_ARRAY_BUFFER_TYPE ||
instance_type == JS_DATA_VIEW_TYPE || instance_type == JS_DATA_VIEW_TYPE ||
instance_type == JS_GLOBAL_OBJECT_TYPE || instance_type == JS_GLOBAL_OBJECT_TYPE ||
instance_type == JS_GLOBAL_PROXY_TYPE || instance_type == JS_GLOBAL_PROXY_TYPE ||
instance_type == JS_SPECIAL_API_OBJECT_TYPE || instance_type == JS_SPECIAL_API_OBJECT_TYPE ||
instance_type == JS_TYPED_ARRAY_TYPE; instance_type == JS_TYPED_ARRAY_TYPE ||
InstanceTypeChecker::IsJSApiObject(instance_type);
} }
bool JSObject::IsDroppableApiWrapper() { bool JSObject::IsDroppableApiWrapper() {
auto instance_type = map().instance_type(); auto instance_type = map().instance_type();
return instance_type == JS_API_OBJECT_TYPE || return InstanceTypeChecker::IsJSApiObject(instance_type) ||
instance_type == JS_SPECIAL_API_OBJECT_TYPE; instance_type == JS_SPECIAL_API_OBJECT_TYPE;
} }
......
...@@ -112,6 +112,10 @@ VisitorId Map::GetVisitorId(Map map) { ...@@ -112,6 +112,10 @@ VisitorId Map::GetVisitorId(Map map) {
UNREACHABLE(); UNREACHABLE();
} }
if (InstanceTypeChecker::IsJSApiObject(map.instance_type())) {
return kVisitJSApiObject;
}
switch (instance_type) { switch (instance_type) {
case BYTE_ARRAY_TYPE: case BYTE_ARRAY_TYPE:
return kVisitByteArray; return kVisitByteArray;
......
...@@ -270,6 +270,7 @@ class ZoneForwardList; ...@@ -270,6 +270,7 @@ class ZoneForwardList;
V(FreeSpaceOrFiller) \ V(FreeSpaceOrFiller) \
V(FunctionContext) \ V(FunctionContext) \
V(JSApiObject) \ V(JSApiObject) \
V(JSLastDummyApiObject) \
V(JSPromiseConstructor) \ V(JSPromiseConstructor) \
V(JSArrayConstructor) \ V(JSArrayConstructor) \
V(JSRegExpConstructor) \ V(JSRegExpConstructor) \
......
...@@ -1006,6 +1006,9 @@ ReturnType BodyDescriptorApply(InstanceType type, T1 p1, T2 p2, T3 p3, T4 p4) { ...@@ -1006,6 +1006,9 @@ ReturnType BodyDescriptorApply(InstanceType type, T1 p1, T2 p2, T3 p3, T4 p4) {
} }
UNREACHABLE(); UNREACHABLE();
} }
if (InstanceTypeChecker::IsJSApiObject(type)) {
return Op::template apply<JSObject::BodyDescriptor>(p1, p2, p3, p4);
}
switch (type) { switch (type) {
case EMBEDDER_DATA_ARRAY_TYPE: case EMBEDDER_DATA_ARRAY_TYPE:
......
...@@ -38,10 +38,12 @@ BOOL_ACCESSORS(FunctionTemplateInfo, flag, accept_any_receiver, ...@@ -38,10 +38,12 @@ BOOL_ACCESSORS(FunctionTemplateInfo, flag, accept_any_receiver,
AcceptAnyReceiverBit::kShift) AcceptAnyReceiverBit::kShift)
BOOL_ACCESSORS(FunctionTemplateInfo, flag, published, PublishedBit::kShift) BOOL_ACCESSORS(FunctionTemplateInfo, flag, published, PublishedBit::kShift)
BIT_FIELD_ACCESSORS(FunctionTemplateInfo, flag, allowed_receiver_range_start, BIT_FIELD_ACCESSORS(
FunctionTemplateInfo::AllowedReceiverRangeStartBits) FunctionTemplateInfo, flag, allowed_receiver_instance_type_range_start,
BIT_FIELD_ACCESSORS(FunctionTemplateInfo, flag, allowed_receiver_range_end, FunctionTemplateInfo::AllowedReceiverInstanceTypeRangeStartBits)
FunctionTemplateInfo::AllowedReceiverRangeEndBits) BIT_FIELD_ACCESSORS(
FunctionTemplateInfo, flag, allowed_receiver_instance_type_range_end,
FunctionTemplateInfo::AllowedReceiverInstanceTypeRangeEndBits)
// static // static
FunctionTemplateRareData FunctionTemplateInfo::EnsureFunctionTemplateRareData( FunctionTemplateRareData FunctionTemplateInfo::EnsureFunctionTemplateRareData(
...@@ -85,10 +87,23 @@ RARE_ACCESSORS(c_function_overloads, CFunctionOverloads, FixedArray, ...@@ -85,10 +87,23 @@ RARE_ACCESSORS(c_function_overloads, CFunctionOverloads, FixedArray,
GetReadOnlyRoots(cage_base).empty_fixed_array()) GetReadOnlyRoots(cage_base).empty_fixed_array())
#undef RARE_ACCESSORS #undef RARE_ACCESSORS
int FunctionTemplateInfo::InstanceType() const { return instance_type(); } int FunctionTemplateInfo::InstanceType() const {
int type = instance_type();
DCHECK(type == kNoJSApiObjectType ||
(type >= Internals::kFirstJSApiObjectType &&
type <= Internals::kLastJSApiObjectType));
return type;
}
void FunctionTemplateInfo::SetInstanceType(int instance_type) { void FunctionTemplateInfo::SetInstanceType(int instance_type) {
set_instance_type(instance_type); if (instance_type == 0) {
set_instance_type(kNoJSApiObjectType);
} else {
DCHECK_GT(instance_type, 0);
DCHECK_LT(Internals::kFirstJSApiObjectType + instance_type,
Internals::kLastJSApiObjectType);
set_instance_type(Internals::kFirstJSApiObjectType + instance_type);
}
} }
bool TemplateInfo::should_cache() const { bool TemplateInfo::should_cache() const {
......
...@@ -18,6 +18,10 @@ ...@@ -18,6 +18,10 @@
namespace v8 { namespace v8 {
namespace internal { namespace internal {
bool FunctionTemplateInfo::HasInstanceType() {
return instance_type() != kNoJSApiObjectType;
}
Handle<SharedFunctionInfo> FunctionTemplateInfo::GetOrCreateSharedFunctionInfo( Handle<SharedFunctionInfo> FunctionTemplateInfo::GetOrCreateSharedFunctionInfo(
Isolate* isolate, Handle<FunctionTemplateInfo> info, Isolate* isolate, Handle<FunctionTemplateInfo> info,
MaybeHandle<Name> maybe_name) { MaybeHandle<Name> maybe_name) {
...@@ -61,6 +65,17 @@ bool FunctionTemplateInfo::IsTemplateFor(Map map) const { ...@@ -61,6 +65,17 @@ bool FunctionTemplateInfo::IsTemplateFor(Map map) const {
// There is a constraint on the object; check. // There is a constraint on the object; check.
if (!map.IsJSObjectMap()) return false; if (!map.IsJSObjectMap()) return false;
if (FLAG_embedder_instance_types) {
DCHECK_IMPLIES(allowed_receiver_instance_type_range_start() == 0,
allowed_receiver_instance_type_range_end() == 0);
if (base::IsInRange(map.instance_type(),
allowed_receiver_instance_type_range_start(),
allowed_receiver_instance_type_range_end())) {
return true;
}
}
// Fetch the constructor function of the object. // Fetch the constructor function of the object.
Object cons_obj = map.GetConstructor(); Object cons_obj = map.GetConstructor();
Object type; Object type;
......
...@@ -123,8 +123,10 @@ class FunctionTemplateInfo ...@@ -123,8 +123,10 @@ class FunctionTemplateInfo
// safely read concurrently. // safely read concurrently.
DECL_BOOLEAN_ACCESSORS(published) DECL_BOOLEAN_ACCESSORS(published)
DECL_INT_ACCESSORS(allowed_receiver_range_start) // This specifies the permissable range of instance type of objects that can
DECL_INT_ACCESSORS(allowed_receiver_range_end) // be allowed to be used as receivers with the given template.
DECL_INT16_ACCESSORS(allowed_receiver_instance_type_range_start)
DECL_INT16_ACCESSORS(allowed_receiver_instance_type_range_end)
// End flag bits --------------------- // End flag bits ---------------------
// Dispatched behavior. // Dispatched behavior.
...@@ -157,6 +159,7 @@ class FunctionTemplateInfo ...@@ -157,6 +159,7 @@ class FunctionTemplateInfo
inline bool instantiated(); inline bool instantiated();
bool BreakAtEntry(); bool BreakAtEntry();
bool HasInstanceType();
// Helper function for cached accessors. // Helper function for cached accessors.
static base::Optional<Name> TryGetCachedPropertyName(Isolate* isolate, static base::Optional<Name> TryGetCachedPropertyName(Isolate* isolate,
...@@ -174,6 +177,7 @@ class FunctionTemplateInfo ...@@ -174,6 +177,7 @@ class FunctionTemplateInfo
DEFINE_TORQUE_GENERATED_FUNCTION_TEMPLATE_INFO_FLAGS() DEFINE_TORQUE_GENERATED_FUNCTION_TEMPLATE_INFO_FLAGS()
private: private:
static constexpr int kNoJSApiObjectType = 0;
static inline FunctionTemplateRareData EnsureFunctionTemplateRareData( static inline FunctionTemplateRareData EnsureFunctionTemplateRareData(
Isolate* isolate, Handle<FunctionTemplateInfo> function_template_info); Isolate* isolate, Handle<FunctionTemplateInfo> function_template_info);
......
...@@ -35,8 +35,8 @@ bitfield struct FunctionTemplateInfoFlags extends uint31 { ...@@ -35,8 +35,8 @@ bitfield struct FunctionTemplateInfoFlags extends uint31 {
// Allowed receiver ranges are used for instance type checking to check // Allowed receiver ranges are used for instance type checking to check
// whether the receiver calling the associated JSFunction is a compatible // whether the receiver calling the associated JSFunction is a compatible
// receiver. // receiver.
allowed_receiver_range_start: int32: 12 bit; allowed_receiver_instance_type_range_start: int16: 12 bit;
allowed_receiver_range_end: int32: 12 bit; allowed_receiver_instance_type_range_end: int16: 12 bit;
} }
extern class FunctionTemplateInfo extends TemplateInfo { extern class FunctionTemplateInfo extends TemplateInfo {
......
...@@ -414,7 +414,9 @@ int RegisterThreadedTest::count_ = 0; ...@@ -414,7 +414,9 @@ int RegisterThreadedTest::count_ = 0;
bool IsValidUnwrapObject(v8::Object* object) { bool IsValidUnwrapObject(v8::Object* object) {
i::Address addr = *reinterpret_cast<i::Address*>(object); i::Address addr = *reinterpret_cast<i::Address*>(object);
auto instance_type = i::Internals::GetInstanceType(addr); auto instance_type = i::Internals::GetInstanceType(addr);
return (instance_type == i::Internals::kJSObjectType || return (v8::base::IsInRange(instance_type,
instance_type == i::Internals::kJSApiObjectType || i::Internals::kFirstJSApiObjectType,
i::Internals::kLastJSApiObjectType) ||
instance_type == i::Internals::kJSObjectType ||
instance_type == i::Internals::kJSSpecialApiObjectType); instance_type == i::Internals::kJSSpecialApiObjectType);
} }
...@@ -29251,3 +29251,57 @@ TEST(TestSetSabConstructorEnabledCallback) { ...@@ -29251,3 +29251,57 @@ TEST(TestSetSabConstructorEnabledCallback) {
sab_constructor_enabled_value = true; sab_constructor_enabled_value = true;
CHECK(i_isolate->IsSharedArrayBufferConstructorEnabled(i_context)); CHECK(i_isolate->IsSharedArrayBufferConstructorEnabled(i_context));
} }
namespace {
void NodeTypeCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
v8::Isolate* isolate = args.GetIsolate();
args.GetReturnValue().Set(v8::Number::New(isolate, 1));
}
} // namespace
TEST(EmbedderInstanceTypes) {
LocalContext env;
v8::Isolate* isolate = env->GetIsolate();
v8::HandleScope scope(isolate);
i::FLAG_embedder_instance_types = true;
Local<FunctionTemplate> node = FunctionTemplate::New(isolate);
Local<ObjectTemplate> proto_template = node->PrototypeTemplate();
Local<FunctionTemplate> nodeType = v8::FunctionTemplate::New(
isolate, NodeTypeCallback, Local<Value>(),
v8::Signature::New(isolate, node), 0, v8::ConstructorBehavior::kThrow,
v8::SideEffectType::kHasSideEffect, nullptr, 0, 1, 3);
proto_template->SetAccessorProperty(
String::NewFromUtf8Literal(isolate, "nodeType"), nodeType);
Local<FunctionTemplate> element = FunctionTemplate::New(
isolate, nullptr, Local<Value>(), Local<v8::Signature>(), 0,
v8::ConstructorBehavior::kAllow, v8::SideEffectType::kHasSideEffect,
nullptr, 1);
element->Inherit(node);
Local<FunctionTemplate> html_element = FunctionTemplate::New(
isolate, nullptr, Local<Value>(), Local<v8::Signature>(), 0,
v8::ConstructorBehavior::kAllow, v8::SideEffectType::kHasSideEffect,
nullptr, 2);
html_element->Inherit(element);
Local<FunctionTemplate> div_element = FunctionTemplate::New(
isolate, nullptr, Local<Value>(), Local<v8::Signature>(), 0,
v8::ConstructorBehavior::kAllow, v8::SideEffectType::kHasSideEffect,
nullptr, 3);
div_element->Inherit(html_element);
CHECK(env->Global()
->Set(env.local(), v8_str("div"),
div_element->GetFunction(env.local())
.ToLocalChecked()
->NewInstance(env.local())
.ToLocalChecked())
.FromJust());
CompileRun("var x = div.nodeType;");
Local<Value> res =
env->Global()->Get(env.local(), v8_str("x")).ToLocalChecked();
CHECK_EQ(1, res->ToInt32(env.local()).ToLocalChecked()->Value());
}
...@@ -156,81 +156,82 @@ INSTANCE_TYPES = { ...@@ -156,81 +156,82 @@ INSTANCE_TYPES = {
191: "JS_MODULE_NAMESPACE_TYPE", 191: "JS_MODULE_NAMESPACE_TYPE",
1040: "JS_SPECIAL_API_OBJECT_TYPE", 1040: "JS_SPECIAL_API_OBJECT_TYPE",
1041: "JS_PRIMITIVE_WRAPPER_TYPE", 1041: "JS_PRIMITIVE_WRAPPER_TYPE",
1042: "JS_ARRAY_ITERATOR_PROTOTYPE_TYPE", 1058: "JS_API_OBJECT_TYPE",
1043: "JS_ITERATOR_PROTOTYPE_TYPE", 2058: "JS_LAST_DUMMY_API_OBJECT_TYPE",
1044: "JS_MAP_ITERATOR_PROTOTYPE_TYPE", 2059: "JS_BOUND_FUNCTION_TYPE",
1045: "JS_OBJECT_PROTOTYPE_TYPE", 2060: "JS_FUNCTION_TYPE",
1046: "JS_PROMISE_PROTOTYPE_TYPE", 2061: "BIGINT64_TYPED_ARRAY_CONSTRUCTOR_TYPE",
1047: "JS_REG_EXP_PROTOTYPE_TYPE", 2062: "BIGUINT64_TYPED_ARRAY_CONSTRUCTOR_TYPE",
1048: "JS_SET_ITERATOR_PROTOTYPE_TYPE", 2063: "FLOAT32_TYPED_ARRAY_CONSTRUCTOR_TYPE",
1049: "JS_SET_PROTOTYPE_TYPE", 2064: "FLOAT64_TYPED_ARRAY_CONSTRUCTOR_TYPE",
1050: "JS_STRING_ITERATOR_PROTOTYPE_TYPE", 2065: "INT16_TYPED_ARRAY_CONSTRUCTOR_TYPE",
1051: "JS_TYPED_ARRAY_PROTOTYPE_TYPE", 2066: "INT32_TYPED_ARRAY_CONSTRUCTOR_TYPE",
1052: "JS_GENERATOR_OBJECT_TYPE", 2067: "INT8_TYPED_ARRAY_CONSTRUCTOR_TYPE",
1053: "JS_ASYNC_FUNCTION_OBJECT_TYPE", 2068: "UINT16_TYPED_ARRAY_CONSTRUCTOR_TYPE",
1054: "JS_ASYNC_GENERATOR_OBJECT_TYPE", 2069: "UINT32_TYPED_ARRAY_CONSTRUCTOR_TYPE",
1055: "JS_ARGUMENTS_OBJECT_TYPE", 2070: "UINT8_CLAMPED_TYPED_ARRAY_CONSTRUCTOR_TYPE",
1056: "JS_API_OBJECT_TYPE", 2071: "UINT8_TYPED_ARRAY_CONSTRUCTOR_TYPE",
1058: "JS_BOUND_FUNCTION_TYPE", 2072: "JS_ARRAY_CONSTRUCTOR_TYPE",
1059: "JS_FUNCTION_TYPE", 2073: "JS_PROMISE_CONSTRUCTOR_TYPE",
1060: "BIGINT64_TYPED_ARRAY_CONSTRUCTOR_TYPE", 2074: "JS_REG_EXP_CONSTRUCTOR_TYPE",
1061: "BIGUINT64_TYPED_ARRAY_CONSTRUCTOR_TYPE", 2075: "JS_ARRAY_ITERATOR_PROTOTYPE_TYPE",
1062: "FLOAT32_TYPED_ARRAY_CONSTRUCTOR_TYPE", 2076: "JS_ITERATOR_PROTOTYPE_TYPE",
1063: "FLOAT64_TYPED_ARRAY_CONSTRUCTOR_TYPE", 2077: "JS_MAP_ITERATOR_PROTOTYPE_TYPE",
1064: "INT16_TYPED_ARRAY_CONSTRUCTOR_TYPE", 2078: "JS_OBJECT_PROTOTYPE_TYPE",
1065: "INT32_TYPED_ARRAY_CONSTRUCTOR_TYPE", 2079: "JS_PROMISE_PROTOTYPE_TYPE",
1066: "INT8_TYPED_ARRAY_CONSTRUCTOR_TYPE", 2080: "JS_REG_EXP_PROTOTYPE_TYPE",
1067: "UINT16_TYPED_ARRAY_CONSTRUCTOR_TYPE", 2081: "JS_SET_ITERATOR_PROTOTYPE_TYPE",
1068: "UINT32_TYPED_ARRAY_CONSTRUCTOR_TYPE", 2082: "JS_SET_PROTOTYPE_TYPE",
1069: "UINT8_CLAMPED_TYPED_ARRAY_CONSTRUCTOR_TYPE", 2083: "JS_STRING_ITERATOR_PROTOTYPE_TYPE",
1070: "UINT8_TYPED_ARRAY_CONSTRUCTOR_TYPE", 2084: "JS_TYPED_ARRAY_PROTOTYPE_TYPE",
1071: "JS_ARRAY_CONSTRUCTOR_TYPE", 2085: "JS_MAP_KEY_ITERATOR_TYPE",
1072: "JS_PROMISE_CONSTRUCTOR_TYPE", 2086: "JS_MAP_KEY_VALUE_ITERATOR_TYPE",
1073: "JS_REG_EXP_CONSTRUCTOR_TYPE", 2087: "JS_MAP_VALUE_ITERATOR_TYPE",
1074: "JS_MAP_KEY_ITERATOR_TYPE", 2088: "JS_SET_KEY_VALUE_ITERATOR_TYPE",
1075: "JS_MAP_KEY_VALUE_ITERATOR_TYPE", 2089: "JS_SET_VALUE_ITERATOR_TYPE",
1076: "JS_MAP_VALUE_ITERATOR_TYPE", 2090: "JS_GENERATOR_OBJECT_TYPE",
1077: "JS_SET_KEY_VALUE_ITERATOR_TYPE", 2091: "JS_ASYNC_FUNCTION_OBJECT_TYPE",
1078: "JS_SET_VALUE_ITERATOR_TYPE", 2092: "JS_ASYNC_GENERATOR_OBJECT_TYPE",
1079: "JS_DATA_VIEW_TYPE", 2093: "JS_DATA_VIEW_TYPE",
1080: "JS_TYPED_ARRAY_TYPE", 2094: "JS_TYPED_ARRAY_TYPE",
1081: "JS_MAP_TYPE", 2095: "JS_MAP_TYPE",
1082: "JS_SET_TYPE", 2096: "JS_SET_TYPE",
1083: "JS_WEAK_MAP_TYPE", 2097: "JS_WEAK_MAP_TYPE",
1084: "JS_WEAK_SET_TYPE", 2098: "JS_WEAK_SET_TYPE",
1085: "JS_ARRAY_TYPE", 2099: "JS_ARGUMENTS_OBJECT_TYPE",
1086: "JS_ARRAY_BUFFER_TYPE", 2100: "JS_ARRAY_TYPE",
1087: "JS_ARRAY_ITERATOR_TYPE", 2101: "JS_ARRAY_BUFFER_TYPE",
1088: "JS_ASYNC_FROM_SYNC_ITERATOR_TYPE", 2102: "JS_ARRAY_ITERATOR_TYPE",
1089: "JS_COLLATOR_TYPE", 2103: "JS_ASYNC_FROM_SYNC_ITERATOR_TYPE",
1090: "JS_CONTEXT_EXTENSION_OBJECT_TYPE", 2104: "JS_COLLATOR_TYPE",
1091: "JS_DATE_TYPE", 2105: "JS_CONTEXT_EXTENSION_OBJECT_TYPE",
1092: "JS_DATE_TIME_FORMAT_TYPE", 2106: "JS_DATE_TYPE",
1093: "JS_DISPLAY_NAMES_TYPE", 2107: "JS_DATE_TIME_FORMAT_TYPE",
1094: "JS_ERROR_TYPE", 2108: "JS_DISPLAY_NAMES_TYPE",
1095: "JS_FINALIZATION_REGISTRY_TYPE", 2109: "JS_ERROR_TYPE",
1096: "JS_LIST_FORMAT_TYPE", 2110: "JS_FINALIZATION_REGISTRY_TYPE",
1097: "JS_LOCALE_TYPE", 2111: "JS_LIST_FORMAT_TYPE",
1098: "JS_MESSAGE_OBJECT_TYPE", 2112: "JS_LOCALE_TYPE",
1099: "JS_NUMBER_FORMAT_TYPE", 2113: "JS_MESSAGE_OBJECT_TYPE",
1100: "JS_PLURAL_RULES_TYPE", 2114: "JS_NUMBER_FORMAT_TYPE",
1101: "JS_PROMISE_TYPE", 2115: "JS_PLURAL_RULES_TYPE",
1102: "JS_REG_EXP_TYPE", 2116: "JS_PROMISE_TYPE",
1103: "JS_REG_EXP_STRING_ITERATOR_TYPE", 2117: "JS_REG_EXP_TYPE",
1104: "JS_RELATIVE_TIME_FORMAT_TYPE", 2118: "JS_REG_EXP_STRING_ITERATOR_TYPE",
1105: "JS_SEGMENT_ITERATOR_TYPE", 2119: "JS_RELATIVE_TIME_FORMAT_TYPE",
1106: "JS_SEGMENTER_TYPE", 2120: "JS_SEGMENT_ITERATOR_TYPE",
1107: "JS_SEGMENTS_TYPE", 2121: "JS_SEGMENTER_TYPE",
1108: "JS_STRING_ITERATOR_TYPE", 2122: "JS_SEGMENTS_TYPE",
1109: "JS_V8_BREAK_ITERATOR_TYPE", 2123: "JS_STRING_ITERATOR_TYPE",
1110: "JS_WEAK_REF_TYPE", 2124: "JS_V8_BREAK_ITERATOR_TYPE",
1111: "WASM_GLOBAL_OBJECT_TYPE", 2125: "JS_WEAK_REF_TYPE",
1112: "WASM_INSTANCE_OBJECT_TYPE", 2126: "WASM_GLOBAL_OBJECT_TYPE",
1113: "WASM_MEMORY_OBJECT_TYPE", 2127: "WASM_INSTANCE_OBJECT_TYPE",
1114: "WASM_MODULE_OBJECT_TYPE", 2128: "WASM_MEMORY_OBJECT_TYPE",
1115: "WASM_TABLE_OBJECT_TYPE", 2129: "WASM_MODULE_OBJECT_TYPE",
1116: "WASM_TAG_OBJECT_TYPE", 2130: "WASM_TABLE_OBJECT_TYPE",
1117: "WASM_VALUE_OBJECT_TYPE", 2131: "WASM_TAG_OBJECT_TYPE",
2132: "WASM_VALUE_OBJECT_TYPE",
} }
# List of known V8 maps. # List of known V8 maps.
...@@ -390,7 +391,7 @@ KNOWN_MAPS = { ...@@ -390,7 +391,7 @@ KNOWN_MAPS = {
("read_only_space", 0x05fa9): (82, "StoreHandler2Map"), ("read_only_space", 0x05fa9): (82, "StoreHandler2Map"),
("read_only_space", 0x05fd1): (82, "StoreHandler3Map"), ("read_only_space", 0x05fd1): (82, "StoreHandler3Map"),
("map_space", 0x02119): (1057, "ExternalMap"), ("map_space", 0x02119): (1057, "ExternalMap"),
("map_space", 0x02141): (1098, "JSMessageObjectMap"), ("map_space", 0x02141): (2113, "JSMessageObjectMap"),
} }
# List of known V8 objects. # List of known V8 objects.
......
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