From f991de3b3869977f9f5f3332e3593e0929df4eb4 Mon Sep 17 00:00:00 2001 From: Victor Gomes Date: Wed, 26 Jul 2023 12:57:38 +0200 Subject: [PATCH] [maglev][turbofan] Use the fast construct builtin when deopting ... from constructor calls. The fast construct builtin has a simplified frame, so we do not need to maintain the closure, nor the arguments in the translated frame states. Bug: v8:14192 Change-Id: Ice30a1d990bab807fa19a7c2d74078c6401191e5 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4717489 Commit-Queue: Victor Gomes Reviewed-by: Leszek Swirski Reviewed-by: Darius Mercadier Cr-Commit-Position: refs/heads/main@{#89205} --- src/builtins/arm/builtins-arm.cc | 27 +-- src/builtins/arm64/builtins-arm64.cc | 26 +-- src/builtins/ia32/builtins-ia32.cc | 27 +-- src/builtins/loong64/builtins-loong64.cc | 27 +-- src/builtins/mips64/builtins-mips64.cc | 27 +-- src/builtins/ppc/builtins-ppc.cc | 27 +-- src/builtins/s390/builtins-s390.cc | 27 +-- src/builtins/x64/builtins-x64.cc | 27 ++- src/compiler/backend/code-generator.cc | 2 +- src/compiler/backend/instruction-selector.cc | 18 +- src/compiler/backend/instruction.cc | 9 +- src/compiler/backend/instruction.h | 3 + src/compiler/js-call-reducer.cc | 29 ++-- src/compiler/js-inlining.cc | 4 +- src/compiler/js-inlining.h | 3 + src/deoptimizer/deoptimizer.cc | 164 +++++++++++++++--- src/deoptimizer/deoptimizer.h | 6 +- src/deoptimizer/translated-state.cc | 17 +- src/deoptimizer/translated-state.h | 2 +- src/deoptimizer/translation-array.cc | 5 +- src/deoptimizer/translation-array.h | 2 +- src/deoptimizer/translation-opcode.h | 2 +- src/execution/frames.cc | 17 ++ src/execution/frames.h | 23 +++ src/maglev/maglev-code-generator.cc | 14 +- src/maglev/maglev-compiler.cc | 7 +- src/maglev/maglev-graph-builder.cc | 13 +- src/maglev/maglev-graph-printer.cc | 14 +- src/maglev/maglev-ir-inl.h | 10 -- src/maglev/maglev-ir.cc | 4 +- src/maglev/maglev-ir.h | 24 +-- src/snapshot/embedded/embedded-file-writer.cc | 12 +- 32 files changed, 366 insertions(+), 253 deletions(-) diff --git a/src/builtins/arm/builtins-arm.cc b/src/builtins/arm/builtins-arm.cc index 88920f332fbe..7df6dfc169e0 100644 --- a/src/builtins/arm/builtins-arm.cc +++ b/src/builtins/arm/builtins-arm.cc @@ -241,19 +241,6 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { // Call the function. __ InvokeFunctionWithNewTarget(r1, r3, r0, InvokeType::kCall); - // ----------- S t a t e ------------- - // -- r0: constructor result - // -- sp[0*kPointerSize]: implicit receiver - // -- sp[1*kPointerSize]: padding - // -- sp[2*kPointerSize]: constructor function - // -- sp[3*kPointerSize]: number of arguments - // -- sp[4*kPointerSize]: context - // ----------------------------------- - - // Store offset of return address for deoptimizer. - masm->isolate()->heap()->SetConstructStubInvokeDeoptPCOffset( - masm->pc_offset()); - // If the result is an object (in the ECMA sense), we should get rid // of the receiver and use the result; see ECMA-262 section 13.2.2-7 // on page 74. @@ -1595,6 +1582,20 @@ void Builtins::Generate_InterpreterPushArgsThenFastConstructFunction( // Call the function. __ InvokeFunctionWithNewTarget(r1, r3, r0, InvokeType::kCall); + // ----------- S t a t e ------------- + // -- r0 constructor result + // + // Stack: + // -- Implicit Receiver + // -- Context + // -- FastConstructMarker + // -- FramePointer + // ----------------------------------- + + // Store offset of return address for deoptimizer. + masm->isolate()->heap()->SetConstructStubInvokeDeoptPCOffset( + masm->pc_offset()); + // If the result is an object (in the ECMA sense), we should get rid // of the receiver and use the result; see ECMA-262 section 13.2.2-7 // on page 74. diff --git a/src/builtins/arm64/builtins-arm64.cc b/src/builtins/arm64/builtins-arm64.cc index 96a4a7877d82..201520c82b03 100644 --- a/src/builtins/arm64/builtins-arm64.cc +++ b/src/builtins/arm64/builtins-arm64.cc @@ -319,18 +319,6 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { __ Mov(x0, x12); __ InvokeFunctionWithNewTarget(x1, x3, x0, InvokeType::kCall); - // ----------- S t a t e ------------- - // -- sp[0*kSystemPointerSize]: implicit receiver - // -- sp[1*kSystemPointerSize]: padding - // -- sp[2*kSystemPointerSize]: constructor function - // -- sp[3*kSystemPointerSize]: number of arguments - // -- sp[4*kSystemPointerSize]: context - // ----------------------------------- - - // Store offset of return address for deoptimizer. - masm->isolate()->heap()->SetConstructStubInvokeDeoptPCOffset( - masm->pc_offset()); - // If the result is an object (in the ECMA sense), we should get rid // of the receiver and use the result; see ECMA-262 section 13.2.2-7 // on page 74. @@ -1796,6 +1784,20 @@ void Builtins::Generate_InterpreterPushArgsThenFastConstructFunction( // Call the function. __ InvokeFunctionWithNewTarget(x1, x3, x0, InvokeType::kCall); + // ----------- S t a t e ------------- + // -- x0 constructor result + // + // Stack: + // -- Implicit Receiver + // -- Context + // -- FastConstructMarker + // -- FramePointer + // ----------------------------------- + + // Store offset of return address for deoptimizer. + masm->isolate()->heap()->SetConstructStubInvokeDeoptPCOffset( + masm->pc_offset()); + // If the result is an object (in the ECMA sense), we should get rid // of the receiver and use the result; see ECMA-262 section 13.2.2-7 // on page 74. diff --git a/src/builtins/ia32/builtins-ia32.cc b/src/builtins/ia32/builtins-ia32.cc index 21cb0bd93921..85a6f9680d21 100644 --- a/src/builtins/ia32/builtins-ia32.cc +++ b/src/builtins/ia32/builtins-ia32.cc @@ -248,19 +248,6 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { __ mov(edi, Operand(ebp, ConstructFrameConstants::kConstructorOffset)); __ InvokeFunction(edi, edx, eax, InvokeType::kCall); - // ----------- S t a t e ------------- - // -- eax: constructor result - // -- sp[0*kSystemPointerSize]: implicit receiver - // -- sp[1*kSystemPointerSize]: padding - // -- sp[2*kSystemPointerSize]: constructor function - // -- sp[3*kSystemPointerSize]: number of arguments - // -- sp[4*kSystemPointerSize]: context - // ----------------------------------- - - // Store offset of return address for deoptimizer. - masm->isolate()->heap()->SetConstructStubInvokeDeoptPCOffset( - masm->pc_offset()); - // If the result is an object (in the ECMA sense), we should get rid // of the receiver and use the result; see ECMA-262 section 13.2.2-7 // on page 74. @@ -1539,6 +1526,20 @@ void Builtins::Generate_InterpreterPushArgsThenFastConstructFunction( // Call the constructor. __ InvokeFunction(edi, edx, eax, InvokeType::kCall); + // ----------- S t a t e ------------- + // -- eax constructor result + // + // Stack: + // -- Implicit Receiver + // -- Context + // -- FastConstructMarker + // -- FramePointer + // ----------------------------------- + + // Store offset of return address for deoptimizer. + masm->isolate()->heap()->SetConstructStubInvokeDeoptPCOffset( + masm->pc_offset()); + // If the result is an object (in the ECMA sense), we should get rid // of the receiver and use the result; see ECMA-262 section 13.2.2-7 // on page 74. diff --git a/src/builtins/loong64/builtins-loong64.cc b/src/builtins/loong64/builtins-loong64.cc index 6cd2c773d769..ddb8f8d914f9 100644 --- a/src/builtins/loong64/builtins-loong64.cc +++ b/src/builtins/loong64/builtins-loong64.cc @@ -231,19 +231,6 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { // Call the function. __ InvokeFunctionWithNewTarget(a1, a3, a0, InvokeType::kCall); - // ----------- S t a t e ------------- - // -- s0: constructor result - // -- sp[0*kSystemPointerSize]: implicit receiver - // -- sp[1*kSystemPointerSize]: padding - // -- sp[2*kSystemPointerSize]: constructor function - // -- sp[3*kSystemPointerSize]: number of arguments - // -- sp[4*kSystemPointerSize]: context - // ----------------------------------- - - // Store offset of return address for deoptimizer. - masm->isolate()->heap()->SetConstructStubInvokeDeoptPCOffset( - masm->pc_offset()); - // If the result is an object (in the ECMA sense), we should get rid // of the receiver and use the result; see ECMA-262 section 13.2.2-7 // on page 74. @@ -1597,6 +1584,20 @@ void Builtins::Generate_InterpreterPushArgsThenFastConstructFunction( // Call the function. __ InvokeFunctionWithNewTarget(a1, a3, a0, InvokeType::kCall); + // ----------- S t a t e ------------- + // -- a0 constructor result + // + // Stack: + // -- Implicit Receiver + // -- Context + // -- FastConstructMarker + // -- FramePointer + // ----------------------------------- + + // Store offset of return address for deoptimizer. + masm->isolate()->heap()->SetConstructStubInvokeDeoptPCOffset( + masm->pc_offset()); + // If the result is an object (in the ECMA sense), we should get rid // of the receiver and use the result; see ECMA-262 section 13.2.2-7 // on page 74. diff --git a/src/builtins/mips64/builtins-mips64.cc b/src/builtins/mips64/builtins-mips64.cc index 3a0fa5096794..d208956c178d 100644 --- a/src/builtins/mips64/builtins-mips64.cc +++ b/src/builtins/mips64/builtins-mips64.cc @@ -230,19 +230,6 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { // Call the function. __ InvokeFunctionWithNewTarget(a1, a3, a0, InvokeType::kCall); - // ----------- S t a t e ------------- - // -- v0: constructor result - // -- sp[0*kSystemPointerSize]: implicit receiver - // -- sp[1*kSystemPointerSize]: padding - // -- sp[2*kSystemPointerSize]: constructor function - // -- sp[3*kSystemPointerSize]: number of arguments - // -- sp[4*kSystemPointerSize]: context - // ----------------------------------- - - // Store offset of return address for deoptimizer. - masm->isolate()->heap()->SetConstructStubInvokeDeoptPCOffset( - masm->pc_offset()); - // If the result is an object (in the ECMA sense), we should get rid // of the receiver and use the result; see ECMA-262 section 13.2.2-7 // on page 74. @@ -1562,6 +1549,20 @@ void Builtins::Generate_InterpreterPushArgsThenFastConstructFunction( // Call the function. __ InvokeFunctionWithNewTarget(a1, a3, a0, InvokeType::kCall); + // ----------- S t a t e ------------- + // -- v0 constructor result + // + // Stack: + // -- Implicit Receiver + // -- Context + // -- FastConstructMarker + // -- FramePointer + // ----------------------------------- + + // Store offset of return address for deoptimizer. + masm->isolate()->heap()->SetConstructStubInvokeDeoptPCOffset( + masm->pc_offset()); + // If the result is an object (in the ECMA sense), we should get rid // of the receiver and use the result; see ECMA-262 section 13.2.2-7 // on page 74. diff --git a/src/builtins/ppc/builtins-ppc.cc b/src/builtins/ppc/builtins-ppc.cc index 3bc43e04c456..62df2e28d6e9 100644 --- a/src/builtins/ppc/builtins-ppc.cc +++ b/src/builtins/ppc/builtins-ppc.cc @@ -581,19 +581,6 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { __ InvokeFunctionWithNewTarget(r4, r6, r3, InvokeType::kCall); } - // ----------- S t a t e ------------- - // -- r0: constructor result - // -- sp[0*kSystemPointerSize]: implicit receiver - // -- sp[1*kSystemPointerSize]: padding - // -- sp[2*kSystemPointerSize]: constructor function - // -- sp[3*kSystemPointerSize]: number of arguments - // -- sp[4*kSystemPointerSize]: context - // ----------------------------------- - - // Store offset of return address for deoptimizer. - masm->isolate()->heap()->SetConstructStubInvokeDeoptPCOffset( - masm->pc_offset()); - // If the result is an object (in the ECMA sense), we should get rid // of the receiver and use the result; see ECMA-262 section 13.2.2-7 // on page 74. @@ -1873,6 +1860,20 @@ void Builtins::Generate_InterpreterPushArgsThenFastConstructFunction( // Call the function. __ InvokeFunctionWithNewTarget(r4, r6, r3, InvokeType::kCall); + // ----------- S t a t e ------------- + // -- r0 constructor result + // + // Stack: + // -- Implicit Receiver + // -- Context + // -- FastConstructMarker + // -- FramePointer + // ----------------------------------- + + // Store offset of return address for deoptimizer. + masm->isolate()->heap()->SetConstructStubInvokeDeoptPCOffset( + masm->pc_offset()); + // If the result is an object (in the ECMA sense), we should get rid // of the receiver and use the result; see ECMA-262 section 13.2.2-7 // on page 74. diff --git a/src/builtins/s390/builtins-s390.cc b/src/builtins/s390/builtins-s390.cc index e495faae3183..e71ec01c65dd 100644 --- a/src/builtins/s390/builtins-s390.cc +++ b/src/builtins/s390/builtins-s390.cc @@ -556,19 +556,6 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { // Call the function. __ InvokeFunctionWithNewTarget(r3, r5, r2, InvokeType::kCall); - // ----------- S t a t e ------------- - // -- r0: constructor result - // -- sp[0*kSystemPointerSize]: implicit receiver - // -- sp[1*kSystemPointerSize]: padding - // -- sp[2*kSystemPointerSize]: constructor function - // -- sp[3*kSystemPointerSize]: number of arguments - // -- sp[4*kSystemPointerSize]: context - // ----------------------------------- - - // Store offset of return address for deoptimizer. - masm->isolate()->heap()->SetConstructStubInvokeDeoptPCOffset( - masm->pc_offset()); - // If the result is an object (in the ECMA sense), we should get rid // of the receiver and use the result; see ECMA-262 section 13.2.2-7 // on page 74. @@ -1896,6 +1883,20 @@ void Builtins::Generate_InterpreterPushArgsThenFastConstructFunction( // Call the function. __ InvokeFunctionWithNewTarget(r3, r5, r2, InvokeType::kCall); + // ----------- S t a t e ------------- + // -- r0 constructor result + // + // Stack: + // -- Implicit Receiver + // -- Context + // -- FastConstructMarker + // -- FramePointer + // ----------------------------------- + + // Store offset of return address for deoptimizer. + masm->isolate()->heap()->SetConstructStubInvokeDeoptPCOffset( + masm->pc_offset()); + // If the result is an object (in the ECMA sense), we should get rid // of the receiver and use the result; see ECMA-262 section 13.2.2-7 // on page 74. diff --git a/src/builtins/x64/builtins-x64.cc b/src/builtins/x64/builtins-x64.cc index 101e433bf2fe..9ba0f009f849 100644 --- a/src/builtins/x64/builtins-x64.cc +++ b/src/builtins/x64/builtins-x64.cc @@ -248,19 +248,6 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { // Call the function. __ InvokeFunction(rdi, rdx, rax, InvokeType::kCall); - // ----------- S t a t e ------------- - // -- rax constructor result - // -- sp[0*kSystemPointerSize] implicit receiver - // -- sp[1*kSystemPointerSize] padding - // -- sp[2*kSystemPointerSize] constructor function - // -- sp[3*kSystemPointerSize] number of arguments - // -- sp[4*kSystemPointerSize] context - // ----------------------------------- - - // Store offset of return address for deoptimizer. - masm->isolate()->heap()->SetConstructStubInvokeDeoptPCOffset( - masm->pc_offset()); - // If the result is an object (in the ECMA sense), we should get rid // of the receiver and use the result; see ECMA-262 section 13.2.2-7 // on page 74. @@ -1520,7 +1507,19 @@ void Builtins::Generate_InterpreterPushArgsThenFastConstructFunction( // Call the function. __ InvokeFunction(rdi, rdx, rax, InvokeType::kCall); - // TODO(victorgomes): Change deopt frame in Maglev/TF and point to here! + // ----------- S t a t e ------------- + // -- rax constructor result + // + // Stack: + // -- Implicit Receiver + // -- Context + // -- FastConstructMarker + // -- FramePointer + // ----------------------------------- + + // Store offset of return address for deoptimizer. + masm->isolate()->heap()->SetConstructStubInvokeDeoptPCOffset( + masm->pc_offset()); // If the result is an object (in the ECMA sense), we should get rid // of the receiver and use the result; see ECMA-262 section 13.2.2-7 diff --git a/src/compiler/backend/code-generator.cc b/src/compiler/backend/code-generator.cc index deac7d559e84..ab1d4475aba5 100644 --- a/src/compiler/backend/code-generator.cc +++ b/src/compiler/backend/code-generator.cc @@ -1105,7 +1105,7 @@ void CodeGenerator::BuildTranslationForFrameStateDescriptor( translations_.BeginConstructCreateStubFrame(shared_info_id, height); break; case FrameStateType::kConstructInvokeStub: - translations_.BeginConstructInvokeStubFrame(shared_info_id, height); + translations_.BeginConstructInvokeStubFrame(shared_info_id); break; case FrameStateType::kBuiltinContinuation: { translations_.BeginBuiltinContinuationFrame(bailout_id, shared_info_id, diff --git a/src/compiler/backend/instruction-selector.cc b/src/compiler/backend/instruction-selector.cc index 109c183b471a..3f1c7158cfe1 100644 --- a/src/compiler/backend/instruction-selector.cc +++ b/src/compiler/backend/instruction-selector.cc @@ -1017,9 +1017,11 @@ size_t InstructionSelectorT::AddInputsToFrameStateDescriptor( values_descriptor->ReserveSize(descriptor->GetSize()); // Function - entries += v8::internal::compiler::AddOperandToStateValueDescriptor( - this, values_descriptor, inputs, g, deduplicator, &it, - FrameStateInputKind::kStackSlot, zone); + if (descriptor->HasClosure()) { + entries += v8::internal::compiler::AddOperandToStateValueDescriptor( + this, values_descriptor, inputs, g, deduplicator, &it, + FrameStateInputKind::kStackSlot, zone); + } // Parameters for (size_t i = 0; i < descriptor->parameters_count(); ++i) { @@ -1082,10 +1084,12 @@ size_t InstructionSelectorT::AddInputsToFrameStateDescriptor( DCHECK_EQ(values_descriptor->size(), 0u); values_descriptor->ReserveSize(descriptor->GetSize()); - DCHECK_NOT_NULL(function); - entries += AddOperandToStateValueDescriptor( - values_descriptor, inputs, g, deduplicator, function, - MachineType::AnyTagged(), FrameStateInputKind::kStackSlot, zone); + if (descriptor->HasClosure()) { + DCHECK_NOT_NULL(function); + entries += AddOperandToStateValueDescriptor( + values_descriptor, inputs, g, deduplicator, function, + MachineType::AnyTagged(), FrameStateInputKind::kStackSlot, zone); + } entries += AddInputsToFrameStateDescriptor( values_descriptor, inputs, g, deduplicator, parameters, kind, zone); diff --git a/src/compiler/backend/instruction.cc b/src/compiler/backend/instruction.cc index cc182120a2a6..e05df3576ef2 100644 --- a/src/compiler/backend/instruction.cc +++ b/src/compiler/backend/instruction.cc @@ -1147,12 +1147,13 @@ size_t GetConservativeFrameSizeInBytes(FrameStateType type, #if V8_ENABLE_WEBASSEMBLY case FrameStateType::kWasmInlinedIntoJS: #endif - case FrameStateType::kConstructCreateStub: - case FrameStateType::kConstructInvokeStub: { + case FrameStateType::kConstructCreateStub: { auto info = ConstructStubFrameInfo::Conservative( static_cast(parameters_count)); return info.frame_size_in_bytes(); } + case FrameStateType::kConstructInvokeStub: + return FastConstructStubFrameInfo::Conservative().frame_size_in_bytes(); case FrameStateType::kBuiltinContinuation: #if V8_ENABLE_WEBASSEMBLY case FrameStateType::kJSToWasmBuiltinContinuation: @@ -1234,8 +1235,8 @@ size_t FrameStateDescriptor::GetHeight() const { } size_t FrameStateDescriptor::GetSize() const { - return 1 + parameters_count() + locals_count() + stack_count() + - (HasContext() ? 1 : 0); + return (HasClosure() ? 1 : 0) + parameters_count() + locals_count() + + stack_count() + (HasContext() ? 1 : 0); } size_t FrameStateDescriptor::GetTotalSize() const { diff --git a/src/compiler/backend/instruction.h b/src/compiler/backend/instruction.h index 0ec20ebe4ba1..43c6438a12a6 100644 --- a/src/compiler/backend/instruction.h +++ b/src/compiler/backend/instruction.h @@ -1457,6 +1457,9 @@ class FrameStateDescriptor : public ZoneObject { size_t stack_count() const { return stack_count_; } MaybeHandle shared_info() const { return shared_info_; } FrameStateDescriptor* outer_state() const { return outer_state_; } + bool HasClosure() const { + return type_ != FrameStateType::kConstructInvokeStub; + } bool HasContext() const { return FrameStateFunctionInfo::IsJSFunctionType(type_) || type_ == FrameStateType::kBuiltinContinuation || diff --git a/src/compiler/js-call-reducer.cc b/src/compiler/js-call-reducer.cc index 1b1e649fdae5..f97dfa0bdc89 100644 --- a/src/compiler/js-call-reducer.cc +++ b/src/compiler/js-call-reducer.cc @@ -2316,13 +2316,12 @@ struct PromiseCtorFrameStateParams { // Remnant of old-style JSCallReducer code. Could be ported to graph assembler, // but probably not worth the effort. -FrameState CreateArtificialFrameState( - Node* node, Node* outer_frame_state, int parameter_count, - FrameStateType frame_state_type, SharedFunctionInfoRef shared, +FrameState CreateConstructInvokeStubFrameState( + Node* node, Node* outer_frame_state, SharedFunctionInfoRef shared, Node* context, CommonOperatorBuilder* common, Graph* graph) { const FrameStateFunctionInfo* state_info = - common->CreateFrameStateFunctionInfo( - frame_state_type, parameter_count + 1, 0, shared.object()); + common->CreateFrameStateFunctionInfo(FrameStateType::kConstructInvokeStub, + 1, 0, shared.object()); const Operator* op = common->FrameState( BytecodeOffset::None(), OutputFrameStateCombine::Ignore(), state_info); @@ -2331,12 +2330,8 @@ FrameState CreateArtificialFrameState( static constexpr int kTargetInputIndex = 0; static constexpr int kReceiverInputIndex = 1; - const int parameter_count_with_receiver = parameter_count + 1; std::vector params; - params.reserve(parameter_count_with_receiver); - for (int i = 0; i < parameter_count_with_receiver; i++) { - params.push_back(node->InputAt(kReceiverInputIndex + i)); - } + params.push_back(node->InputAt(kReceiverInputIndex)); const Operator* op_param = common->StateValues( static_cast(params.size()), SparseInputMask::Dense()); Node* params_node = graph->NewNode(op_param, static_cast(params.size()), @@ -2352,10 +2347,9 @@ FrameState PromiseConstructorFrameState( Graph* graph) { DCHECK_EQ(1, params.shared.internal_formal_parameter_count_without_receiver()); - return CreateArtificialFrameState(params.node_ptr, params.outer_frame_state, - 1, FrameStateType::kConstructInvokeStub, - params.shared, params.context, common, - graph); + return CreateConstructInvokeStubFrameState( + params.node_ptr, params.outer_frame_state, params.shared, params.context, + common, graph); } FrameState PromiseConstructorLazyFrameState( @@ -7385,8 +7379,6 @@ Reduction JSCallReducer::ReducePromiseResolveTrampoline(Node* node) { Reduction JSCallReducer::ReduceTypedArrayConstructor( Node* node, SharedFunctionInfoRef shared) { JSConstructNode n(node); - ConstructParameters const& p = n.Parameters(); - int arity = p.arity_without_implicit_args(); Node* target = n.target(); Node* arg0 = n.ArgumentOrUndefined(0, jsgraph()); Node* arg1 = n.ArgumentOrUndefined(1, jsgraph()); @@ -7399,9 +7391,8 @@ Reduction JSCallReducer::ReduceTypedArrayConstructor( // Insert a construct stub frame into the chain of frame states. This will // reconstruct the proper frame when deoptimizing within the constructor. - frame_state = CreateArtificialFrameState(node, frame_state, arity, - FrameStateType::kConstructInvokeStub, - shared, context, common(), graph()); + frame_state = CreateConstructInvokeStubFrameState(node, frame_state, shared, + context, common(), graph()); // This continuation just returns the newly created JSTypedArray. We // pass the_hole as the receiver, just like the builtin construct stub diff --git a/src/compiler/js-inlining.cc b/src/compiler/js-inlining.cc index f750c6efc5ab..e28fefcbfdcf 100644 --- a/src/compiler/js-inlining.cc +++ b/src/compiler/js-inlining.cc @@ -892,8 +892,8 @@ Reduction JSInliner::ReduceJSCall(Node* node) { // Insert a construct stub frame into the chain of frame states. This will // reconstruct the proper frame when deoptimizing within the constructor. frame_state = CreateArtificialFrameState( - node, frame_state, n.ArgumentCount(), - FrameStateType::kConstructInvokeStub, *shared_info, caller_context); + node, frame_state, 0, FrameStateType::kConstructInvokeStub, + *shared_info, caller_context); } // Insert a JSConvertReceiver node for sloppy callees. Note that the context diff --git a/src/compiler/js-inlining.h b/src/compiler/js-inlining.h index a9966a98e543..209c94235b40 100644 --- a/src/compiler/js-inlining.h +++ b/src/compiler/js-inlining.h @@ -78,6 +78,9 @@ class JSInliner final : public AdvancedReducer { OptionalSharedFunctionInfoRef DetermineCallTarget(Node* node); FeedbackCellRef DetermineCallContext(Node* node, Node** context_out); + // TODO(victorgomes): This function is used to create 3 *quite* different + // artificial frame states, we should perhaps split it into three different + // functions. FrameState CreateArtificialFrameState( Node* node, FrameState outer_frame_state, int parameter_count, FrameStateType frame_state_type, SharedFunctionInfoRef shared, diff --git a/src/deoptimizer/deoptimizer.cc b/src/deoptimizer/deoptimizer.cc index 1ffe24085d6f..123fd7d8fcc6 100644 --- a/src/deoptimizer/deoptimizer.cc +++ b/src/deoptimizer/deoptimizer.cc @@ -846,8 +846,10 @@ void Deoptimizer::DoComputeOutputFrames() { DoComputeInlinedExtraArguments(translated_frame, frame_index); break; case TranslatedFrame::kConstructCreateStub: + DoComputeConstructCreateStubFrame(translated_frame, frame_index); + break; case TranslatedFrame::kConstructInvokeStub: - DoComputeConstructStubFrame(translated_frame, frame_index); + DoComputeConstructInvokeStubFrame(translated_frame, frame_index); break; case TranslatedFrame::kBuiltinContinuation: #if V8_ENABLE_WEBASSEMBLY @@ -1349,22 +1351,16 @@ void Deoptimizer::DoComputeInlinedExtraArguments( } } -void Deoptimizer::DoComputeConstructStubFrame(TranslatedFrame* translated_frame, - int frame_index) { +void Deoptimizer::DoComputeConstructCreateStubFrame( + TranslatedFrame* translated_frame, int frame_index) { TranslatedFrame::iterator value_iterator = translated_frame->begin(); const bool is_topmost = (output_count_ - 1 == frame_index); // The construct frame could become topmost only if we inlined a constructor // call which does a tail call (otherwise the tail callee's frame would be // the topmost one). So it could only be the DeoptimizeKind::kLazy case. CHECK(!is_topmost || deopt_kind_ == DeoptimizeKind::kLazy); + DCHECK_EQ(translated_frame->kind(), TranslatedFrame::kConstructCreateStub); - bool is_create_stub = - (translated_frame->kind() == TranslatedFrame::kConstructCreateStub); - DCHECK(is_create_stub || - (translated_frame->kind() == TranslatedFrame::kConstructInvokeStub)); - - Builtins* builtins = isolate_->builtins(); - Code construct_stub = builtins->code(Builtin::kJSConstructStubGeneric); const int parameters_count = translated_frame->height(); ConstructStubFrameInfo frame_info = ConstructStubFrameInfo::Precise(parameters_count, is_topmost); @@ -1373,9 +1369,8 @@ void Deoptimizer::DoComputeConstructStubFrame(TranslatedFrame* translated_frame, TranslatedFrame::iterator function_iterator = value_iterator++; if (verbose_tracing_enabled()) { PrintF(trace_scope()->file(), - " translating construct %s stub => variable_frame_size=%d, " + " translating construct create stub => variable_frame_size=%d, " "frame_size=%d\n", - is_create_stub ? "create" : "invoke", frame_info.frame_size_in_bytes_without_fixed(), output_frame_size); } @@ -1383,8 +1378,6 @@ void Deoptimizer::DoComputeConstructStubFrame(TranslatedFrame* translated_frame, FrameDescription* output_frame = new (output_frame_size) FrameDescription(output_frame_size, parameters_count, isolate()); FrameWriter frame_writer(this, output_frame, verbose_trace_scope()); - - // Construct stub can not be topmost. DCHECK(frame_index > 0 && frame_index < output_count_); DCHECK_NULL(output_[frame_index]); output_[frame_index] = output_frame; @@ -1449,12 +1442,8 @@ void Deoptimizer::DoComputeConstructStubFrame(TranslatedFrame* translated_frame, // The deopt info contains the implicit receiver or the new target at the // position of the receiver. Copy it to the top of stack, with the hole value // as padding to maintain alignment. - frame_writer.PushRawObject(roots.the_hole_value(), "padding\n"); - - const char* debug_hint = - is_create_stub ? "new target\n" : "allocated receiver\n"; - frame_writer.PushTranslatedValue(receiver_iterator, debug_hint); + frame_writer.PushTranslatedValue(receiver_iterator, "new target\n"); if (is_topmost) { for (int i = 0; i < ArgumentPaddingSlots(1); ++i) { @@ -1470,11 +1459,11 @@ void Deoptimizer::DoComputeConstructStubFrame(TranslatedFrame* translated_frame, CHECK_EQ(0u, frame_writer.top_offset()); // Compute this frame's PC. + Code construct_stub = + isolate_->builtins()->code(Builtin::kJSConstructStubGeneric); Address start = construct_stub->instruction_start(); const int pc_offset = - is_create_stub - ? isolate_->heap()->construct_stub_create_deopt_pc_offset().value() - : isolate_->heap()->construct_stub_invoke_deopt_pc_offset().value(); + isolate_->heap()->construct_stub_create_deopt_pc_offset().value(); intptr_t pc_value = static_cast(start + pc_offset); if (is_topmost) { // Only the pc of the topmost frame needs to be signed since it is @@ -1504,12 +1493,139 @@ void Deoptimizer::DoComputeConstructStubFrame(TranslatedFrame* translated_frame, intptr_t context_value = static_cast(Smi::zero().ptr()); Register context_reg = JavaScriptFrame::context_register(); output_frame->SetRegister(context_reg.code(), context_value); + + // Set the continuation for the topmost frame. + DCHECK_EQ(DeoptimizeKind::kLazy, deopt_kind_); + Code continuation = isolate_->builtins()->code(Builtin::kNotifyDeoptimized); + output_frame->SetContinuation( + static_cast(continuation->instruction_start())); + } +} + +void Deoptimizer::DoComputeConstructInvokeStubFrame( + TranslatedFrame* translated_frame, int frame_index) { + TranslatedFrame::iterator value_iterator = translated_frame->begin(); + const bool is_topmost = (output_count_ - 1 == frame_index); + // The construct frame could become topmost only if we inlined a constructor + // call which does a tail call (otherwise the tail callee's frame would be + // the topmost one). So it could only be the DeoptimizeKind::kLazy case. + CHECK(!is_topmost || deopt_kind_ == DeoptimizeKind::kLazy); + DCHECK_EQ(translated_frame->kind(), TranslatedFrame::kConstructInvokeStub); + DCHECK_EQ(translated_frame->height(), 0); + + FastConstructStubFrameInfo frame_info = + FastConstructStubFrameInfo::Precise(is_topmost); + const uint32_t output_frame_size = frame_info.frame_size_in_bytes(); + if (verbose_tracing_enabled()) { + PrintF(trace_scope()->file(), + " translating construct invoke stub => variable_frame_size=%d, " + "frame_size=%d\n", + frame_info.frame_size_in_bytes_without_fixed(), output_frame_size); + } + + // Allocate and store the output frame description. + FrameDescription* output_frame = + new (output_frame_size) FrameDescription(output_frame_size, 0, isolate()); + FrameWriter frame_writer(this, output_frame, verbose_trace_scope()); + DCHECK(frame_index > 0 && frame_index < output_count_); + DCHECK_NULL(output_[frame_index]); + output_[frame_index] = output_frame; + + // The top address of the frame is computed from the previous frame's top and + // this frame's size. + const intptr_t top_address = + output_[frame_index - 1]->GetTop() - output_frame_size; + output_frame->SetTop(top_address); + + // The allocated receiver of a construct stub frame is passed as the + // receiver parameter through the translation. It might be encoding + // a captured object, so we need save it for later. + TranslatedFrame::iterator receiver_iterator = value_iterator; + value_iterator++; + + // Read caller's PC from the previous frame. + const intptr_t caller_pc = output_[frame_index - 1]->GetPc(); + frame_writer.PushApprovedCallerPc(caller_pc); + + // Read caller's FP from the previous frame, and set this frame's FP. + const intptr_t caller_fp = output_[frame_index - 1]->GetFp(); + frame_writer.PushCallerFp(caller_fp); + + const intptr_t fp_value = top_address + frame_writer.top_offset(); + output_frame->SetFp(fp_value); + if (is_topmost) { + Register fp_reg = JavaScriptFrame::fp_register(); + output_frame->SetRegister(fp_reg.code(), fp_value); + } + + if (V8_EMBEDDED_CONSTANT_POOL_BOOL) { + // Read the caller's constant pool from the previous frame. + const intptr_t caller_cp = output_[frame_index - 1]->GetConstantPool(); + frame_writer.PushCallerConstantPool(caller_cp); + } + intptr_t marker = StackFrame::TypeToMarker(StackFrame::FAST_CONSTRUCT); + frame_writer.PushRawValue(marker, "fast construct stub sentinel\n"); + frame_writer.PushTranslatedValue(value_iterator++, "context"); + frame_writer.PushTranslatedValue(receiver_iterator, "implicit receiver"); + + // The FastConstructFrame needs to be aligned in some architectures. + ReadOnlyRoots roots(isolate()); + for (int i = 0; i < ArgumentPaddingSlots(1); ++i) { + frame_writer.PushRawObject(roots.the_hole_value(), "padding\n"); + } + + if (is_topmost) { + for (int i = 0; i < ArgumentPaddingSlots(1); ++i) { + frame_writer.PushRawObject(roots.the_hole_value(), "padding\n"); + } + // Ensure the result is restored back when we return to the stub. + Register result_reg = kReturnRegister0; + intptr_t result = input_->GetRegister(result_reg.code()); + frame_writer.PushRawValue(result, "subcall result\n"); } - // Set the continuation for the topmost frame. + CHECK_EQ(translated_frame->end(), value_iterator); + CHECK_EQ(0u, frame_writer.top_offset()); + + // Compute this frame's PC. + Code construct_stub = isolate_->builtins()->code( + Builtin::kInterpreterPushArgsThenFastConstructFunction); + Address start = construct_stub->instruction_start(); + const int pc_offset = + isolate_->heap()->construct_stub_invoke_deopt_pc_offset().value(); + intptr_t pc_value = static_cast(start + pc_offset); if (is_topmost) { + // Only the pc of the topmost frame needs to be signed since it is + // authenticated at the end of the DeoptimizationEntry builtin. + output_frame->SetPc(PointerAuthentication::SignAndCheckPC( + isolate(), pc_value, frame_writer.frame()->GetTop())); + } else { + output_frame->SetPc(pc_value); + } + + // Update constant pool. + if (V8_EMBEDDED_CONSTANT_POOL_BOOL) { + intptr_t constant_pool_value = + static_cast(construct_stub->constant_pool()); + output_frame->SetConstantPool(constant_pool_value); + if (is_topmost) { + Register constant_pool_reg = + JavaScriptFrame::constant_pool_pointer_register(); + output_frame->SetRegister(constant_pool_reg.code(), constant_pool_value); + } + } + + // Clear the context register. The context might be a de-materialized object + // and will be materialized by {Runtime_NotifyDeoptimized}. For additional + // safety we use Smi(0) instead of the potential {arguments_marker} here. + if (is_topmost) { + intptr_t context_value = static_cast(Smi::zero().ptr()); + Register context_reg = JavaScriptFrame::context_register(); + output_frame->SetRegister(context_reg.code(), context_value); + + // Set the continuation for the topmost frame. DCHECK_EQ(DeoptimizeKind::kLazy, deopt_kind_); - Code continuation = builtins->code(Builtin::kNotifyDeoptimized); + Code continuation = isolate_->builtins()->code(Builtin::kNotifyDeoptimized); output_frame->SetContinuation( static_cast(continuation->instruction_start())); } diff --git a/src/deoptimizer/deoptimizer.h b/src/deoptimizer/deoptimizer.h index 139b3019fca6..f40721ecf72e 100644 --- a/src/deoptimizer/deoptimizer.h +++ b/src/deoptimizer/deoptimizer.h @@ -159,8 +159,10 @@ class Deoptimizer : public Malloced { int frame_index, bool goto_catch_handler); void DoComputeInlinedExtraArguments(TranslatedFrame* translated_frame, int frame_index); - void DoComputeConstructStubFrame(TranslatedFrame* translated_frame, - int frame_index); + void DoComputeConstructCreateStubFrame(TranslatedFrame* translated_frame, + int frame_index); + void DoComputeConstructInvokeStubFrame(TranslatedFrame* translated_frame, + int frame_index); static Builtin TrampolineForBuiltinContinuation(BuiltinContinuationMode mode, bool must_handle_result); diff --git a/src/deoptimizer/translated-state.cc b/src/deoptimizer/translated-state.cc index 2e60686abe5b..497978413493 100644 --- a/src/deoptimizer/translated-state.cc +++ b/src/deoptimizer/translated-state.cc @@ -109,13 +109,12 @@ void TranslationArrayPrintSingleFrame( } case TranslationOpcode::CONSTRUCT_INVOKE_STUB_FRAME: { - DCHECK_EQ(TranslationOpcodeOperandCount(opcode), 2); + DCHECK_EQ(TranslationOpcodeOperandCount(opcode), 1); int shared_info_id = iterator.NextOperand(); Object shared_info = literal_array->get(shared_info_id); - unsigned height = iterator.NextOperand(); os << "{construct invoke stub, function=" << SharedFunctionInfo::cast(shared_info)->DebugNameCStr().get() - << ", height=" << height << "}"; + << "}"; break; } @@ -805,8 +804,8 @@ TranslatedFrame TranslatedFrame::ConstructCreateStubFrame( } TranslatedFrame TranslatedFrame::ConstructInvokeStubFrame( - SharedFunctionInfo shared_info, int height) { - return TranslatedFrame(kConstructInvokeStub, shared_info, height); + SharedFunctionInfo shared_info) { + return TranslatedFrame(kConstructInvokeStub, shared_info, 0); } TranslatedFrame TranslatedFrame::BuiltinContinuationFrame( @@ -967,15 +966,13 @@ TranslatedFrame TranslatedState::CreateNextTranslatedFrame( case TranslationOpcode::CONSTRUCT_INVOKE_STUB_FRAME: { SharedFunctionInfo shared_info = SharedFunctionInfo::cast(literal_array->get(iterator->NextOperand())); - int height = iterator->NextOperand(); if (trace_file != nullptr) { std::unique_ptr name = shared_info->DebugNameCStr(); PrintF(trace_file, - " reading construct invoke stub frame %s => height = %d; " - "inputs:\n", - name.get(), height); + " reading construct invoke stub frame %s, inputs:\n", + name.get()); } - return TranslatedFrame::ConstructInvokeStubFrame(shared_info, height); + return TranslatedFrame::ConstructInvokeStubFrame(shared_info); } case TranslationOpcode::BUILTIN_CONTINUATION_FRAME: { diff --git a/src/deoptimizer/translated-state.h b/src/deoptimizer/translated-state.h index 2a8e91bc4442..02bbf1ce4b7a 100644 --- a/src/deoptimizer/translated-state.h +++ b/src/deoptimizer/translated-state.h @@ -293,7 +293,7 @@ class TranslatedFrame { static TranslatedFrame ConstructCreateStubFrame( SharedFunctionInfo shared_info, int height); static TranslatedFrame ConstructInvokeStubFrame( - SharedFunctionInfo shared_info, int height); + SharedFunctionInfo shared_info); static TranslatedFrame BuiltinContinuationFrame( BytecodeOffset bailout_id, SharedFunctionInfo shared_info, int height); #if V8_ENABLE_WEBASSEMBLY diff --git a/src/deoptimizer/translation-array.cc b/src/deoptimizer/translation-array.cc index e648358d815c..2f7cc627ad9a 100644 --- a/src/deoptimizer/translation-array.cc +++ b/src/deoptimizer/translation-array.cc @@ -466,10 +466,9 @@ void TranslationArrayBuilder::BeginConstructCreateStubFrame(int literal_id, Add(opcode, SignedOperand(literal_id), SignedOperand(height)); } -void TranslationArrayBuilder::BeginConstructInvokeStubFrame(int literal_id, - unsigned height) { +void TranslationArrayBuilder::BeginConstructInvokeStubFrame(int literal_id) { auto opcode = TranslationOpcode::CONSTRUCT_INVOKE_STUB_FRAME; - Add(opcode, SignedOperand(literal_id), SignedOperand(height)); + Add(opcode, SignedOperand(literal_id)); } void TranslationArrayBuilder::BeginInlinedExtraArguments(int literal_id, diff --git a/src/deoptimizer/translation-array.h b/src/deoptimizer/translation-array.h index c64d397ac4c7..3082f94480a1 100644 --- a/src/deoptimizer/translation-array.h +++ b/src/deoptimizer/translation-array.h @@ -82,7 +82,7 @@ class TranslationArrayBuilder { int return_value_count); void BeginInlinedExtraArguments(int literal_id, unsigned height); void BeginConstructCreateStubFrame(int literal_id, unsigned height); - void BeginConstructInvokeStubFrame(int literal_id, unsigned height); + void BeginConstructInvokeStubFrame(int literal_id); void BeginBuiltinContinuationFrame(BytecodeOffset bailout_id, int literal_id, unsigned height); #if V8_ENABLE_WEBASSEMBLY diff --git a/src/deoptimizer/translation-opcode.h b/src/deoptimizer/translation-opcode.h index c1d1269bc00e..d9872b0b36ab 100644 --- a/src/deoptimizer/translation-opcode.h +++ b/src/deoptimizer/translation-opcode.h @@ -20,7 +20,7 @@ namespace internal { #define TRANSLATION_OPCODE_LIST(V) \ TRANSLATION_JS_FRAME_OPCODE_LIST(V) \ V(CONSTRUCT_CREATE_STUB_FRAME, 2) \ - V(CONSTRUCT_INVOKE_STUB_FRAME, 2) \ + V(CONSTRUCT_INVOKE_STUB_FRAME, 1) \ V(BUILTIN_CONTINUATION_FRAME, 3) \ IF_WASM(V, JS_TO_WASM_BUILTIN_CONTINUATION_FRAME, 4) \ IF_WASM(V, WASM_INLINED_INTO_JS_FRAME, 3) \ diff --git a/src/execution/frames.cc b/src/execution/frames.cc index 834fdb3da824..0e72bf688752 100644 --- a/src/execution/frames.cc +++ b/src/execution/frames.cc @@ -3383,6 +3383,23 @@ ConstructStubFrameInfo::ConstructStubFrameInfo(int translation_height, ConstructFrameConstants::kFixedFrameSize; } +FastConstructStubFrameInfo::FastConstructStubFrameInfo(bool is_topmost) { + // If the construct frame appears to be topmost we should ensure that the + // value of result register is preserved during continuation execution. + // We do this here by "pushing" the result of the constructor function to + // the top of the reconstructed stack and popping it in + // {Builtin::kNotifyDeoptimized}. + + static constexpr int kTopOfStackPadding = TopOfStackRegisterPaddingSlots(); + static constexpr int kTheResult = 1; + const int adjusted_height = + ArgumentPaddingSlots(1) + + (is_topmost ? kTheResult + kTopOfStackPadding : 0); + frame_size_in_bytes_without_fixed_ = adjusted_height * kSystemPointerSize; + frame_size_in_bytes_ = frame_size_in_bytes_without_fixed_ + + FastConstructFrameConstants::kFixedFrameSize; +} + BuiltinContinuationFrameInfo::BuiltinContinuationFrameInfo( int translation_height, const CallInterfaceDescriptor& continuation_descriptor, diff --git a/src/execution/frames.h b/src/execution/frames.h index 239e993dabac..b77c7b791336 100644 --- a/src/execution/frames.h +++ b/src/execution/frames.h @@ -1712,6 +1712,29 @@ class ConstructStubFrameInfo { uint32_t frame_size_in_bytes_; }; +class FastConstructStubFrameInfo { + public: + static FastConstructStubFrameInfo Precise(bool is_topmost) { + return FastConstructStubFrameInfo(is_topmost); + } + + static FastConstructStubFrameInfo Conservative() { + // Assume it is the top most frame when conservative. + return FastConstructStubFrameInfo(true); + } + + uint32_t frame_size_in_bytes_without_fixed() const { + return frame_size_in_bytes_without_fixed_; + } + uint32_t frame_size_in_bytes() const { return frame_size_in_bytes_; } + + private: + explicit FastConstructStubFrameInfo(bool is_topmost); + + uint32_t frame_size_in_bytes_without_fixed_; + uint32_t frame_size_in_bytes_; +}; + // Used by BuiltinContinuationFrameInfo. class CallInterfaceDescriptor; class RegisterConfiguration; diff --git a/src/maglev/maglev-code-generator.cc b/src/maglev/maglev-code-generator.cc index c9d4a2db4605..03374daa8e77 100644 --- a/src/maglev/maglev-code-generator.cc +++ b/src/maglev/maglev-code-generator.cc @@ -1200,21 +1200,13 @@ class MaglevTranslationArrayBuilder { void BuildSingleDeoptFrame(const ConstructInvokeStubDeoptFrame& frame, const InputLocation*& current_input_location) { translation_array_builder_->BeginConstructInvokeStubFrame( - GetDeoptLiteral(GetSharedFunctionInfo(frame)), - frame.arguments_without_receiver().length() + 1); + GetDeoptLiteral(GetSharedFunctionInfo(frame))); - // Closure - BuildDeoptFrameSingleValue(frame.closure(), current_input_location); - - // Arguments + // Implicit receiver BuildDeoptFrameSingleValue(frame.receiver(), current_input_location); - for (ValueNode* value : frame.arguments_without_receiver()) { - BuildDeoptFrameSingleValue(value, current_input_location); - } // Context - ValueNode* value = frame.context(); - BuildDeoptFrameSingleValue(value, current_input_location); + BuildDeoptFrameSingleValue(frame.context(), current_input_location); } void BuildSingleDeoptFrame(const BuiltinContinuationDeoptFrame& frame, diff --git a/src/maglev/maglev-compiler.cc b/src/maglev/maglev-compiler.cc index 1f21880b5ec6..092a04e2c6ed 100644 --- a/src/maglev/maglev-compiler.cc +++ b/src/maglev/maglev-compiler.cc @@ -133,12 +133,7 @@ class MaxCallDepthProcessor { return info.frame_size_in_bytes(); } case DeoptFrame::FrameType::kConstructInvokeStubFrame: { - int arg_count = deopt_frame->as_construct_stub() - .arguments_without_receiver() - .length() + - 1; - auto info = ConstructStubFrameInfo::Conservative(arg_count); - return info.frame_size_in_bytes(); + return FastConstructStubFrameInfo::Conservative().frame_size_in_bytes(); } case DeoptFrame::FrameType::kInlinedArgumentsFrame: { return std::max( diff --git a/src/maglev/maglev-graph-builder.cc b/src/maglev/maglev-graph-builder.cc index 8c0a214cdc0a..875183f4c1f2 100644 --- a/src/maglev/maglev-graph-builder.cc +++ b/src/maglev/maglev-graph-builder.cc @@ -275,15 +275,12 @@ class V8_NODISCARD MaglevGraphBuilder::DeoptFrameScope { builder_->current_deopt_scope_ = this; } - DeoptFrameScope(MaglevGraphBuilder* builder, ValueNode* closure, - ValueNode* receiver, - const base::Vector arguments_without_receiver) + DeoptFrameScope(MaglevGraphBuilder* builder, ValueNode* receiver) : builder_(builder), parent_(builder->current_deopt_scope_), data_(DeoptFrame::ConstructInvokeStubFrameData{ *builder->compilation_unit(), builder->current_source_position_, - closure, receiver, arguments_without_receiver, - builder->GetContext()}) { + receiver, builder->GetContext()}) { builder_->current_deopt_scope_ = this; } @@ -7401,8 +7398,7 @@ ReduceResult MaglevGraphBuilder::ReduceConstruct( args.set_receiver(implicit_receiver); ValueNode* call_result; { - DeoptFrameScope construct(this, target, implicit_receiver, - construct_arguments_without_receiver); + DeoptFrameScope construct(this, implicit_receiver); ReduceResult result = TryBuildCallKnownJSFunction( function, new_target, args, feedback_source); RETURN_IF_ABORT(result); @@ -7444,8 +7440,7 @@ ReduceResult MaglevGraphBuilder::ReduceConstruct( args.set_receiver(implicit_receiver); ValueNode* call_result; { - DeoptFrameScope construct(this, target, implicit_receiver, - construct_arguments_without_receiver); + DeoptFrameScope construct(this, implicit_receiver); ReduceResult result = TryBuildCallKnownJSFunction( function, new_target, args, feedback_source); RETURN_IF_ABORT(result); diff --git a/src/maglev/maglev-graph-printer.cc b/src/maglev/maglev-graph-printer.cc index 5670860191f4..c816d4730ca5 100644 --- a/src/maglev/maglev-graph-printer.cc +++ b/src/maglev/maglev-graph-printer.cc @@ -416,23 +416,11 @@ void PrintSingleDeoptFrame( os << "@ConstructInvokeStub"; if (!v8_flags.print_maglev_deopt_verbose) return; os << " : {"; - auto arguments_without_receiver = - frame.as_construct_stub().arguments_without_receiver(); os << ":" << PrintNodeLabel(graph_labeller, frame.as_construct_stub().receiver()) << ":" << current_input_location->operand(); current_input_location++; - if (arguments_without_receiver.size() > 0) { - os << ", "; - } - for (size_t i = 0; i < arguments_without_receiver.size(); i++) { - os << "a" << i << ":" - << PrintNodeLabel(graph_labeller, arguments_without_receiver[i]) - << ":" << current_input_location->operand(); - current_input_location++; - os << ", "; - } - os << ":" + os << ", :" << PrintNodeLabel(graph_labeller, frame.as_construct_stub().context()) << ":" << current_input_location->operand(); current_input_location++; diff --git a/src/maglev/maglev-ir-inl.h b/src/maglev/maglev-ir-inl.h index 2f95c25c1892..d0848b183075 100644 --- a/src/maglev/maglev-ir-inl.h +++ b/src/maglev/maglev-ir-inl.h @@ -59,12 +59,7 @@ void DeepForEachInputImpl( break; } case DeoptFrame::FrameType::kConstructInvokeStubFrame: { - f(frame.as_construct_stub().closure(), &input_locations[index++]); f(frame.as_construct_stub().receiver(), &input_locations[index++]); - for (first_argument node : - frame.as_construct_stub().arguments_without_receiver()) { - f(node, &input_locations[index++]); - } f(frame.as_construct_stub().context(), &input_locations[index++]); break; } @@ -112,12 +107,7 @@ void DeepForEachInput(const_if_function_first_arg_not_reference< }); break; case DeoptFrame::FrameType::kConstructInvokeStubFrame: { - f(top_frame.as_construct_stub().closure(), &input_locations[index++]); f(top_frame.as_construct_stub().receiver(), &input_locations[index++]); - for (first_argument node : - top_frame.as_construct_stub().arguments_without_receiver()) { - f(node, &input_locations[index++]); - } f(top_frame.as_construct_stub().context(), &input_locations[index++]); break; } diff --git a/src/maglev/maglev-ir.cc b/src/maglev/maglev-ir.cc index 9e25d937a365..a7e9b4f0b65d 100644 --- a/src/maglev/maglev-ir.cc +++ b/src/maglev/maglev-ir.cc @@ -231,9 +231,7 @@ size_t GetInputLocationsArraySize(const DeoptFrame& top_frame) { size += kClosureSize + frame->as_inlined_arguments().arguments().size(); break; case DeoptFrame::FrameType::kConstructInvokeStubFrame: - size += kClosureSize + kReceiverSize + - frame->as_construct_stub().arguments_without_receiver().size() + - kContextSize; + size += kReceiverSize + kContextSize; break; case DeoptFrame::FrameType::kBuiltinContinuationFrame: size += diff --git a/src/maglev/maglev-ir.h b/src/maglev/maglev-ir.h index b2929e0b8653..877698619e9b 100644 --- a/src/maglev/maglev-ir.h +++ b/src/maglev/maglev-ir.h @@ -1099,9 +1099,7 @@ class DeoptFrame { struct ConstructInvokeStubFrameData { const MaglevCompilationUnit& unit; const SourcePosition source_position; - ValueNode* closure; ValueNode* receiver; - const base::Vector arguments_without_receiver; ValueNode* context; }; @@ -1235,25 +1233,17 @@ inline InlinedArgumentsDeoptFrame& DeoptFrame::as_inlined_arguments() { class ConstructInvokeStubDeoptFrame : public DeoptFrame { public: - ConstructInvokeStubDeoptFrame( - const MaglevCompilationUnit& unit, SourcePosition source_position, - ValueNode* closure, ValueNode* receiver, - base::Vector arguments_without_receiver, ValueNode* context, - DeoptFrame* parent) - : DeoptFrame( - ConstructInvokeStubFrameData{unit, source_position, closure, - receiver, arguments_without_receiver, - context}, - parent) {} + ConstructInvokeStubDeoptFrame(const MaglevCompilationUnit& unit, + SourcePosition source_position, + ValueNode* receiver, ValueNode* context, + DeoptFrame* parent) + : DeoptFrame(ConstructInvokeStubFrameData{unit, source_position, receiver, + context}, + parent) {} const MaglevCompilationUnit& unit() const { return data().unit; } - ValueNode*& closure() { return data().closure; } - ValueNode* closure() const { return data().closure; } ValueNode*& receiver() { return data().receiver; } ValueNode* receiver() const { return data().receiver; } - base::Vector arguments_without_receiver() const { - return data().arguments_without_receiver; - } ValueNode*& context() { return data().context; } ValueNode* context() const { return data().context; } SourcePosition source_position() const { return data().source_position; } diff --git a/src/snapshot/embedded/embedded-file-writer.cc b/src/snapshot/embedded/embedded-file-writer.cc index 6c7a410957b0..f64a44ce101a 100644 --- a/src/snapshot/embedded/embedded-file-writer.cc +++ b/src/snapshot/embedded/embedded-file-writer.cc @@ -81,9 +81,10 @@ void EmbeddedFileWriter::WriteBuiltin(PlatformEmbeddedFileWriterBase* w, CHECK(positions.done()); // Release builds must not contain debug infos. #endif - // Some builtins (JSConstructStubGeneric) have entry points located in the - // middle of them, we need to store their addresses since they are part of - // the list of allowed return addresses in the deoptimizer. + // Some builtins (InterpreterPushArgsThenFastConstructFunction, + // JSConstructStubGeneric) have entry points located in the middle of them, we + // need to store their addresses since they are part of the list of allowed + // return addresses in the deoptimizer. const std::vector& current_labels = label_info_[builtin_id]; auto label = current_labels.begin(); @@ -283,8 +284,9 @@ void EmbeddedFileWriter::PrepareBuiltinLabelInfoMap(int create_offset, int invoke_offset) { label_info_[static_cast(Builtin::kJSConstructStubGeneric)].push_back( {create_offset, "construct_stub_create_deopt_addr"}); - label_info_[static_cast(Builtin::kJSConstructStubGeneric)].push_back( - {invoke_offset, "construct_stub_invoke_deopt_addr"}); + label_info_[static_cast( + Builtin::kInterpreterPushArgsThenFastConstructFunction)] + .push_back({invoke_offset, "construct_stub_invoke_deopt_addr"}); } } // namespace internal