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) { ...@@ -3696,10 +3696,7 @@ void Builtins::Generate_WasmReturnPromiseOnSuspend(MacroAssembler* masm) {
// ------------------------------------------- // -------------------------------------------
Register active_continuation = rax; Register active_continuation = rax;
Register foreign_jmpbuf = rbx; Register foreign_jmpbuf = rbx;
__ LoadAnyTaggedField( __ LoadRoot(active_continuation, RootIndex::kActiveContinuation);
active_continuation,
FieldOperand(wasm_instance,
WasmInstanceObject::kActiveContinuationOffset));
__ LoadAnyTaggedField( __ LoadAnyTaggedField(
foreign_jmpbuf, foreign_jmpbuf,
FieldOperand(active_continuation, WasmContinuationObject::kJmpbufOffset)); FieldOperand(active_continuation, WasmContinuationObject::kJmpbufOffset));
...@@ -3726,10 +3723,9 @@ void Builtins::Generate_WasmReturnPromiseOnSuspend(MacroAssembler* masm) { ...@@ -3726,10 +3723,9 @@ void Builtins::Generate_WasmReturnPromiseOnSuspend(MacroAssembler* masm) {
// ------------------------------------------- // -------------------------------------------
MemOperand GCScanSlotPlace = MemOperand GCScanSlotPlace =
MemOperand(rbp, BuiltinWasmWrapperConstants::kGCScanSlotCountOffset); MemOperand(rbp, BuiltinWasmWrapperConstants::kGCScanSlotCountOffset);
__ Move(GCScanSlotPlace, 3); __ Move(GCScanSlotPlace, 2);
__ Push(wasm_instance); __ Push(wasm_instance);
__ Push(function_data); __ Push(function_data);
__ Push(wasm_instance);
__ Move(kContextRegister, Smi::zero()); __ Move(kContextRegister, Smi::zero());
__ CallRuntime(Runtime::kWasmAllocateContinuation); __ CallRuntime(Runtime::kWasmAllocateContinuation);
__ Pop(function_data); __ Pop(function_data);
...@@ -3753,10 +3749,9 @@ void Builtins::Generate_WasmReturnPromiseOnSuspend(MacroAssembler* masm) { ...@@ -3753,10 +3749,9 @@ void Builtins::Generate_WasmReturnPromiseOnSuspend(MacroAssembler* masm) {
// Switch stack! // Switch stack!
LoadJumpBuffer(masm, target_jmpbuf); LoadJumpBuffer(masm, target_jmpbuf);
__ movq(rbp, rsp); // New stack, there is no frame yet. __ movq(rbp, rsp); // New stack, there is no frame yet.
__ Move(GCScanSlotPlace, 3); __ Move(GCScanSlotPlace, 2);
__ Push(wasm_instance); __ Push(wasm_instance);
__ Push(function_data); __ Push(function_data);
__ Push(wasm_instance);
__ Move(kContextRegister, Smi::zero()); __ Move(kContextRegister, Smi::zero());
__ CallRuntime(Runtime::kWasmSyncStackLimit); __ CallRuntime(Runtime::kWasmSyncStackLimit);
__ Pop(function_data); __ Pop(function_data);
...@@ -3799,10 +3794,7 @@ void Builtins::Generate_WasmReturnPromiseOnSuspend(MacroAssembler* masm) { ...@@ -3799,10 +3794,7 @@ void Builtins::Generate_WasmReturnPromiseOnSuspend(MacroAssembler* masm) {
// Reload parent continuation. // Reload parent continuation.
// ------------------------------------------- // -------------------------------------------
active_continuation = rbx; active_continuation = rbx;
__ LoadAnyTaggedField( __ LoadRoot(active_continuation, RootIndex::kActiveContinuation);
active_continuation,
FieldOperand(wasm_instance,
WasmInstanceObject::kActiveContinuationOffset));
Register parent = rdx; Register parent = rdx;
__ LoadAnyTaggedField( __ LoadAnyTaggedField(
parent, parent,
...@@ -3813,20 +3805,7 @@ void Builtins::Generate_WasmReturnPromiseOnSuspend(MacroAssembler* masm) { ...@@ -3813,20 +3805,7 @@ void Builtins::Generate_WasmReturnPromiseOnSuspend(MacroAssembler* masm) {
// ------------------------------------------- // -------------------------------------------
// Update instance active continuation. // Update instance active continuation.
// ------------------------------------------- // -------------------------------------------
Register object = WriteBarrierDescriptor::ObjectRegister(); __ movq(masm->RootAsOperand(RootIndex::kActiveContinuation), parent);
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);
foreign_jmpbuf = rax; foreign_jmpbuf = rax;
__ LoadAnyTaggedField( __ LoadAnyTaggedField(
foreign_jmpbuf, foreign_jmpbuf,
...@@ -3838,9 +3817,8 @@ void Builtins::Generate_WasmReturnPromiseOnSuspend(MacroAssembler* masm) { ...@@ -3838,9 +3817,8 @@ void Builtins::Generate_WasmReturnPromiseOnSuspend(MacroAssembler* masm) {
// Switch stack! // Switch stack!
LoadJumpBuffer(masm, jmpbuf); LoadJumpBuffer(masm, jmpbuf);
__ leaq(rbp, Operand(rsp, (kNumSpillSlots + 1) * kSystemPointerSize)); __ leaq(rbp, Operand(rsp, (kNumSpillSlots + 1) * kSystemPointerSize));
__ Move(GCScanSlotPlace, 2); __ Move(GCScanSlotPlace, 1);
__ Push(wasm_instance); // Spill. __ Push(wasm_instance); // Spill.
__ Push(wasm_instance); // First arg.
__ Move(kContextRegister, Smi::zero()); __ Move(kContextRegister, Smi::zero());
__ CallRuntime(Runtime::kWasmSyncStackLimit); __ CallRuntime(Runtime::kWasmSyncStackLimit);
__ Pop(wasm_instance); __ Pop(wasm_instance);
......
...@@ -804,6 +804,9 @@ void Heap::CreateInitialObjects() { ...@@ -804,6 +804,9 @@ void Heap::CreateInitialObjects() {
set_feedback_vectors_for_profiling_tools(roots.undefined_value()); set_feedback_vectors_for_profiling_tools(roots.undefined_value());
set_pending_optimize_for_test_bytecode(roots.undefined_value()); set_pending_optimize_for_test_bytecode(roots.undefined_value());
set_shared_wasm_memories(roots.empty_weak_array_list()); 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()); set_script_list(roots.empty_weak_array_list());
......
...@@ -310,7 +310,8 @@ class Symbol; ...@@ -310,7 +310,8 @@ class Symbol;
V(Object, pending_optimize_for_test_bytecode, \ V(Object, pending_optimize_for_test_bytecode, \
PendingOptimizeForTestBytecode) \ PendingOptimizeForTestBytecode) \
V(ArrayList, basic_block_profiling_data, BasicBlockProfilingData) \ 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. // Entries in this list are limited to Smis and are not visited during GC.
#define SMI_ROOT_LIST(V) \ #define SMI_ROOT_LIST(V) \
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
// found in the LICENSE file. // found in the LICENSE file.
#include "src/base/memory.h" #include "src/base/memory.h"
#include "src/common/assert-scope.h"
#include "src/common/message-template.h" #include "src/common/message-template.h"
#include "src/compiler/wasm-compiler.h" #include "src/compiler/wasm-compiler.h"
#include "src/debug/debug.h" #include "src/debug/debug.h"
...@@ -705,10 +706,12 @@ namespace { ...@@ -705,10 +706,12 @@ namespace {
// contains a sentinel value, and it is also thread-safe. So if an interrupt is // 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 // requested before, during or after this call, it will be preserved and handled
// at the next stack check. // at the next stack check.
void SyncStackLimit(Isolate* isolate, Handle<WasmInstanceObject> instance) { void SyncStackLimit(Isolate* isolate) {
auto jmpbuf = Managed<wasm::JumpBuffer>::cast( DisallowGarbageCollection no_gc;
instance->active_continuation().managed_jmpbuf()) auto continuation = WasmContinuationObject::cast(
.get(); *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); uintptr_t limit = reinterpret_cast<uintptr_t>(jmpbuf->stack_limit);
isolate->stack_guard()->SetStackLimit(limit); isolate->stack_guard()->SetStackLimit(limit);
} }
...@@ -718,22 +721,21 @@ void SyncStackLimit(Isolate* isolate, Handle<WasmInstanceObject> instance) { ...@@ -718,22 +721,21 @@ void SyncStackLimit(Isolate* isolate, Handle<WasmInstanceObject> instance) {
// active continuation and setting the stack limit. // active continuation and setting the stack limit.
RUNTIME_FUNCTION(Runtime_WasmAllocateContinuation) { RUNTIME_FUNCTION(Runtime_WasmAllocateContinuation) {
CHECK(FLAG_experimental_wasm_stack_switching); CHECK(FLAG_experimental_wasm_stack_switching);
DCHECK_EQ(1, args.length());
HandleScope scope(isolate); HandleScope scope(isolate);
CONVERT_ARG_HANDLE_CHECKED(WasmInstanceObject, instance, 0); auto parent =
auto parent = instance->active_continuation(); handle(WasmContinuationObject::cast(
auto target = WasmContinuationObject::New(isolate, parent); *isolate->roots_table().slot(RootIndex::kActiveContinuation)),
instance->set_active_continuation(*target); isolate);
SyncStackLimit(isolate, instance); auto target = WasmContinuationObject::New(isolate, *parent);
isolate->roots_table().slot(RootIndex::kActiveContinuation).store(*target);
SyncStackLimit(isolate);
return *target; return *target;
} }
// Update the stack limit after a stack switch, and preserve pending interrupts. // Update the stack limit after a stack switch, and preserve pending interrupts.
RUNTIME_FUNCTION(Runtime_WasmSyncStackLimit) { RUNTIME_FUNCTION(Runtime_WasmSyncStackLimit) {
CHECK(FLAG_experimental_wasm_stack_switching); CHECK(FLAG_experimental_wasm_stack_switching);
HandleScope scope(isolate); SyncStackLimit(isolate);
CONVERT_ARG_HANDLE_CHECKED(WasmInstanceObject, instance, 0);
SyncStackLimit(isolate, instance);
return ReadOnlyRoots(isolate).undefined_value(); return ReadOnlyRoots(isolate).undefined_value();
} }
......
...@@ -593,8 +593,8 @@ namespace internal { ...@@ -593,8 +593,8 @@ namespace internal {
F(WasmDebugBreak, 0, 1) \ F(WasmDebugBreak, 0, 1) \
F(WasmAllocateRtt, 3, 1) \ F(WasmAllocateRtt, 3, 1) \
F(WasmArrayCopy, 5, 1) \ F(WasmArrayCopy, 5, 1) \
F(WasmAllocateContinuation, 1, 1) \ F(WasmAllocateContinuation, 0, 1) \
F(WasmSyncStackLimit, 1, 1) F(WasmSyncStackLimit, 0, 1)
#define FOR_EACH_INTRINSIC_WASM_TEST(F, I) \ #define FOR_EACH_INTRINSIC_WASM_TEST(F, I) \
F(DeserializeWasmModule, 2, 1) \ F(DeserializeWasmModule, 2, 1) \
......
...@@ -2830,6 +2830,13 @@ void WasmJs::Install(Isolate* isolate, bool exposed_on_global_object) { ...@@ -2830,6 +2830,13 @@ void WasmJs::Install(Isolate* isolate, bool exposed_on_global_object) {
WasmSuspenderObject::kHeaderSize, "WebAssembly.Suspender"); WasmSuspenderObject::kHeaderSize, "WebAssembly.Suspender");
InstallFunc(isolate, suspender_proto, "returnPromiseOnSuspend", InstallFunc(isolate, suspender_proto, "returnPromiseOnSuspend",
WebAssemblySuspenderReturnPromiseOnSuspend, 1); 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 // Setup Function
......
...@@ -227,8 +227,6 @@ PRIMITIVE_ACCESSORS(WasmInstanceObject, hook_on_function_call_address, Address, ...@@ -227,8 +227,6 @@ PRIMITIVE_ACCESSORS(WasmInstanceObject, hook_on_function_call_address, Address,
kHookOnFunctionCallAddressOffset) kHookOnFunctionCallAddressOffset)
PRIMITIVE_ACCESSORS(WasmInstanceObject, num_liftoff_function_calls_array, PRIMITIVE_ACCESSORS(WasmInstanceObject, num_liftoff_function_calls_array,
uint32_t*, kNumLiftoffFunctionCallsArrayOffset) uint32_t*, kNumLiftoffFunctionCallsArrayOffset)
ACCESSORS(WasmInstanceObject, active_continuation, WasmContinuationObject,
kActiveContinuationOffset)
PRIMITIVE_ACCESSORS(WasmInstanceObject, break_on_entry, uint8_t, PRIMITIVE_ACCESSORS(WasmInstanceObject, break_on_entry, uint8_t,
kBreakOnEntryOffset) kBreakOnEntryOffset)
......
...@@ -1208,15 +1208,6 @@ Handle<WasmInstanceObject> WasmInstanceObject::New( ...@@ -1208,15 +1208,6 @@ Handle<WasmInstanceObject> WasmInstanceObject::New(
module_object->native_module()->num_liftoff_function_calls_array()); module_object->native_module()->num_liftoff_function_calls_array());
instance->set_break_on_entry(module_object->script().break_on_entry()); 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 // Insert the new instance into the scripts weak list of instances. This list
// is used for breakpoints affecting all instances belonging to the script. // is used for breakpoints affecting all instances belonging to the script.
if (module_object->script().type() == Script::TYPE_WASM) { if (module_object->script().type() == Script::TYPE_WASM) {
......
...@@ -353,7 +353,6 @@ class V8_EXPORT_PRIVATE WasmInstanceObject : public JSObject { ...@@ -353,7 +353,6 @@ class V8_EXPORT_PRIVATE WasmInstanceObject : public JSObject {
DECL_PRIMITIVE_ACCESSORS(dropped_elem_segments, byte*) DECL_PRIMITIVE_ACCESSORS(dropped_elem_segments, byte*)
DECL_PRIMITIVE_ACCESSORS(hook_on_function_call_address, Address) DECL_PRIMITIVE_ACCESSORS(hook_on_function_call_address, Address)
DECL_PRIMITIVE_ACCESSORS(num_liftoff_function_calls_array, uint32_t*) DECL_PRIMITIVE_ACCESSORS(num_liftoff_function_calls_array, uint32_t*)
DECL_ACCESSORS(active_continuation, WasmContinuationObject)
DECL_PRIMITIVE_ACCESSORS(break_on_entry, uint8_t) DECL_PRIMITIVE_ACCESSORS(break_on_entry, uint8_t)
// Clear uninitialized padding space. This ensures that the snapshot content // Clear uninitialized padding space. This ensures that the snapshot content
...@@ -410,7 +409,6 @@ class V8_EXPORT_PRIVATE WasmInstanceObject : public JSObject { ...@@ -410,7 +409,6 @@ class V8_EXPORT_PRIVATE WasmInstanceObject : public JSObject {
V(kWasmExternalFunctionsOffset, kTaggedSize) \ V(kWasmExternalFunctionsOffset, kTaggedSize) \
V(kManagedObjectMapsOffset, kTaggedSize) \ V(kManagedObjectMapsOffset, kTaggedSize) \
V(kFeedbackVectorsOffset, kTaggedSize) \ V(kFeedbackVectorsOffset, kTaggedSize) \
V(kActiveContinuationOffset, kTaggedSize) \
V(kBreakOnEntryOffset, kUInt8Size) \ V(kBreakOnEntryOffset, kUInt8Size) \
/* More padding to make the header pointer-size aligned */ \ /* More padding to make the header pointer-size aligned */ \
V(kHeaderPaddingOffset, POINTER_SIZE_PADDING(kHeaderPaddingOffset)) \ 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