Commit 1cd7a582 authored by Patrick Thier's avatar Patrick Thier Committed by V8 LUCI CQ

Create Instance Type for Class Constructors

Class Constructors are special, because they are callable but [[Call]]
raises an exception. Instead of checking if a JS function is a class
constructor for every JS function call, this CL adds a new instance
type for class constructors.
This way we can use a fast instance type range check for the common
case, and only check for class constructors in the uncommon case were
a class constructor is called and when we need to raise an exception.

Change-Id: Ic6fdd9829722d05559fdfd01f6100c61873a0872
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3186434Reviewed-by: 's avatarCamillo Bruni <cbruni@chromium.org>
Reviewed-by: 's avatarDominik Inführ <dinfuehr@chromium.org>
Reviewed-by: 's avatarJakob Gruber <jgruber@chromium.org>
Commit-Queue: Patrick Thier <pthier@chromium.org>
Cr-Commit-Position: refs/heads/main@{#77140}
parent e57ec7ae
...@@ -2282,13 +2282,7 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm, ...@@ -2282,13 +2282,7 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm,
// ----------------------------------- // -----------------------------------
__ AssertFunction(r1); __ AssertFunction(r1);
// See ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList)
// Check that the function is not a "classConstructor".
Label class_constructor;
__ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); __ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
__ ldr(r3, FieldMemOperand(r2, SharedFunctionInfo::kFlagsOffset));
__ tst(r3, Operand(SharedFunctionInfo::IsClassConstructorBit::kMask));
__ b(ne, &class_constructor);
// Enter the context of the function; ToObject has to run in the function // Enter the context of the function; ToObject has to run in the function
// context, and we also need to take the global proxy from the function // context, and we also need to take the global proxy from the function
...@@ -2363,14 +2357,6 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm, ...@@ -2363,14 +2357,6 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm,
__ ldrh(r2, __ ldrh(r2,
FieldMemOperand(r2, SharedFunctionInfo::kFormalParameterCountOffset)); FieldMemOperand(r2, SharedFunctionInfo::kFormalParameterCountOffset));
__ InvokeFunctionCode(r1, no_reg, r2, r0, InvokeType::kJump); __ InvokeFunctionCode(r1, no_reg, r2, r0, InvokeType::kJump);
// The function is a "classConstructor", need to raise an exception.
__ bind(&class_constructor);
{
FrameScope frame(masm, StackFrame::INTERNAL);
__ push(r1);
__ CallRuntime(Runtime::kThrowConstructorNonCallableError);
}
} }
namespace { namespace {
...@@ -2481,12 +2467,11 @@ void Builtins::Generate_Call(MacroAssembler* masm, ConvertReceiverMode mode) { ...@@ -2481,12 +2467,11 @@ void Builtins::Generate_Call(MacroAssembler* masm, ConvertReceiverMode mode) {
// -- r1 : the target to call (can be any Object). // -- r1 : the target to call (can be any Object).
// ----------------------------------- // -----------------------------------
Label non_callable, non_smi; Label non_callable, class_constructor;
__ JumpIfSmi(r1, &non_callable); __ JumpIfSmi(r1, &non_callable);
__ bind(&non_smi);
__ LoadMap(r4, r1); __ LoadMap(r4, r1);
__ CompareInstanceTypeRange(r4, r5, FIRST_JS_FUNCTION_TYPE, __ CompareInstanceTypeRange(r4, r5, FIRST_CALLABLE_JS_FUNCTION_TYPE,
LAST_JS_FUNCTION_TYPE); LAST_CALLABLE_JS_FUNCTION_TYPE);
__ Jump(masm->isolate()->builtins()->CallFunction(mode), __ Jump(masm->isolate()->builtins()->CallFunction(mode),
RelocInfo::CODE_TARGET, ls); RelocInfo::CODE_TARGET, ls);
__ cmp(r5, Operand(JS_BOUND_FUNCTION_TYPE)); __ cmp(r5, Operand(JS_BOUND_FUNCTION_TYPE));
...@@ -2502,6 +2487,11 @@ void Builtins::Generate_Call(MacroAssembler* masm, ConvertReceiverMode mode) { ...@@ -2502,6 +2487,11 @@ void Builtins::Generate_Call(MacroAssembler* masm, ConvertReceiverMode mode) {
__ cmp(r5, Operand(JS_PROXY_TYPE)); __ cmp(r5, Operand(JS_PROXY_TYPE));
__ Jump(BUILTIN_CODE(masm->isolate(), CallProxy), RelocInfo::CODE_TARGET, eq); __ Jump(BUILTIN_CODE(masm->isolate(), CallProxy), RelocInfo::CODE_TARGET, eq);
// ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList)
// Check that the function is not a "classConstructor".
__ cmp(r5, Operand(JS_CLASS_CONSTRUCTOR_TYPE));
__ b(eq, &class_constructor);
// 2. Call to something else, which might have a [[Call]] internal method (if // 2. Call to something else, which might have a [[Call]] internal method (if
// not we raise an exception). // not we raise an exception).
// Overwrite the original receiver the (original) target. // Overwrite the original receiver the (original) target.
...@@ -2518,6 +2508,16 @@ void Builtins::Generate_Call(MacroAssembler* masm, ConvertReceiverMode mode) { ...@@ -2518,6 +2508,16 @@ void Builtins::Generate_Call(MacroAssembler* masm, ConvertReceiverMode mode) {
FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
__ Push(r1); __ Push(r1);
__ CallRuntime(Runtime::kThrowCalledNonCallable); __ CallRuntime(Runtime::kThrowCalledNonCallable);
__ Trap(); // Unreachable.
}
// 4. The function is a "classConstructor", need to raise an exception.
__ bind(&class_constructor);
{
FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
__ Push(r1);
__ CallRuntime(Runtime::kThrowConstructorNonCallableError);
__ Trap(); // Unreachable.
} }
} }
......
...@@ -2648,14 +2648,8 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm, ...@@ -2648,14 +2648,8 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm,
// ----------------------------------- // -----------------------------------
__ AssertFunction(x1); __ AssertFunction(x1);
// See ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList)
// Check that function is not a "classConstructor".
Label class_constructor;
__ LoadTaggedPointerField( __ LoadTaggedPointerField(
x2, FieldMemOperand(x1, JSFunction::kSharedFunctionInfoOffset)); x2, FieldMemOperand(x1, JSFunction::kSharedFunctionInfoOffset));
__ Ldr(w3, FieldMemOperand(x2, SharedFunctionInfo::kFlagsOffset));
__ TestAndBranchIfAnySet(w3, SharedFunctionInfo::IsClassConstructorBit::kMask,
&class_constructor);
// Enter the context of the function; ToObject has to run in the function // Enter the context of the function; ToObject has to run in the function
// context, and we also need to take the global proxy from the function // context, and we also need to take the global proxy from the function
...@@ -2664,6 +2658,7 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm, ...@@ -2664,6 +2658,7 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm,
FieldMemOperand(x1, JSFunction::kContextOffset)); FieldMemOperand(x1, JSFunction::kContextOffset));
// We need to convert the receiver for non-native sloppy mode functions. // We need to convert the receiver for non-native sloppy mode functions.
Label done_convert; Label done_convert;
__ Ldr(w3, FieldMemOperand(x2, SharedFunctionInfo::kFlagsOffset));
__ TestAndBranchIfAnySet(w3, __ TestAndBranchIfAnySet(w3,
SharedFunctionInfo::IsNativeBit::kMask | SharedFunctionInfo::IsNativeBit::kMask |
SharedFunctionInfo::IsStrictBit::kMask, SharedFunctionInfo::IsStrictBit::kMask,
...@@ -2730,15 +2725,6 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm, ...@@ -2730,15 +2725,6 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm,
__ Ldrh(x2, __ Ldrh(x2,
FieldMemOperand(x2, SharedFunctionInfo::kFormalParameterCountOffset)); FieldMemOperand(x2, SharedFunctionInfo::kFormalParameterCountOffset));
__ InvokeFunctionCode(x1, no_reg, x2, x0, InvokeType::kJump); __ InvokeFunctionCode(x1, no_reg, x2, x0, InvokeType::kJump);
// The function is a "classConstructor", need to raise an exception.
__ Bind(&class_constructor);
{
FrameScope frame(masm, StackFrame::INTERNAL);
__ PushArgument(x1);
__ CallRuntime(Runtime::kThrowConstructorNonCallableError);
__ Unreachable();
}
} }
namespace { namespace {
...@@ -2906,12 +2892,11 @@ void Builtins::Generate_Call(MacroAssembler* masm, ConvertReceiverMode mode) { ...@@ -2906,12 +2892,11 @@ void Builtins::Generate_Call(MacroAssembler* masm, ConvertReceiverMode mode) {
// -- x1 : the target to call (can be any Object). // -- x1 : the target to call (can be any Object).
// ----------------------------------- // -----------------------------------
Label non_callable, non_smi; Label non_callable, class_constructor;
__ JumpIfSmi(x1, &non_callable); __ JumpIfSmi(x1, &non_callable);
__ Bind(&non_smi);
__ LoadMap(x4, x1); __ LoadMap(x4, x1);
__ CompareInstanceTypeRange(x4, x5, FIRST_JS_FUNCTION_TYPE, __ CompareInstanceTypeRange(x4, x5, FIRST_CALLABLE_JS_FUNCTION_TYPE,
LAST_JS_FUNCTION_TYPE); LAST_CALLABLE_JS_FUNCTION_TYPE);
__ Jump(masm->isolate()->builtins()->CallFunction(mode), __ Jump(masm->isolate()->builtins()->CallFunction(mode),
RelocInfo::CODE_TARGET, ls); RelocInfo::CODE_TARGET, ls);
__ Cmp(x5, JS_BOUND_FUNCTION_TYPE); __ Cmp(x5, JS_BOUND_FUNCTION_TYPE);
...@@ -2927,6 +2912,11 @@ void Builtins::Generate_Call(MacroAssembler* masm, ConvertReceiverMode mode) { ...@@ -2927,6 +2912,11 @@ void Builtins::Generate_Call(MacroAssembler* masm, ConvertReceiverMode mode) {
__ Cmp(x5, JS_PROXY_TYPE); __ Cmp(x5, JS_PROXY_TYPE);
__ Jump(BUILTIN_CODE(masm->isolate(), CallProxy), RelocInfo::CODE_TARGET, eq); __ Jump(BUILTIN_CODE(masm->isolate(), CallProxy), RelocInfo::CODE_TARGET, eq);
// ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList)
// Check that the function is not a "classConstructor".
__ Cmp(x5, JS_CLASS_CONSTRUCTOR_TYPE);
__ B(eq, &class_constructor);
// 2. Call to something else, which might have a [[Call]] internal method (if // 2. Call to something else, which might have a [[Call]] internal method (if
// not we raise an exception). // not we raise an exception).
// Overwrite the original receiver with the (original) target. // Overwrite the original receiver with the (original) target.
...@@ -2946,6 +2936,15 @@ void Builtins::Generate_Call(MacroAssembler* masm, ConvertReceiverMode mode) { ...@@ -2946,6 +2936,15 @@ void Builtins::Generate_Call(MacroAssembler* masm, ConvertReceiverMode mode) {
__ CallRuntime(Runtime::kThrowCalledNonCallable); __ CallRuntime(Runtime::kThrowCalledNonCallable);
__ Unreachable(); __ Unreachable();
} }
// 4. The function is a "classConstructor", need to raise an exception.
__ bind(&class_constructor);
{
FrameScope frame(masm, StackFrame::INTERNAL);
__ PushArgument(x1);
__ CallRuntime(Runtime::kThrowConstructorNonCallableError);
__ Unreachable();
}
} }
// static // static
......
...@@ -2447,13 +2447,7 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm, ...@@ -2447,13 +2447,7 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm,
StackArgumentsAccessor args(eax); StackArgumentsAccessor args(eax);
__ AssertFunction(edi, edx); __ AssertFunction(edi, edx);
// See ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList)
// Check that the function is not a "classConstructor".
Label class_constructor;
__ mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); __ mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
__ test(FieldOperand(edx, SharedFunctionInfo::kFlagsOffset),
Immediate(SharedFunctionInfo::IsClassConstructorBit::kMask));
__ j(not_zero, &class_constructor);
// Enter the context of the function; ToObject has to run in the function // Enter the context of the function; ToObject has to run in the function
// context, and we also need to take the global proxy from the function // context, and we also need to take the global proxy from the function
...@@ -2534,13 +2528,6 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm, ...@@ -2534,13 +2528,6 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm,
__ movzx_w( __ movzx_w(
ecx, FieldOperand(edx, SharedFunctionInfo::kFormalParameterCountOffset)); ecx, FieldOperand(edx, SharedFunctionInfo::kFormalParameterCountOffset));
__ InvokeFunctionCode(edi, no_reg, ecx, eax, InvokeType::kJump); __ InvokeFunctionCode(edi, no_reg, ecx, eax, InvokeType::kJump);
// The function is a "classConstructor", need to raise an exception.
__ bind(&class_constructor);
{
FrameScope frame(masm, StackFrame::INTERNAL);
__ push(edi);
__ CallRuntime(Runtime::kThrowConstructorNonCallableError);
}
} }
namespace { namespace {
...@@ -2657,18 +2644,18 @@ void Builtins::Generate_Call(MacroAssembler* masm, ConvertReceiverMode mode) { ...@@ -2657,18 +2644,18 @@ void Builtins::Generate_Call(MacroAssembler* masm, ConvertReceiverMode mode) {
// ----------------------------------- // -----------------------------------
StackArgumentsAccessor args(eax); StackArgumentsAccessor args(eax);
Label non_callable, non_function, non_smi, non_jsfunction, Label non_callable, non_smi, non_callable_jsfunction, non_jsboundfunction,
non_jsboundfunction; non_proxy, class_constructor;
__ JumpIfSmi(edi, &non_callable); __ JumpIfSmi(edi, &non_callable);
__ bind(&non_smi); __ bind(&non_smi);
__ LoadMap(ecx, edi); __ LoadMap(ecx, edi);
__ CmpInstanceTypeRange(ecx, ecx, FIRST_JS_FUNCTION_TYPE, __ CmpInstanceTypeRange(ecx, ecx, FIRST_CALLABLE_JS_FUNCTION_TYPE,
LAST_JS_FUNCTION_TYPE); LAST_CALLABLE_JS_FUNCTION_TYPE);
__ j(above, &non_jsfunction); __ j(above, &non_callable_jsfunction);
__ Jump(masm->isolate()->builtins()->CallFunction(mode), __ Jump(masm->isolate()->builtins()->CallFunction(mode),
RelocInfo::CODE_TARGET); RelocInfo::CODE_TARGET);
__ bind(&non_jsfunction); __ bind(&non_callable_jsfunction);
__ LoadMap(ecx, edi); __ LoadMap(ecx, edi);
__ CmpInstanceType(ecx, JS_BOUND_FUNCTION_TYPE); __ CmpInstanceType(ecx, JS_BOUND_FUNCTION_TYPE);
__ j(not_equal, &non_jsboundfunction); __ j(not_equal, &non_jsboundfunction);
...@@ -2683,12 +2670,17 @@ void Builtins::Generate_Call(MacroAssembler* masm, ConvertReceiverMode mode) { ...@@ -2683,12 +2670,17 @@ void Builtins::Generate_Call(MacroAssembler* masm, ConvertReceiverMode mode) {
// Call CallProxy external builtin // Call CallProxy external builtin
__ CmpInstanceType(ecx, JS_PROXY_TYPE); __ CmpInstanceType(ecx, JS_PROXY_TYPE);
__ j(not_equal, &non_function); __ j(not_equal, &non_proxy);
__ Jump(BUILTIN_CODE(masm->isolate(), CallProxy), RelocInfo::CODE_TARGET); __ Jump(BUILTIN_CODE(masm->isolate(), CallProxy), RelocInfo::CODE_TARGET);
// ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList)
// Check that the function is not a "classConstructor".
__ bind(&non_proxy);
__ CmpInstanceType(ecx, JS_CLASS_CONSTRUCTOR_TYPE);
__ j(equal, &class_constructor);
// 2. Call to something else, which might have a [[Call]] internal method (if // 2. Call to something else, which might have a [[Call]] internal method (if
// not we raise an exception). // not we raise an exception).
__ bind(&non_function);
// Overwrite the original receiver with the (original) target. // Overwrite the original receiver with the (original) target.
__ mov(args.GetReceiverOperand(), edi); __ mov(args.GetReceiverOperand(), edi);
// Let the "call_as_function_delegate" take care of the rest. // Let the "call_as_function_delegate" take care of the rest.
...@@ -2703,6 +2695,16 @@ void Builtins::Generate_Call(MacroAssembler* masm, ConvertReceiverMode mode) { ...@@ -2703,6 +2695,16 @@ void Builtins::Generate_Call(MacroAssembler* masm, ConvertReceiverMode mode) {
FrameScope scope(masm, StackFrame::INTERNAL); FrameScope scope(masm, StackFrame::INTERNAL);
__ Push(edi); __ Push(edi);
__ CallRuntime(Runtime::kThrowCalledNonCallable); __ CallRuntime(Runtime::kThrowCalledNonCallable);
__ Trap(); // Unreachable.
}
// 4. The function is a "classConstructor", need to raise an exception.
__ bind(&class_constructor);
{
FrameScope frame(masm, StackFrame::INTERNAL);
__ Push(edi);
__ CallRuntime(Runtime::kThrowConstructorNonCallableError);
__ Trap(); // Unreachable.
} }
} }
......
...@@ -2377,15 +2377,8 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm, ...@@ -2377,15 +2377,8 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm,
StackArgumentsAccessor args(rax); StackArgumentsAccessor args(rax);
__ AssertFunction(rdi); __ AssertFunction(rdi);
// ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList)
// Check that the function is not a "classConstructor".
Label class_constructor;
__ LoadTaggedPointerField( __ LoadTaggedPointerField(
rdx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset)); rdx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
__ testl(FieldOperand(rdx, SharedFunctionInfo::kFlagsOffset),
Immediate(SharedFunctionInfo::IsClassConstructorBit::kMask));
__ j(not_zero, &class_constructor);
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- rax : the number of arguments // -- rax : the number of arguments
// -- rdx : the shared function info. // -- rdx : the shared function info.
...@@ -2470,14 +2463,6 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm, ...@@ -2470,14 +2463,6 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm,
__ movzxwq( __ movzxwq(
rbx, FieldOperand(rdx, SharedFunctionInfo::kFormalParameterCountOffset)); rbx, FieldOperand(rdx, SharedFunctionInfo::kFormalParameterCountOffset));
__ InvokeFunctionCode(rdi, no_reg, rbx, rax, InvokeType::kJump); __ InvokeFunctionCode(rdi, no_reg, rbx, rax, InvokeType::kJump);
// The function is a "classConstructor", need to raise an exception.
__ bind(&class_constructor);
{
FrameScope frame(masm, StackFrame::INTERNAL);
__ Push(rdi);
__ CallRuntime(Runtime::kThrowConstructorNonCallableError);
}
} }
namespace { namespace {
...@@ -2591,10 +2576,11 @@ void Builtins::Generate_Call(MacroAssembler* masm, ConvertReceiverMode mode) { ...@@ -2591,10 +2576,11 @@ void Builtins::Generate_Call(MacroAssembler* masm, ConvertReceiverMode mode) {
// ----------------------------------- // -----------------------------------
StackArgumentsAccessor args(rax); StackArgumentsAccessor args(rax);
Label non_callable; Label non_callable, class_constructor;
__ JumpIfSmi(rdi, &non_callable); __ JumpIfSmi(rdi, &non_callable);
__ LoadMap(rcx, rdi); __ LoadMap(rcx, rdi);
__ CmpInstanceTypeRange(rcx, FIRST_JS_FUNCTION_TYPE, LAST_JS_FUNCTION_TYPE); __ CmpInstanceTypeRange(rcx, FIRST_CALLABLE_JS_FUNCTION_TYPE,
LAST_CALLABLE_JS_FUNCTION_TYPE);
__ Jump(masm->isolate()->builtins()->CallFunction(mode), __ Jump(masm->isolate()->builtins()->CallFunction(mode),
RelocInfo::CODE_TARGET, below_equal); RelocInfo::CODE_TARGET, below_equal);
...@@ -2612,6 +2598,11 @@ void Builtins::Generate_Call(MacroAssembler* masm, ConvertReceiverMode mode) { ...@@ -2612,6 +2598,11 @@ void Builtins::Generate_Call(MacroAssembler* masm, ConvertReceiverMode mode) {
__ Jump(BUILTIN_CODE(masm->isolate(), CallProxy), RelocInfo::CODE_TARGET, __ Jump(BUILTIN_CODE(masm->isolate(), CallProxy), RelocInfo::CODE_TARGET,
equal); equal);
// ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList)
// Check that the function is not a "classConstructor".
__ CmpInstanceType(rcx, JS_CLASS_CONSTRUCTOR_TYPE);
__ j(equal, &class_constructor);
// 2. Call to something else, which might have a [[Call]] internal method (if // 2. Call to something else, which might have a [[Call]] internal method (if
// not we raise an exception). // not we raise an exception).
...@@ -2629,6 +2620,16 @@ void Builtins::Generate_Call(MacroAssembler* masm, ConvertReceiverMode mode) { ...@@ -2629,6 +2620,16 @@ void Builtins::Generate_Call(MacroAssembler* masm, ConvertReceiverMode mode) {
FrameScope scope(masm, StackFrame::INTERNAL); FrameScope scope(masm, StackFrame::INTERNAL);
__ Push(rdi); __ Push(rdi);
__ CallRuntime(Runtime::kThrowCalledNonCallable); __ CallRuntime(Runtime::kThrowCalledNonCallable);
__ Trap(); // Unreachable.
}
// 4. The function is a "classConstructor", need to raise an exception.
__ bind(&class_constructor);
{
FrameScope frame(masm, StackFrame::INTERNAL);
__ Push(rdi);
__ CallRuntime(Runtime::kThrowConstructorNonCallableError);
__ Trap(); // Unreachable.
} }
} }
......
...@@ -275,6 +275,7 @@ Type::bitset BitsetType::Lub(const MapRefLike& map) { ...@@ -275,6 +275,7 @@ Type::bitset BitsetType::Lub(const MapRefLike& map) {
DCHECK(!map.is_undetectable()); DCHECK(!map.is_undetectable());
return kBoundFunction; return kBoundFunction;
case JS_FUNCTION_TYPE: case JS_FUNCTION_TYPE:
case JS_CLASS_CONSTRUCTOR_TYPE:
case JS_PROMISE_CONSTRUCTOR_TYPE: case JS_PROMISE_CONSTRUCTOR_TYPE:
case JS_REG_EXP_CONSTRUCTOR_TYPE: case JS_REG_EXP_CONSTRUCTOR_TYPE:
case JS_ARRAY_CONSTRUCTOR_TYPE: case JS_ARRAY_CONSTRUCTOR_TYPE:
......
...@@ -293,6 +293,7 @@ void HeapObject::HeapObjectVerify(Isolate* isolate) { ...@@ -293,6 +293,7 @@ void HeapObject::HeapObjectVerify(Isolate* isolate) {
BigIntBase::cast(*this).BigIntBaseVerify(isolate); BigIntBase::cast(*this).BigIntBaseVerify(isolate);
break; break;
case JS_CLASS_CONSTRUCTOR_TYPE:
case JS_PROMISE_CONSTRUCTOR_TYPE: case JS_PROMISE_CONSTRUCTOR_TYPE:
case JS_REG_EXP_CONSTRUCTOR_TYPE: case JS_REG_EXP_CONSTRUCTOR_TYPE:
case JS_ARRAY_CONSTRUCTOR_TYPE: case JS_ARRAY_CONSTRUCTOR_TYPE:
......
...@@ -234,6 +234,7 @@ void HeapObject::HeapObjectPrint(std::ostream& os) { ...@@ -234,6 +234,7 @@ void HeapObject::HeapObjectPrint(std::ostream& os) {
case BIG_INT_BASE_TYPE: case BIG_INT_BASE_TYPE:
BigIntBase::cast(*this).BigIntBasePrint(os); BigIntBase::cast(*this).BigIntBasePrint(os);
break; break;
case JS_CLASS_CONSTRUCTOR_TYPE:
case JS_PROMISE_CONSTRUCTOR_TYPE: case JS_PROMISE_CONSTRUCTOR_TYPE:
case JS_REG_EXP_CONSTRUCTOR_TYPE: case JS_REG_EXP_CONSTRUCTOR_TYPE:
case JS_ARRAY_CONSTRUCTOR_TYPE: case JS_ARRAY_CONSTRUCTOR_TYPE:
......
...@@ -3654,7 +3654,8 @@ Handle<Map> Factory::CreateStrictFunctionMap( ...@@ -3654,7 +3654,8 @@ Handle<Map> Factory::CreateStrictFunctionMap(
} }
Handle<Map> Factory::CreateClassFunctionMap(Handle<JSFunction> empty_function) { Handle<Map> Factory::CreateClassFunctionMap(Handle<JSFunction> empty_function) {
Handle<Map> map = NewMap(JS_FUNCTION_TYPE, JSFunction::kSizeWithPrototype); Handle<Map> map =
NewMap(JS_CLASS_CONSTRUCTOR_TYPE, JSFunction::kSizeWithPrototype);
{ {
DisallowGarbageCollection no_gc; DisallowGarbageCollection no_gc;
Map raw_map = *map; Map raw_map = *map;
......
...@@ -128,6 +128,9 @@ enum InstanceType : uint16_t { ...@@ -128,6 +128,9 @@ enum InstanceType : uint16_t {
FIRST_UNIQUE_NAME_TYPE = INTERNALIZED_STRING_TYPE, FIRST_UNIQUE_NAME_TYPE = INTERNALIZED_STRING_TYPE,
LAST_UNIQUE_NAME_TYPE = SYMBOL_TYPE, LAST_UNIQUE_NAME_TYPE = SYMBOL_TYPE,
FIRST_NONSTRING_TYPE = SYMBOL_TYPE, FIRST_NONSTRING_TYPE = SYMBOL_TYPE,
// Callable JS Functions are all JS Functions except class constructors.
FIRST_CALLABLE_JS_FUNCTION_TYPE = FIRST_JS_FUNCTION_TYPE,
LAST_CALLABLE_JS_FUNCTION_TYPE = JS_CLASS_CONSTRUCTOR_TYPE - 1,
// Boundary for testing JSReceivers that need special property lookup handling // Boundary for testing JSReceivers that need special property lookup handling
LAST_SPECIAL_RECEIVER_TYPE = LAST_JS_SPECIAL_OBJECT_TYPE, LAST_SPECIAL_RECEIVER_TYPE = LAST_JS_SPECIAL_OBJECT_TYPE,
// Boundary case for testing JSReceivers that may have elements while having // Boundary case for testing JSReceivers that may have elements while having
...@@ -171,6 +174,13 @@ STRING_TYPE_LIST(CHECK_STRING_RANGE) ...@@ -171,6 +174,13 @@ STRING_TYPE_LIST(CHECK_STRING_RANGE)
TORQUE_ASSIGNED_INSTANCE_TYPE_LIST(CHECK_NONSTRING_RANGE) TORQUE_ASSIGNED_INSTANCE_TYPE_LIST(CHECK_NONSTRING_RANGE)
#undef CHECK_NONSTRING_RANGE #undef CHECK_NONSTRING_RANGE
// classConstructor type has to be the last one in the JS Function type range.
STATIC_ASSERT(JS_CLASS_CONSTRUCTOR_TYPE == LAST_JS_FUNCTION_TYPE);
static_assert(JS_CLASS_CONSTRUCTOR_TYPE < FIRST_CALLABLE_JS_FUNCTION_TYPE ||
JS_CLASS_CONSTRUCTOR_TYPE > LAST_CALLABLE_JS_FUNCTION_TYPE,
"JS_CLASS_CONSTRUCTOR_TYPE must not be in the callable JS "
"function type range");
// Two ranges don't cleanly follow the inheritance hierarchy. Here we ensure // Two ranges don't cleanly follow the inheritance hierarchy. Here we ensure
// that only expected types fall within these ranges. // that only expected types fall within these ranges.
// - From FIRST_JS_RECEIVER_TYPE to LAST_SPECIAL_RECEIVER_TYPE should correspond // - From FIRST_JS_RECEIVER_TYPE to LAST_SPECIAL_RECEIVER_TYPE should correspond
......
...@@ -549,6 +549,7 @@ bool CanSubclassHaveInobjectProperties(InstanceType instance_type) { ...@@ -549,6 +549,7 @@ bool CanSubclassHaveInobjectProperties(InstanceType instance_type) {
case JS_DATE_TYPE: case JS_DATE_TYPE:
case JS_GENERATOR_OBJECT_TYPE: case JS_GENERATOR_OBJECT_TYPE:
case JS_FUNCTION_TYPE: case JS_FUNCTION_TYPE:
case JS_CLASS_CONSTRUCTOR_TYPE:
case JS_PROMISE_CONSTRUCTOR_TYPE: case JS_PROMISE_CONSTRUCTOR_TYPE:
case JS_REG_EXP_CONSTRUCTOR_TYPE: case JS_REG_EXP_CONSTRUCTOR_TYPE:
case JS_ARRAY_CONSTRUCTOR_TYPE: case JS_ARRAY_CONSTRUCTOR_TYPE:
......
...@@ -28,4 +28,13 @@ extern class JSFunction extends JSFunctionOrBoundFunction { ...@@ -28,4 +28,13 @@ extern class JSFunction extends JSFunctionOrBoundFunction {
@noVerifier prototype_or_initial_map: JSReceiver|Map; @noVerifier prototype_or_initial_map: JSReceiver|Map;
} }
// Class constructors are special, because they are callable, but [[Call]] will
// raise an exception.
// See ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList ).
@doNotGenerateCast
@noVerifier
@highestInstanceTypeWithinParentClassRange
extern class JSClassConstructor extends JSFunction
generates 'TNode<JSFunction>';
type JSFunctionWithPrototypeSlot extends JSFunction; type JSFunctionWithPrototypeSlot extends JSFunction;
...@@ -2243,6 +2243,7 @@ int JSObject::GetHeaderSize(InstanceType type, ...@@ -2243,6 +2243,7 @@ int JSObject::GetHeaderSize(InstanceType type,
case JS_BOUND_FUNCTION_TYPE: case JS_BOUND_FUNCTION_TYPE:
return JSBoundFunction::kHeaderSize; return JSBoundFunction::kHeaderSize;
case JS_FUNCTION_TYPE: case JS_FUNCTION_TYPE:
case JS_CLASS_CONSTRUCTOR_TYPE:
case JS_PROMISE_CONSTRUCTOR_TYPE: case JS_PROMISE_CONSTRUCTOR_TYPE:
case JS_REG_EXP_CONSTRUCTOR_TYPE: case JS_REG_EXP_CONSTRUCTOR_TYPE:
case JS_ARRAY_CONSTRUCTOR_TYPE: case JS_ARRAY_CONSTRUCTOR_TYPE:
...@@ -2589,6 +2590,7 @@ void JSObject::JSObjectShortPrint(StringStream* accumulator) { ...@@ -2589,6 +2590,7 @@ void JSObject::JSObjectShortPrint(StringStream* accumulator) {
case TYPE##_TYPED_ARRAY_CONSTRUCTOR_TYPE: case TYPE##_TYPED_ARRAY_CONSTRUCTOR_TYPE:
TYPED_ARRAYS(TYPED_ARRAY_CONSTRUCTORS_SWITCH) TYPED_ARRAYS(TYPED_ARRAY_CONSTRUCTORS_SWITCH)
#undef TYPED_ARRAY_CONSTRUCTORS_SWITCH #undef TYPED_ARRAY_CONSTRUCTORS_SWITCH
case JS_CLASS_CONSTRUCTOR_TYPE:
case JS_FUNCTION_TYPE: { case JS_FUNCTION_TYPE: {
JSFunction function = JSFunction::cast(*this); JSFunction function = JSFunction::cast(*this);
std::unique_ptr<char[]> fun_name = function.shared().DebugNameCStr(); std::unique_ptr<char[]> fun_name = function.shared().DebugNameCStr();
......
...@@ -206,6 +206,7 @@ VisitorId Map::GetVisitorId(Map map) { ...@@ -206,6 +206,7 @@ VisitorId Map::GetVisitorId(Map map) {
return kVisitJSDataView; return kVisitJSDataView;
case JS_FUNCTION_TYPE: case JS_FUNCTION_TYPE:
case JS_CLASS_CONSTRUCTOR_TYPE:
case JS_PROMISE_CONSTRUCTOR_TYPE: case JS_PROMISE_CONSTRUCTOR_TYPE:
case JS_REG_EXP_CONSTRUCTOR_TYPE: case JS_REG_EXP_CONSTRUCTOR_TYPE:
case JS_ARRAY_CONSTRUCTOR_TYPE: case JS_ARRAY_CONSTRUCTOR_TYPE:
......
...@@ -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(JSClassConstructor) \
V(JSLastDummyApiObject) \ V(JSLastDummyApiObject) \
V(JSPromiseConstructor) \ V(JSPromiseConstructor) \
V(JSArrayConstructor) \ V(JSArrayConstructor) \
......
...@@ -1114,6 +1114,7 @@ ReturnType BodyDescriptorApply(InstanceType type, T1 p1, T2 p2, T3 p3, T4 p4) { ...@@ -1114,6 +1114,7 @@ ReturnType BodyDescriptorApply(InstanceType type, T1 p1, T2 p2, T3 p3, T4 p4) {
case JS_STRING_ITERATOR_TYPE: case JS_STRING_ITERATOR_TYPE:
case JS_TYPED_ARRAY_PROTOTYPE_TYPE: case JS_TYPED_ARRAY_PROTOTYPE_TYPE:
case JS_FUNCTION_TYPE: case JS_FUNCTION_TYPE:
case JS_CLASS_CONSTRUCTOR_TYPE:
case JS_PROMISE_CONSTRUCTOR_TYPE: case JS_PROMISE_CONSTRUCTOR_TYPE:
case JS_REG_EXP_CONSTRUCTOR_TYPE: case JS_REG_EXP_CONSTRUCTOR_TYPE:
case JS_ARRAY_CONSTRUCTOR_TYPE: case JS_ARRAY_CONSTRUCTOR_TYPE:
......
...@@ -694,19 +694,16 @@ void WebSnapshotSerializer::WriteValue(Handle<Object> object, ...@@ -694,19 +694,16 @@ void WebSnapshotSerializer::WriteValue(Handle<Object> object,
serializer.WriteUint32(ValueType::DOUBLE); serializer.WriteUint32(ValueType::DOUBLE);
serializer.WriteDouble(HeapNumber::cast(*object).value()); serializer.WriteDouble(HeapNumber::cast(*object).value());
break; break;
case JS_FUNCTION_TYPE: { case JS_FUNCTION_TYPE:
Handle<JSFunction> function = Handle<JSFunction>::cast(object); SerializeFunction(Handle<JSFunction>::cast(object), id);
FunctionKind kind = function->shared().kind(); serializer.WriteUint32(ValueType::FUNCTION_ID);
if (IsClassConstructor(kind)) { serializer.WriteUint32(id);
SerializeClass(function, id); break;
serializer.WriteUint32(ValueType::CLASS_ID); case JS_CLASS_CONSTRUCTOR_TYPE:
} else { SerializeClass(Handle<JSFunction>::cast(object), id);
SerializeFunction(function, id); serializer.WriteUint32(ValueType::CLASS_ID);
serializer.WriteUint32(ValueType::FUNCTION_ID);
}
serializer.WriteUint32(id); serializer.WriteUint32(id);
break; break;
}
case JS_OBJECT_TYPE: case JS_OBJECT_TYPE:
SerializeObject(Handle<JSObject>::cast(object), id); SerializeObject(Handle<JSObject>::cast(object), id);
serializer.WriteUint32(ValueType::OBJECT_ID); serializer.WriteUint32(ValueType::OBJECT_ID);
......
...@@ -173,64 +173,65 @@ INSTANCE_TYPES = { ...@@ -173,64 +173,65 @@ INSTANCE_TYPES = {
2072: "JS_ARRAY_CONSTRUCTOR_TYPE", 2072: "JS_ARRAY_CONSTRUCTOR_TYPE",
2073: "JS_PROMISE_CONSTRUCTOR_TYPE", 2073: "JS_PROMISE_CONSTRUCTOR_TYPE",
2074: "JS_REG_EXP_CONSTRUCTOR_TYPE", 2074: "JS_REG_EXP_CONSTRUCTOR_TYPE",
2075: "JS_ARRAY_ITERATOR_PROTOTYPE_TYPE", 2075: "JS_CLASS_CONSTRUCTOR_TYPE",
2076: "JS_ITERATOR_PROTOTYPE_TYPE", 2076: "JS_ARRAY_ITERATOR_PROTOTYPE_TYPE",
2077: "JS_MAP_ITERATOR_PROTOTYPE_TYPE", 2077: "JS_ITERATOR_PROTOTYPE_TYPE",
2078: "JS_OBJECT_PROTOTYPE_TYPE", 2078: "JS_MAP_ITERATOR_PROTOTYPE_TYPE",
2079: "JS_PROMISE_PROTOTYPE_TYPE", 2079: "JS_OBJECT_PROTOTYPE_TYPE",
2080: "JS_REG_EXP_PROTOTYPE_TYPE", 2080: "JS_PROMISE_PROTOTYPE_TYPE",
2081: "JS_SET_ITERATOR_PROTOTYPE_TYPE", 2081: "JS_REG_EXP_PROTOTYPE_TYPE",
2082: "JS_SET_PROTOTYPE_TYPE", 2082: "JS_SET_ITERATOR_PROTOTYPE_TYPE",
2083: "JS_STRING_ITERATOR_PROTOTYPE_TYPE", 2083: "JS_SET_PROTOTYPE_TYPE",
2084: "JS_TYPED_ARRAY_PROTOTYPE_TYPE", 2084: "JS_STRING_ITERATOR_PROTOTYPE_TYPE",
2085: "JS_MAP_KEY_ITERATOR_TYPE", 2085: "JS_TYPED_ARRAY_PROTOTYPE_TYPE",
2086: "JS_MAP_KEY_VALUE_ITERATOR_TYPE", 2086: "JS_MAP_KEY_ITERATOR_TYPE",
2087: "JS_MAP_VALUE_ITERATOR_TYPE", 2087: "JS_MAP_KEY_VALUE_ITERATOR_TYPE",
2088: "JS_SET_KEY_VALUE_ITERATOR_TYPE", 2088: "JS_MAP_VALUE_ITERATOR_TYPE",
2089: "JS_SET_VALUE_ITERATOR_TYPE", 2089: "JS_SET_KEY_VALUE_ITERATOR_TYPE",
2090: "JS_GENERATOR_OBJECT_TYPE", 2090: "JS_SET_VALUE_ITERATOR_TYPE",
2091: "JS_ASYNC_FUNCTION_OBJECT_TYPE", 2091: "JS_GENERATOR_OBJECT_TYPE",
2092: "JS_ASYNC_GENERATOR_OBJECT_TYPE", 2092: "JS_ASYNC_FUNCTION_OBJECT_TYPE",
2093: "JS_DATA_VIEW_TYPE", 2093: "JS_ASYNC_GENERATOR_OBJECT_TYPE",
2094: "JS_TYPED_ARRAY_TYPE", 2094: "JS_DATA_VIEW_TYPE",
2095: "JS_MAP_TYPE", 2095: "JS_TYPED_ARRAY_TYPE",
2096: "JS_SET_TYPE", 2096: "JS_MAP_TYPE",
2097: "JS_WEAK_MAP_TYPE", 2097: "JS_SET_TYPE",
2098: "JS_WEAK_SET_TYPE", 2098: "JS_WEAK_MAP_TYPE",
2099: "JS_ARGUMENTS_OBJECT_TYPE", 2099: "JS_WEAK_SET_TYPE",
2100: "JS_ARRAY_TYPE", 2100: "JS_ARGUMENTS_OBJECT_TYPE",
2101: "JS_ARRAY_BUFFER_TYPE", 2101: "JS_ARRAY_TYPE",
2102: "JS_ARRAY_ITERATOR_TYPE", 2102: "JS_ARRAY_BUFFER_TYPE",
2103: "JS_ASYNC_FROM_SYNC_ITERATOR_TYPE", 2103: "JS_ARRAY_ITERATOR_TYPE",
2104: "JS_COLLATOR_TYPE", 2104: "JS_ASYNC_FROM_SYNC_ITERATOR_TYPE",
2105: "JS_CONTEXT_EXTENSION_OBJECT_TYPE", 2105: "JS_COLLATOR_TYPE",
2106: "JS_DATE_TYPE", 2106: "JS_CONTEXT_EXTENSION_OBJECT_TYPE",
2107: "JS_DATE_TIME_FORMAT_TYPE", 2107: "JS_DATE_TYPE",
2108: "JS_DISPLAY_NAMES_TYPE", 2108: "JS_DATE_TIME_FORMAT_TYPE",
2109: "JS_ERROR_TYPE", 2109: "JS_DISPLAY_NAMES_TYPE",
2110: "JS_FINALIZATION_REGISTRY_TYPE", 2110: "JS_ERROR_TYPE",
2111: "JS_LIST_FORMAT_TYPE", 2111: "JS_FINALIZATION_REGISTRY_TYPE",
2112: "JS_LOCALE_TYPE", 2112: "JS_LIST_FORMAT_TYPE",
2113: "JS_MESSAGE_OBJECT_TYPE", 2113: "JS_LOCALE_TYPE",
2114: "JS_NUMBER_FORMAT_TYPE", 2114: "JS_MESSAGE_OBJECT_TYPE",
2115: "JS_PLURAL_RULES_TYPE", 2115: "JS_NUMBER_FORMAT_TYPE",
2116: "JS_PROMISE_TYPE", 2116: "JS_PLURAL_RULES_TYPE",
2117: "JS_REG_EXP_TYPE", 2117: "JS_PROMISE_TYPE",
2118: "JS_REG_EXP_STRING_ITERATOR_TYPE", 2118: "JS_REG_EXP_TYPE",
2119: "JS_RELATIVE_TIME_FORMAT_TYPE", 2119: "JS_REG_EXP_STRING_ITERATOR_TYPE",
2120: "JS_SEGMENT_ITERATOR_TYPE", 2120: "JS_RELATIVE_TIME_FORMAT_TYPE",
2121: "JS_SEGMENTER_TYPE", 2121: "JS_SEGMENT_ITERATOR_TYPE",
2122: "JS_SEGMENTS_TYPE", 2122: "JS_SEGMENTER_TYPE",
2123: "JS_STRING_ITERATOR_TYPE", 2123: "JS_SEGMENTS_TYPE",
2124: "JS_V8_BREAK_ITERATOR_TYPE", 2124: "JS_STRING_ITERATOR_TYPE",
2125: "JS_WEAK_REF_TYPE", 2125: "JS_V8_BREAK_ITERATOR_TYPE",
2126: "WASM_GLOBAL_OBJECT_TYPE", 2126: "JS_WEAK_REF_TYPE",
2127: "WASM_INSTANCE_OBJECT_TYPE", 2127: "WASM_GLOBAL_OBJECT_TYPE",
2128: "WASM_MEMORY_OBJECT_TYPE", 2128: "WASM_INSTANCE_OBJECT_TYPE",
2129: "WASM_MODULE_OBJECT_TYPE", 2129: "WASM_MEMORY_OBJECT_TYPE",
2130: "WASM_TABLE_OBJECT_TYPE", 2130: "WASM_MODULE_OBJECT_TYPE",
2131: "WASM_TAG_OBJECT_TYPE", 2131: "WASM_TABLE_OBJECT_TYPE",
2132: "WASM_VALUE_OBJECT_TYPE", 2132: "WASM_TAG_OBJECT_TYPE",
2133: "WASM_VALUE_OBJECT_TYPE",
} }
# List of known V8 maps. # List of known V8 maps.
...@@ -389,7 +390,7 @@ KNOWN_MAPS = { ...@@ -389,7 +390,7 @@ KNOWN_MAPS = {
("read_only_space", 0x05f81): (82, "StoreHandler2Map"), ("read_only_space", 0x05f81): (82, "StoreHandler2Map"),
("read_only_space", 0x05fa9): (82, "StoreHandler3Map"), ("read_only_space", 0x05fa9): (82, "StoreHandler3Map"),
("map_space", 0x02119): (1057, "ExternalMap"), ("map_space", 0x02119): (1057, "ExternalMap"),
("map_space", 0x02141): (2113, "JSMessageObjectMap"), ("map_space", 0x02141): (2114, "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