[wasm] Add builtin and runtime function for debug breaks
This CL adds the "WasmDebugBreak" builtin for x64, ia32, arm and arm64. It stores all wasm parameter registers to the stack and calls the respective runtime function. The runtime function does not do anything yet, but the inspector/debugger/wasm-set-breakpoint-liftoff test will already execute both the builtin and the runtime function. R=thibaudm@chromium.org Bug: v8:10147 Change-Id: I445fdd7c202480ece951f5efbb4845cf21410d91 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2036082 Reviewed-by: Thibaud Michaud <thibaudm@chromium.org> Reviewed-by: Jakob Kummerow <jkummerow@chromium.org> Commit-Queue: Clemens Backes <clemensb@chromium.org> Cr-Commit-Position: refs/heads/master@{#66126}
This commit is contained in:
parent
cf1fad5899
commit
59bda19676
@ -6,15 +6,15 @@
|
||||
|
||||
#include "src/api/api-arguments.h"
|
||||
#include "src/codegen/code-factory.h"
|
||||
// For interpreter_entry_return_pc_offset. TODO(jkummerow): Drop.
|
||||
#include "src/codegen/macro-assembler-inl.h"
|
||||
#include "src/codegen/register-configuration.h"
|
||||
#include "src/debug/debug.h"
|
||||
#include "src/deoptimizer/deoptimizer.h"
|
||||
#include "src/execution/frame-constants.h"
|
||||
#include "src/execution/frames.h"
|
||||
#include "src/logging/counters.h"
|
||||
// For interpreter_entry_return_pc_offset. TODO(jkummerow): Drop.
|
||||
#include "src/codegen/macro-assembler-inl.h"
|
||||
#include "src/codegen/register-configuration.h"
|
||||
#include "src/heap/heap-inl.h"
|
||||
#include "src/logging/counters.h"
|
||||
#include "src/objects/cell.h"
|
||||
#include "src/objects/foreign.h"
|
||||
#include "src/objects/heap-number.h"
|
||||
@ -22,6 +22,7 @@
|
||||
#include "src/objects/objects-inl.h"
|
||||
#include "src/objects/smi.h"
|
||||
#include "src/runtime/runtime.h"
|
||||
#include "src/wasm/wasm-linkage.h"
|
||||
#include "src/wasm/wasm-objects.h"
|
||||
|
||||
namespace v8 {
|
||||
@ -2433,6 +2434,37 @@ void Builtins::Generate_WasmCompileLazy(MacroAssembler* masm) {
|
||||
__ Jump(r8);
|
||||
}
|
||||
|
||||
void Builtins::Generate_WasmDebugBreak(MacroAssembler* masm) {
|
||||
HardAbortScope hard_abort(masm); // Avoid calls to Abort.
|
||||
{
|
||||
// TODO(clemensb): Use a separate frame type and make it inspectable.
|
||||
FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
|
||||
|
||||
// Save all parameter registers. They might hold live values, we restore
|
||||
// them after the runtime call.
|
||||
RegList gp_regs = 0;
|
||||
for (Register reg : wasm::kGpParamRegisters) gp_regs |= reg.bit();
|
||||
constexpr DwVfpRegister lowest_fp_reg = wasm::kFpParamRegisters[0];
|
||||
constexpr DwVfpRegister highest_fp_reg =
|
||||
wasm::kFpParamRegisters[arraysize(wasm::kFpParamRegisters) - 1];
|
||||
STATIC_ASSERT(arraysize(wasm::kFpParamRegisters) ==
|
||||
highest_fp_reg.code() - lowest_fp_reg.code() + 1);
|
||||
|
||||
__ stm(db_w, sp, gp_regs);
|
||||
__ vstm(db_w, sp, lowest_fp_reg, highest_fp_reg);
|
||||
|
||||
// Initialize the JavaScript context with 0. CEntry will use it to
|
||||
// set the current context on the isolate.
|
||||
__ Move(cp, Smi::zero());
|
||||
__ CallRuntime(Runtime::kWasmDebugBreak, 0);
|
||||
|
||||
// Restore registers.
|
||||
__ vldm(ia_w, sp, lowest_fp_reg, highest_fp_reg);
|
||||
__ ldm(ia_w, sp, gp_regs);
|
||||
}
|
||||
__ Ret();
|
||||
}
|
||||
|
||||
void Builtins::Generate_CEntry(MacroAssembler* masm, int result_size,
|
||||
SaveFPRegsMode save_doubles, ArgvMode argv_mode,
|
||||
bool builtin_exit_frame) {
|
||||
|
@ -6,15 +6,15 @@
|
||||
|
||||
#include "src/api/api-arguments.h"
|
||||
#include "src/codegen/code-factory.h"
|
||||
// For interpreter_entry_return_pc_offset. TODO(jkummerow): Drop.
|
||||
#include "src/codegen/macro-assembler-inl.h"
|
||||
#include "src/codegen/register-configuration.h"
|
||||
#include "src/debug/debug.h"
|
||||
#include "src/deoptimizer/deoptimizer.h"
|
||||
#include "src/execution/frame-constants.h"
|
||||
#include "src/execution/frames.h"
|
||||
#include "src/logging/counters.h"
|
||||
// For interpreter_entry_return_pc_offset. TODO(jkummerow): Drop.
|
||||
#include "src/codegen/macro-assembler-inl.h"
|
||||
#include "src/codegen/register-configuration.h"
|
||||
#include "src/heap/heap-inl.h"
|
||||
#include "src/logging/counters.h"
|
||||
#include "src/objects/cell.h"
|
||||
#include "src/objects/foreign.h"
|
||||
#include "src/objects/heap-number.h"
|
||||
@ -22,6 +22,7 @@
|
||||
#include "src/objects/objects-inl.h"
|
||||
#include "src/objects/smi.h"
|
||||
#include "src/runtime/runtime.h"
|
||||
#include "src/wasm/wasm-linkage.h"
|
||||
#include "src/wasm/wasm-objects.h"
|
||||
|
||||
#if defined(V8_OS_WIN)
|
||||
@ -2950,6 +2951,40 @@ void Builtins::Generate_WasmCompileLazy(MacroAssembler* masm) {
|
||||
__ Jump(x8);
|
||||
}
|
||||
|
||||
void Builtins::Generate_WasmDebugBreak(MacroAssembler* masm) {
|
||||
HardAbortScope hard_abort(masm); // Avoid calls to Abort.
|
||||
{
|
||||
// TODO(clemensb): Use a separate frame type and make it inspectable.
|
||||
FrameScope scope(masm, StackFrame::INTERNAL);
|
||||
|
||||
// Save all parameter registers. They might hold live values, we restore
|
||||
// them after the runtime call.
|
||||
RegList gp_regs = 0;
|
||||
for (Register reg : wasm::kGpParamRegisters) gp_regs |= reg.bit();
|
||||
// The size of {gp_regs} must be a multiple of 2, so that the total pushed
|
||||
// size is a multiple of 16 bytes.
|
||||
if (NumRegs(gp_regs) % 2) {
|
||||
// Just add any unset register.
|
||||
gp_regs |= 1 << base::bits::CountTrailingZeros(~gp_regs);
|
||||
}
|
||||
RegList fp_regs = 0;
|
||||
for (DoubleRegister reg : wasm::kFpParamRegisters) fp_regs |= reg.bit();
|
||||
|
||||
__ PushXRegList(gp_regs);
|
||||
__ PushDRegList(fp_regs);
|
||||
|
||||
// Initialize the JavaScript context with 0. CEntry will use it to
|
||||
// set the current context on the isolate.
|
||||
__ Move(cp, Smi::zero());
|
||||
__ CallRuntime(Runtime::kWasmDebugBreak, 0);
|
||||
|
||||
// Restore registers.
|
||||
__ PopDRegList(fp_regs);
|
||||
__ PopXRegList(gp_regs);
|
||||
}
|
||||
__ Ret();
|
||||
}
|
||||
|
||||
void Builtins::Generate_CEntry(MacroAssembler* masm, int result_size,
|
||||
SaveFPRegsMode save_doubles, ArgvMode argv_mode,
|
||||
bool builtin_exit_frame) {
|
||||
|
@ -858,6 +858,7 @@ namespace internal {
|
||||
\
|
||||
/* Wasm */ \
|
||||
ASM(WasmCompileLazy, Dummy) \
|
||||
ASM(WasmDebugBreak, Dummy) \
|
||||
TFC(WasmAtomicNotify, WasmAtomicNotify) \
|
||||
TFC(WasmI32AtomicWait, WasmI32AtomicWait) \
|
||||
TFC(WasmI64AtomicWait, WasmI64AtomicWait) \
|
||||
|
@ -7,15 +7,15 @@
|
||||
#include "src/api/api-arguments.h"
|
||||
#include "src/base/iterator.h"
|
||||
#include "src/codegen/code-factory.h"
|
||||
// For interpreter_entry_return_pc_offset. TODO(jkummerow): Drop.
|
||||
#include "src/codegen/macro-assembler-inl.h"
|
||||
#include "src/codegen/register-configuration.h"
|
||||
#include "src/debug/debug.h"
|
||||
#include "src/deoptimizer/deoptimizer.h"
|
||||
#include "src/execution/frame-constants.h"
|
||||
#include "src/execution/frames.h"
|
||||
#include "src/logging/counters.h"
|
||||
// For interpreter_entry_return_pc_offset. TODO(jkummerow): Drop.
|
||||
#include "src/codegen/macro-assembler-inl.h"
|
||||
#include "src/codegen/register-configuration.h"
|
||||
#include "src/heap/heap-inl.h"
|
||||
#include "src/logging/counters.h"
|
||||
#include "src/objects/cell.h"
|
||||
#include "src/objects/foreign.h"
|
||||
#include "src/objects/heap-number.h"
|
||||
@ -2594,6 +2594,47 @@ void Builtins::Generate_WasmCompileLazy(MacroAssembler* masm) {
|
||||
__ jmp(edi);
|
||||
}
|
||||
|
||||
void Builtins::Generate_WasmDebugBreak(MacroAssembler* masm) {
|
||||
HardAbortScope hard_abort(masm); // Avoid calls to Abort.
|
||||
{
|
||||
// TODO(clemensb): Use a separate frame type and make it inspectable.
|
||||
FrameScope scope(masm, StackFrame::INTERNAL);
|
||||
|
||||
// Save all parameter registers. They might hold live values, we restore
|
||||
// them after the runtime call.
|
||||
// TODO(clemensb): Make these registers available for inspection.
|
||||
for (Register reg : wasm::kGpParamRegisters) {
|
||||
__ Push(reg);
|
||||
}
|
||||
|
||||
constexpr int kFpStackSize =
|
||||
kSimd128Size * arraysize(wasm::kFpParamRegisters);
|
||||
__ AllocateStackSpace(kFpStackSize);
|
||||
int offset = 0;
|
||||
for (DoubleRegister reg : wasm::kFpParamRegisters) {
|
||||
__ movdqu(Operand(esp, offset), reg);
|
||||
offset += kSimd128Size;
|
||||
}
|
||||
|
||||
// Initialize the JavaScript context with 0. CEntry will use it to
|
||||
// set the current context on the isolate.
|
||||
__ Move(kContextRegister, Smi::zero());
|
||||
__ CallRuntime(Runtime::kWasmDebugBreak, 0);
|
||||
|
||||
// Restore registers.
|
||||
for (DoubleRegister reg : base::Reversed(wasm::kFpParamRegisters)) {
|
||||
offset -= kSimd128Size;
|
||||
__ movdqu(reg, Operand(esp, offset));
|
||||
}
|
||||
__ add(esp, Immediate(kFpStackSize));
|
||||
for (Register reg : base::Reversed(wasm::kGpParamRegisters)) {
|
||||
__ Pop(reg);
|
||||
}
|
||||
}
|
||||
|
||||
__ ret(0);
|
||||
}
|
||||
|
||||
void Builtins::Generate_CEntry(MacroAssembler* masm, int result_size,
|
||||
SaveFPRegsMode save_doubles, ArgvMode argv_mode,
|
||||
bool builtin_exit_frame) {
|
||||
|
@ -7,15 +7,15 @@
|
||||
#include "src/api/api-arguments.h"
|
||||
#include "src/base/iterator.h"
|
||||
#include "src/codegen/code-factory.h"
|
||||
// For interpreter_entry_return_pc_offset. TODO(jkummerow): Drop.
|
||||
#include "src/codegen/macro-assembler-inl.h"
|
||||
#include "src/codegen/register-configuration.h"
|
||||
#include "src/codegen/x64/assembler-x64.h"
|
||||
#include "src/deoptimizer/deoptimizer.h"
|
||||
#include "src/execution/frame-constants.h"
|
||||
#include "src/execution/frames.h"
|
||||
#include "src/logging/counters.h"
|
||||
// For interpreter_entry_return_pc_offset. TODO(jkummerow): Drop.
|
||||
#include "src/codegen/macro-assembler-inl.h"
|
||||
#include "src/codegen/register-configuration.h"
|
||||
#include "src/heap/heap-inl.h"
|
||||
#include "src/logging/counters.h"
|
||||
#include "src/objects/cell.h"
|
||||
#include "src/objects/debug-objects.h"
|
||||
#include "src/objects/foreign.h"
|
||||
@ -23,6 +23,7 @@
|
||||
#include "src/objects/js-generator.h"
|
||||
#include "src/objects/objects-inl.h"
|
||||
#include "src/objects/smi.h"
|
||||
#include "src/wasm/baseline/liftoff-assembler-defs.h"
|
||||
#include "src/wasm/wasm-linkage.h"
|
||||
#include "src/wasm/wasm-objects.h"
|
||||
|
||||
@ -2575,6 +2576,46 @@ void Builtins::Generate_WasmCompileLazy(MacroAssembler* masm) {
|
||||
__ jmp(r11);
|
||||
}
|
||||
|
||||
void Builtins::Generate_WasmDebugBreak(MacroAssembler* masm) {
|
||||
HardAbortScope hard_abort(masm); // Avoid calls to Abort.
|
||||
{
|
||||
// TODO(clemensb): Use a separate frame type and make it inspectable.
|
||||
FrameScope scope(masm, StackFrame::INTERNAL);
|
||||
|
||||
// Save all parameter registers. They might hold live values, we restore
|
||||
// them after the runtime call.
|
||||
for (Register reg : wasm::kGpParamRegisters) {
|
||||
__ Push(reg);
|
||||
}
|
||||
|
||||
constexpr int kFpStackSize =
|
||||
kSimd128Size * arraysize(wasm::kFpParamRegisters);
|
||||
__ AllocateStackSpace(kFpStackSize);
|
||||
int offset = 0;
|
||||
for (DoubleRegister reg : wasm::kFpParamRegisters) {
|
||||
__ movdqu(Operand(rsp, offset), reg);
|
||||
offset += kSimd128Size;
|
||||
}
|
||||
|
||||
// Initialize the JavaScript context with 0. CEntry will use it to
|
||||
// set the current context on the isolate.
|
||||
__ Move(kContextRegister, Smi::zero());
|
||||
__ CallRuntime(Runtime::kWasmDebugBreak, 0);
|
||||
|
||||
// Restore registers.
|
||||
for (DoubleRegister reg : base::Reversed(wasm::kFpParamRegisters)) {
|
||||
offset -= kSimd128Size;
|
||||
__ movdqu(reg, Operand(rsp, offset));
|
||||
}
|
||||
__ addq(rsp, Immediate(kFpStackSize));
|
||||
for (Register reg : base::Reversed(wasm::kGpParamRegisters)) {
|
||||
__ Pop(reg);
|
||||
}
|
||||
}
|
||||
|
||||
__ ret(0);
|
||||
}
|
||||
|
||||
void Builtins::Generate_CEntry(MacroAssembler* masm, int result_size,
|
||||
SaveFPRegsMode save_doubles, ArgvMode argv_mode,
|
||||
bool builtin_exit_frame) {
|
||||
|
@ -602,5 +602,15 @@ RUNTIME_FUNCTION(Runtime_WasmNewMultiReturnJSArray) {
|
||||
fixed_array_handle, PACKED_ELEMENTS);
|
||||
return *array;
|
||||
}
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_WasmDebugBreak) {
|
||||
HandleScope scope(isolate);
|
||||
DCHECK_EQ(0, args.length());
|
||||
|
||||
// TODO(clemensb): Implement.
|
||||
|
||||
return ReadOnlyRoots(isolate).undefined_value();
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
@ -570,7 +570,8 @@ namespace internal {
|
||||
F(WasmIsValidFuncRefValue, 1, 1) \
|
||||
F(WasmCompileLazy, 2, 1) \
|
||||
F(WasmNewMultiReturnFixedArray, 1, 1) \
|
||||
F(WasmNewMultiReturnJSArray, 1, 1)
|
||||
F(WasmNewMultiReturnJSArray, 1, 1) \
|
||||
F(WasmDebugBreak, 0, 1)
|
||||
|
||||
#define FOR_EACH_INTRINSIC_RETURN_PAIR_IMPL(F, I) \
|
||||
F(DebugBreakOnBytecode, 1, 2) \
|
||||
|
@ -714,6 +714,7 @@ class LiftoffAssembler : public TurboAssembler {
|
||||
inline void DeallocateStackSlot(uint32_t size);
|
||||
|
||||
inline void DebugBreak();
|
||||
|
||||
////////////////////////////////////
|
||||
// End of platform-specific part. //
|
||||
////////////////////////////////////
|
||||
|
@ -651,16 +651,20 @@ class LiftoffCompiler {
|
||||
if (next_breakpoint_ptr_ == next_breakpoint_end_) {
|
||||
next_breakpoint_ptr_ = next_breakpoint_end_ = nullptr;
|
||||
}
|
||||
EmitBreakpoint();
|
||||
EmitBreakpoint(decoder);
|
||||
}
|
||||
TraceCacheState(decoder);
|
||||
SLOW_DCHECK(__ ValidateCacheState());
|
||||
DEBUG_CODE_COMMENT(WasmOpcodes::OpcodeName(opcode));
|
||||
}
|
||||
|
||||
void EmitBreakpoint() {
|
||||
void EmitBreakpoint(FullDecoder* decoder) {
|
||||
DEBUG_CODE_COMMENT("breakpoint");
|
||||
// TODO(clemensb): Actually emit a breakpoint.
|
||||
source_position_table_builder_.AddPosition(
|
||||
__ pc_offset(), SourcePosition(decoder->position()), false);
|
||||
__ CallRuntimeStub(WasmCode::kWasmDebugBreak);
|
||||
RegisterDebugSideTableEntry();
|
||||
safepoint_table_builder_.DefineSafepoint(&asm_, Safepoint::kNoLazyDeopt);
|
||||
}
|
||||
|
||||
void Block(FullDecoder* decoder, Control* block) {}
|
||||
|
@ -48,6 +48,7 @@ struct WasmModule;
|
||||
#define WASM_RUNTIME_STUB_LIST(V, VTRAP) \
|
||||
FOREACH_WASM_TRAPREASON(VTRAP) \
|
||||
V(WasmCompileLazy) \
|
||||
V(WasmDebugBreak) \
|
||||
V(WasmAtomicNotify) \
|
||||
V(WasmI32AtomicWait) \
|
||||
V(WasmI64AtomicWait) \
|
||||
|
Loading…
Reference in New Issue
Block a user