Commit 843a1f45 authored by Clemens Backes's avatar Clemens Backes Committed by Commit Bot

[wasm][interpreter] Remove breakpoint support

The interpreter is not used for debugging any more. Hence any breakpoint
support and related functionality is dead code.

This CL removes
- the {SetBreakpoint} and {GetBreakpoint} methods,
- the {break_pc_} field which holds the current pause position,
- the {break_flags_} field which is used to break at function entry and
  after calls,
- functions to modify {break_flags_},
- the dead {kInternalBreakpoint} and {kInvalidPc} constants (plus
  respective macros and enums),
- the {orig_start} and {orig_end} fields (code is not being modified any
  more, so we just use {start} and {end} now),
- the {PrepareStepIn} method,
- the unimplemented {SetTracing} method, and
- two tests that test breakpoints in the interpreter.

R=thibaudm@chromium.org

Bug: v8:10389
Change-Id: I52103c37516446e40d3dfa365d6b480a7c623577
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2215163
Commit-Queue: Clemens Backes <clemensb@chromium.org>
Reviewed-by: 's avatarThibaud Michaud <thibaudm@chromium.org>
Cr-Commit-Position: refs/heads/master@{#67958}
parent 447d7d67
...@@ -50,8 +50,6 @@ using base::WriteUnalignedValue; ...@@ -50,8 +50,6 @@ using base::WriteUnalignedValue;
#define LANE(i, type) (i) #define LANE(i, type) (i)
#endif #endif
#define FOREACH_INTERNAL_OPCODE(V) V(Breakpoint, 0xFF)
#define FOREACH_SIMPLE_BINOP(V) \ #define FOREACH_SIMPLE_BINOP(V) \
V(I32Add, uint32_t, +) \ V(I32Add, uint32_t, +) \
V(I32Sub, uint32_t, -) \ V(I32Sub, uint32_t, -) \
...@@ -624,23 +622,6 @@ inline int64_t ExecuteI64ReinterpretF64(WasmValue a) { ...@@ -624,23 +622,6 @@ inline int64_t ExecuteI64ReinterpretF64(WasmValue a) {
return a.to_f64_boxed().get_bits(); return a.to_f64_boxed().get_bits();
} }
enum InternalOpcode {
#define DECL_INTERNAL_ENUM(name, value) kInternal##name = value,
FOREACH_INTERNAL_OPCODE(DECL_INTERNAL_ENUM)
#undef DECL_INTERNAL_ENUM
};
const char* OpcodeName(uint32_t val) {
switch (val) {
#define DECL_INTERNAL_CASE(name, value) \
case kInternal##name: \
return "Internal" #name;
FOREACH_INTERNAL_OPCODE(DECL_INTERNAL_CASE)
#undef DECL_INTERNAL_CASE
}
return WasmOpcodes::OpcodeName(static_cast<WasmOpcode>(val));
}
constexpr int32_t kCatchInArity = 1; constexpr int32_t kCatchInArity = 1;
} // namespace } // namespace
...@@ -651,11 +632,9 @@ class SideTable; ...@@ -651,11 +632,9 @@ class SideTable;
struct InterpreterCode { struct InterpreterCode {
const WasmFunction* function; // wasm function const WasmFunction* function; // wasm function
BodyLocalDecls locals; // local declarations BodyLocalDecls locals; // local declarations
const byte* orig_start; // start of original code const byte* start; // start of code
const byte* orig_end; // end of original code const byte* end; // end of code
byte* start; // start of (maybe altered) code SideTable* side_table; // precomputed side table for control flow
byte* end; // end of (maybe altered) code
SideTable* side_table; // precomputed side table for control flow.
const byte* at(pc_t pc) { return start + pc; } const byte* at(pc_t pc) { return start + pc; }
}; };
...@@ -769,7 +748,7 @@ class SideTable : public ZoneObject { ...@@ -769,7 +748,7 @@ class SideTable : public ZoneObject {
static_cast<uint32_t>(code->function->sig->return_count()); static_cast<uint32_t>(code->function->sig->return_count());
CLabel* func_label = CLabel* func_label =
CLabel::New(&control_transfer_zone, stack_height, func_arity); CLabel::New(&control_transfer_zone, stack_height, func_arity);
control_stack.emplace_back(code->orig_start, func_label, func_arity); control_stack.emplace_back(code->start, func_label, func_arity);
auto control_parent = [&]() -> Control& { auto control_parent = [&]() -> Control& {
DCHECK_LE(2, control_stack.size()); DCHECK_LE(2, control_stack.size());
return control_stack[control_stack.size() - 2]; return control_stack[control_stack.size() - 2];
...@@ -777,7 +756,7 @@ class SideTable : public ZoneObject { ...@@ -777,7 +756,7 @@ class SideTable : public ZoneObject {
auto copy_unreachable = [&] { auto copy_unreachable = [&] {
control_stack.back().unreachable = control_parent().unreachable; control_stack.back().unreachable = control_parent().unreachable;
}; };
for (BytecodeIterator i(code->orig_start, code->orig_end, &code->locals); for (BytecodeIterator i(code->start, code->end, &code->locals);
i.has_next(); i.next()) { i.has_next(); i.next()) {
WasmOpcode opcode = i.current(); WasmOpcode opcode = i.current();
int32_t exceptional_stack_height = 0; int32_t exceptional_stack_height = 0;
...@@ -809,7 +788,8 @@ class SideTable : public ZoneObject { ...@@ -809,7 +788,8 @@ class SideTable : public ZoneObject {
if (exceptional_stack_height + kCatchInArity > max_stack_height_) { if (exceptional_stack_height + kCatchInArity > max_stack_height_) {
max_stack_height_ = exceptional_stack_height + kCatchInArity; max_stack_height_ = exceptional_stack_height + kCatchInArity;
} }
TRACE("handler @%u: %s -> try @%u\n", i.pc_offset(), OpcodeName(opcode), TRACE("handler @%u: %s -> try @%u\n", i.pc_offset(),
WasmOpcodes::OpcodeName(opcode),
static_cast<uint32_t>(c->pc - code->start)); static_cast<uint32_t>(c->pc - code->start));
} }
switch (opcode) { switch (opcode) {
...@@ -859,7 +839,7 @@ class SideTable : public ZoneObject { ...@@ -859,7 +839,7 @@ class SideTable : public ZoneObject {
} }
DCHECK_NOT_NULL(c->else_label); DCHECK_NOT_NULL(c->else_label);
c->else_label->Bind(i.pc() + 1); c->else_label->Bind(i.pc() + 1);
c->else_label->Finish(&map_, code->orig_start); c->else_label->Finish(&map_, code->start);
stack_height = c->else_label->target_stack_height; stack_height = c->else_label->target_stack_height;
c->else_label = nullptr; c->else_label = nullptr;
DCHECK_IMPLIES(!unreachable, DCHECK_IMPLIES(!unreachable,
...@@ -895,7 +875,7 @@ class SideTable : public ZoneObject { ...@@ -895,7 +875,7 @@ class SideTable : public ZoneObject {
} }
DCHECK_NOT_NULL(c->else_label); DCHECK_NOT_NULL(c->else_label);
c->else_label->Bind(i.pc() + 1); c->else_label->Bind(i.pc() + 1);
c->else_label->Finish(&map_, code->orig_start); c->else_label->Finish(&map_, code->start);
c->else_label = nullptr; c->else_label = nullptr;
DCHECK_IMPLIES(!unreachable, DCHECK_IMPLIES(!unreachable,
stack_height >= c->end_label->target_stack_height); stack_height >= c->end_label->target_stack_height);
...@@ -924,7 +904,7 @@ class SideTable : public ZoneObject { ...@@ -924,7 +904,7 @@ class SideTable : public ZoneObject {
if (c->else_label) c->else_label->Bind(i.pc()); if (c->else_label) c->else_label->Bind(i.pc());
c->end_label->Bind(i.pc() + 1); c->end_label->Bind(i.pc() + 1);
} }
c->Finish(&map_, code->orig_start); c->Finish(&map_, code->start);
DCHECK_IMPLIES(!unreachable, DCHECK_IMPLIES(!unreachable,
stack_height >= c->end_label->target_stack_height); stack_height >= c->end_label->target_stack_height);
stack_height = c->end_label->target_stack_height + c->exit_arity; stack_height = c->end_label->target_stack_height + c->exit_arity;
...@@ -1030,10 +1010,8 @@ class CodeMap { ...@@ -1030,10 +1010,8 @@ class CodeMap {
void AddFunction(const WasmFunction* function, const byte* code_start, void AddFunction(const WasmFunction* function, const byte* code_start,
const byte* code_end) { const byte* code_end) {
InterpreterCode code = { InterpreterCode code = {function, BodyLocalDecls(zone_), code_start,
function, BodyLocalDecls(zone_), code_start, code_end, nullptr};
code_end, const_cast<byte*>(code_start), const_cast<byte*>(code_end),
nullptr};
DCHECK_EQ(interpreter_code_.size(), function->func_index); DCHECK_EQ(interpreter_code_.size(), function->func_index);
interpreter_code_.push_back(code); interpreter_code_.push_back(code);
...@@ -1044,8 +1022,6 @@ class CodeMap { ...@@ -1044,8 +1022,6 @@ class CodeMap {
DCHECK_LT(function->func_index, interpreter_code_.size()); DCHECK_LT(function->func_index, interpreter_code_.size());
InterpreterCode* code = &interpreter_code_[function->func_index]; InterpreterCode* code = &interpreter_code_[function->func_index];
DCHECK_EQ(function, code->function); DCHECK_EQ(function, code->function);
code->orig_start = start;
code->orig_end = end;
code->start = const_cast<byte*>(start); code->start = const_cast<byte*>(start);
code->end = const_cast<byte*>(end); code->end = const_cast<byte*>(end);
code->side_table = nullptr; code->side_table = nullptr;
...@@ -1239,16 +1215,10 @@ class ThreadImpl { ...@@ -1239,16 +1215,10 @@ class ThreadImpl {
TrapReason GetTrapReason() { return trap_reason_; } TrapReason GetTrapReason() { return trap_reason_; }
pc_t GetBreakpointPc() { return break_pc_; }
bool PossibleNondeterminism() { return possible_nondeterminism_; } bool PossibleNondeterminism() { return possible_nondeterminism_; }
uint64_t NumInterpretedCalls() { return num_interpreted_calls_; } uint64_t NumInterpretedCalls() { return num_interpreted_calls_; }
void AddBreakFlags(uint8_t flags) { break_flags_ |= flags; }
void ClearBreakFlags() { break_flags_ = WasmInterpreter::BreakFlag::None; }
Handle<Cell> reference_stack_cell() const { return reference_stack_cell_; } Handle<Cell> reference_stack_cell() const { return reference_stack_cell_; }
uint32_t NumActivations() { uint32_t NumActivations() {
...@@ -1409,10 +1379,8 @@ class ThreadImpl { ...@@ -1409,10 +1379,8 @@ class ThreadImpl {
Handle<Cell> reference_stack_cell_; // References are on an on-heap stack. Handle<Cell> reference_stack_cell_; // References are on an on-heap stack.
ZoneVector<Frame> frames_; ZoneVector<Frame> frames_;
WasmInterpreter::State state_ = WasmInterpreter::STOPPED; WasmInterpreter::State state_ = WasmInterpreter::STOPPED;
pc_t break_pc_ = kInvalidPc;
TrapReason trap_reason_ = kTrapCount; TrapReason trap_reason_ = kTrapCount;
bool possible_nondeterminism_ = false; bool possible_nondeterminism_ = false;
uint8_t break_flags_ = 0; // a combination of WasmInterpreter::BreakFlag
uint64_t num_interpreted_calls_ = 0; uint64_t num_interpreted_calls_ = 0;
// Store the stack height of each activation (for unwind and frame // Store the stack height of each activation (for unwind and frame
// inspection). // inspection).
...@@ -1490,15 +1458,6 @@ class ThreadImpl { ...@@ -1490,15 +1458,6 @@ class ThreadImpl {
frames_.back().pc = pc; frames_.back().pc = pc;
} }
bool SkipBreakpoint(InterpreterCode* code, pc_t pc) {
if (pc == break_pc_) {
// Skip the previously hit breakpoint when resuming.
break_pc_ = kInvalidPc;
return true;
}
return false;
}
void ReloadFromFrameOnException(Decoder* decoder, InterpreterCode** code, void ReloadFromFrameOnException(Decoder* decoder, InterpreterCode** code,
pc_t* pc, pc_t* limit) { pc_t* pc, pc_t* limit) {
Frame* top = &frames_.back(); Frame* top = &frames_.back();
...@@ -1527,7 +1486,7 @@ class ThreadImpl { ...@@ -1527,7 +1486,7 @@ class ThreadImpl {
} }
pc_t ReturnPc(Decoder* decoder, InterpreterCode* code, pc_t pc) { pc_t ReturnPc(Decoder* decoder, InterpreterCode* code, pc_t pc) {
switch (code->orig_start[pc]) { switch (code->start[pc]) {
case kExprCallFunction: { case kExprCallFunction: {
CallFunctionImmediate<Decoder::kNoValidate> imm(decoder, code->at(pc)); CallFunctionImmediate<Decoder::kNoValidate> imm(decoder, code->at(pc));
return pc + 1 + imm.length; return pc + 1 + imm.length;
...@@ -1966,8 +1925,9 @@ class ThreadImpl { ...@@ -1966,8 +1925,9 @@ class ThreadImpl {
return true; return true;
} }
default: default:
FATAL("Unknown or unimplemented opcode #%d:%s", code->start[pc], FATAL(
OpcodeName(code->start[pc])); "Unknown or unimplemented opcode #%d:%s", code->start[pc],
WasmOpcodes::OpcodeName(static_cast<WasmOpcode>(code->start[pc])));
UNREACHABLE(); UNREACHABLE();
} }
return false; return false;
...@@ -3053,20 +3013,11 @@ class ThreadImpl { ...@@ -3053,20 +3013,11 @@ class ThreadImpl {
Decoder decoder(code->start, code->end); Decoder decoder(code->start, code->end);
pc_t limit = code->end - code->start; pc_t limit = code->end - code->start;
bool hit_break = false;
while (true) { while (true) {
#define PAUSE_IF_BREAK_FLAG(flag) \
if (V8_UNLIKELY(break_flags_ & WasmInterpreter::BreakFlag::flag)) { \
hit_break = true; \
max = 0; \
}
DCHECK_GT(limit, pc); DCHECK_GT(limit, pc);
DCHECK_NOT_NULL(code->start); DCHECK_NOT_NULL(code->start);
// Do first check for a breakpoint, in order to set hit_break correctly.
const char* skip = " ";
int len = 1; int len = 1;
// We need to store this, because SIMD opcodes are LEB encoded, and later // We need to store this, because SIMD opcodes are LEB encoded, and later
// on when executing, we need to know where to read immediates from. // on when executing, we need to know where to read immediates from.
...@@ -3078,23 +3029,6 @@ class ThreadImpl { ...@@ -3078,23 +3029,6 @@ class ThreadImpl {
&code->start[pc], &simd_opcode_length); &code->start[pc], &simd_opcode_length);
len += simd_opcode_length; len += simd_opcode_length;
} }
if (V8_UNLIKELY(orig == kInternalBreakpoint)) {
orig = code->orig_start[pc];
if (WasmOpcodes::IsPrefixOpcode(static_cast<WasmOpcode>(orig))) {
opcode = decoder.read_prefixed_opcode<Decoder::kNoValidate>(
&code->start[pc]);
}
if (SkipBreakpoint(code, pc)) {
// skip breakpoint by switching on original code.
skip = "[skip] ";
} else {
TRACE("@%-3zu: [break] %-24s:", pc, WasmOpcodes::OpcodeName(opcode));
TraceValueStack();
TRACE("\n");
hit_break = true;
break;
}
}
// If max is 0, break. If max is positive (a limit is set), decrement it. // If max is 0, break. If max is positive (a limit is set), decrement it.
if (max >= 0 && WasmOpcodes::IsBreakable(opcode)) { if (max >= 0 && WasmOpcodes::IsBreakable(opcode)) {
...@@ -3102,8 +3036,7 @@ class ThreadImpl { ...@@ -3102,8 +3036,7 @@ class ThreadImpl {
--max; --max;
} }
USE(skip); TRACE("@%-3zu: %-24s:", pc, WasmOpcodes::OpcodeName(opcode));
TRACE("@%-3zu: %s%-24s:", pc, skip, WasmOpcodes::OpcodeName(opcode));
TraceValueStack(); TraceValueStack();
TRACE("\n"); TRACE("\n");
...@@ -3112,7 +3045,7 @@ class ThreadImpl { ...@@ -3112,7 +3045,7 @@ class ThreadImpl {
// stack was modified accordingly. // stack was modified accordingly.
std::pair<uint32_t, uint32_t> stack_effect = std::pair<uint32_t, uint32_t> stack_effect =
StackEffect(codemap_->module(), frames_.back().code->function->sig, StackEffect(codemap_->module(), frames_.back().code->function->sig,
code->orig_start + pc, code->orig_end); code->start + pc, code->end);
sp_t expected_new_stack_height = sp_t expected_new_stack_height =
StackHeight() - stack_effect.first + stack_effect.second; StackHeight() - stack_effect.first + stack_effect.second;
#endif #endif
...@@ -3239,7 +3172,6 @@ class ThreadImpl { ...@@ -3239,7 +3172,6 @@ class ThreadImpl {
case kExprReturn: { case kExprReturn: {
size_t arity = code->function->sig->return_count(); size_t arity = code->function->sig->return_count();
if (!DoReturn(&decoder, &code, &pc, &limit, arity)) return; if (!DoReturn(&decoder, &code, &pc, &limit, arity)) return;
PAUSE_IF_BREAK_FLAG(AfterReturn);
continue; // Do not bump pc. continue; // Do not bump pc.
} }
case kExprUnreachable: { case kExprUnreachable: {
...@@ -3334,7 +3266,6 @@ class ThreadImpl { ...@@ -3334,7 +3266,6 @@ class ThreadImpl {
// Direct calls are checked statically. // Direct calls are checked statically.
UNREACHABLE(); UNREACHABLE();
case ExternalCallResult::EXTERNAL_RETURNED: case ExternalCallResult::EXTERNAL_RETURNED:
PAUSE_IF_BREAK_FLAG(AfterCall);
len = 1 + imm.length; len = 1 + imm.length;
break; break;
case ExternalCallResult::EXTERNAL_UNWOUND: case ExternalCallResult::EXTERNAL_UNWOUND:
...@@ -3348,7 +3279,6 @@ class ThreadImpl { ...@@ -3348,7 +3279,6 @@ class ThreadImpl {
// Execute an internal call. // Execute an internal call.
if (!DoCall(&decoder, target, &pc, &limit)) return; if (!DoCall(&decoder, target, &pc, &limit)) return;
code = target; code = target;
PAUSE_IF_BREAK_FLAG(AfterCall);
continue; // Do not bump pc. continue; // Do not bump pc.
} break; } break;
...@@ -3365,14 +3295,12 @@ class ThreadImpl { ...@@ -3365,14 +3295,12 @@ class ThreadImpl {
if (!DoCall(&decoder, result.interpreter_code, &pc, &limit)) if (!DoCall(&decoder, result.interpreter_code, &pc, &limit))
return; return;
code = result.interpreter_code; code = result.interpreter_code;
PAUSE_IF_BREAK_FLAG(AfterCall);
continue; // Do not bump pc. continue; // Do not bump pc.
case ExternalCallResult::INVALID_FUNC: case ExternalCallResult::INVALID_FUNC:
return DoTrap(kTrapFuncInvalid, pc); return DoTrap(kTrapFuncInvalid, pc);
case ExternalCallResult::SIGNATURE_MISMATCH: case ExternalCallResult::SIGNATURE_MISMATCH:
return DoTrap(kTrapFuncSigMismatch, pc); return DoTrap(kTrapFuncSigMismatch, pc);
case ExternalCallResult::EXTERNAL_RETURNED: case ExternalCallResult::EXTERNAL_RETURNED:
PAUSE_IF_BREAK_FLAG(AfterCall);
len = 1 + imm.length; len = 1 + imm.length;
break; break;
case ExternalCallResult::EXTERNAL_UNWOUND: case ExternalCallResult::EXTERNAL_UNWOUND:
...@@ -3392,8 +3320,6 @@ class ThreadImpl { ...@@ -3392,8 +3320,6 @@ class ThreadImpl {
// Enter internal found function. // Enter internal found function.
if (!DoReturnCall(&decoder, target, &pc, &limit)) return; if (!DoReturnCall(&decoder, target, &pc, &limit)) return;
code = target; code = target;
PAUSE_IF_BREAK_FLAG(AfterCall);
continue; // Do not bump pc. continue; // Do not bump pc.
} }
// Function is imported. // Function is imported.
...@@ -3418,7 +3344,6 @@ class ThreadImpl { ...@@ -3418,7 +3344,6 @@ class ThreadImpl {
} }
size_t arity = code->function->sig->return_count(); size_t arity = code->function->sig->return_count();
if (!DoReturn(&decoder, &code, &pc, &limit, arity)) return; if (!DoReturn(&decoder, &code, &pc, &limit, arity)) return;
PAUSE_IF_BREAK_FLAG(AfterReturn);
continue; continue;
} break; } break;
...@@ -3441,7 +3366,6 @@ class ThreadImpl { ...@@ -3441,7 +3366,6 @@ class ThreadImpl {
// The function belongs to this instance. Enter it directly. // The function belongs to this instance. Enter it directly.
if (!DoReturnCall(&decoder, target, &pc, &limit)) return; if (!DoReturnCall(&decoder, target, &pc, &limit)) return;
code = result.interpreter_code; code = result.interpreter_code;
PAUSE_IF_BREAK_FLAG(AfterCall);
continue; // Do not bump pc. continue; // Do not bump pc.
} }
case ExternalCallResult::INVALID_FUNC: case ExternalCallResult::INVALID_FUNC:
...@@ -3453,7 +3377,6 @@ class ThreadImpl { ...@@ -3453,7 +3377,6 @@ class ThreadImpl {
size_t arity = code->function->sig->return_count(); size_t arity = code->function->sig->return_count();
if (!DoReturn(&decoder, &code, &pc, &limit, arity)) return; if (!DoReturn(&decoder, &code, &pc, &limit, arity)) return;
PAUSE_IF_BREAK_FLAG(AfterCall);
break; break;
} }
case ExternalCallResult::EXTERNAL_UNWOUND: case ExternalCallResult::EXTERNAL_UNWOUND:
...@@ -3753,7 +3676,8 @@ class ThreadImpl { ...@@ -3753,7 +3676,8 @@ class ThreadImpl {
default: default:
FATAL("Unknown or unimplemented opcode #%d:%s", code->start[pc], FATAL("Unknown or unimplemented opcode #%d:%s", code->start[pc],
OpcodeName(code->start[pc])); WasmOpcodes::OpcodeName(
static_cast<WasmOpcode>(code->start[pc])));
UNREACHABLE(); UNREACHABLE();
} }
...@@ -3770,13 +3694,10 @@ class ThreadImpl { ...@@ -3770,13 +3694,10 @@ class ThreadImpl {
size_t arity = code->function->sig->return_count(); size_t arity = code->function->sig->return_count();
DCHECK_EQ(StackHeight() - arity, frames_.back().llimit()); DCHECK_EQ(StackHeight() - arity, frames_.back().llimit());
if (!DoReturn(&decoder, &code, &pc, &limit, arity)) return; if (!DoReturn(&decoder, &code, &pc, &limit, arity)) return;
PAUSE_IF_BREAK_FLAG(AfterReturn);
} }
#undef PAUSE_IF_BREAK_FLAG
} }
state_ = WasmInterpreter::PAUSED; state_ = WasmInterpreter::PAUSED;
break_pc_ = hit_break ? pc : kInvalidPc;
CommitPc(pc); CommitPc(pc);
} }
...@@ -4230,9 +4151,6 @@ WasmInterpreter::Thread::RaiseException(Isolate* isolate, ...@@ -4230,9 +4151,6 @@ WasmInterpreter::Thread::RaiseException(Isolate* isolate,
ThreadImpl::ReferenceStackScope stack_scope(impl); ThreadImpl::ReferenceStackScope stack_scope(impl);
return impl->RaiseException(isolate, exception); return impl->RaiseException(isolate, exception);
} }
pc_t WasmInterpreter::Thread::GetBreakpointPc() {
return ToImpl(this)->GetBreakpointPc();
}
int WasmInterpreter::Thread::GetFrameCount() { int WasmInterpreter::Thread::GetFrameCount() {
return ToImpl(this)->GetFrameCount(); return ToImpl(this)->GetFrameCount();
} }
...@@ -4255,12 +4173,6 @@ bool WasmInterpreter::Thread::PossibleNondeterminism() { ...@@ -4255,12 +4173,6 @@ bool WasmInterpreter::Thread::PossibleNondeterminism() {
uint64_t WasmInterpreter::Thread::NumInterpretedCalls() { uint64_t WasmInterpreter::Thread::NumInterpretedCalls() {
return ToImpl(this)->NumInterpretedCalls(); return ToImpl(this)->NumInterpretedCalls();
} }
void WasmInterpreter::Thread::AddBreakFlags(uint8_t flags) {
ToImpl(this)->AddBreakFlags(flags);
}
void WasmInterpreter::Thread::ClearBreakFlags() {
ToImpl(this)->ClearBreakFlags();
}
uint32_t WasmInterpreter::Thread::NumActivations() { uint32_t WasmInterpreter::Thread::NumActivations() {
return ToImpl(this)->NumActivations(); return ToImpl(this)->NumActivations();
} }
...@@ -4336,48 +4248,6 @@ void WasmInterpreter::Run() { internals_->threads_[0].Run(); } ...@@ -4336,48 +4248,6 @@ void WasmInterpreter::Run() { internals_->threads_[0].Run(); }
void WasmInterpreter::Pause() { internals_->threads_[0].Pause(); } void WasmInterpreter::Pause() { internals_->threads_[0].Pause(); }
void WasmInterpreter::PrepareStepIn(const WasmFunction* function) {
// Set a breakpoint at the start of function.
InterpreterCode* code = internals_->codemap_.GetCode(function);
pc_t pc = code->locals.encoded_size;
SetBreakpoint(function, pc, true);
}
bool WasmInterpreter::SetBreakpoint(const WasmFunction* function, pc_t pc,
bool enabled) {
InterpreterCode* code = internals_->codemap_.GetCode(function);
size_t size = static_cast<size_t>(code->end - code->start);
// Check bounds for {pc}.
if (pc < code->locals.encoded_size || pc >= size) return false;
// Make a copy of the code before enabling a breakpoint.
if (enabled && code->orig_start == code->start) {
code->start = reinterpret_cast<byte*>(zone_.New(size));
memcpy(code->start, code->orig_start, size);
code->end = code->start + size;
}
bool prev = code->start[pc] == kInternalBreakpoint;
if (enabled) {
code->start[pc] = kInternalBreakpoint;
} else {
code->start[pc] = code->orig_start[pc];
}
return prev;
}
bool WasmInterpreter::GetBreakpoint(const WasmFunction* function, pc_t pc) {
InterpreterCode* code = internals_->codemap_.GetCode(function);
size_t size = static_cast<size_t>(code->end - code->start);
// Check bounds for {pc}.
if (pc < code->locals.encoded_size || pc >= size) return false;
// Check if a breakpoint is present at that place in the code.
return code->start[pc] == kInternalBreakpoint;
}
bool WasmInterpreter::SetTracing(const WasmFunction* function, bool enabled) {
UNIMPLEMENTED();
return false;
}
int WasmInterpreter::GetThreadCount() { int WasmInterpreter::GetThreadCount() {
return 1; // only one thread for now. return 1; // only one thread for now.
} }
...@@ -4409,8 +4279,7 @@ ControlTransferMap WasmInterpreter::ComputeControlTransfersForTesting( ...@@ -4409,8 +4279,7 @@ ControlTransferMap WasmInterpreter::ComputeControlTransfersForTesting(
false, // imported false, // imported
false, // exported false, // exported
false}; // declared false}; // declared
InterpreterCode code{ InterpreterCode code{&function, BodyLocalDecls(zone), start, end, nullptr};
&function, BodyLocalDecls(zone), start, end, nullptr, nullptr, nullptr};
// Now compute and return the control transfers. // Now compute and return the control transfers.
SideTable side_table(zone, module, &code); SideTable side_table(zone, module, &code);
...@@ -4445,7 +4314,6 @@ void InterpretedFrameDeleter::operator()(InterpretedFrame* ptr) { ...@@ -4445,7 +4314,6 @@ void InterpretedFrameDeleter::operator()(InterpretedFrame* ptr) {
#undef TRACE #undef TRACE
#undef LANE #undef LANE
#undef FOREACH_INTERNAL_OPCODE
#undef FOREACH_SIMPLE_BINOP #undef FOREACH_SIMPLE_BINOP
#undef FOREACH_OTHER_BINOP #undef FOREACH_OTHER_BINOP
#undef FOREACH_I32CONV_FLOATOP #undef FOREACH_I32CONV_FLOATOP
......
...@@ -29,8 +29,6 @@ using sp_t = size_t; ...@@ -29,8 +29,6 @@ using sp_t = size_t;
using pcdiff_t = int32_t; using pcdiff_t = int32_t;
using spdiff_t = uint32_t; using spdiff_t = uint32_t;
constexpr pc_t kInvalidPc = 0x80000000;
struct ControlTransferEntry { struct ControlTransferEntry {
// Distance from the instruction to the label to jump to (forward, but can be // Distance from the instruction to the label to jump to (forward, but can be
// negative). // negative).
...@@ -132,7 +130,6 @@ class V8_EXPORT_PRIVATE WasmInterpreter { ...@@ -132,7 +130,6 @@ class V8_EXPORT_PRIVATE WasmInterpreter {
ExceptionHandlingResult RaiseException(Isolate*, Handle<Object> exception); ExceptionHandlingResult RaiseException(Isolate*, Handle<Object> exception);
// Stack inspection and modification. // Stack inspection and modification.
pc_t GetBreakpointPc();
int GetFrameCount(); int GetFrameCount();
// The InterpretedFrame is only valid as long as the Thread is paused. // The InterpretedFrame is only valid as long as the Thread is paused.
FramePtr GetFrame(int index); FramePtr GetFrame(int index);
...@@ -147,14 +144,6 @@ class V8_EXPORT_PRIVATE WasmInterpreter { ...@@ -147,14 +144,6 @@ class V8_EXPORT_PRIVATE WasmInterpreter {
// Returns the number of calls / function frames executed on this thread. // Returns the number of calls / function frames executed on this thread.
uint64_t NumInterpretedCalls(); uint64_t NumInterpretedCalls();
// Thread-specific breakpoints.
// TODO(wasm): Implement this once we support multiple threads.
// bool SetBreakpoint(const WasmFunction* function, int pc, bool enabled);
// bool GetBreakpoint(const WasmFunction* function, int pc);
void AddBreakFlags(uint8_t flags);
void ClearBreakFlags();
// Each thread can have multiple activations, each represented by a portion // Each thread can have multiple activations, each represented by a portion
// of the stack frames of this thread. StartActivation returns the id // of the stack frames of this thread. StartActivation returns the id
// (counting from 0 up) of the started activation. // (counting from 0 up) of the started activation.
...@@ -180,19 +169,6 @@ class V8_EXPORT_PRIVATE WasmInterpreter { ...@@ -180,19 +169,6 @@ class V8_EXPORT_PRIVATE WasmInterpreter {
void Run(); void Run();
void Pause(); void Pause();
// Prepare {function} for stepping in from Javascript.
void PrepareStepIn(const WasmFunction* function);
// Set a breakpoint at {pc} in {function} to be {enabled}. Returns the
// previous state of the breakpoint at {pc}.
bool SetBreakpoint(const WasmFunction* function, pc_t pc, bool enabled);
// Gets the current state of the breakpoint at {function}.
bool GetBreakpoint(const WasmFunction* function, pc_t pc);
// Enable or disable tracing for {function}. Return the previous state.
bool SetTracing(const WasmFunction* function, bool enabled);
//========================================================================== //==========================================================================
// Thread iteration and inspection. // Thread iteration and inspection.
//========================================================================== //==========================================================================
......
...@@ -273,49 +273,6 @@ std::unique_ptr<int[]> Find(byte* code, size_t code_size, int n, ...) { ...@@ -273,49 +273,6 @@ std::unique_ptr<int[]> Find(byte* code, size_t code_size, int n, ...) {
return offsets; return offsets;
} }
TEST(Breakpoint_I32Add) {
static const int kLocalsDeclSize = 1;
static const int kNumBreakpoints = 3;
byte code[] = {WASM_I32_ADD(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))};
std::unique_ptr<int[]> offsets =
Find(code, sizeof(code), kNumBreakpoints, kExprLocalGet, kExprLocalGet,
kExprI32Add);
WasmRunner<int32_t, uint32_t, uint32_t> r(ExecutionTier::kInterpreter);
r.Build(code, code + arraysize(code));
WasmInterpreter* interpreter = r.interpreter();
WasmInterpreter::Thread* thread = interpreter->GetThread(0);
for (int i = 0; i < kNumBreakpoints; i++) {
interpreter->SetBreakpoint(r.function(), kLocalsDeclSize + offsets[i],
true);
}
FOR_UINT32_INPUTS(a) {
for (uint32_t b = 11; b < 3000000000u; b += 1000000000u) {
thread->Reset();
WasmValue args[] = {WasmValue(a), WasmValue(b)};
thread->InitFrame(r.function(), args);
for (int i = 0; i < kNumBreakpoints; i++) {
thread->Run(); // run to next breakpoint
// Check the thread stopped at the right pc.
CHECK_EQ(WasmInterpreter::PAUSED, thread->state());
CHECK_EQ(static_cast<size_t>(kLocalsDeclSize + offsets[i]),
thread->GetBreakpointPc());
}
thread->Run(); // run to completion
// Check the thread finished with the right value.
CHECK_EQ(WasmInterpreter::FINISHED, thread->state());
uint32_t expected = (a) + (b);
CHECK_EQ(expected, thread->GetReturnValue().to<uint32_t>());
}
}
}
TEST(Step_I32Mul) { TEST(Step_I32Mul) {
static const int kTraceLength = 4; static const int kTraceLength = 4;
byte code[] = {WASM_I32_MUL(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))}; byte code[] = {WASM_I32_MUL(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))};
...@@ -351,49 +308,6 @@ TEST(Step_I32Mul) { ...@@ -351,49 +308,6 @@ TEST(Step_I32Mul) {
} }
} }
TEST(Breakpoint_I32And_disable) {
static const int kLocalsDeclSize = 1;
static const int kNumBreakpoints = 1;
byte code[] = {WASM_I32_AND(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))};
std::unique_ptr<int[]> offsets =
Find(code, sizeof(code), kNumBreakpoints, kExprI32And);
WasmRunner<int32_t, uint32_t, uint32_t> r(ExecutionTier::kInterpreter);
r.Build(code, code + arraysize(code));
WasmInterpreter* interpreter = r.interpreter();
WasmInterpreter::Thread* thread = interpreter->GetThread(0);
FOR_UINT32_INPUTS(a) {
for (uint32_t b = 11; b < 3000000000u; b += 1000000000u) {
// Run with and without breakpoints.
for (int do_break = 0; do_break < 2; do_break++) {
interpreter->SetBreakpoint(r.function(), kLocalsDeclSize + offsets[0],
do_break);
thread->Reset();
WasmValue args[] = {WasmValue(a), WasmValue(b)};
thread->InitFrame(r.function(), args);
if (do_break) {
thread->Run(); // run to next breakpoint
// Check the thread stopped at the right pc.
CHECK_EQ(WasmInterpreter::PAUSED, thread->state());
CHECK_EQ(static_cast<size_t>(kLocalsDeclSize + offsets[0]),
thread->GetBreakpointPc());
}
thread->Run(); // run to completion
// Check the thread finished with the right value.
CHECK_EQ(WasmInterpreter::FINISHED, thread->state());
uint32_t expected = (a) & (b);
CHECK_EQ(expected, thread->GetReturnValue().to<uint32_t>());
}
}
}
}
TEST(MemoryGrow) { TEST(MemoryGrow) {
{ {
WasmRunner<int32_t, uint32_t> r(ExecutionTier::kInterpreter); WasmRunner<int32_t, uint32_t> r(ExecutionTier::kInterpreter);
......
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