diff --git a/src/builtins/x64/builtins-x64.cc b/src/builtins/x64/builtins-x64.cc index b3fe7d56a2..c2de46498f 100644 --- a/src/builtins/x64/builtins-x64.cc +++ b/src/builtins/x64/builtins-x64.cc @@ -2962,15 +2962,9 @@ void Builtins::Generate_GenericJSToWasmWrapper(MacroAssembler* masm) { // ------------------------------------------- // Compute offsets and prepare for GC. // ------------------------------------------- - // We will have to save a value indicating the GC the number - // of values on the top of the stack that have to be scanned before calling - // the Wasm function. - constexpr int kFrameMarkerOffset = -kSystemPointerSize; - constexpr int kGCScanSlotCountOffset = - kFrameMarkerOffset - kSystemPointerSize; // The number of parameters passed to this function. constexpr int kInParamCountOffset = - kGCScanSlotCountOffset - kSystemPointerSize; + BuiltinWasmWrapperConstants::kGCScanSlotCountOffset - kSystemPointerSize; // The number of parameters according to the signature. constexpr int kParamCountOffset = kInParamCountOffset - kSystemPointerSize; constexpr int kReturnCountOffset = kParamCountOffset - kSystemPointerSize; @@ -3387,7 +3381,8 @@ void Builtins::Generate_GenericJSToWasmWrapper(MacroAssembler* masm) { // We set the indicating value for the GC to the proper one for Wasm call. constexpr int kWasmCallGCScanSlotCount = 0; - __ Move(MemOperand(rbp, kGCScanSlotCountOffset), kWasmCallGCScanSlotCount); + __ Move(MemOperand(rbp, BuiltinWasmWrapperConstants::kGCScanSlotCountOffset), + kWasmCallGCScanSlotCount); // ------------------------------------------- // Call the Wasm function. @@ -3470,10 +3465,12 @@ void Builtins::Generate_GenericJSToWasmWrapper(MacroAssembler* masm) { // The builtin expects the parameter to be in register param = rax. constexpr int kBuiltinCallGCScanSlotCount = 2; - PrepareForBuiltinCall(masm, MemOperand(rbp, kGCScanSlotCountOffset), - kBuiltinCallGCScanSlotCount, current_param, param_limit, - current_int_param_slot, current_float_param_slot, - valuetypes_array_ptr, wasm_instance, function_data); + PrepareForBuiltinCall( + masm, + MemOperand(rbp, BuiltinWasmWrapperConstants::kGCScanSlotCountOffset), + kBuiltinCallGCScanSlotCount, current_param, param_limit, + current_int_param_slot, current_float_param_slot, valuetypes_array_ptr, + wasm_instance, function_data); Label param_kWasmI32_not_smi; Label param_kWasmI64; @@ -3620,7 +3617,8 @@ void Builtins::Generate_GenericJSToWasmWrapper(MacroAssembler* masm) { // ------------------------------------------- __ bind(&compile_wrapper); // Enable GC. - MemOperand GCScanSlotPlace = MemOperand(rbp, kGCScanSlotCountOffset); + MemOperand GCScanSlotPlace = + MemOperand(rbp, BuiltinWasmWrapperConstants::kGCScanSlotCountOffset); __ Move(GCScanSlotPlace, 4); // Save registers to the stack. __ pushq(wasm_instance); @@ -3651,7 +3649,7 @@ void LoadJumpBuffer(MacroAssembler* masm, Register jmpbuf) { void Builtins::Generate_WasmReturnPromiseOnSuspend(MacroAssembler* masm) { // Set up the stackframe. - __ EnterFrame(StackFrame::JS_TO_WASM); + __ EnterFrame(StackFrame::RETURN_PROMISE_ON_SUSPEND); // Parameters. Register closure = kJSFunctionRegister; // rdi @@ -3661,7 +3659,10 @@ void Builtins::Generate_WasmReturnPromiseOnSuspend(MacroAssembler* masm) { } constexpr int kFrameMarkerOffset = -kSystemPointerSize; - constexpr int kParamCountOffset = kFrameMarkerOffset - kSystemPointerSize; + // This slot contains the number of slots at the top of the frame that need to + // be scanned by the GC. + constexpr int kParamCountOffset = + BuiltinWasmWrapperConstants::kGCScanSlotCountOffset - kSystemPointerSize; // The frame marker is not included in the slot count. constexpr int kNumSpillSlots = -(kParamCountOffset - kFrameMarkerOffset) / kSystemPointerSize; @@ -3723,11 +3724,13 @@ void Builtins::Generate_WasmReturnPromiseOnSuspend(MacroAssembler* masm) { // ------------------------------------------- // Allocate a new continuation. // ------------------------------------------- + MemOperand GCScanSlotPlace = + MemOperand(rbp, BuiltinWasmWrapperConstants::kGCScanSlotCountOffset); + __ Move(GCScanSlotPlace, 3); __ Push(wasm_instance); __ Push(function_data); __ Push(wasm_instance); __ Move(kContextRegister, Smi::zero()); - // TODO(thibaudm): Handle GC. __ CallRuntime(Runtime::kWasmAllocateContinuation); __ Pop(function_data); __ Pop(wasm_instance); @@ -3750,6 +3753,14 @@ void Builtins::Generate_WasmReturnPromiseOnSuspend(MacroAssembler* masm) { // Switch stack! LoadJumpBuffer(masm, target_jmpbuf); __ movq(rbp, rsp); // New stack, there is no frame yet. + __ Move(GCScanSlotPlace, 3); + __ Push(wasm_instance); + __ Push(function_data); + __ Push(wasm_instance); + __ Move(kContextRegister, Smi::zero()); + __ CallRuntime(Runtime::kWasmSyncStackLimit); + __ Pop(function_data); + __ Pop(wasm_instance); foreign_jmpbuf = no_reg; target_jmpbuf = no_reg; // live: [rsi, rdi] @@ -3827,6 +3838,7 @@ void Builtins::Generate_WasmReturnPromiseOnSuspend(MacroAssembler* masm) { // Switch stack! LoadJumpBuffer(masm, jmpbuf); __ leaq(rbp, Operand(rsp, (kNumSpillSlots + 1) * kSystemPointerSize)); + __ Move(GCScanSlotPlace, 2); __ Push(wasm_instance); // Spill. __ Push(wasm_instance); // First arg. __ Move(kContextRegister, Smi::zero()); @@ -3841,7 +3853,7 @@ void Builtins::Generate_WasmReturnPromiseOnSuspend(MacroAssembler* masm) { // Epilogue. // ------------------------------------------- __ movq(param_count, MemOperand(rbp, kParamCountOffset)); - __ LeaveFrame(StackFrame::JS_TO_WASM); + __ LeaveFrame(StackFrame::RETURN_PROMISE_ON_SUSPEND); __ DropArguments(param_count, r8, TurboAssembler::kCountIsInteger, TurboAssembler::kCountExcludesReceiver); __ ret(0); diff --git a/src/execution/frame-constants.h b/src/execution/frame-constants.h index d353a7092d..989532d47d 100644 --- a/src/execution/frame-constants.h +++ b/src/execution/frame-constants.h @@ -204,6 +204,14 @@ class BuiltinFrameConstants : public TypedFrameConstants { DEFINE_TYPED_FRAME_SIZES(2); }; +class BuiltinWasmWrapperConstants : public TypedFrameConstants { + public: + // This slot contains the number of slots at the top of the frame that need to + // be scanned by the GC. + static constexpr int kGCScanSlotCountOffset = + kFrameTypeOffset - kSystemPointerSize; +}; + class ConstructFrameConstants : public TypedFrameConstants { public: // FP-relative. diff --git a/src/execution/frames-inl.h b/src/execution/frames-inl.h index ba2a7bce9a..f4b69413aa 100644 --- a/src/execution/frames-inl.h +++ b/src/execution/frames-inl.h @@ -239,6 +239,10 @@ inline WasmToJsFrame::WasmToJsFrame(StackFrameIteratorBase* iterator) inline JsToWasmFrame::JsToWasmFrame(StackFrameIteratorBase* iterator) : StubFrame(iterator) {} +inline ReturnPromiseOnSuspendFrame::ReturnPromiseOnSuspendFrame( + StackFrameIteratorBase* iterator) + : StubFrame(iterator) {} + inline CWasmEntryFrame::CWasmEntryFrame(StackFrameIteratorBase* iterator) : StubFrame(iterator) {} diff --git a/src/execution/frames.cc b/src/execution/frames.cc index 1fc3830dd6..78313cb672 100644 --- a/src/execution/frames.cc +++ b/src/execution/frames.cc @@ -680,6 +680,7 @@ StackFrame::Type StackFrame::ComputeType(const StackFrameIteratorBase* iterator, case WASM_EXIT: case WASM_DEBUG_BREAK: case JS_TO_WASM: + case RETURN_PROMISE_ON_SUSPEND: #endif // V8_ENABLE_WEBASSEMBLY return candidate; case OPTIMIZED: @@ -1036,6 +1037,7 @@ void CommonFrame::IterateCompiledFrame(RootVisitor* v) const { case CONSTRUCT: #if V8_ENABLE_WEBASSEMBLY case JS_TO_WASM: + case RETURN_PROMISE_ON_SUSPEND: case C_WASM_ENTRY: case WASM_DEBUG_BREAK: #endif // V8_ENABLE_WEBASSEMBLY @@ -2084,10 +2086,29 @@ void JsToWasmFrame::Iterate(RootVisitor* v) const { IterateCompiledFrame(v); return; } - // The [fp - 2*kSystemPointerSize] on the stack is a value indicating how - // many values should be scanned from the top. - intptr_t scan_count = - *reinterpret_cast(fp() - 2 * kSystemPointerSize); + // The [fp + BuiltinFrameConstants::kGCScanSlotCount] on the stack is a value + // indicating how many values should be scanned from the top. + intptr_t scan_count = *reinterpret_cast( + fp() + BuiltinWasmWrapperConstants::kGCScanSlotCountOffset); + + FullObjectSlot spill_slot_base(&Memory
(sp())); + FullObjectSlot spill_slot_limit( + &Memory
(sp() + scan_count * kSystemPointerSize)); + v->VisitRootPointers(Root::kStackRoots, nullptr, spill_slot_base, + spill_slot_limit); +} + +void ReturnPromiseOnSuspendFrame::Iterate(RootVisitor* v) const { + // See JsToWasmFrame layout. +#ifdef DEBUG + Code code = GetContainingCode(isolate(), pc()); + DCHECK(code.is_builtin() && + code.builtin_id() == Builtin::kWasmReturnPromiseOnSuspend); +#endif + // The [fp + BuiltinFrameConstants::kGCScanSlotCountOffset] on the stack is a + // value indicating how many values should be scanned from the top. + intptr_t scan_count = *reinterpret_cast( + fp() + BuiltinWasmWrapperConstants::kGCScanSlotCountOffset); FullObjectSlot spill_slot_base(&Memory
(sp())); FullObjectSlot spill_slot_limit( diff --git a/src/execution/frames.h b/src/execution/frames.h index 04979509a2..58554ff2ce 100644 --- a/src/execution/frames.h +++ b/src/execution/frames.h @@ -100,6 +100,7 @@ class StackHandler { IF_WASM(V, WASM, WasmFrame) \ IF_WASM(V, WASM_TO_JS, WasmToJsFrame) \ IF_WASM(V, JS_TO_WASM, JsToWasmFrame) \ + IF_WASM(V, RETURN_PROMISE_ON_SUSPEND, ReturnPromiseOnSuspendFrame) \ IF_WASM(V, WASM_DEBUG_BREAK, WasmDebugBreakFrame) \ IF_WASM(V, C_WASM_ENTRY, CWasmEntryFrame) \ IF_WASM(V, WASM_EXIT, WasmExitFrame) \ @@ -1045,6 +1046,19 @@ class JsToWasmFrame : public StubFrame { friend class StackFrameIteratorBase; }; +class ReturnPromiseOnSuspendFrame : public StubFrame { + public: + Type type() const override { return RETURN_PROMISE_ON_SUSPEND; } + + void Iterate(RootVisitor* v) const override; + + protected: + inline explicit ReturnPromiseOnSuspendFrame(StackFrameIteratorBase* iterator); + + private: + friend class StackFrameIteratorBase; +}; + class CWasmEntryFrame : public StubFrame { public: Type type() const override { return C_WASM_ENTRY; } diff --git a/tools/v8heapconst.py b/tools/v8heapconst.py index d3635a91e7..c4f03285e1 100644 --- a/tools/v8heapconst.py +++ b/tools/v8heapconst.py @@ -542,6 +542,7 @@ FRAME_MARKERS = ( "WASM", "WASM_TO_JS", "JS_TO_WASM", + "RETURN_PROMISE_ON_SUSPEND", "WASM_DEBUG_BREAK", "C_WASM_ENTRY", "WASM_EXIT",