Skip to content

Commit a672d08

Browse files
thibaudmichaudV8 LUCI CQ
authored andcommitted
[wasmfx] Prepare arg buffer for cont.bind
Instead of reserving the arg buffer in the source frame when resuming a continuation, reserve it in the suspended frame when the stack is suspended. This way, the buffer already exists when the continuation is created, and it stays valid until it is resumed, which is just what we need for cont.bind. The cont.bind instruction will fill some slots of this buffer with its arguments, and the resume instruction will fill the remaining slots (if any) and switch to the target stack. Then, the target stack can just unpack the buffer as usual. Instead of allocating a separate buffer in the suspending frame, we reuse the existing argument buffer used to pass the tag parameters. We simply need to ensure that it is big enough to store either the arguments or the return values of the tag. A special case is needed for new continuations since they don't have a frame yet. Instead, the argument buffer is simply reserved below the initial SP. The address of the argument buffer is stored in the StackMemory object so that it can be picked up by the resume instruction. In the future, it will also be used by the cont.bind instruction, and by the GC to visit any potential references. R=clemensb@chromium.org Bug: 388533754 Change-Id: Iabe7ce865a59904160387c517006140e1ff31ded Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/7526772 Commit-Queue: Thibaud Michaud <thibaudm@chromium.org> Reviewed-by: Clemens Backes <clemensb@chromium.org> Cr-Commit-Position: refs/heads/main@{#104983}
1 parent 1164437 commit a672d08

File tree

11 files changed

+75
-49
lines changed

11 files changed

+75
-49
lines changed

