Commit 814e6b0b authored by Nico Hartmann's avatar Nico Hartmann Committed by V8 LUCI CQ

Revert "[wasm] WasmCompileLazyFrame scanning"

This reverts commit eb3fb6cb.

Reason for revert: https://ci.chromium.org/ui/p/v8/builders/ci/V8%20Mac64%20GC%20Stress/23845/overview

Original change's description:
> [wasm] WasmCompileLazyFrame scanning
>
> Feedback vector allocation can trigger a GC, and thereby make the
> WasmCompileLazyFrame visible for the GC. This CL add stack scanning
> for the WasmCompileLazyFrame.
>
> Design doc: http://doc/1peovM6N6C4nSEdC77l4uxU1L0njA0RTaOjy5F12r2CQ
>
> Change-Id: Iec16f50ad2c8ad7e6dcf05f9e620163d3b60ea0a
> Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3789516
> Reviewed-by: Jakob Kummerow <jkummerow@chromium.org>
> Commit-Queue: Andreas Haas <ahaas@chromium.org>
> Cr-Commit-Position: refs/heads/main@{#82119}

Change-Id: I694cd288d3a299bd397d4417e6864f7075a7c181
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3804256
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
Auto-Submit: Nico Hartmann <nicohartmann@chromium.org>
Commit-Queue: Nico Hartmann <nicohartmann@chromium.org>
Owners-Override: Nico Hartmann <nicohartmann@chromium.org>
Cr-Commit-Position: refs/heads/main@{#82130}
parent d1edb568
......@@ -2688,7 +2688,7 @@ void Builtins::Generate_WasmCompileLazy(MacroAssembler* masm) {
CHECK_EQ(highest_fp_reg.code() - lowest_fp_reg.code() + 1,
arraysize(wasm::kFpParamRegisters));
CHECK_EQ(gp_regs.Count(),
WasmCompileLazyFrameConstants::kNumberOfSavedGpParamRegs + 1);
WasmCompileLazyFrameConstants::kNumberOfSavedGpParamRegs);
CHECK_EQ(highest_fp_reg.code() - lowest_fp_reg.code() + 1,
WasmCompileLazyFrameConstants::kNumberOfSavedFpParamRegs);
......@@ -2699,13 +2699,10 @@ void Builtins::Generate_WasmCompileLazy(MacroAssembler* masm) {
__ push(kWasmInstanceRegister);
// Push the function index as second argument.
__ push(kWasmCompileLazyFuncIndexRegister);
// Allocate a stack slot for the NativeModule, the pushed value does not
// matter.
__ push(r8);
// Initialize the JavaScript context with 0. CEntry will use it to
// set the current context on the isolate.
__ Move(cp, Smi::zero());
__ CallRuntime(Runtime::kWasmCompileLazy, 3);
__ CallRuntime(Runtime::kWasmCompileLazy, 2);
// The runtime function returns the jump table slot offset as a Smi. Use
// that to compute the jump target in r8.
__ mov(r8, Operand::SmiUntag(kReturnRegister0));
......
......@@ -3075,8 +3075,7 @@ void Builtins::Generate_WasmCompileLazy(MacroAssembler* masm) {
CHECK_EQ(0, saved_gp_regs.Count() % 2);
// The Wasm instance must be part of the saved registers.
CHECK(saved_gp_regs.has(kWasmInstanceRegister));
// + instance + alignment
CHECK_EQ(WasmCompileLazyFrameConstants::kNumberOfSavedGpParamRegs + 2,
CHECK_EQ(WasmCompileLazyFrameConstants::kNumberOfSavedGpParamRegs,
saved_gp_regs.Count());
return saved_gp_regs;
})();
......@@ -3103,14 +3102,13 @@ void Builtins::Generate_WasmCompileLazy(MacroAssembler* masm) {
__ PushXRegList(kSavedGpRegs);
__ PushQRegList(kSavedFpRegs);
// Pass instance, function index, and an additional stack slot for the
// native module, as explicit arguments to the runtime function. The first
// pushed register is for alignment. {x0} and {x1} are picked arbitrarily.
__ Push(x0, kWasmInstanceRegister, kWasmCompileLazyFuncIndexRegister, x1);
// Pass instance and function index as explicit arguments to the runtime
// function.
__ Push(kWasmInstanceRegister, kWasmCompileLazyFuncIndexRegister);
// Initialize the JavaScript context with 0. CEntry will use it to
// set the current context on the isolate.
__ Mov(cp, Smi::zero());
__ CallRuntime(Runtime::kWasmCompileLazy, 3);
__ CallRuntime(Runtime::kWasmCompileLazy, 2);
// Untag the returned Smi into into x17 (ip1), for later use.
static_assert(!kSavedGpRegs.has(x17));
......
......@@ -2915,10 +2915,9 @@ void Builtins::Generate_WasmCompileLazy(MacroAssembler* masm) {
// Save all parameter registers (see wasm-linkage.h). They might be
// overwritten in the runtime call below. We don't have any callee-saved
// registers in wasm, so no need to store anything else.
static_assert(
WasmCompileLazyFrameConstants::kNumberOfSavedGpParamRegs + 1 ==
arraysize(wasm::kGpParamRegisters),
"frame size mismatch");
static_assert(WasmCompileLazyFrameConstants::kNumberOfSavedGpParamRegs ==
arraysize(wasm::kGpParamRegisters),
"frame size mismatch");
for (Register reg : wasm::kGpParamRegisters) {
__ Push(reg);
}
......@@ -2936,13 +2935,10 @@ void Builtins::Generate_WasmCompileLazy(MacroAssembler* masm) {
__ Push(kWasmInstanceRegister);
// Push the function index as second argument.
__ Push(kWasmCompileLazyFuncIndexRegister);
// Allocate a stack slot, where the runtime function can spill a pointer to
// the the NativeModule.
__ Push(esp);
// Initialize the JavaScript context with 0. CEntry will use it to
// set the current context on the isolate.
__ Move(kContextRegister, Smi::zero());
__ CallRuntime(Runtime::kWasmCompileLazy, 3);
__ CallRuntime(Runtime::kWasmCompileLazy, 2);
// The runtime function returns the jump table slot offset as a Smi. Use
// that to compute the jump target in edi.
__ SmiUntag(kReturnRegister0);
......
......@@ -2838,10 +2838,9 @@ void Builtins::Generate_WasmCompileLazy(MacroAssembler* masm) {
// Save all parameter registers (see wasm-linkage.h). They might be
// overwritten in the runtime call below. We don't have any callee-saved
// registers in wasm, so no need to store anything else.
static_assert(
WasmCompileLazyFrameConstants::kNumberOfSavedGpParamRegs + 1 ==
arraysize(wasm::kGpParamRegisters),
"frame size mismatch");
static_assert(WasmCompileLazyFrameConstants::kNumberOfSavedGpParamRegs ==
arraysize(wasm::kGpParamRegisters),
"frame size mismatch");
for (Register reg : wasm::kGpParamRegisters) {
__ Push(reg);
}
......@@ -2859,14 +2858,10 @@ void Builtins::Generate_WasmCompileLazy(MacroAssembler* masm) {
__ Push(kWasmInstanceRegister);
// Push the function index as second argument.
__ Push(r15);
// Allocate a stack slot, where the runtime function can spill a pointer to
// the the NativeModule.
__ Push(rsp);
// Initialize the JavaScript context with 0. CEntry will use it to
// set the current context on the isolate.
__ Move(kContextRegister, Smi::zero());
__ CallRuntime(Runtime::kWasmCompileLazy, 3);
__ CallRuntime(Runtime::kWasmCompileLazy, 2);
// The runtime function returns the jump table slot offset as a Smi. Use
// that to compute the jump target in r15.
__ SmiUntag(kReturnRegister0);
......
......@@ -57,26 +57,18 @@ class EntryFrameConstants : public AllStatic {
class WasmCompileLazyFrameConstants : public TypedFrameConstants {
public:
// Number of gp parameters, without the instance.
static constexpr int kNumberOfSavedGpParamRegs = 3;
static constexpr int kNumberOfSavedGpParamRegs = 4;
static constexpr int kNumberOfSavedFpParamRegs = 8;
// On arm, spilled registers are implicitly sorted backwards by number.
// We spill:
// r3: param0 = instance
// r0, r2, r6: param1, param2, param3
// in the following FP-relative order: [r6, r3, r2, r0].
static constexpr int kInstanceSpillOffset =
TYPED_FRAME_PUSHED_VALUE_OFFSET(1);
static constexpr int kParameterSpillsOffset[] = {
TYPED_FRAME_PUSHED_VALUE_OFFSET(3), TYPED_FRAME_PUSHED_VALUE_OFFSET(2),
TYPED_FRAME_PUSHED_VALUE_OFFSET(0)};
// SP-relative.
static constexpr int kWasmInstanceOffset = 2 * kSystemPointerSize;
static constexpr int kFunctionIndexOffset = 1 * kSystemPointerSize;
static constexpr int kNativeModuleOffset = 0;
// FP-relative.
// The instance is pushed as part of the saved registers. Being in {r3}, it is
// at position 1 in the list [r0, r2, r3, r6] (kGpParamRegisters sorted by
// number and indexed zero-based from the back).
static constexpr int kWasmInstanceOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(1);
static constexpr int kFixedFrameSizeFromFp =
TypedFrameConstants::kFixedFrameSizeFromFp +
kNumberOfSavedGpParamRegs * kPointerSize +
kNumberOfSavedFpParamRegs * kDoubleSize;
};
// Frame constructed by the {WasmDebugBreak} builtin.
......
......@@ -74,29 +74,20 @@ class EntryFrameConstants : public AllStatic {
class WasmCompileLazyFrameConstants : public TypedFrameConstants {
public:
// Number of gp parameters, without the instance.
static constexpr int kNumberOfSavedGpParamRegs = 6;
static constexpr int kNumberOfSavedGpParamRegs = 8;
static constexpr int kNumberOfSavedFpParamRegs = 8;
// On arm, spilled registers are implicitly sorted backwards by number.
// We spill:
// x7: param0 = instance
// x0, x2, x3, x4, x5, x6: param1, param2, ..., param6
// x1: for alignment
// in the following FP-relative order: [x7, x6, x5, x4, x3, x2, x1, x0].
// For frame alignment, the first spill slot is at position '1', not at '0'.
static constexpr int kInstanceSpillOffset =
TYPED_FRAME_PUSHED_VALUE_OFFSET(1);
static constexpr int kParameterSpillsOffset[] = {
TYPED_FRAME_PUSHED_VALUE_OFFSET(8), TYPED_FRAME_PUSHED_VALUE_OFFSET(6),
TYPED_FRAME_PUSHED_VALUE_OFFSET(5), TYPED_FRAME_PUSHED_VALUE_OFFSET(4),
TYPED_FRAME_PUSHED_VALUE_OFFSET(3), TYPED_FRAME_PUSHED_VALUE_OFFSET(2)};
// SP-relative.
static constexpr int kWasmInstanceOffset = 2 * kSystemPointerSize;
static constexpr int kFunctionIndexOffset = 1 * kSystemPointerSize;
static constexpr int kNativeModuleOffset = 0;
// FP-relative.
// The instance is pushed as part of the saved registers. Being in {r7}, it is
// the first register pushed (highest register code in
// {wasm::kGpParamRegisters}). Because of padding of the frame header, it is
// actually one word further down the stack though (thus at position {1}).
static constexpr int kWasmInstanceOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(1);
static constexpr int kFixedFrameSizeFromFp =
// Header is padded to 16 byte (see {MacroAssembler::EnterFrame}).
RoundUp<16>(TypedFrameConstants::kFixedFrameSizeFromFp) +
kNumberOfSavedGpParamRegs * kSystemPointerSize +
kNumberOfSavedFpParamRegs * kSimd128Size;
};
// Frame constructed by the {WasmDebugBreak} builtin.
......
......@@ -2577,88 +2577,21 @@ void StackSwitchFrame::GetStateForJumpBuffer(wasm::JumpBuffer* jmpbuf,
DCHECK_NE(*state->pc_address, kNullAddress);
}
int WasmCompileLazyFrame::GetFunctionIndex() const {
Object func_index(Memory<Address>(
sp() + WasmCompileLazyFrameConstants::kFunctionIndexOffset));
return Smi::ToInt(func_index);
}
wasm::NativeModule* WasmCompileLazyFrame::GetNativeModule() const {
return *reinterpret_cast<wasm::NativeModule**>(
sp() + WasmCompileLazyFrameConstants::kNativeModuleOffset);
WasmInstanceObject WasmCompileLazyFrame::wasm_instance() const {
return WasmInstanceObject::cast(*wasm_instance_slot());
}
FullObjectSlot WasmCompileLazyFrame::wasm_instance_slot() const {
return FullObjectSlot(&Memory<Address>(
sp() + WasmCompileLazyFrameConstants::kWasmInstanceOffset));
const int offset = WasmCompileLazyFrameConstants::kWasmInstanceOffset;
return FullObjectSlot(&Memory<Address>(fp() + offset));
}
void WasmCompileLazyFrame::Iterate(RootVisitor* v) const {
FullObjectSlot spilled_instance_slot(&Memory<Address>(
fp() + WasmCompileLazyFrameConstants::kInstanceSpillOffset));
v->VisitRootPointer(Root::kStackRoots, "spilled wasm instance",
spilled_instance_slot);
v->VisitRootPointer(Root::kStackRoots, "wasm instance parameter",
wasm_instance_slot());
int func_index = GetFunctionIndex();
wasm::NativeModule* native_module = GetNativeModule();
// Scan the spill slots of the parameter registers. Parameters in WebAssembly
// get reordered such that first all value parameters get put into registers.
// If there are more registers than value parameters, the remaining registers
// are used for reference parameters. Therefore we can determine which
// registers get used for which parameters by counting the number of value
// parameters and the number of reference parameters.
int num_int_params = 0;
int num_ref_params = 0;
const wasm::FunctionSig* sig =
native_module->module()->functions[func_index].sig;
for (auto param : sig->parameters()) {
if (param == wasm::kWasmI32) {
num_int_params++;
} else if (param == wasm::kWasmI64) {
num_int_params += kSystemPointerSize == 8 ? 1 : 2;
} else if (param.is_reference()) {
num_ref_params++;
}
}
// There are no reference parameters, there is nothing to scan.
if (num_ref_params == 0) return;
int num_int_params_in_registers = std::min(
num_int_params, WasmCompileLazyFrameConstants::kNumberOfSavedGpParamRegs);
int num_ref_params_in_registers = std::min(
num_ref_params, WasmCompileLazyFrameConstants::kNumberOfSavedGpParamRegs -
num_int_params_in_registers);
for (int i = 0; i < num_ref_params_in_registers; ++i) {
FullObjectSlot spill_slot(
fp() + WasmCompileLazyFrameConstants::kParameterSpillsOffset
[num_int_params_in_registers + i]);
v->VisitRootPointer(Root::kStackRoots, "register parameter", spill_slot);
}
// Next we scan the slots of stack parameters.
wasm::WasmCode* wasm_code = native_module->GetCode(func_index);
uint32_t first_tagged_stack_slot = wasm_code->first_tagged_parameter_slot();
uint32_t num_tagged_stack_slots = wasm_code->num_tagged_parameter_slots();
// Visit tagged parameters that have been passed to the function of this
// frame. Conceptionally these parameters belong to the parent frame. However,
// the exact count is only known by this frame (in the presence of tail calls,
// this information cannot be derived from the call site).
if (num_tagged_stack_slots > 0) {
FullObjectSlot tagged_parameter_base(&Memory<Address>(caller_sp()));
tagged_parameter_base += first_tagged_stack_slot;
FullObjectSlot tagged_parameter_limit =
tagged_parameter_base + num_tagged_stack_slots;
v->VisitRootPointers(Root::kStackRoots, "stack parameter",
tagged_parameter_base, tagged_parameter_limit);
}
const int header_size = WasmCompileLazyFrameConstants::kFixedFrameSizeFromFp;
FullObjectSlot base(&Memory<Address>(sp()));
FullObjectSlot limit(&Memory<Address>(fp() - header_size));
v->VisitRootPointers(Root::kStackRoots, nullptr, base, limit);
v->VisitRootPointer(Root::kStackRoots, nullptr, wasm_instance_slot());
}
#endif // V8_ENABLE_WEBASSEMBLY
......
......@@ -1113,12 +1113,9 @@ class WasmCompileLazyFrame : public TypedFrame {
public:
Type type() const override { return WASM_COMPILE_LAZY; }
WasmInstanceObject wasm_instance() const;
FullObjectSlot wasm_instance_slot() const;
int GetFunctionIndex() const;
wasm::NativeModule* GetNativeModule() const;
// Garbage collection support.
void Iterate(RootVisitor* v) const override;
......
......@@ -36,21 +36,15 @@ class EntryFrameConstants : public AllStatic {
class WasmCompileLazyFrameConstants : public TypedFrameConstants {
public:
// Number of gp parameters, without the instance.
static constexpr int kNumberOfSavedGpParamRegs = 3;
static constexpr int kNumberOfSavedGpParamRegs = 4;
static constexpr int kNumberOfSavedFpParamRegs = 6;
static constexpr int kInstanceSpillOffset =
TYPED_FRAME_PUSHED_VALUE_OFFSET(0);
static constexpr int kParameterSpillsOffset[] = {
TYPED_FRAME_PUSHED_VALUE_OFFSET(1), TYPED_FRAME_PUSHED_VALUE_OFFSET(2),
TYPED_FRAME_PUSHED_VALUE_OFFSET(3)};
// SP-relative.
static constexpr int kWasmInstanceOffset = 2 * kSystemPointerSize;
static constexpr int kFunctionIndexOffset = 1 * kSystemPointerSize;
static constexpr int kNativeModuleOffset = 0;
// FP-relative.
static constexpr int kWasmInstanceOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(0);
static constexpr int kFixedFrameSizeFromFp =
TypedFrameConstants::kFixedFrameSizeFromFp +
kNumberOfSavedGpParamRegs * kSystemPointerSize +
kNumberOfSavedFpParamRegs * kSimd128Size;
};
// Frame constructed by the {WasmDebugBreak} builtin.
......
......@@ -45,22 +45,15 @@ class EntryFrameConstants : public AllStatic {
class WasmCompileLazyFrameConstants : public TypedFrameConstants {
public:
// Number of gp parameters, without the instance.
static constexpr int kNumberOfSavedGpParamRegs = 5;
static constexpr int kNumberOfSavedGpParamRegs = 6;
static constexpr int kNumberOfSavedFpParamRegs = 6;
static constexpr int kInstanceSpillOffset =
TYPED_FRAME_PUSHED_VALUE_OFFSET(0);
static constexpr int kParameterSpillsOffset[] = {
TYPED_FRAME_PUSHED_VALUE_OFFSET(1), TYPED_FRAME_PUSHED_VALUE_OFFSET(2),
TYPED_FRAME_PUSHED_VALUE_OFFSET(3), TYPED_FRAME_PUSHED_VALUE_OFFSET(4),
TYPED_FRAME_PUSHED_VALUE_OFFSET(5)};
// SP-relative.
static constexpr int kWasmInstanceOffset = 2 * kSystemPointerSize;
static constexpr int kFunctionIndexOffset = 1 * kSystemPointerSize;
static constexpr int kNativeModuleOffset = 0;
// FP-relative.
static constexpr int kWasmInstanceOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(0);
static constexpr int kFixedFrameSizeFromFp =
TypedFrameConstants::kFixedFrameSizeFromFp +
kNumberOfSavedGpParamRegs * kSystemPointerSize +
kNumberOfSavedFpParamRegs * kSimd128Size;
};
// Frame constructed by the {WasmDebugBreak} builtin.
......
......@@ -219,21 +219,35 @@ RUNTIME_FUNCTION(Runtime_WasmStackGuard) {
}
RUNTIME_FUNCTION(Runtime_WasmCompileLazy) {
// The parameters of the called function we are going to compile have been
// spilled on the stack. Some of these parameters may be references. As we
// don't know which parameters are references, we have to make sure that no GC
// is triggered during the compilation of the function.
base::Optional<DisallowGarbageCollection> no_gc(base::in_place);
ClearThreadInWasmScope wasm_flag(isolate);
HandleScope scope(isolate);
DCHECK_EQ(3, args.length());
DCHECK_EQ(2, args.length());
// TODO(jkummerow): This can be an unhandlified object once
// {wasm::CompileLazy()} no longer allocates even when speculative inlining
// is enabled.
Handle<WasmInstanceObject> instance(WasmInstanceObject::cast(args[0]),
isolate);
int func_index = args.smi_value_at(1);
wasm::NativeModule** native_module_stack_slot =
reinterpret_cast<wasm::NativeModule**>(args.address_of_arg_at(2));
#ifdef DEBUG
FrameFinder<WasmCompileLazyFrame> frame_finder(isolate);
DCHECK_EQ(*instance, frame_finder.frame()->wasm_instance());
#endif
DCHECK(isolate->context().is_null());
isolate->set_context(instance->native_context());
bool success = wasm::CompileLazy(isolate, instance, func_index,
native_module_stack_slot);
bool success = wasm::CompileLazy(isolate, instance, func_index);
if (!success) {
{
// Compilation of function failed. We have to allocate the exception
// object. This allocation may trigger a GC, but that's okay, because the
// parameters on the stack will not be used anymore anyways.
no_gc.reset();
wasm::ThrowLazyCompilationError(
isolate, instance->module_object().native_module(), func_index);
}
......
......@@ -603,7 +603,7 @@ namespace internal {
F(WasmTableGrow, 3, 1) \
F(WasmTableFill, 5, 1) \
F(WasmIsValidRefValue, 3, 1) \
F(WasmCompileLazy, 3, 1) \
F(WasmCompileLazy, 2, 1) \
F(WasmCompileWrapper, 2, 1) \
F(WasmTriggerTierUp, 1, 1) \
F(WasmDebugBreak, 0, 1) \
......
......@@ -1135,7 +1135,7 @@ bool IsLazyModule(const WasmModule* module) {
} // namespace
bool CompileLazy(Isolate* isolate, Handle<WasmInstanceObject> instance,
int func_index, NativeModule** out_native_module) {
int func_index) {
Handle<WasmModuleObject> module_object(instance->module_object(), isolate);
NativeModule* native_module = module_object->native_module();
const WasmModule* module = native_module->module();
......@@ -1189,6 +1189,15 @@ bool CompileLazy(Isolate* isolate, Handle<WasmInstanceObject> instance,
return false;
}
// Allocate feedback vector if needed.
if (result.feedback_vector_slots > 0) {
DCHECK(FLAG_wasm_speculative_inlining);
Handle<FixedArray> vector = isolate->factory()->NewFixedArrayWithZeroes(
result.feedback_vector_slots);
instance->feedback_vectors().set(
declared_function_index(module, func_index), *vector);
}
WasmCodeRefScope code_ref_scope;
WasmCode* code;
{
......@@ -1217,17 +1226,6 @@ bool CompileLazy(Isolate* isolate, Handle<WasmInstanceObject> instance,
compilation_state->CommitTopTierCompilationUnit(tiering_unit);
}
// Allocate feedback vector if needed.
if (result.feedback_vector_slots > 0) {
DCHECK(FLAG_wasm_speculative_inlining);
// We have to save the native_module on the stack, in case the allocation
// triggers a GC and we need the module to scan WasmCompileLazy stack frame.
*out_native_module = native_module;
Handle<FixedArray> vector = isolate->factory()->NewFixedArrayWithZeroes(
result.feedback_vector_slots);
instance->feedback_vectors().set(
declared_function_index(module, func_index), *vector);
}
return true;
}
......
......@@ -80,8 +80,7 @@ WasmCode* CompileImportWrapper(
// Triggered by the WasmCompileLazy builtin. The return value indicates whether
// compilation was successful. Lazy compilation can fail only if validation is
// also lazy.
bool CompileLazy(Isolate*, Handle<WasmInstanceObject>, int func_index,
NativeModule** out_native_module);
bool CompileLazy(Isolate*, Handle<WasmInstanceObject>, int func_index);
// Throws the compilation error after failed lazy compilation.
void ThrowLazyCompilationError(Isolate* isolate,
......
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