Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(120)

Side by Side Diff: src/wasm/wasm-debug.cc

Issue 2629823003: [wasm] Implement frame inspection for interpreted frames (Closed)
Patch Set: Rebase after Yangs revert ಠ益ಠ Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/wasm/managed.h ('k') | src/wasm/wasm-interpreter.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2016 the V8 project authors. All rights reserved. 1 // Copyright 2016 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/assembler-inl.h" 5 #include "src/assembler-inl.h"
6 #include "src/assert-scope.h" 6 #include "src/assert-scope.h"
7 #include "src/compiler/wasm-compiler.h" 7 #include "src/compiler/wasm-compiler.h"
8 #include "src/debug/debug.h" 8 #include "src/debug/debug.h"
9 #include "src/factory.h" 9 #include "src/factory.h"
10 #include "src/frames-inl.h" 10 #include "src/frames-inl.h"
11 #include "src/isolate.h" 11 #include "src/isolate.h"
12 #include "src/wasm/module-decoder.h" 12 #include "src/wasm/module-decoder.h"
13 #include "src/wasm/wasm-interpreter.h" 13 #include "src/wasm/wasm-interpreter.h"
14 #include "src/wasm/wasm-limits.h" 14 #include "src/wasm/wasm-limits.h"
15 #include "src/wasm/wasm-module.h" 15 #include "src/wasm/wasm-module.h"
16 #include "src/wasm/wasm-objects.h" 16 #include "src/wasm/wasm-objects.h"
17 #include "src/zone/accounting-allocator.h" 17 #include "src/zone/accounting-allocator.h"
18 18
19 using namespace v8::internal; 19 using namespace v8::internal;
20 using namespace v8::internal::wasm; 20 using namespace v8::internal::wasm;
21 21
22 namespace { 22 namespace {
23 23
24 // Forward declaration.
25 class InterpreterHandle;
26 InterpreterHandle* GetInterpreterHandle(WasmDebugInfo* debug_info);
27
24 class InterpreterHandle { 28 class InterpreterHandle {
25 AccountingAllocator allocator_; 29 AccountingAllocator allocator_;
26 WasmInstance instance_; 30 WasmInstance instance_;
27 WasmInterpreter interpreter_; 31 WasmInterpreter interpreter_;
32 Isolate* isolate_;
28 33
29 public: 34 public:
30 // Initialize in the right order, using helper methods to make this possible. 35 // Initialize in the right order, using helper methods to make this possible.
31 // WasmInterpreter has to be allocated in place, since it is not movable. 36 // WasmInterpreter has to be allocated in place, since it is not movable.
32 InterpreterHandle(Isolate* isolate, WasmDebugInfo* debug_info) 37 InterpreterHandle(Isolate* isolate, WasmDebugInfo* debug_info)
33 : instance_(debug_info->wasm_instance()->compiled_module()->module()), 38 : instance_(debug_info->wasm_instance()->compiled_module()->module()),
34 interpreter_(GetBytesEnv(&instance_, debug_info), &allocator_) { 39 interpreter_(GetBytesEnv(&instance_, debug_info), &allocator_),
40 isolate_(isolate) {
35 Handle<JSArrayBuffer> mem_buffer = 41 Handle<JSArrayBuffer> mem_buffer =
36 handle(debug_info->wasm_instance()->memory_buffer(), isolate); 42 handle(debug_info->wasm_instance()->memory_buffer(), isolate);
37 if (mem_buffer->IsUndefined(isolate)) { 43 if (mem_buffer->IsUndefined(isolate)) {
38 DCHECK_EQ(0, instance_.module->min_mem_pages); 44 DCHECK_EQ(0, instance_.module->min_mem_pages);
39 instance_.mem_start = nullptr; 45 instance_.mem_start = nullptr;
40 instance_.mem_size = 0; 46 instance_.mem_size = 0;
41 } else { 47 } else {
42 instance_.mem_start = 48 instance_.mem_start =
43 reinterpret_cast<byte*>(mem_buffer->backing_store()); 49 reinterpret_cast<byte*>(mem_buffer->backing_store());
44 CHECK(mem_buffer->byte_length()->ToUint32(&instance_.mem_size)); 50 CHECK(mem_buffer->byte_length()->ToUint32(&instance_.mem_size));
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
88 // We do not support reentering an already running interpreter at the moment 94 // We do not support reentering an already running interpreter at the moment
89 // (like INTERPRETER -> JS -> WASM -> INTERPRETER). 95 // (like INTERPRETER -> JS -> WASM -> INTERPRETER).
90 DCHECK(thread->state() == WasmInterpreter::STOPPED || 96 DCHECK(thread->state() == WasmInterpreter::STOPPED ||
91 thread->state() == WasmInterpreter::FINISHED); 97 thread->state() == WasmInterpreter::FINISHED);
92 thread->Reset(); 98 thread->Reset();
93 thread->PushFrame(&module()->functions[func_index], wasm_args.start()); 99 thread->PushFrame(&module()->functions[func_index], wasm_args.start());
94 WasmInterpreter::State state; 100 WasmInterpreter::State state;
95 do { 101 do {
96 state = thread->Run(); 102 state = thread->Run();
97 switch (state) { 103 switch (state) {
98 case WasmInterpreter::State::PAUSED: { 104 case WasmInterpreter::State::PAUSED:
99 // We hit a breakpoint. 105 NotifyDebugEventListeners();
100 // TODO(clemensh): Handle this. 106 break;
101 } break;
102 case WasmInterpreter::State::FINISHED: 107 case WasmInterpreter::State::FINISHED:
103 // Perfect, just break the switch and exit the loop. 108 // Perfect, just break the switch and exit the loop.
104 break; 109 break;
105 case WasmInterpreter::State::TRAPPED: 110 case WasmInterpreter::State::TRAPPED:
106 // TODO(clemensh): Generate appropriate JS exception. 111 // TODO(clemensh): Generate appropriate JS exception.
107 UNIMPLEMENTED(); 112 UNIMPLEMENTED();
108 break; 113 break;
109 // STOPPED and RUNNING should never occur here. 114 // STOPPED and RUNNING should never occur here.
110 case WasmInterpreter::State::STOPPED: 115 case WasmInterpreter::State::STOPPED:
111 case WasmInterpreter::State::RUNNING: 116 case WasmInterpreter::State::RUNNING:
(...skipping 17 matching lines...) Expand all
129 CASE_RET_TYPE(kWasmI32, uint32_t) 134 CASE_RET_TYPE(kWasmI32, uint32_t)
130 CASE_RET_TYPE(kWasmI64, uint64_t) 135 CASE_RET_TYPE(kWasmI64, uint64_t)
131 CASE_RET_TYPE(kWasmF32, float) 136 CASE_RET_TYPE(kWasmF32, float)
132 CASE_RET_TYPE(kWasmF64, double) 137 CASE_RET_TYPE(kWasmF64, double)
133 #undef CASE_RET_TYPE 138 #undef CASE_RET_TYPE
134 default: 139 default:
135 UNREACHABLE(); 140 UNREACHABLE();
136 } 141 }
137 } 142 }
138 } 143 }
144
145 Handle<WasmInstanceObject> GetInstanceObject() {
146 StackTraceFrameIterator it(isolate_);
147 WasmInterpreterEntryFrame* frame =
148 WasmInterpreterEntryFrame::cast(it.frame());
149 Handle<WasmInstanceObject> instance_obj(frame->wasm_instance(), isolate_);
150 DCHECK_EQ(this, GetInterpreterHandle(instance_obj->debug_info()));
151 return instance_obj;
152 }
153
154 void NotifyDebugEventListeners() {
155 // Enter the debugger.
156 DebugScope debug_scope(isolate_->debug());
157 if (debug_scope.failed()) return;
158
159 // Postpone interrupt during breakpoint processing.
160 PostponeInterruptsScope postpone(isolate_);
161
162 // If we are paused on a breakpoint, clear all stepping and notify the
163 // listeners.
164 Handle<WasmCompiledModule> compiled_module(
165 GetInstanceObject()->compiled_module(), isolate_);
166 int position = GetTopPosition(compiled_module);
167 MaybeHandle<FixedArray> hit_breakpoints;
168 if (isolate_->debug()->break_points_active()) {
169 hit_breakpoints = compiled_module->CheckBreakPoints(position);
170 }
171
172 // If we hit a breakpoint, pass a JSArray with all breakpoints, otherwise
173 // pass undefined.
174 Handle<Object> hit_breakpoints_js;
175 if (hit_breakpoints.is_null()) {
176 hit_breakpoints_js = isolate_->factory()->undefined_value();
177 } else {
178 hit_breakpoints_js = isolate_->factory()->NewJSArrayWithElements(
179 hit_breakpoints.ToHandleChecked());
180 }
181
182 isolate_->debug()->OnDebugBreak(hit_breakpoints_js, false);
183 }
184
185 int GetTopPosition(Handle<WasmCompiledModule> compiled_module) {
186 DCHECK_EQ(1, interpreter()->GetThreadCount());
187 WasmInterpreter::Thread* thread = interpreter()->GetThread(0);
188 DCHECK_LT(0, thread->GetFrameCount());
189
190 wasm::InterpretedFrame frame =
191 thread->GetFrame(thread->GetFrameCount() - 1);
192 return compiled_module->GetFunctionOffset(frame.function()->func_index) +
193 frame.pc();
194 }
195
196 std::vector<std::pair<uint32_t, int>> GetInterpretedStack(
197 Address frame_pointer) {
198 // TODO(clemensh): Use frame_pointer.
199 USE(frame_pointer);
200
201 DCHECK_EQ(1, interpreter()->GetThreadCount());
202 WasmInterpreter::Thread* thread = interpreter()->GetThread(0);
203 std::vector<std::pair<uint32_t, int>> stack(thread->GetFrameCount());
204 for (int i = 0, e = thread->GetFrameCount(); i < e; ++i) {
205 wasm::InterpretedFrame frame = thread->GetFrame(i);
206 stack[i] = {frame.function()->func_index, frame.pc()};
207 }
208 return stack;
209 }
210
211 std::unique_ptr<wasm::InterpretedFrame> GetInterpretedFrame(
212 Address frame_pointer, int idx) {
213 // TODO(clemensh): Use frame_pointer.
214 USE(frame_pointer);
215
216 DCHECK_EQ(1, interpreter()->GetThreadCount());
217 WasmInterpreter::Thread* thread = interpreter()->GetThread(0);
218 return std::unique_ptr<wasm::InterpretedFrame>(
219 new wasm::InterpretedFrame(thread->GetMutableFrame(idx)));
220 }
139 }; 221 };
140 222
141 InterpreterHandle* GetOrCreateInterpreterHandle( 223 InterpreterHandle* GetOrCreateInterpreterHandle(
142 Isolate* isolate, Handle<WasmDebugInfo> debug_info) { 224 Isolate* isolate, Handle<WasmDebugInfo> debug_info) {
143 Handle<Object> handle(debug_info->get(WasmDebugInfo::kInterpreterHandle), 225 Handle<Object> handle(debug_info->get(WasmDebugInfo::kInterpreterHandle),
144 isolate); 226 isolate);
145 if (handle->IsUndefined(isolate)) { 227 if (handle->IsUndefined(isolate)) {
146 InterpreterHandle* cpp_handle = new InterpreterHandle(isolate, *debug_info); 228 InterpreterHandle* cpp_handle = new InterpreterHandle(isolate, *debug_info);
147 handle = Managed<InterpreterHandle>::New(isolate, cpp_handle); 229 handle = Managed<InterpreterHandle>::New(isolate, cpp_handle);
148 debug_info->set(WasmDebugInfo::kInterpreterHandle, *handle); 230 debug_info->set(WasmDebugInfo::kInterpreterHandle, *handle);
149 } 231 }
150 232
151 return Handle<Managed<InterpreterHandle>>::cast(handle)->get(); 233 return Handle<Managed<InterpreterHandle>>::cast(handle)->get();
152 } 234 }
153 235
236 InterpreterHandle* GetInterpreterHandle(WasmDebugInfo* debug_info) {
237 Object* handle_obj = debug_info->get(WasmDebugInfo::kInterpreterHandle);
238 DCHECK(!handle_obj->IsUndefined(debug_info->GetIsolate()));
239 return Managed<InterpreterHandle>::cast(handle_obj)->get();
240 }
241
154 int GetNumFunctions(WasmInstanceObject* instance) { 242 int GetNumFunctions(WasmInstanceObject* instance) {
155 size_t num_functions = 243 size_t num_functions =
156 instance->compiled_module()->module()->functions.size(); 244 instance->compiled_module()->module()->functions.size();
157 DCHECK_GE(kMaxInt, num_functions); 245 DCHECK_GE(kMaxInt, num_functions);
158 return static_cast<int>(num_functions); 246 return static_cast<int>(num_functions);
159 } 247 }
160 248
161 Handle<FixedArray> GetOrCreateInterpretedFunctions( 249 Handle<FixedArray> GetOrCreateInterpretedFunctions(
162 Isolate* isolate, Handle<WasmDebugInfo> debug_info) { 250 Isolate* isolate, Handle<WasmDebugInfo> debug_info) {
163 Handle<Object> obj(debug_info->get(WasmDebugInfo::kInterpretedFunctions), 251 Handle<Object> obj(debug_info->get(WasmDebugInfo::kInterpretedFunctions),
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
258 Isolate* isolate = debug_info->GetIsolate(); 346 Isolate* isolate = debug_info->GetIsolate();
259 InterpreterHandle* handle = GetOrCreateInterpreterHandle(isolate, debug_info); 347 InterpreterHandle* handle = GetOrCreateInterpreterHandle(isolate, debug_info);
260 WasmInterpreter* interpreter = handle->interpreter(); 348 WasmInterpreter* interpreter = handle->interpreter();
261 DCHECK_LE(0, func_index); 349 DCHECK_LE(0, func_index);
262 DCHECK_GT(handle->module()->functions.size(), func_index); 350 DCHECK_GT(handle->module()->functions.size(), func_index);
263 const WasmFunction* func = &handle->module()->functions[func_index]; 351 const WasmFunction* func = &handle->module()->functions[func_index];
264 interpreter->SetBreakpoint(func, offset, true); 352 interpreter->SetBreakpoint(func, offset, true);
265 EnsureRedirectToInterpreter(isolate, debug_info, func_index); 353 EnsureRedirectToInterpreter(isolate, debug_info, func_index);
266 } 354 }
267 355
268 void WasmDebugInfo::RunInterpreter(Handle<WasmDebugInfo> debug_info, 356 void WasmDebugInfo::RunInterpreter(int func_index, uint8_t* arg_buffer) {
269 int func_index, uint8_t* arg_buffer) {
270 DCHECK_LE(0, func_index); 357 DCHECK_LE(0, func_index);
271 InterpreterHandle* interp_handle = 358 GetInterpreterHandle(this)->Execute(static_cast<uint32_t>(func_index),
272 GetOrCreateInterpreterHandle(debug_info->GetIsolate(), debug_info); 359 arg_buffer);
273 interp_handle->Execute(static_cast<uint32_t>(func_index), arg_buffer);
274 } 360 }
361
362 std::vector<std::pair<uint32_t, int>> WasmDebugInfo::GetInterpretedStack(
363 Address frame_pointer) {
364 return GetInterpreterHandle(this)->GetInterpretedStack(frame_pointer);
365 }
366
367 std::unique_ptr<wasm::InterpretedFrame> WasmDebugInfo::GetInterpretedFrame(
368 Address frame_pointer, int idx) {
369 return GetInterpreterHandle(this)->GetInterpretedFrame(frame_pointer, idx);
370 }
OLDNEW
« no previous file with comments | « src/wasm/managed.h ('k') | src/wasm/wasm-interpreter.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698