[wasm] Update suspender's parent on resume
Only the parent of the continuation itself was updated. Also update the parent of the suspender R=ahaas@chromium.org Bug: v8:12191 Change-Id: I06684548abe70f4bbda48c12e9e8adda84e1ec27 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3726293 Reviewed-by: Andreas Haas <ahaas@chromium.org> Commit-Queue: Thibaud Michaud <thibaudm@chromium.org> Cr-Commit-Position: refs/heads/main@{#81419}
This commit is contained in:
parent
80575e2816
commit
5ef3bb9b58
@ -4157,7 +4157,9 @@ void Generate_WasmResumeHelper(MacroAssembler* masm, wasm::OnResume on_resume) {
|
||||
__ LoadAnyTaggedField(
|
||||
function_data,
|
||||
FieldOperand(sfi, SharedFunctionInfo::kFunctionDataOffset));
|
||||
Register suspender = rax;
|
||||
// The write barrier uses a fixed register for the host object (rdi). The next
|
||||
// barrier is on the suspender, so load it in rdi directly.
|
||||
Register suspender = rdi;
|
||||
__ LoadAnyTaggedField(
|
||||
suspender, FieldOperand(function_data, WasmResumeData::kSuspenderOffset));
|
||||
// Check the suspender state.
|
||||
@ -4178,7 +4180,7 @@ void Generate_WasmResumeHelper(MacroAssembler* masm, wasm::OnResume on_resume) {
|
||||
Label suspend;
|
||||
Register active_continuation = r9;
|
||||
__ LoadRoot(active_continuation, RootIndex::kActiveContinuation);
|
||||
Register current_jmpbuf = rdi;
|
||||
Register current_jmpbuf = rax;
|
||||
__ LoadAnyTaggedField(
|
||||
current_jmpbuf,
|
||||
FieldOperand(active_continuation, WasmContinuationObject::kJmpbufOffset));
|
||||
@ -4190,16 +4192,28 @@ void Generate_WasmResumeHelper(MacroAssembler* masm, wasm::OnResume on_resume) {
|
||||
current_jmpbuf = no_reg;
|
||||
|
||||
// -------------------------------------------
|
||||
// Set suspender's parent to active continuation.
|
||||
// Set the suspender and continuation parents and update the roots
|
||||
// -------------------------------------------
|
||||
Register active_suspender = rcx;
|
||||
Register slot_address = WriteBarrierDescriptor::SlotAddressRegister();
|
||||
// Check that the fixed register isn't one that is already in use.
|
||||
DCHECK(slot_address == rbx || slot_address == r8);
|
||||
__ LoadRoot(active_suspender, RootIndex::kActiveSuspender);
|
||||
__ StoreTaggedField(
|
||||
FieldOperand(suspender, WasmSuspenderObject::kParentOffset),
|
||||
active_suspender);
|
||||
__ RecordWriteField(suspender, WasmSuspenderObject::kParentOffset,
|
||||
active_suspender, slot_address, SaveFPRegsMode::kIgnore);
|
||||
__ StoreTaggedSignedField(
|
||||
FieldOperand(suspender, WasmSuspenderObject::kStateOffset),
|
||||
Smi::FromInt(WasmSuspenderObject::kActive));
|
||||
Register target_continuation = rdi;
|
||||
__ movq(masm->RootAsOperand(RootIndex::kActiveSuspender), suspender);
|
||||
|
||||
Register target_continuation = suspender;
|
||||
__ LoadAnyTaggedField(
|
||||
target_continuation,
|
||||
FieldOperand(suspender, WasmSuspenderObject::kContinuationOffset));
|
||||
Register slot_address = WriteBarrierDescriptor::SlotAddressRegister();
|
||||
suspender = no_reg;
|
||||
__ StoreTaggedField(
|
||||
FieldOperand(target_continuation, WasmContinuationObject::kParentOffset),
|
||||
active_continuation);
|
||||
@ -4207,14 +4221,8 @@ void Generate_WasmResumeHelper(MacroAssembler* masm, wasm::OnResume on_resume) {
|
||||
target_continuation, WasmContinuationObject::kParentOffset,
|
||||
active_continuation, slot_address, SaveFPRegsMode::kIgnore);
|
||||
active_continuation = no_reg;
|
||||
|
||||
// -------------------------------------------
|
||||
// Update roots.
|
||||
// -------------------------------------------
|
||||
__ movq(masm->RootAsOperand(RootIndex::kActiveContinuation),
|
||||
target_continuation);
|
||||
__ movq(masm->RootAsOperand(RootIndex::kActiveSuspender), suspender);
|
||||
suspender = no_reg;
|
||||
|
||||
MemOperand GCScanSlotPlace =
|
||||
MemOperand(rbp, BuiltinWasmWrapperConstants::kGCScanSlotCountOffset);
|
||||
@ -4227,7 +4235,7 @@ void Generate_WasmResumeHelper(MacroAssembler* masm, wasm::OnResume on_resume) {
|
||||
// -------------------------------------------
|
||||
// Load state from target jmpbuf (longjmp).
|
||||
// -------------------------------------------
|
||||
Register target_jmpbuf = target_continuation;
|
||||
Register target_jmpbuf = rdi;
|
||||
__ LoadAnyTaggedField(
|
||||
target_jmpbuf,
|
||||
FieldOperand(target_continuation, WasmContinuationObject::kJmpbufOffset));
|
||||
|
@ -364,3 +364,43 @@ load("test/mjsunit/wasm/wasm-module-builder.js");
|
||||
assertThrows(wrapped_export, WebAssembly.RuntimeError,
|
||||
/re-entering an active\/suspended suspender/);
|
||||
})();
|
||||
|
||||
(function TestNestedSuspenders() {
|
||||
// Nest two suspenders. The call chain looks like:
|
||||
// outer (wasm) -> outer (js) -> inner (wasm) -> inner (js)
|
||||
// The inner JS function returns a Promise, which suspends the inner wasm
|
||||
// function, which returns a Promise, which suspends the outer wasm function,
|
||||
// which returns a Promise. The inner Promise resolves first, which resumes
|
||||
// the inner continuation. Then the outer promise resolves which resumes the
|
||||
// outer continuation.
|
||||
print(arguments.callee.name);
|
||||
let builder = new WasmModuleBuilder();
|
||||
inner_index = builder.addImport('m', 'inner', kSig_i_v);
|
||||
outer_index = builder.addImport('m', 'outer', kSig_i_v);
|
||||
builder.addFunction("outer", kSig_i_v)
|
||||
.addBody([
|
||||
kExprCallFunction, outer_index
|
||||
]).exportFunc();
|
||||
builder.addFunction("inner", kSig_i_v)
|
||||
.addBody([
|
||||
kExprCallFunction, inner_index
|
||||
]).exportFunc();
|
||||
let outer_suspender = new WebAssembly.Suspender();
|
||||
let inner_suspender = new WebAssembly.Suspender();
|
||||
|
||||
let inner = inner_suspender.suspendOnReturnedPromise(
|
||||
new WebAssembly.Function(
|
||||
{parameters: [], results: ['externref']},
|
||||
() => Promise.resolve(42)));
|
||||
|
||||
let export_inner;
|
||||
let outer = outer_suspender.suspendOnReturnedPromise(
|
||||
new WebAssembly.Function(
|
||||
{parameters: [], results: ['externref']},
|
||||
() => export_inner()));
|
||||
|
||||
let instance = builder.instantiate({m: {inner, outer}});
|
||||
export_inner = inner_suspender.returnPromiseOnSuspend(instance.exports.inner);
|
||||
let export_outer = outer_suspender.returnPromiseOnSuspend(instance.exports.outer);
|
||||
assertPromiseResult(export_outer(), v => assertEquals(42, v));
|
||||
})();
|
||||
|
Loading…
Reference in New Issue
Block a user