src/builtins/arm/builtins-arm.cc

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3374,14 +3374,15 @@ void Builtins::Generate_WasmFXSuspend(MacroAssembler* masm) {
33743374
__ Push(cont, kContextRegister);
33753375
{
33763376
FrameScope scope(masm, StackFrame::MANUAL);
3377-
__ PrepareCallCFunction(6);
3377+
__ PrepareCallCFunction(7);
33783378
__ str(tag, MemOperand(sp, 0)); // arg 4
33793379
__ str(cont, MemOperand(sp, kSystemPointerSize)); // arg 5
3380+
__ str(arg_buffer, MemOperand(sp, 2 * kSystemPointerSize)); // arg 6
33803381
__ Move(kCArgRegs[0], ExternalReference::isolate_address());
33813382
__ Move(kCArgRegs[1], sp);
33823383
__ Move(kCArgRegs[2], fp);
33833384
__ GetLabelAddress(kCArgRegs[3], &resume);
3384-
__ CallCFunction(ExternalReference::wasm_suspend_wasmfx_stack(), 6);
3385+
__ CallCFunction(ExternalReference::wasm_suspend_wasmfx_stack(), 7);
33853386
}
33863387
Register target_stack = r1;
33873388
__ Move(target_stack, kReturnRegister0);

src/builtins/arm64/builtins-arm64.cc

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3928,14 +3928,16 @@ void Builtins::Generate_WasmFXSuspend(MacroAssembler* masm) {
39283928
__ Push(cont, kContextRegister);
39293929
{
39303930
FrameScope scope(masm, StackFrame::MANUAL);
3931-
DCHECK_NE(kCArgRegs[4], cont);
3931+
DCHECK(!AreAliased(kCArgRegs[4], cont, arg_buffer));
3932+
DCHECK(!AreAliased(kCArgRegs[5], arg_buffer));
39323933
__ Mov(kCArgRegs[4], tag);
39333934
__ Mov(kCArgRegs[5], cont);
3935+
__ Mov(kCArgRegs[6], arg_buffer);
39343936
__ Mov(kCArgRegs[0], ExternalReference::isolate_address());
39353937
__ Mov(kCArgRegs[1], sp);
39363938
__ Mov(kCArgRegs[2], fp);
39373939
__ Adr(kCArgRegs[3], &resume);
3938-
__ CallCFunction(ExternalReference::wasm_suspend_wasmfx_stack(), 6);
3940+
__ CallCFunction(ExternalReference::wasm_suspend_wasmfx_stack(), 7);
39393941
}
39403942
Register target_stack = x1;
39413943
__ Move(target_stack, kReturnRegister0);

src/builtins/ia32/builtins-ia32.cc

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3921,16 +3921,17 @@ void Builtins::Generate_WasmFXSuspend(MacroAssembler* masm) {
39213921
__ Push(kContextRegister);
39223922
{
39233923
FrameScope scope(masm, StackFrame::MANUAL);
3924-
__ PrepareCallCFunction(6, edi);
3924+
__ PrepareCallCFunction(7, edi);
39253925
__ Move(Operand(esp, 0 * kSystemPointerSize),
39263926
Immediate(ExternalReference::isolate_address()));
39273927
__ mov(MemOperand(esp, 1 * kSystemPointerSize), esp);
39283928
__ mov(MemOperand(esp, 2 * kSystemPointerSize), ebp);
3929-
__ LoadLabelAddress(ecx, &resume);
3930-
__ mov(MemOperand(esp, 3 * kSystemPointerSize), ecx);
39313929
__ mov(MemOperand(esp, 4 * kSystemPointerSize), tag);
39323930
__ mov(MemOperand(esp, 5 * kSystemPointerSize), cont);
3933-
__ CallCFunction(ExternalReference::wasm_suspend_wasmfx_stack(), 6);
3931+
__ mov(MemOperand(esp, 6 * kSystemPointerSize), arg_buffer);
3932+
__ LoadLabelAddress(ecx, &resume);
3933+
__ mov(MemOperand(esp, 3 * kSystemPointerSize), ecx);
3934+
__ CallCFunction(ExternalReference::wasm_suspend_wasmfx_stack(), 7);
39343935
}
39353936
Register target_stack = edi;
39363937
__ mov(target_stack, kReturnRegister0);

src/builtins/x64/builtins-x64.cc

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4006,20 +4006,22 @@ void Builtins::Generate_WasmFXSuspend(MacroAssembler* masm) {
40064006
__ Push(kContextRegister);
40074007
{
40084008
FrameScope scope(masm, StackFrame::MANUAL);
4009-
__ PrepareCallCFunction(6);
4009+
__ PrepareCallCFunction(7);
40104010
#ifdef V8_TARGET_OS_WIN
40114011
__ movq(MemOperand(rsp, 4 * kSystemPointerSize), tag);
40124012
__ movq(MemOperand(rsp, 5 * kSystemPointerSize), cont);
4013+
__ movq(MemOperand(rsp, 6 * kSystemPointerSize), arg_buffer);
40134014
#else
40144015
DCHECK_NE(kCArgRegs[4], cont);
40154016
__ Move(kCArgRegs[4], tag);
40164017
__ Move(kCArgRegs[5], cont);
4018+
__ movq(MemOperand(rsp, 0), arg_buffer);
40174019
#endif
40184020
__ Move(kCArgRegs[0], ExternalReference::isolate_address());
40194021
__ Move(kCArgRegs[1], rsp);
40204022
__ Move(kCArgRegs[2], rbp);
40214023
__ leaq(kCArgRegs[3], MemOperand(&resume, 0));
4022-
__ CallCFunction(ExternalReference::wasm_suspend_wasmfx_stack(), 6);
4024+
__ CallCFunction(ExternalReference::wasm_suspend_wasmfx_stack(), 7);
40234025
}
40244026
Register target_stack = rbx;
40254027
__ Move(target_stack, kReturnRegister0);

src/runtime/runtime-wasm.cc

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2773,17 +2773,23 @@ RUNTIME_FUNCTION(Runtime_WasmAllocateContinuation) {
27732773
handle(Cast<WasmFuncRef>(args[1]), isolate);
27742774
std::unique_ptr<wasm::StackMemory> stack =
27752775
isolate->stack_pool().GetOrAllocate();
2776+
const wasm::CanonicalSig* sig = func_ref->internal(isolate)->sig();
2777+
auto [arg_buffer_size, alignment] =
2778+
GetBufferSizeAndAlignmentFor(sig->parameters());
2779+
#if V8_TARGET_ARCH_ARM64
2780+
// For stack alignment.
2781+
alignment = RoundUp(alignment, 2 * kSystemPointerSize);
2782+
#endif
27762783
stack->jmpbuf()->fp = kNullAddress;
2777-
stack->jmpbuf()->sp = stack->base();
2784+
stack->jmpbuf()->sp = RoundDown(stack->base() - arg_buffer_size, alignment);
2785+
Address arg_buffer = stack->jmpbuf()->sp;
2786+
stack->set_arg_buffer(arg_buffer);
27782787
stack->jmpbuf()->state = wasm::JumpBuffer::Suspended;
27792788
stack->jmpbuf()->stack_limit = stack->jslimit();
27802789
stack->jmpbuf()->is_on_central_stack = false;
27812790
stack->jmpbuf()->parent = nullptr;
27822791
stack->set_index(isolate->wasm_stacks().size());
27832792
// TODO(thibaudm): Store the WasmCodePointer instead.
2784-
IsolateForSandbox isolate_for_sandbox(isolate);
2785-
const wasm::CanonicalSig* sig =
2786-
func_ref->internal(isolate_for_sandbox)->sig();
27872793
wasm::StackEntryWrapperCacheKey key{sig};
27882794
std::shared_ptr<wasm::WasmWrapperHandle> wrapper =
27892795
wasm::GetWasmStackEntryWrapperCache()->GetCompiled(isolate, key);

src/wasm/stacks.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,7 @@ void StackMemory::Reset() {
196196
clear_stack_switch_info();
197197
current_cont_ = {};
198198
func_ref_ = {};
199+
arg_buffer_ = kNullAddress;
199200
}
200201

201202
bool StackMemory::IsValidContinuation(Tagged<WasmContinuationObject> cont) {

src/wasm/stacks.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
#include <optional>
1313

14+
#include "src/base/functional/function-ref.h"
1415
#include "src/common/globals.h"
1516
#include "src/flags/flags.h"
1617
#include "src/objects/visitors.h"
@@ -214,6 +215,10 @@ class StackMemory {
214215
constexpr static uint32_t current_continuation_offset() {
215216
return OFFSET_OF(StackMemory, current_cont_);
216217
}
218+
constexpr static uint32_t arg_buffer_offset() {
219+
return OFFSET_OF(StackMemory, arg_buffer_);
220+
}
221+
void set_arg_buffer(Address addr) { arg_buffer_ = addr; }
217222
Address central_stack_sp() const { return central_stack_sp_; }
218223
void set_central_stack_sp(Address sp) { central_stack_sp_ = sp; }
219224

@@ -241,6 +246,7 @@ class StackMemory {
241246
StackSegment* active_segment_ = nullptr;
242247
Tagged<WasmContinuationObject> current_cont_ = {};
243248
Tagged<WasmFuncRef> func_ref_ = {};
249+
Address arg_buffer_ = kNullAddress;
244250
// When adding fields here, also check if it needs to be cleared in
245251
// StackMemory::Reset() when the stack is moved to the stack pool after
246252
// retiring.
@@ -279,6 +285,31 @@ class StackPool {
279285
static constexpr int kMaxSize = 4 * MB;
280286
};
281287

288+
using WasmFXArgBufferCallback =
289+
base::FunctionRef<void(size_t value_index, int offset)>;
290+
291+
template <typename T>
292+
int IterateWasmFXArgBuffer(base::Vector<const T> types,
293+
WasmFXArgBufferCallback callback) {
294+
int offset = 0;
295+
for (size_t i = 0; i < types.size(); i++) {
296+
int param_size = types[i].value_kind_full_size();
297+
offset = RoundUp(offset, param_size);
298+
callback(i, offset);
299+
offset += param_size;
300+
}
301+
return offset;
302+
}
303+
304+
template <typename T>
305+
std::pair<int, int> GetBufferSizeAndAlignmentFor(base::Vector<const T> types) {
306+
int alignment = kSystemPointerSize;
307+
int size = IterateWasmFXArgBuffer(types, [&](size_t index, int offset) {
308+
alignment = std::max(alignment, types[index].value_kind_full_size());
309+
});
310+
return {size, alignment};
311+
}
312+
282313
} // namespace v8::internal::wasm
283314

284315
#endif // V8_WASM_STACKS_H_

src/wasm/turboshaft-graph-interface.cc

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3861,8 +3861,9 @@ class TurboshaftGraphBuildingInterface
38613861
// target stack.
38623862
const FunctionSig* sig =
38633863
decoder->module_->signature(imm.cont_type->contfun_typeindex());
3864-
auto [size, alignment] = GetBufferSizeAndAlignmentFor(sig->parameters());
3865-
OpIndex arg_buffer = __ StackSlot(size, alignment);
3864+
V<WordPtr> arg_buffer = __ Load(stack, LoadOp::Kind::RawAligned(),
3865+
MemoryRepresentation::UintPtr(),
3866+
StackMemory::arg_buffer_offset());
38663867
IterateWasmFXArgBuffer(sig->parameters(), [&](size_t index, int offset) {
38673868
DCHECK_EQ(args[index].type, sig->GetParam(index));
38683869
this->Asm().StoreOffHeap(arg_buffer, args[index].op,
@@ -3983,7 +3984,10 @@ class TurboshaftGraphBuildingInterface
39833984
// Reserve a stack buffer, move the tag params there and pass it to the
39843985
// target stack.
39853986
const FunctionSig* sig = imm.tag->sig;
3986-
auto [size, alignment] = GetBufferSizeAndAlignmentFor(sig->parameters());
3987+
auto [arg_size, arg_alignment] =
3988+
GetBufferSizeAndAlignmentFor(sig->parameters());
3989+
auto [return_size, return_alignment] =
3990+
GetBufferSizeAndAlignmentFor(sig->returns());
39873991
V<FixedArray> instance_tags =
39883992
LOAD_IMMUTABLE_INSTANCE_FIELD(trusted_instance_data(false), TagsTable,
39893993
MemoryRepresentation::TaggedPointer());
@@ -3992,16 +3996,17 @@ class TurboshaftGraphBuildingInterface
39923996
V<WasmContinuationObject> cont = __ WasmCallRuntime(
39933997
decoder->zone(), Runtime::kWasmAllocateEmptyContinuation, {},
39943998
native_context);
3995-
OpIndex arg_buffer = __ StackSlot(size, alignment);
3999+
OpIndex arg_buffer =
4000+
__ StackSlot(std::max(arg_size, return_size),
4001+
std::max(arg_alignment, return_alignment));
39964002
IterateWasmFXArgBuffer(sig->parameters(), [&](size_t index, int offset) {
39974003
DCHECK_EQ(args[index].type, sig->GetParam(index));
39984004
__ StoreOffHeap(arg_buffer, args[index].op,
39994005
MemoryRepresentationFor(args[index].type), offset);
40004006
});
4001-
arg_buffer =
4002-
CallBuiltinThroughJumptable<BuiltinCallDescriptor::WasmFXSuspend>(
4003-
decoder, native_context, {wanted_tag, cont, arg_buffer},
4004-
CheckForException::kCatchInThisFrame);
4007+
CallBuiltinThroughJumptable<BuiltinCallDescriptor::WasmFXSuspend>(
4008+
decoder, native_context, {wanted_tag, cont, arg_buffer},
4009+
CheckForException::kCatchInThisFrame);
40054010

40064011
// Unpack tag returns.
40074012
IterateWasmFXArgBuffer(sig->returns(), [&](size_t index, int offset) {

src/wasm/turboshaft-graph-interface.h

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -133,31 +133,6 @@ class V8_EXPORT_PRIVATE WasmGraphBuilderBase {
133133
Assembler& asm_;
134134
};
135135

136-
using WasmFXArgBufferCallback =
137-
base::FunctionRef<void(size_t value_index, int offset)>;
138-
139-
template <typename T>
140-
int IterateWasmFXArgBuffer(base::Vector<const T> types,
141-
WasmFXArgBufferCallback callback) {
142-
int offset = 0;
143-
for (size_t i = 0; i < types.size(); i++) {
144-
int param_size = types[i].value_kind_full_size();
145-
offset = RoundUp(offset, param_size);
146-
callback(i, offset);
147-
offset += param_size;
148-
}
149-
return offset;
150-
}
151-
152-
template <typename T>
153-
std::pair<int, int> GetBufferSizeAndAlignmentFor(base::Vector<const T> types) {
154-
int alignment = kSystemPointerSize;
155-
int size = IterateWasmFXArgBuffer(types, [&](size_t index, int offset) {
156-
alignment = std::max(alignment, types[index].value_kind_full_size());
157-
});
158-
return {size, alignment};
159-
}
160-
161136
} // namespace wasm
162137
} // namespace v8::internal
163138

src/wasm/wasm-external-refs.cc

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1013,12 +1013,14 @@ void resume_wasmfx_stack(Isolate* isolate, wasm::StackMemory* to, Address sp,
10131013

10141014
Address suspend_wasmfx_stack(Isolate* isolate, Address sp, Address fp,
10151015
Address pc, Address wanted_tag_raw,
1016-
Address cont_raw) {
1016+
Address cont_raw, Address arg_buffer) {
10171017
Tagged<Object> tag_obj(wanted_tag_raw);
10181018
auto wanted_tag = TrustedCast<WasmExceptionTag>(tag_obj);
10191019
Tagged<Object> cont_obj(cont_raw);
10201020
auto cont = TrustedCast<WasmContinuationObject>(cont_obj);
10211021
wasm::StackMemory* from = isolate->isolate_data()->active_stack();
1022+
DCHECK(from->Contains(arg_buffer));
1023+
from->set_arg_buffer(arg_buffer);
10221024
cont->set_stack(isolate, from);
10231025
from->set_current_continuation(cont);
10241026
wasm::StackMemory* to = from->jmpbuf()->parent;

0 commit comments

Comments
 (0)