Commit f4d265b0 authored by Thibaud Michaud's avatar Thibaud Michaud Committed by V8 LUCI CQ

[wasm] Make ActiveContinuation a root

Switching stack affects all instances, therefore make the active
continuation a root object instead of an instance field.

Bug: v8:12191
Change-Id: Ia521bf4e7c3cbca035f916e47804c2f75bbd8f18
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3268296Reviewed-by: 's avatarAndreas Haas <ahaas@chromium.org>
Reviewed-by: 's avatarMichael Lippautz <mlippautz@chromium.org>
Reviewed-by: 's avatarJakob Kummerow <jkummerow@chromium.org>
Commit-Queue: Thibaud Michaud <thibaudm@chromium.org>
Cr-Commit-Position: refs/heads/main@{#77876}
parent 18311df3
......@@ -3696,10 +3696,7 @@ void Builtins::Generate_WasmReturnPromiseOnSuspend(MacroAssembler* masm) {
// -------------------------------------------
Register active_continuation = rax;
Register foreign_jmpbuf = rbx;
__ LoadAnyTaggedField(
active_continuation,
FieldOperand(wasm_instance,
WasmInstanceObject::kActiveContinuationOffset));
__ LoadRoot(active_continuation, RootIndex::kActiveContinuation);
__ LoadAnyTaggedField(
foreign_jmpbuf,
FieldOperand(active_continuation, WasmContinuationObject::kJmpbufOffset));
......@@ -3726,10 +3723,9 @@ void Builtins::Generate_WasmReturnPromiseOnSuspend(MacroAssembler* masm) {
// -------------------------------------------
MemOperand GCScanSlotPlace =
MemOperand(rbp, BuiltinWasmWrapperConstants::kGCScanSlotCountOffset);
__ Move(GCScanSlotPlace, 3);
__ Move(GCScanSlotPlace, 2);
__ Push(wasm_instance);
__ Push(function_data);
__ Push(wasm_instance);
__ Move(kContextRegister, Smi::zero());
__ CallRuntime(Runtime::kWasmAllocateContinuation);
__ Pop(function_data);
......@@ -3753,10 +3749,9 @@ 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);
__ Move(GCScanSlotPlace, 2);
__ Push(wasm_instance);
__ Push(function_data);
__ Push(wasm_instance);
__ Move(kContextRegister, Smi::zero());
__ CallRuntime(Runtime::kWasmSyncStackLimit);
__ Pop(function_data);
......@@ -3799,10 +3794,7 @@ void Builtins::Generate_WasmReturnPromiseOnSuspend(MacroAssembler* masm) {
// Reload parent continuation.
// -------------------------------------------
active_continuation = rbx;
__ LoadAnyTaggedField(
active_continuation,
FieldOperand(wasm_instance,
WasmInstanceObject::kActiveContinuationOffset));
__ LoadRoot(active_continuation, RootIndex::kActiveContinuation);
Register parent = rdx;
__ LoadAnyTaggedField(
parent,
......@@ -3813,20 +3805,7 @@ void Builtins::Generate_WasmReturnPromiseOnSuspend(MacroAssembler* masm) {
// -------------------------------------------
// Update instance active continuation.
// -------------------------------------------
Register object = WriteBarrierDescriptor::ObjectRegister();
Register slot_address = WriteBarrierDescriptor::SlotAddressRegister();
DCHECK_EQ(object, rdi);
DCHECK((slot_address == rbx || slot_address == r8));
// Save reg clobbered by the write barrier.
__ movq(rax, parent);
__ movq(object, wasm_instance);
__ StoreTaggedField(
FieldOperand(object, WasmInstanceObject::kActiveContinuationOffset),
parent);
__ RecordWriteField(object, WasmInstanceObject::kActiveContinuationOffset,
parent, slot_address, SaveFPRegsMode::kIgnore);
// Restore reg clobbered by the write barrier.
__ movq(parent, rax);
__ movq(masm->RootAsOperand(RootIndex::kActiveContinuation), parent);
foreign_jmpbuf = rax;
__ LoadAnyTaggedField(
foreign_jmpbuf,
......@@ -3838,9 +3817,8 @@ void Builtins::Generate_WasmReturnPromiseOnSuspend(MacroAssembler* masm) {
// Switch stack!
LoadJumpBuffer(masm, jmpbuf);
__ leaq(rbp, Operand(rsp, (kNumSpillSlots + 1) * kSystemPointerSize));
__ Move(GCScanSlotPlace, 2);
__ Move(GCScanSlotPlace, 1);
__ Push(wasm_instance); // Spill.
__ Push(wasm_instance); // First arg.
__ Move(kContextRegister, Smi::zero());
__ CallRuntime(Runtime::kWasmSyncStackLimit);
__ Pop(wasm_instance);
......
......@@ -804,6 +804,9 @@ void Heap::CreateInitialObjects() {
set_feedback_vectors_for_profiling_tools(roots.undefined_value());
set_pending_optimize_for_test_bytecode(roots.undefined_value());
set_shared_wasm_memories(roots.empty_weak_array_list());
#ifdef V8_ENABLE_WEBASSEMBLY
set_active_continuation(roots.undefined_value());
#endif // V8_ENABLE_WEBASSEMBLY
set_script_list(roots.empty_weak_array_list());
......
......@@ -310,7 +310,8 @@ class Symbol;
V(Object, pending_optimize_for_test_bytecode, \
PendingOptimizeForTestBytecode) \
V(ArrayList, basic_block_profiling_data, BasicBlockProfilingData) \
V(WeakArrayList, shared_wasm_memories, SharedWasmMemories)
V(WeakArrayList, shared_wasm_memories, SharedWasmMemories) \
IF_WASM(V, HeapObject, active_continuation, ActiveContinuation)
// Entries in this list are limited to Smis and are not visited during GC.
#define SMI_ROOT_LIST(V) \
......
......@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "src/base/memory.h"
#include "src/common/assert-scope.h"
#include "src/common/message-template.h"
#include "src/compiler/wasm-compiler.h"
#include "src/debug/debug.h"
......@@ -705,10 +706,12 @@ namespace {
// contains a sentinel value, and it is also thread-safe. So if an interrupt is
// requested before, during or after this call, it will be preserved and handled
// at the next stack check.
void SyncStackLimit(Isolate* isolate, Handle<WasmInstanceObject> instance) {
auto jmpbuf = Managed<wasm::JumpBuffer>::cast(
instance->active_continuation().managed_jmpbuf())
.get();
void SyncStackLimit(Isolate* isolate) {
DisallowGarbageCollection no_gc;
auto continuation = WasmContinuationObject::cast(
*isolate->roots_table().slot(RootIndex::kActiveContinuation));
auto jmpbuf =
Managed<wasm::JumpBuffer>::cast(continuation.managed_jmpbuf()).get();
uintptr_t limit = reinterpret_cast<uintptr_t>(jmpbuf->stack_limit);
isolate->stack_guard()->SetStackLimit(limit);
}
......@@ -718,22 +721,21 @@ void SyncStackLimit(Isolate* isolate, Handle<WasmInstanceObject> instance) {
// active continuation and setting the stack limit.
RUNTIME_FUNCTION(Runtime_WasmAllocateContinuation) {
CHECK(FLAG_experimental_wasm_stack_switching);
DCHECK_EQ(1, args.length());
HandleScope scope(isolate);
CONVERT_ARG_HANDLE_CHECKED(WasmInstanceObject, instance, 0);
auto parent = instance->active_continuation();
auto target = WasmContinuationObject::New(isolate, parent);
instance->set_active_continuation(*target);
SyncStackLimit(isolate, instance);
auto parent =
handle(WasmContinuationObject::cast(
*isolate->roots_table().slot(RootIndex::kActiveContinuation)),
isolate);
auto target = WasmContinuationObject::New(isolate, *parent);
isolate->roots_table().slot(RootIndex::kActiveContinuation).store(*target);
SyncStackLimit(isolate);
return *target;
}
// Update the stack limit after a stack switch, and preserve pending interrupts.
RUNTIME_FUNCTION(Runtime_WasmSyncStackLimit) {
CHECK(FLAG_experimental_wasm_stack_switching);
HandleScope scope(isolate);
CONVERT_ARG_HANDLE_CHECKED(WasmInstanceObject, instance, 0);
SyncStackLimit(isolate, instance);
SyncStackLimit(isolate);
return ReadOnlyRoots(isolate).undefined_value();
}
......
......@@ -593,8 +593,8 @@ namespace internal {
F(WasmDebugBreak, 0, 1) \
F(WasmAllocateRtt, 3, 1) \
F(WasmArrayCopy, 5, 1) \
F(WasmAllocateContinuation, 1, 1) \
F(WasmSyncStackLimit, 1, 1)
F(WasmAllocateContinuation, 0, 1) \
F(WasmSyncStackLimit, 0, 1)
#define FOR_EACH_INTRINSIC_WASM_TEST(F, I) \
F(DeserializeWasmModule, 2, 1) \
......
......@@ -2830,6 +2830,13 @@ void WasmJs::Install(Isolate* isolate, bool exposed_on_global_object) {
WasmSuspenderObject::kHeaderSize, "WebAssembly.Suspender");
InstallFunc(isolate, suspender_proto, "returnPromiseOnSuspend",
WebAssemblySuspenderReturnPromiseOnSuspend, 1);
std::unique_ptr<wasm::StackMemory> stack(
wasm::StackMemory::GetCurrentStackView(isolate));
auto continuation = WasmContinuationObject::New(isolate, std::move(stack));
isolate->heap()
->roots_table()
.slot(RootIndex::kActiveContinuation)
.store(*continuation);
}
// Setup Function
......
......@@ -227,8 +227,6 @@ PRIMITIVE_ACCESSORS(WasmInstanceObject, hook_on_function_call_address, Address,
kHookOnFunctionCallAddressOffset)
PRIMITIVE_ACCESSORS(WasmInstanceObject, num_liftoff_function_calls_array,
uint32_t*, kNumLiftoffFunctionCallsArrayOffset)
ACCESSORS(WasmInstanceObject, active_continuation, WasmContinuationObject,
kActiveContinuationOffset)
PRIMITIVE_ACCESSORS(WasmInstanceObject, break_on_entry, uint8_t,
kBreakOnEntryOffset)
......
......@@ -1208,15 +1208,6 @@ Handle<WasmInstanceObject> WasmInstanceObject::New(
module_object->native_module()->num_liftoff_function_calls_array());
instance->set_break_on_entry(module_object->script().break_on_entry());
if (FLAG_experimental_wasm_stack_switching) {
// TODO(thibaudm): If there is already a continuation object for the current
// execution context, re-use that instead of creating a new one.
std::unique_ptr<wasm::StackMemory> stack(
wasm::StackMemory::GetCurrentStackView(isolate));
auto continuation = WasmContinuationObject::New(isolate, std::move(stack));
instance->set_active_continuation(*continuation);
}
// Insert the new instance into the scripts weak list of instances. This list
// is used for breakpoints affecting all instances belonging to the script.
if (module_object->script().type() == Script::TYPE_WASM) {
......
......@@ -353,7 +353,6 @@ class V8_EXPORT_PRIVATE WasmInstanceObject : public JSObject {
DECL_PRIMITIVE_ACCESSORS(dropped_elem_segments, byte*)
DECL_PRIMITIVE_ACCESSORS(hook_on_function_call_address, Address)
DECL_PRIMITIVE_ACCESSORS(num_liftoff_function_calls_array, uint32_t*)
DECL_ACCESSORS(active_continuation, WasmContinuationObject)
DECL_PRIMITIVE_ACCESSORS(break_on_entry, uint8_t)
// Clear uninitialized padding space. This ensures that the snapshot content
......@@ -410,7 +409,6 @@ class V8_EXPORT_PRIVATE WasmInstanceObject : public JSObject {
V(kWasmExternalFunctionsOffset, kTaggedSize) \
V(kManagedObjectMapsOffset, kTaggedSize) \
V(kFeedbackVectorsOffset, kTaggedSize) \
V(kActiveContinuationOffset, kTaggedSize) \
V(kBreakOnEntryOffset, kUInt8Size) \
/* More padding to make the header pointer-size aligned */ \
V(kHeaderPaddingOffset, POINTER_SIZE_PADDING(kHeaderPaddingOffset)) \
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment