| Index: src/wasm/wasm-debug.cc
|
| diff --git a/src/wasm/wasm-debug.cc b/src/wasm/wasm-debug.cc
|
| index 6cb865d59cfbeafb0f98db4ef1a30fabdf391738..fe135dd1eca63b9266be0e47f43ee3ee5fbdeb83 100644
|
| --- a/src/wasm/wasm-debug.cc
|
| +++ b/src/wasm/wasm-debug.cc
|
| @@ -21,17 +21,23 @@ using namespace v8::internal::wasm;
|
|
|
| namespace {
|
|
|
| +// Forward declaration.
|
| +class InterpreterHandle;
|
| +InterpreterHandle* GetInterpreterHandle(WasmDebugInfo* debug_info);
|
| +
|
| class InterpreterHandle {
|
| AccountingAllocator allocator_;
|
| WasmInstance instance_;
|
| WasmInterpreter interpreter_;
|
| + Isolate* isolate_;
|
|
|
| public:
|
| // Initialize in the right order, using helper methods to make this possible.
|
| // WasmInterpreter has to be allocated in place, since it is not movable.
|
| InterpreterHandle(Isolate* isolate, WasmDebugInfo* debug_info)
|
| : instance_(debug_info->wasm_instance()->compiled_module()->module()),
|
| - interpreter_(GetBytesEnv(&instance_, debug_info), &allocator_) {
|
| + interpreter_(GetBytesEnv(&instance_, debug_info), &allocator_),
|
| + isolate_(isolate) {
|
| Handle<JSArrayBuffer> mem_buffer =
|
| handle(debug_info->wasm_instance()->memory_buffer(), isolate);
|
| if (mem_buffer->IsUndefined(isolate)) {
|
| @@ -95,10 +101,9 @@ class InterpreterHandle {
|
| do {
|
| state = thread->Run();
|
| switch (state) {
|
| - case WasmInterpreter::State::PAUSED: {
|
| - // We hit a breakpoint.
|
| - // TODO(clemensh): Handle this.
|
| - } break;
|
| + case WasmInterpreter::State::PAUSED:
|
| + NotifyDebugEventListeners();
|
| + break;
|
| case WasmInterpreter::State::FINISHED:
|
| // Perfect, just break the switch and exit the loop.
|
| break;
|
| @@ -136,6 +141,83 @@ class InterpreterHandle {
|
| }
|
| }
|
| }
|
| +
|
| + Handle<WasmInstanceObject> GetInstanceObject() {
|
| + StackTraceFrameIterator it(isolate_);
|
| + WasmInterpreterEntryFrame* frame =
|
| + WasmInterpreterEntryFrame::cast(it.frame());
|
| + Handle<WasmInstanceObject> instance_obj(frame->wasm_instance(), isolate_);
|
| + DCHECK_EQ(this, GetInterpreterHandle(instance_obj->debug_info()));
|
| + return instance_obj;
|
| + }
|
| +
|
| + void NotifyDebugEventListeners() {
|
| + // Enter the debugger.
|
| + DebugScope debug_scope(isolate_->debug());
|
| + if (debug_scope.failed()) return;
|
| +
|
| + // Postpone interrupt during breakpoint processing.
|
| + PostponeInterruptsScope postpone(isolate_);
|
| +
|
| + // If we are paused on a breakpoint, clear all stepping and notify the
|
| + // listeners.
|
| + Handle<WasmCompiledModule> compiled_module(
|
| + GetInstanceObject()->compiled_module(), isolate_);
|
| + int position = GetTopPosition(compiled_module);
|
| + MaybeHandle<FixedArray> hit_breakpoints;
|
| + if (isolate_->debug()->break_points_active()) {
|
| + hit_breakpoints = compiled_module->CheckBreakPoints(position);
|
| + }
|
| +
|
| + // If we hit a breakpoint, pass a JSArray with all breakpoints, otherwise
|
| + // pass undefined.
|
| + Handle<Object> hit_breakpoints_js;
|
| + if (hit_breakpoints.is_null()) {
|
| + hit_breakpoints_js = isolate_->factory()->undefined_value();
|
| + } else {
|
| + hit_breakpoints_js = isolate_->factory()->NewJSArrayWithElements(
|
| + hit_breakpoints.ToHandleChecked());
|
| + }
|
| +
|
| + isolate_->debug()->OnDebugBreak(hit_breakpoints_js, false);
|
| + }
|
| +
|
| + int GetTopPosition(Handle<WasmCompiledModule> compiled_module) {
|
| + DCHECK_EQ(1, interpreter()->GetThreadCount());
|
| + WasmInterpreter::Thread* thread = interpreter()->GetThread(0);
|
| + DCHECK_LT(0, thread->GetFrameCount());
|
| +
|
| + wasm::InterpretedFrame frame =
|
| + thread->GetFrame(thread->GetFrameCount() - 1);
|
| + return compiled_module->GetFunctionOffset(frame.function()->func_index) +
|
| + frame.pc();
|
| + }
|
| +
|
| + std::vector<std::pair<uint32_t, int>> GetInterpretedStack(
|
| + Address frame_pointer) {
|
| + // TODO(clemensh): Use frame_pointer.
|
| + USE(frame_pointer);
|
| +
|
| + DCHECK_EQ(1, interpreter()->GetThreadCount());
|
| + WasmInterpreter::Thread* thread = interpreter()->GetThread(0);
|
| + std::vector<std::pair<uint32_t, int>> stack(thread->GetFrameCount());
|
| + for (int i = 0, e = thread->GetFrameCount(); i < e; ++i) {
|
| + wasm::InterpretedFrame frame = thread->GetFrame(i);
|
| + stack[i] = {frame.function()->func_index, frame.pc()};
|
| + }
|
| + return stack;
|
| + }
|
| +
|
| + std::unique_ptr<wasm::InterpretedFrame> GetInterpretedFrame(
|
| + Address frame_pointer, int idx) {
|
| + // TODO(clemensh): Use frame_pointer.
|
| + USE(frame_pointer);
|
| +
|
| + DCHECK_EQ(1, interpreter()->GetThreadCount());
|
| + WasmInterpreter::Thread* thread = interpreter()->GetThread(0);
|
| + return std::unique_ptr<wasm::InterpretedFrame>(
|
| + new wasm::InterpretedFrame(thread->GetMutableFrame(idx)));
|
| + }
|
| };
|
|
|
| InterpreterHandle* GetOrCreateInterpreterHandle(
|
| @@ -151,6 +233,12 @@ InterpreterHandle* GetOrCreateInterpreterHandle(
|
| return Handle<Managed<InterpreterHandle>>::cast(handle)->get();
|
| }
|
|
|
| +InterpreterHandle* GetInterpreterHandle(WasmDebugInfo* debug_info) {
|
| + Object* handle_obj = debug_info->get(WasmDebugInfo::kInterpreterHandle);
|
| + DCHECK(!handle_obj->IsUndefined(debug_info->GetIsolate()));
|
| + return Managed<InterpreterHandle>::cast(handle_obj)->get();
|
| +}
|
| +
|
| int GetNumFunctions(WasmInstanceObject* instance) {
|
| size_t num_functions =
|
| instance->compiled_module()->module()->functions.size();
|
| @@ -265,10 +353,18 @@ void WasmDebugInfo::SetBreakpoint(Handle<WasmDebugInfo> debug_info,
|
| EnsureRedirectToInterpreter(isolate, debug_info, func_index);
|
| }
|
|
|
| -void WasmDebugInfo::RunInterpreter(Handle<WasmDebugInfo> debug_info,
|
| - int func_index, uint8_t* arg_buffer) {
|
| +void WasmDebugInfo::RunInterpreter(int func_index, uint8_t* arg_buffer) {
|
| DCHECK_LE(0, func_index);
|
| - InterpreterHandle* interp_handle =
|
| - GetOrCreateInterpreterHandle(debug_info->GetIsolate(), debug_info);
|
| - interp_handle->Execute(static_cast<uint32_t>(func_index), arg_buffer);
|
| + GetInterpreterHandle(this)->Execute(static_cast<uint32_t>(func_index),
|
| + arg_buffer);
|
| +}
|
| +
|
| +std::vector<std::pair<uint32_t, int>> WasmDebugInfo::GetInterpretedStack(
|
| + Address frame_pointer) {
|
| + return GetInterpreterHandle(this)->GetInterpretedStack(frame_pointer);
|
| +}
|
| +
|
| +std::unique_ptr<wasm::InterpretedFrame> WasmDebugInfo::GetInterpretedFrame(
|
| + Address frame_pointer, int idx) {
|
| + return GetInterpreterHandle(this)->GetInterpretedFrame(frame_pointer, idx);
|
| }
|
|
|