diff --git a/src/arm/macro-assembler-arm.cc b/src/arm/macro-assembler-arm.cc index 82d5ebd3e0..e363e0ecfe 100644 --- a/src/arm/macro-assembler-arm.cc +++ b/src/arm/macro-assembler-arm.cc @@ -1885,6 +1885,20 @@ void MacroAssembler::AssertFixedArray(Register object) { } } +void MacroAssembler::AssertConstructor(Register object) { + if (emit_debug_code()) { + STATIC_ASSERT(kSmiTag == 0); + tst(object, Operand(kSmiTagMask)); + Check(ne, AbortReason::kOperandIsASmiAndNotAConstructor); + push(object); + ldr(object, FieldMemOperand(object, HeapObject::kMapOffset)); + ldrb(object, FieldMemOperand(object, Map::kBitFieldOffset)); + tst(object, Operand(Map::IsConstructorBit::kMask)); + pop(object); + Check(ne, AbortReason::kOperandIsNotAConstructor); + } +} + void MacroAssembler::AssertFunction(Register object) { if (emit_debug_code()) { STATIC_ASSERT(kSmiTag == 0); diff --git a/src/arm/macro-assembler-arm.h b/src/arm/macro-assembler-arm.h index 497ab92d8c..af8b449de6 100644 --- a/src/arm/macro-assembler-arm.h +++ b/src/arm/macro-assembler-arm.h @@ -837,6 +837,9 @@ class MacroAssembler : public TurboAssembler { // Abort execution if argument is not a FixedArray, enabled via --debug-code. void AssertFixedArray(Register object); + // Abort execution if argument is not a Constructor, enabled via --debug-code. + void AssertConstructor(Register object); + // Abort execution if argument is not a JSFunction, enabled via --debug-code. void AssertFunction(Register object); diff --git a/src/arm64/macro-assembler-arm64.cc b/src/arm64/macro-assembler-arm64.cc index 2fbde668e0..5bbf71e28c 100644 --- a/src/arm64/macro-assembler-arm64.cc +++ b/src/arm64/macro-assembler-arm64.cc @@ -1625,6 +1625,21 @@ void MacroAssembler::AssertFixedArray(Register object) { } } +void MacroAssembler::AssertConstructor(Register object) { + if (emit_debug_code()) { + AssertNotSmi(object, AbortReason::kOperandIsASmiAndNotAConstructor); + + UseScratchRegisterScope temps(this); + Register temp = temps.AcquireX(); + + Ldr(temp, FieldMemOperand(object, HeapObject::kMapOffset)); + Ldrb(temp, FieldMemOperand(temp, Map::kBitFieldOffset)); + Tst(temp, Operand(Map::IsConstructorBit::kMask)); + + Check(ne, AbortReason::kOperandIsNotAConstructor); + } +} + void MacroAssembler::AssertFunction(Register object) { if (emit_debug_code()) { AssertNotSmi(object, AbortReason::kOperandIsASmiAndNotAFunction); diff --git a/src/arm64/macro-assembler-arm64.h b/src/arm64/macro-assembler-arm64.h index e385a847cc..6b1b8957cb 100644 --- a/src/arm64/macro-assembler-arm64.h +++ b/src/arm64/macro-assembler-arm64.h @@ -1713,6 +1713,9 @@ class MacroAssembler : public TurboAssembler { // Abort execution if argument is not a FixedArray, enabled via --debug-code. void AssertFixedArray(Register object); + // Abort execution if argument is not a Constructor, enabled via --debug-code. + void AssertConstructor(Register object); + // Abort execution if argument is not a JSFunction, enabled via --debug-code. void AssertFunction(Register object); diff --git a/src/bailout-reason.h b/src/bailout-reason.h index 7844259ede..d29693e3f8 100644 --- a/src/bailout-reason.h +++ b/src/bailout-reason.h @@ -40,11 +40,14 @@ namespace internal { V(kOperandIsASmi, "Operand is a smi") \ V(kOperandIsASmiAndNotABoundFunction, \ "Operand is a smi and not a bound function") \ + V(kOperandIsASmiAndNotAConstructor, \ + "Operand is a smi and not a constructor") \ V(kOperandIsASmiAndNotAFixedArray, "Operand is a smi and not a fixed array") \ V(kOperandIsASmiAndNotAFunction, "Operand is a smi and not a function") \ V(kOperandIsASmiAndNotAGeneratorObject, \ "Operand is a smi and not a generator object") \ V(kOperandIsNotABoundFunction, "Operand is not a bound function") \ + V(kOperandIsNotAConstructor, "Operand is not a constructor") \ V(kOperandIsNotAFixedArray, "Operand is not a fixed array") \ V(kOperandIsNotAFunction, "Operand is not a function") \ V(kOperandIsNotAGeneratorObject, "Operand is not a generator object") \ diff --git a/src/builtins/arm/builtins-arm.cc b/src/builtins/arm/builtins-arm.cc index 2366aeaa23..3ea9df8a51 100644 --- a/src/builtins/arm/builtins-arm.cc +++ b/src/builtins/arm/builtins-arm.cc @@ -2233,6 +2233,7 @@ void Builtins::Generate_ConstructFunction(MacroAssembler* masm) { // -- r1 : the constructor to call (checked to be a JSFunction) // -- r3 : the new target (checked to be a constructor) // ----------------------------------- + __ AssertConstructor(r1); __ AssertFunction(r1); // Calling convention for function specific ConstructStubs require @@ -2253,6 +2254,7 @@ void Builtins::Generate_ConstructBoundFunction(MacroAssembler* masm) { // -- r1 : the function to call (checked to be a JSBoundFunction) // -- r3 : the new target (checked to be a constructor) // ----------------------------------- + __ AssertConstructor(r1); __ AssertBoundFunction(r1); // Push the [[BoundArguments]] onto the stack. @@ -2281,16 +2283,17 @@ void Builtins::Generate_Construct(MacroAssembler* masm) { Label non_constructor, non_proxy; __ JumpIfSmi(r1, &non_constructor); - // Dispatch based on instance type. - __ CompareObjectType(r1, r4, r5, JS_FUNCTION_TYPE); - __ Jump(BUILTIN_CODE(masm->isolate(), ConstructFunction), - RelocInfo::CODE_TARGET, eq); - // Check if target has a [[Construct]] internal method. + __ ldr(r4, FieldMemOperand(r1, HeapObject::kMapOffset)); __ ldrb(r2, FieldMemOperand(r4, Map::kBitFieldOffset)); __ tst(r2, Operand(Map::IsConstructorBit::kMask)); __ b(eq, &non_constructor); + // Dispatch based on instance type. + __ CompareInstanceType(r4, r5, JS_FUNCTION_TYPE); + __ Jump(BUILTIN_CODE(masm->isolate(), ConstructFunction), + RelocInfo::CODE_TARGET, eq); + // Only dispatch to bound functions after checking whether they are // constructors. __ cmp(r5, Operand(JS_BOUND_FUNCTION_TYPE)); diff --git a/src/builtins/arm64/builtins-arm64.cc b/src/builtins/arm64/builtins-arm64.cc index 66ad29d6f5..a6d45da7e7 100644 --- a/src/builtins/arm64/builtins-arm64.cc +++ b/src/builtins/arm64/builtins-arm64.cc @@ -2637,6 +2637,7 @@ void Builtins::Generate_ConstructFunction(MacroAssembler* masm) { // -- x1 : the constructor to call (checked to be a JSFunction) // -- x3 : the new target (checked to be a constructor) // ----------------------------------- + __ AssertConstructor(x1); __ AssertFunction(x1); // Calling convention for function specific ConstructStubs require @@ -2658,6 +2659,7 @@ void Builtins::Generate_ConstructBoundFunction(MacroAssembler* masm) { // -- x1 : the function to call (checked to be a JSBoundFunction) // -- x3 : the new target (checked to be a constructor) // ----------------------------------- + __ AssertConstructor(x1); __ AssertBoundFunction(x1); // Push the [[BoundArguments]] onto the stack. @@ -2691,16 +2693,17 @@ void Builtins::Generate_Construct(MacroAssembler* masm) { Label non_constructor, non_proxy; __ JumpIfSmi(x1, &non_constructor); - // Dispatch based on instance type. - __ CompareObjectType(x1, x4, x5, JS_FUNCTION_TYPE); - __ Jump(BUILTIN_CODE(masm->isolate(), ConstructFunction), - RelocInfo::CODE_TARGET, eq); - // Check if target has a [[Construct]] internal method. + __ Ldr(x4, FieldMemOperand(x1, HeapObject::kMapOffset)); __ Ldrb(x2, FieldMemOperand(x4, Map::kBitFieldOffset)); __ TestAndBranchIfAllClear(x2, Map::IsConstructorBit::kMask, &non_constructor); + // Dispatch based on instance type. + __ CompareInstanceType(x4, x5, JS_FUNCTION_TYPE); + __ Jump(BUILTIN_CODE(masm->isolate(), ConstructFunction), + RelocInfo::CODE_TARGET, eq); + // Only dispatch to bound functions after checking whether they are // constructors. __ Cmp(x5, JS_BOUND_FUNCTION_TYPE); diff --git a/src/builtins/ia32/builtins-ia32.cc b/src/builtins/ia32/builtins-ia32.cc index f645aaa82a..b24b9528b5 100644 --- a/src/builtins/ia32/builtins-ia32.cc +++ b/src/builtins/ia32/builtins-ia32.cc @@ -2377,6 +2377,7 @@ void Builtins::Generate_ConstructFunction(MacroAssembler* masm) { // -- edx : the new target (checked to be a constructor) // -- edi : the constructor to call (checked to be a JSFunction) // ----------------------------------- + __ AssertConstructor(edi); __ AssertFunction(edi); // Calling convention for function specific ConstructStubs require @@ -2398,6 +2399,7 @@ void Builtins::Generate_ConstructBoundFunction(MacroAssembler* masm) { // -- edx : the new target (checked to be a constructor) // -- edi : the constructor to call (checked to be a JSBoundFunction) // ----------------------------------- + __ AssertConstructor(edi); __ AssertBoundFunction(edi); // Push the [[BoundArguments]] onto the stack. @@ -2430,16 +2432,17 @@ void Builtins::Generate_Construct(MacroAssembler* masm) { Label non_constructor, non_proxy; __ JumpIfSmi(edi, &non_constructor, Label::kNear); - // Dispatch based on instance type. - __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); - __ j(equal, BUILTIN_CODE(masm->isolate(), ConstructFunction), - RelocInfo::CODE_TARGET); - // Check if target has a [[Construct]] internal method. + __ mov(ecx, FieldOperand(edi, HeapObject::kMapOffset)); __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), Immediate(Map::IsConstructorBit::kMask)); __ j(zero, &non_constructor, Label::kNear); + // Dispatch based on instance type. + __ CmpInstanceType(ecx, JS_FUNCTION_TYPE); + __ j(equal, BUILTIN_CODE(masm->isolate(), ConstructFunction), + RelocInfo::CODE_TARGET); + // Only dispatch to bound functions after checking whether they are // constructors. __ CmpInstanceType(ecx, JS_BOUND_FUNCTION_TYPE); diff --git a/src/builtins/mips/builtins-mips.cc b/src/builtins/mips/builtins-mips.cc index a4b13b47e1..d5539ddaf3 100644 --- a/src/builtins/mips/builtins-mips.cc +++ b/src/builtins/mips/builtins-mips.cc @@ -2230,6 +2230,7 @@ void Builtins::Generate_ConstructFunction(MacroAssembler* masm) { // -- a1 : the constructor to call (checked to be a JSFunction) // -- a3 : the new target (checked to be a constructor) // ----------------------------------- + __ AssertConstructor(a1); __ AssertFunction(a1); // Calling convention for function specific ConstructStubs require @@ -2250,6 +2251,7 @@ void Builtins::Generate_ConstructBoundFunction(MacroAssembler* masm) { // -- a1 : the function to call (checked to be a JSBoundFunction) // -- a3 : the new target (checked to be a constructor) // ----------------------------------- + __ AssertConstructor(a1); __ AssertBoundFunction(a1); // Load [[BoundArguments]] into a2 and length of that into t0. @@ -2344,16 +2346,17 @@ void Builtins::Generate_Construct(MacroAssembler* masm) { Label non_constructor, non_proxy; __ JumpIfSmi(a1, &non_constructor); - // Dispatch based on instance type. - __ GetObjectType(a1, t1, t2); - __ Jump(BUILTIN_CODE(masm->isolate(), ConstructFunction), - RelocInfo::CODE_TARGET, eq, t2, Operand(JS_FUNCTION_TYPE)); - // Check if target has a [[Construct]] internal method. + __ lw(t1, FieldMemOperand(a1, HeapObject::kMapOffset)); __ lbu(t3, FieldMemOperand(t1, Map::kBitFieldOffset)); __ And(t3, t3, Operand(Map::IsConstructorBit::kMask)); __ Branch(&non_constructor, eq, t3, Operand(zero_reg)); + // Dispatch based on instance type. + __ lhu(t2, FieldMemOperand(t1, Map::kInstanceTypeOffset)); + __ Jump(BUILTIN_CODE(masm->isolate(), ConstructFunction), + RelocInfo::CODE_TARGET, eq, t2, Operand(JS_FUNCTION_TYPE)); + // Only dispatch to bound functions after checking whether they are // constructors. __ Jump(BUILTIN_CODE(masm->isolate(), ConstructBoundFunction), diff --git a/src/builtins/mips64/builtins-mips64.cc b/src/builtins/mips64/builtins-mips64.cc index 868a42b89f..a8c177ca6e 100644 --- a/src/builtins/mips64/builtins-mips64.cc +++ b/src/builtins/mips64/builtins-mips64.cc @@ -2249,6 +2249,7 @@ void Builtins::Generate_ConstructFunction(MacroAssembler* masm) { // -- a1 : the constructor to call (checked to be a JSFunction) // -- a3 : the new target (checked to be a constructor) // ----------------------------------- + __ AssertConstructor(a1); __ AssertFunction(a1); // Calling convention for function specific ConstructStubs require @@ -2270,6 +2271,7 @@ void Builtins::Generate_ConstructBoundFunction(MacroAssembler* masm) { // -- a1 : the function to call (checked to be a JSBoundFunction) // -- a3 : the new target (checked to be a constructor) // ----------------------------------- + __ AssertConstructor(a1); __ AssertBoundFunction(a1); // Load [[BoundArguments]] into a2 and length of that into a4. @@ -2362,16 +2364,17 @@ void Builtins::Generate_Construct(MacroAssembler* masm) { Label non_constructor, non_proxy; __ JumpIfSmi(a1, &non_constructor); - // Dispatch based on instance type. - __ GetObjectType(a1, t1, t2); - __ Jump(BUILTIN_CODE(masm->isolate(), ConstructFunction), - RelocInfo::CODE_TARGET, eq, t2, Operand(JS_FUNCTION_TYPE)); - // Check if target has a [[Construct]] internal method. + __ ld(t1, FieldMemOperand(a1, HeapObject::kMapOffset)); __ Lbu(t3, FieldMemOperand(t1, Map::kBitFieldOffset)); __ And(t3, t3, Operand(Map::IsConstructorBit::kMask)); __ Branch(&non_constructor, eq, t3, Operand(zero_reg)); + // Dispatch based on instance type. + __ Lhu(t2, FieldMemOperand(t1, Map::kInstanceTypeOffset)); + __ Jump(BUILTIN_CODE(masm->isolate(), ConstructFunction), + RelocInfo::CODE_TARGET, eq, t2, Operand(JS_FUNCTION_TYPE)); + // Only dispatch to bound functions after checking whether they are // constructors. __ Jump(BUILTIN_CODE(masm->isolate(), ConstructBoundFunction), diff --git a/src/builtins/x64/builtins-x64.cc b/src/builtins/x64/builtins-x64.cc index 9297282eaa..8d2ae0d40f 100644 --- a/src/builtins/x64/builtins-x64.cc +++ b/src/builtins/x64/builtins-x64.cc @@ -2484,6 +2484,7 @@ void Builtins::Generate_ConstructFunction(MacroAssembler* masm) { // -- rdx : the new target (checked to be a constructor) // -- rdi : the constructor to call (checked to be a JSFunction) // ----------------------------------- + __ AssertConstructor(rdi); __ AssertFunction(rdi); // Calling convention for function specific ConstructStubs require @@ -2505,6 +2506,7 @@ void Builtins::Generate_ConstructBoundFunction(MacroAssembler* masm) { // -- rdx : the new target (checked to be a constructor) // -- rdi : the constructor to call (checked to be a JSBoundFunction) // ----------------------------------- + __ AssertConstructor(rdi); __ AssertBoundFunction(rdi); // Push the [[BoundArguments]] onto the stack. @@ -2539,16 +2541,17 @@ void Builtins::Generate_Construct(MacroAssembler* masm) { Label non_constructor, non_proxy; __ JumpIfSmi(rdi, &non_constructor, Label::kNear); - // Dispatch based on instance type. - __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); - __ j(equal, BUILTIN_CODE(masm->isolate(), ConstructFunction), - RelocInfo::CODE_TARGET); - // Check if target has a [[Construct]] internal method. + __ movq(rcx, FieldOperand(rdi, HeapObject::kMapOffset)); __ testb(FieldOperand(rcx, Map::kBitFieldOffset), Immediate(Map::IsConstructorBit::kMask)); __ j(zero, &non_constructor, Label::kNear); + // Dispatch based on instance type. + __ CmpInstanceType(rcx, JS_FUNCTION_TYPE); + __ j(equal, BUILTIN_CODE(masm->isolate(), ConstructFunction), + RelocInfo::CODE_TARGET); + // Only dispatch to bound functions after checking whether they are // constructors. __ CmpInstanceType(rcx, JS_BOUND_FUNCTION_TYPE); diff --git a/src/compiler/js-inlining.cc b/src/compiler/js-inlining.cc index a995b038a8..c4fc8013ef 100644 --- a/src/compiler/js-inlining.cc +++ b/src/compiler/js-inlining.cc @@ -270,13 +270,6 @@ bool NeedsImplicitReceiver(Handle shared_info) { } } -bool IsNonConstructible(Handle shared_info) { - DisallowHeapAllocation no_gc; - Isolate* const isolate = shared_info->GetIsolate(); - Code* const construct_stub = shared_info->construct_stub(); - return construct_stub == *BUILTIN_CODE(isolate, ConstructedNonConstructable); -} - } // namespace // Determines whether the call target of the given call {node} is statically @@ -402,7 +395,7 @@ Reduction JSInliner::ReduceJSCall(Node* node) { // Constructor must be constructable. if (node->opcode() == IrOpcode::kJSConstruct && - IsNonConstructible(shared_info)) { + !IsConstructable(shared_info->kind())) { TRACE("Not inlining %s into %s because constructor is not constructable.\n", shared_info->DebugName()->ToCString().get(), info_->shared_info()->DebugName()->ToCString().get()); diff --git a/src/compiler/js-typed-lowering.cc b/src/compiler/js-typed-lowering.cc index f2eafa64a3..133cc5d8ad 100644 --- a/src/compiler/js-typed-lowering.cc +++ b/src/compiler/js-typed-lowering.cc @@ -1528,7 +1528,12 @@ Reduction JSTypedLowering::ReduceJSConstructForwardVarargs(Node* node) { Node* new_target = NodeProperties::GetValueInput(node, arity + 1); // Check if {target} is a JSFunction. - if (target_type->Is(Type::Function())) { + if (target_type->IsHeapConstant() && + target_type->AsHeapConstant()->Value()->IsJSFunction()) { + // Only optimize [[Construct]] here if {function} is a Constructor. + Handle function = + Handle::cast(target_type->AsHeapConstant()->Value()); + if (!function->IsConstructor()) return NoChange(); // Patch {node} to an indirect call via ConstructFunctionForwardVarargs. Callable callable = CodeFactory::ConstructFunctionForwardVarargs(isolate()); node->RemoveInput(arity + 1); @@ -1568,6 +1573,9 @@ Reduction JSTypedLowering::ReduceJSConstruct(Node* node) { const int builtin_index = shared->construct_stub()->builtin_index(); const bool is_builtin = (builtin_index != -1); + // Only optimize [[Construct]] here if {function} is a Constructor. + if (!function->IsConstructor()) return NoChange(); + CallDescriptor::Flags flags = CallDescriptor::kNeedsFrameState; if (is_builtin && Builtins::HasCppImplementation(builtin_index) && @@ -1603,23 +1611,6 @@ Reduction JSTypedLowering::ReduceJSConstruct(Node* node) { return Changed(node); } - // Check if {target} is a JSFunction. - if (target_type->Is(Type::Function())) { - // Patch {node} to an indirect call via the ConstructFunction builtin. - Callable callable = CodeFactory::ConstructFunction(isolate()); - node->RemoveInput(arity + 1); - node->InsertInput(graph()->zone(), 0, - jsgraph()->HeapConstant(callable.code())); - node->InsertInput(graph()->zone(), 2, new_target); - node->InsertInput(graph()->zone(), 3, jsgraph()->Constant(arity)); - node->InsertInput(graph()->zone(), 4, jsgraph()->UndefinedConstant()); - NodeProperties::ChangeOp( - node, common()->Call(Linkage::GetStubCallDescriptor( - isolate(), graph()->zone(), callable.descriptor(), 1 + arity, - CallDescriptor::kNeedsFrameState))); - return Changed(node); - } - return NoChange(); } diff --git a/src/factory.cc b/src/factory.cc index e080082ab0..7a2aa7e1a6 100644 --- a/src/factory.cc +++ b/src/factory.cc @@ -2625,11 +2625,7 @@ Handle Factory::NewSharedFunctionInfo( share->set_builtin_id(Builtins::kIllegal); } share->set_outer_scope_info(*the_hole_value()); - DCHECK(!Builtins::IsLazy(Builtins::kConstructedNonConstructable)); - Handle construct_stub = - is_constructor ? isolate()->builtins()->JSConstructStubGeneric() - : BUILTIN_CODE(isolate(), ConstructedNonConstructable); - share->SetConstructStub(*construct_stub); + share->SetConstructStub(*isolate()->builtins()->JSConstructStubGeneric()); share->set_script(*undefined_value(), SKIP_WRITE_BARRIER); share->set_debug_info(Smi::kZero, SKIP_WRITE_BARRIER); share->set_function_identifier(*undefined_value(), SKIP_WRITE_BARRIER); diff --git a/src/ia32/macro-assembler-ia32.cc b/src/ia32/macro-assembler-ia32.cc index 3f4161de1f..e0f3f73804 100644 --- a/src/ia32/macro-assembler-ia32.cc +++ b/src/ia32/macro-assembler-ia32.cc @@ -488,6 +488,19 @@ void MacroAssembler::AssertFixedArray(Register object) { } } +void MacroAssembler::AssertConstructor(Register object) { + if (emit_debug_code()) { + test(object, Immediate(kSmiTagMask)); + Check(not_equal, AbortReason::kOperandIsASmiAndNotAConstructor); + Push(object); + mov(object, FieldOperand(object, HeapObject::kMapOffset)); + test_b(FieldOperand(object, Map::kBitFieldOffset), + Immediate(Map::IsConstructorBit::kMask)); + Pop(object); + Check(not_zero, AbortReason::kOperandIsNotAConstructor); + } +} + void MacroAssembler::AssertFunction(Register object) { if (emit_debug_code()) { test(object, Immediate(kSmiTagMask)); diff --git a/src/ia32/macro-assembler-ia32.h b/src/ia32/macro-assembler-ia32.h index d3414bf7f0..d3ebc3e5d5 100644 --- a/src/ia32/macro-assembler-ia32.h +++ b/src/ia32/macro-assembler-ia32.h @@ -536,6 +536,9 @@ class MacroAssembler : public TurboAssembler { // Abort execution if argument is not a JSFunction, enabled via --debug-code. void AssertFunction(Register object); + // Abort execution if argument is not a Constructor, enabled via --debug-code. + void AssertConstructor(Register object); + // Abort execution if argument is not a JSBoundFunction, // enabled via --debug-code. void AssertBoundFunction(Register object); diff --git a/src/mips/macro-assembler-mips.cc b/src/mips/macro-assembler-mips.cc index b5b4751afc..b48298387f 100644 --- a/src/mips/macro-assembler-mips.cc +++ b/src/mips/macro-assembler-mips.cc @@ -4809,6 +4809,20 @@ void MacroAssembler::AssertFixedArray(Register object) { } } +void MacroAssembler::AssertConstructor(Register object) { + if (emit_debug_code()) { + STATIC_ASSERT(kSmiTag == 0); + SmiTst(object, t8); + Check(ne, AbortReason::kOperandIsASmiAndNotAConstructor, t8, + Operand(zero_reg)); + + lw(t8, FieldMemOperand(object, HeapObject::kMapOffset)); + lbu(t8, FieldMemOperand(t8, Map::kBitFieldOffset)); + And(t8, t8, Operand(Map::IsConstructorBit::kMask)); + Check(ne, AbortReason::kOperandIsNotAConstructor, t8, Operand(zero_reg)); + } +} + void MacroAssembler::AssertFunction(Register object) { if (emit_debug_code()) { STATIC_ASSERT(kSmiTag == 0); diff --git a/src/mips/macro-assembler-mips.h b/src/mips/macro-assembler-mips.h index a9b2c31f59..087f60ac82 100644 --- a/src/mips/macro-assembler-mips.h +++ b/src/mips/macro-assembler-mips.h @@ -1105,6 +1105,9 @@ const Operand& rt = Operand(zero_reg), BranchDelaySlot bd = PROTECT // Abort execution if argument is not a FixedArray, enabled via --debug-code. void AssertFixedArray(Register object); + // Abort execution if argument is not a Constructor, enabled via --debug-code. + void AssertConstructor(Register object); + // Abort execution if argument is not a JSFunction, enabled via --debug-code. void AssertFunction(Register object); diff --git a/src/mips64/macro-assembler-mips64.cc b/src/mips64/macro-assembler-mips64.cc index 8113ead69c..ecb900de50 100644 --- a/src/mips64/macro-assembler-mips64.cc +++ b/src/mips64/macro-assembler-mips64.cc @@ -5147,6 +5147,20 @@ void MacroAssembler::AssertFixedArray(Register object) { } } +void MacroAssembler::AssertConstructor(Register object) { + if (emit_debug_code()) { + STATIC_ASSERT(kSmiTag == 0); + SmiTst(object, t8); + Check(ne, AbortReason::kOperandIsASmiAndNotAConstructor, t8, + Operand(zero_reg)); + + ld(t8, FieldMemOperand(object, HeapObject::kMapOffset)); + Lbu(t8, FieldMemOperand(t8, Map::kBitFieldOffset)); + And(t8, t8, Operand(Map::IsConstructorBit::kMask)); + Check(ne, AbortReason::kOperandIsNotAConstructor, t8, Operand(zero_reg)); + } +} + void MacroAssembler::AssertFunction(Register object) { if (emit_debug_code()) { STATIC_ASSERT(kSmiTag == 0); diff --git a/src/mips64/macro-assembler-mips64.h b/src/mips64/macro-assembler-mips64.h index f090c4952b..6e66029531 100644 --- a/src/mips64/macro-assembler-mips64.h +++ b/src/mips64/macro-assembler-mips64.h @@ -1197,6 +1197,9 @@ const Operand& rt = Operand(zero_reg), BranchDelaySlot bd = PROTECT // Abort execution if argument is not a FixedArray, enabled via --debug-code. void AssertFixedArray(Register object); + // Abort execution if argument is not a Constructor, enabled via --debug-code. + void AssertConstructor(Register object); + // Abort execution if argument is not a JSFunction, enabled via --debug-code. void AssertFunction(Register object); diff --git a/src/objects.cc b/src/objects.cc index 213490717c..982f9e82f3 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -13807,10 +13807,8 @@ void SharedFunctionInfo::InitFromFunctionLiteral( // shared_info->set_kind(lit->kind()); // FunctionKind must have already been set. DCHECK(lit->kind() == shared_info->kind()); - if (!IsConstructable(lit->kind())) { - shared_info->SetConstructStub( - *BUILTIN_CODE(shared_info->GetIsolate(), ConstructedNonConstructable)); - } + DCHECK_EQ(*shared_info->GetIsolate()->builtins()->JSConstructStubGeneric(), + shared_info->construct_stub()); shared_info->set_needs_home_object(lit->scope()->NeedsHomeObject()); shared_info->set_function_literal_id(lit->function_literal_id()); DCHECK_IMPLIES(lit->requires_instance_fields_initializer(), diff --git a/src/x64/macro-assembler-x64.cc b/src/x64/macro-assembler-x64.cc index 64185052d6..ee2b3dc335 100644 --- a/src/x64/macro-assembler-x64.cc +++ b/src/x64/macro-assembler-x64.cc @@ -1835,6 +1835,18 @@ void TurboAssembler::AssertZeroExtended(Register int32_register) { } } +void MacroAssembler::AssertConstructor(Register object) { + if (emit_debug_code()) { + testb(object, Immediate(kSmiTagMask)); + Check(not_equal, AbortReason::kOperandIsASmiAndNotAConstructor); + Push(object); + movq(object, FieldOperand(object, HeapObject::kMapOffset)); + testb(FieldOperand(object, Map::kBitFieldOffset), + Immediate(Map::IsConstructorBit::kMask)); + Pop(object); + Check(not_zero, AbortReason::kOperandIsNotAConstructor); + } +} void MacroAssembler::AssertFunction(Register object) { if (emit_debug_code()) { diff --git a/src/x64/macro-assembler-x64.h b/src/x64/macro-assembler-x64.h index ec1c00152f..2cfe79e993 100644 --- a/src/x64/macro-assembler-x64.h +++ b/src/x64/macro-assembler-x64.h @@ -816,6 +816,9 @@ class MacroAssembler : public TurboAssembler { // Abort execution if argument is not a FixedArray, enabled via --debug-code. void AssertFixedArray(Register object); + // Abort execution if argument is not a Constructor, enabled via --debug-code. + void AssertConstructor(Register object); + // Abort execution if argument is not a JSFunction, enabled via --debug-code. void AssertFunction(Register object);