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

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

Issue 2096863003: [wasm] prototype for breakpoint support. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@extend-script-functionality
Patch Set: Created 4 years, 6 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/wasm-debug.h ('k') | src/wasm/wasm-external-refs.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/wasm/wasm-debug.h" 5 #include "src/wasm/wasm-debug.h"
6 6
7 #include "src/assert-scope.h" 7 #include "src/assert-scope.h"
8 #include "src/compiler/wasm-compiler.h"
8 #include "src/debug/debug.h" 9 #include "src/debug/debug.h"
9 #include "src/factory.h" 10 #include "src/factory.h"
11 #include "src/frames-inl.h"
10 #include "src/isolate.h" 12 #include "src/isolate.h"
13 // We need src/assembler-$arch-inl.h, and macro-assembler.h includes this.
14 #include "src/macro-assembler.h"
11 #include "src/wasm/module-decoder.h" 15 #include "src/wasm/module-decoder.h"
16 #include "src/wasm/wasm-interpreter.h"
12 #include "src/wasm/wasm-module.h" 17 #include "src/wasm/wasm-module.h"
13 18
14 using namespace v8::internal; 19 using namespace v8::internal;
15 using namespace v8::internal::wasm; 20 using namespace v8::internal::wasm;
16 21
17 namespace { 22 namespace {
18 23
19 enum { 24 enum {
20 kWasmDebugInfoWasmObj, 25 kWasmDebugInfoWasmObj,
21 kWasmDebugInfoWasmBytesHash, 26 kWasmDebugInfoWasmBytesHash,
22 kWasmDebugInfoFunctionByteOffsets, 27 kWasmDebugInfoFunctionByteOffsets,
23 kWasmDebugInfoFunctionScripts, 28 kWasmDebugInfoFunctionScripts,
29 kWasmDebugInfoInterpreterAddr,
30 kWasmDebugInfoInterpretedFunctions,
31 kWasmDebugInfoDebugInfos,
24 kWasmDebugInfoNumEntries 32 kWasmDebugInfoNumEntries
25 }; 33 };
26 34
27 ByteArray *GetOrCreateFunctionOffsetTable(Handle<WasmDebugInfo> debug_info) { 35 ByteArray *GetOrCreateFunctionOffsetTable(Handle<WasmDebugInfo> debug_info) {
28 Object *offset_table = debug_info->get(kWasmDebugInfoFunctionByteOffsets); 36 Object *offset_table = debug_info->get(kWasmDebugInfoFunctionByteOffsets);
29 Isolate *isolate = debug_info->GetIsolate(); 37 Isolate *isolate = debug_info->GetIsolate();
30 if (!offset_table->IsUndefined(isolate)) return ByteArray::cast(offset_table); 38 if (!offset_table->IsUndefined(isolate)) return ByteArray::cast(offset_table);
31 39
32 FunctionOffsetsResult function_offsets; 40 FunctionOffsetsResult function_offsets;
33 { 41 {
(...skipping 27 matching lines...) Expand all
61 69
62 int offset = arr->get_int(2 * func_index); 70 int offset = arr->get_int(2 * func_index);
63 int length = arr->get_int(2 * func_index + 1); 71 int length = arr->get_int(2 * func_index + 1);
64 // Assert that it's distinguishable from the "illegal function index" return. 72 // Assert that it's distinguishable from the "illegal function index" return.
65 DCHECK(offset > 0 && length > 0); 73 DCHECK(offset > 0 && length > 0);
66 return {offset, length}; 74 return {offset, length};
67 } 75 }
68 76
69 Vector<const uint8_t> GetFunctionBytes(Handle<WasmDebugInfo> debug_info, 77 Vector<const uint8_t> GetFunctionBytes(Handle<WasmDebugInfo> debug_info,
70 int func_index) { 78 int func_index) {
79 std::pair<int, int> offset_and_length =
80 GetFunctionOffsetAndLength(debug_info, func_index);
71 SeqOneByteString *module_bytes = 81 SeqOneByteString *module_bytes =
72 wasm::GetWasmBytes(debug_info->wasm_object()); 82 wasm::GetWasmBytes(debug_info->wasm_object());
73 std::pair<int, int> offset_and_length =
74 GetFunctionOffsetAndLength(debug_info, func_index);
75 return Vector<const uint8_t>( 83 return Vector<const uint8_t>(
76 module_bytes->GetChars() + offset_and_length.first, 84 module_bytes->GetChars() + offset_and_length.first,
77 offset_and_length.second); 85 offset_and_length.second);
78 } 86 }
79 87
88 FixedArray *GetOrCreateInterpretedFunctions(Handle<WasmDebugInfo> debug_info) {
89 Object *maybe_arr = debug_info->get(kWasmDebugInfoInterpretedFunctions);
90 Isolate *isolate = debug_info->GetIsolate();
91 if (!maybe_arr->IsUndefined(isolate)) return FixedArray::cast(maybe_arr);
92
93 FixedArray *new_arr = *isolate->factory()->NewFixedArray(
94 wasm::GetNumberOfFunctions(debug_info->wasm_object()));
95 debug_info->set(kWasmDebugInfoInterpretedFunctions, new_arr);
96 return new_arr;
97 }
98
99 void RedirectFunction(Code *code, Code *old_target, Code *new_target) {
100 for (RelocIterator it(code, RelocInfo::kCodeTargetMask); !it.done();
101 it.next()) {
102 DCHECK(RelocInfo::IsCodeTarget(it.rinfo()->rmode()));
103 Code *target = Code::GetCodeFromTargetAddress(it.rinfo()->target_address());
104 if (target != old_target) continue;
105 it.rinfo()->set_target_address(new_target->instruction_start(),
106 SKIP_WRITE_BARRIER, SKIP_ICACHE_FLUSH);
107 }
108 }
109
110 void RedirectFunctionEverywhere(Handle<JSObject> wasm, Handle<Code> old_target,
111 Handle<Code> new_target) {
112 // Redirect in all wasm functions.
113 for (int i = 0, e = wasm::GetNumberOfFunctions(*wasm); i < e; ++i)
114 RedirectFunction(wasm::GetWasmFunctionCode(*wasm, i), *old_target,
115 *new_target);
116
117 // Redirect in the code of all exported functions.
118 Isolate *isolate = wasm->GetIsolate();
119 // For AsmJs modules, the exports are stored on the wasm object itself.
120 MaybeHandle<Object> maybe_exports =
121 JSReceiver::GetProperty(isolate, wasm, "exports");
122 Handle<JSObject> exports_object =
123 maybe_exports.is_null()
124 ? wasm
125 : Handle<JSObject>::cast(maybe_exports.ToHandleChecked());
126
127 Handle<FixedArray> values;
128 if (JSReceiver::GetOwnValues(Handle<JSReceiver>::cast(exports_object),
129 ALL_PROPERTIES)
130 .ToHandle(&values)) {
131 for (int i = 0, e = values->length(); i != e; ++i) {
132 if (!values->get(i)->IsJSFunction()) continue;
133 Code *code = JSFunction::cast(values->get(i))->code();
134 RedirectFunction(code, *old_target, *new_target);
135 }
136 }
137 }
138
139 class InterpreterHandle {
140 v8::base::AccountingAllocator allocator;
141 Zone zone;
142 Handle<Object> global_ref;
143 std::unique_ptr<const WasmModule> module;
144 std::unique_ptr<WasmModuleInstance> module_instance;
145 Isolate *isolate;
146
147 uint8_t *parameter_buffer;
148 uint32_t parameter_buffer_size = 0;
149 #ifdef DEBUG
150 // Track the function index for which the last buffer was allocated.
151 // This is updated on AllocateParameterBuffer, and checked at Execute.
152 uint32_t parameter_buffer_taken = static_cast<uint32_t>(-1);
153 #endif
154
155 public:
156 WasmInterpreter interpreter;
157
158 // Initialize in the right order. WasmInterpreter has to be allocate in place,
159 // since it's not std::move'able.
160 explicit InterpreterHandle(WasmDebugInfo *debug_info)
161 : allocator(),
162 zone(&allocator),
163 module(CreateModule(&zone, debug_info)),
164 isolate(debug_info->GetIsolate()),
165 interpreter(CreateModuleInstance(module.get(), debug_info), &zone) {
166 global_ref = debug_info->GetIsolate()->global_handles()->Create(debug_info);
167 GlobalHandles::MakeWeak(global_ref.location(), this,
168 InterpreterHandle::Finalize,
169 v8::WeakCallbackType::kParameter);
170 }
171
172 static void Finalize(const v8::WeakCallbackInfo<void> &data) {
173 void *param = data.GetParameter();
174 InterpreterHandle *handle = reinterpret_cast<InterpreterHandle *>(param);
175 GlobalHandles::ClearWeakness(handle->global_ref.location());
176 GlobalHandles::Destroy(handle->global_ref.location());
177 delete handle;
178 }
179
180 static const WasmModule *CreateModule(Zone *zone, WasmDebugInfo *debug_info) {
181 SeqOneByteString *wasm_bytes =
182 wasm::GetWasmBytes(debug_info->wasm_object());
183 const byte *bytes_start = wasm_bytes->GetChars();
184 const byte *bytes_end = bytes_start + wasm_bytes->length();
185 ModuleResult module_result =
186 DecodeWasmModule(debug_info->GetIsolate(), zone, bytes_start, bytes_end,
187 false, ModuleOrigin::kWasmOrigin);
188 DCHECK(module_result.ok());
189 return module_result.val;
190 }
191
192 static WasmModuleInstance *CreateModuleInstance(const WasmModule *module,
193 WasmDebugInfo *debug_info) {
194 JSArrayBuffer *memory =
195 wasm::GetWasmMemoryBuffer(debug_info->wasm_object());
196
197 WasmModuleInstance *instance = new WasmModuleInstance(module);
198 instance->mem_start = reinterpret_cast<byte *>(memory->backing_store());
199 instance->mem_size = memory->byte_length()->Number();
200 instance->mem_buffer = handle(memory, debug_info->GetIsolate());
201
202 return instance;
203 }
204
205 uint8_t *GetParameterBuffer(uint32_t function_index) {
206 DCHECK_LE(function_index, module->functions.size());
207 DCHECK_EQ(static_cast<uint32_t>(-1), parameter_buffer_taken);
208 #ifdef DEBUG
209 parameter_buffer_taken = function_index;
210 #endif
211 uint32_t size_needed = 0;
212 FunctionSig *sig = module->functions[function_index].sig;
213 for (size_t i = 0, e = sig->parameter_count(); i != e; ++i) {
214 size_needed += 1 << ElementSizeLog2Of(sig->GetParam(i));
215 }
216 if (size_needed > parameter_buffer_size) {
217 uint32_t alloc_size = 2 * parameter_buffer_size;
218 if (size_needed > alloc_size) alloc_size = size_needed;
219 parameter_buffer = zone.NewArray<uint8_t>(alloc_size);
220 parameter_buffer_size = alloc_size;
221 }
222 return parameter_buffer;
223 }
224
225 void Execute(uint32_t func_index) {
226 DCHECK_EQ(parameter_buffer_taken, func_index);
227 #ifdef DEBUG
228 parameter_buffer_taken = static_cast<uint32_t>(-1);
229 #endif
230 FunctionSig *sig = module->functions[func_index].sig;
231 DCHECK_LE(sig->parameter_count(), static_cast<size_t>(kMaxInt));
232 int num_params = static_cast<int>(sig->parameter_count());
233 ScopedVector<WasmVal> wasm_args(num_params);
234 uint8_t *buf_ptr = parameter_buffer;
235 for (int i = 0; i < num_params; ++i) {
236 uint32_t param_size = 1 << ElementSizeLog2Of(sig->GetParam(i));
237 switch (sig->GetParam(i)) {
238 case kAstI32:
239 DCHECK_EQ(param_size, sizeof(uint32_t));
240 wasm_args[i] = WasmVal(*reinterpret_cast<uint32_t *>(buf_ptr));
241 break;
242 case kAstI64:
243 DCHECK_EQ(param_size, sizeof(uint64_t));
244 wasm_args[i] = WasmVal(*reinterpret_cast<uint64_t *>(buf_ptr));
245 break;
246 case kAstF32:
247 DCHECK_EQ(param_size, sizeof(float));
248 wasm_args[i] = WasmVal(*reinterpret_cast<float *>(buf_ptr));
249 break;
250 case kAstF64:
251 DCHECK_EQ(param_size, sizeof(double));
252 wasm_args[i] = WasmVal(*reinterpret_cast<double *>(buf_ptr));
253 break;
254 default:
255 UNREACHABLE();
256 }
257 buf_ptr += param_size;
258 }
259
260 WasmInterpreter::Thread *thread = interpreter.GetThread(0);
261 // We do not support reentering an already running interpreter at the moment
262 // (like INTERPRETER -> JS -> WASM -> INTERPRETER).
263 DCHECK(thread->state() == WasmInterpreter::STOPPED ||
264 thread->state() == WasmInterpreter::FINISHED);
265 thread->Reset();
266 thread->PushFrame(&module->functions[func_index], wasm_args.start());
267 WasmInterpreter::State state;
268 do {
269 state = thread->Run();
270 switch (state) {
271 case WasmInterpreter::State::PAUSED: {
272 // We hit a breakpoint.
273 StackTraceFrameIterator frame_it(isolate);
274 WasmInterpretedFrame *top_frame =
275 WasmInterpretedFrame::cast(frame_it.frame());
276 isolate->debug()->Break(top_frame);
277 } break;
278 case WasmInterpreter::State::FINISHED:
279 // Perfect, just break the switch and exit the loop.
280 break;
281 case WasmInterpreter::State::TRAPPED:
282 // TODO(clemensh): Generate appropriate JS exception.
283 UNIMPLEMENTED();
284 break;
285 // STOPPED and RUNNING should never occur here.
286 case WasmInterpreter::State::STOPPED:
287 case WasmInterpreter::State::RUNNING:
288 default:
289 UNREACHABLE();
290 }
291 } while (state != WasmInterpreter::State::FINISHED);
292 }
293
294 void EnsureInterpreterRedirect(Handle<WasmDebugInfo> debug_info,
295 int func_index) {
296 Isolate *isolate = debug_info->GetIsolate();
297 Handle<FixedArray> interpreted_functions(
298 GetOrCreateInterpretedFunctions(debug_info), isolate);
299 DCHECK_LT(func_index, interpreted_functions->length());
300 if (!interpreted_functions->get(func_index)->IsUndefined(isolate)) return;
301
302 Handle<JSObject> wasm(debug_info->wasm_object(), isolate);
303 Handle<Code> new_code = compiler::CompileWasmToInterpreter(
304 isolate, func_index, module->functions[func_index].sig, wasm);
305 Handle<Code> old_code(wasm::GetWasmFunctionCode(*wasm, func_index),
306 isolate);
307 interpreted_functions->set(func_index, *new_code);
308
309 RedirectFunctionEverywhere(wasm, old_code, new_code);
310 }
311 };
312
313 InterpreterHandle *GetOrCreateInterpreterHandle(WasmDebugInfo *debug_info) {
314 DisallowHeapAllocation no_gc;
315 // We store the raw pointer to the InterpreterHandle in a slot in the debug
316 // info.
317 // Since the pointer is aligned, it will look like a Smi, and the gc will
318 // ignore it.
319 Object *handle_obj = debug_info->get(kWasmDebugInfoInterpreterAddr);
320 if (!handle_obj->IsUndefined(debug_info->GetIsolate())) {
321 DCHECK(!handle_obj->IsHeapObject());
322 return reinterpret_cast<InterpreterHandle *>(handle_obj);
323 }
324
325 InterpreterHandle *handle = new InterpreterHandle(debug_info);
326 handle_obj = reinterpret_cast<Object *>(handle);
327 DCHECK(!handle_obj->IsHeapObject());
328 debug_info->set(kWasmDebugInfoInterpreterAddr, handle_obj);
329 return handle;
330 }
331
332 InterpreterHandle *GetInterpreterHandleIfExists(WasmDebugInfo *debug_info) {
333 DisallowHeapAllocation no_gc;
334 Object *handle_obj = debug_info->get(kWasmDebugInfoInterpreterAddr);
335 return handle_obj->IsUndefined(debug_info->GetIsolate())
336 ? nullptr
337 : reinterpret_cast<InterpreterHandle *>(handle_obj);
338 }
339
80 } // namespace 340 } // namespace
81 341
342 WasmInstructionIterator::WasmInstructionIterator(const byte *start,
343 const byte *end)
344 : start_(start), end_(end) {
345 base::AccountingAllocator allocator;
346 Zone tmp_zone(&allocator);
347 AstLocalDecls locals(&tmp_zone);
348 bool valid = DecodeLocalDecls(locals, start, end);
349 DCHECK(valid);
350 USE(valid);
351 pc_ = start + locals.decls_encoded_size;
352 }
353
354 void WasmInstructionIterator::Next() {
355 DCHECK(!Done());
356 int len = OpcodeLength(pc_, end_);
357 DCHECK_LE(0, len); // 0 means validation error / read past the end.
358 pc_ += len;
359 }
360
361 Script *InterpreterFrameInfo::GetScript() const {
362 return WasmDebugInfo::GetFunctionScript(debug_info_, func_index_);
363 }
364
365 InterpreterFrameIterator::InterpreterFrameIterator(
366 Handle<WasmDebugInfo> debug_info)
367 : frame_nr_(0),
368 frame_count_(GetOrCreateInterpreterHandle(*debug_info)
369 ->interpreter.GetThread(0)
370 ->GetFrameCount()),
371 debug_info_(debug_info) {}
372
373 InterpreterFrameInfo InterpreterFrameIterator::GetFrameInfo() const {
374 DCHECK(!Done());
375 WasmInterpreter::Thread *thread =
376 GetOrCreateInterpreterHandle(*debug_info_)->interpreter.GetThread(0);
377 DCHECK_EQ(frame_count_, thread->GetFrameCount());
378 DCHECK_LE(0, frame_nr_);
379 std::unique_ptr<const WasmInterpreterFrame> frame(
380 thread->GetFrame(frame_nr_));
381 return InterpreterFrameInfo(debug_info_, frame->function()->func_index,
382 frame->pc());
383 }
384
82 Handle<WasmDebugInfo> WasmDebugInfo::New(Handle<JSObject> wasm) { 385 Handle<WasmDebugInfo> WasmDebugInfo::New(Handle<JSObject> wasm) {
83 Isolate *isolate = wasm->GetIsolate(); 386 Isolate *isolate = wasm->GetIsolate();
84 Factory *factory = isolate->factory(); 387 Factory *factory = isolate->factory();
85 Handle<FixedArray> arr = 388 Handle<FixedArray> arr =
86 factory->NewFixedArray(kWasmDebugInfoNumEntries, TENURED); 389 factory->NewFixedArray(kWasmDebugInfoNumEntries, TENURED);
87 arr->set(kWasmDebugInfoWasmObj, *wasm); 390 arr->set(kWasmDebugInfoWasmObj, *wasm);
88 int hash = 0; 391 int hash = 0;
89 Handle<SeqOneByteString> wasm_bytes(GetWasmBytes(*wasm), isolate); 392 Handle<SeqOneByteString> wasm_bytes(GetWasmBytes(*wasm), isolate);
90 { 393 {
91 DisallowHeapAllocation no_gc; 394 DisallowHeapAllocation no_gc;
92 hash = StringHasher::HashSequentialString( 395 hash = StringHasher::HashSequentialString(
93 wasm_bytes->GetChars(), wasm_bytes->length(), kZeroHashSeed); 396 wasm_bytes->GetChars(), wasm_bytes->length(), kZeroHashSeed);
94 } 397 }
95 Handle<Object> hash_obj = factory->NewNumberFromInt(hash, TENURED); 398 Handle<Object> hash_obj = factory->NewNumberFromInt(hash, TENURED);
96 arr->set(kWasmDebugInfoWasmBytesHash, *hash_obj); 399 arr->set(kWasmDebugInfoWasmBytesHash, *hash_obj);
97 400
98 return Handle<WasmDebugInfo>::cast(arr); 401 return Handle<WasmDebugInfo>::cast(arr);
99 } 402 }
100 403
101 bool WasmDebugInfo::IsDebugInfo(Object *object) { 404 bool WasmDebugInfo::IsWasmDebugInfo(Object *object) {
102 if (!object->IsFixedArray()) return false; 405 if (!object->IsFixedArray()) return false;
103 FixedArray *arr = FixedArray::cast(object); 406 FixedArray *arr = FixedArray::cast(object);
104 Isolate *isolate = arr->GetIsolate(); 407 Isolate *isolate = arr->GetIsolate();
105 return arr->length() == kWasmDebugInfoNumEntries && 408 return arr->length() == kWasmDebugInfoNumEntries &&
106 IsWasmObject(arr->get(kWasmDebugInfoWasmObj)) && 409 IsWasmObject(arr->get(kWasmDebugInfoWasmObj)) &&
107 arr->get(kWasmDebugInfoWasmBytesHash)->IsNumber() && 410 arr->get(kWasmDebugInfoWasmBytesHash)->IsNumber() &&
108 (arr->get(kWasmDebugInfoFunctionByteOffsets)->IsUndefined(isolate) || 411 (arr->get(kWasmDebugInfoFunctionByteOffsets)->IsUndefined(isolate) ||
109 arr->get(kWasmDebugInfoFunctionByteOffsets)->IsByteArray()) && 412 arr->get(kWasmDebugInfoFunctionByteOffsets)->IsByteArray()) &&
110 (arr->get(kWasmDebugInfoFunctionScripts)->IsUndefined(isolate) || 413 (arr->get(kWasmDebugInfoFunctionScripts)->IsUndefined(isolate) ||
111 arr->get(kWasmDebugInfoFunctionScripts)->IsFixedArray()); 414 arr->get(kWasmDebugInfoFunctionScripts)->IsFixedArray()) &&
415 (arr->get(kWasmDebugInfoInterpretedFunctions)->IsUndefined(isolate) ||
416 arr->get(kWasmDebugInfoInterpretedFunctions)->IsFixedArray()) &&
417 (arr->get(kWasmDebugInfoDebugInfos)->IsUndefined(isolate) ||
418 arr->get(kWasmDebugInfoDebugInfos)->IsFixedArray());
112 } 419 }
113 420
114 WasmDebugInfo *WasmDebugInfo::cast(Object *object) { 421 WasmDebugInfo *WasmDebugInfo::cast(Object *object) {
115 DCHECK(IsDebugInfo(object)); 422 DCHECK(IsWasmDebugInfo(object));
116 return reinterpret_cast<WasmDebugInfo *>(object); 423 return reinterpret_cast<WasmDebugInfo *>(object);
117 } 424 }
118 425
119 JSObject *WasmDebugInfo::wasm_object() { 426 JSObject *WasmDebugInfo::wasm_object() {
120 return JSObject::cast(get(kWasmDebugInfoWasmObj)); 427 return JSObject::cast(get(kWasmDebugInfoWasmObj));
121 } 428 }
122 429
430 void WasmDebugInfo::SetBreakpoint(Handle<WasmDebugInfo> debug_info,
431 int func_index, int byte_offset) {
432 DCHECK_LE(0, func_index);
433 DCHECK_LE(0, byte_offset);
434 InterpreterHandle *handle = GetOrCreateInterpreterHandle(*debug_info);
435 handle->EnsureInterpreterRedirect(debug_info, func_index);
436 handle->interpreter.SetBreakpoint(static_cast<uint32_t>(func_index),
437 byte_offset, true);
438 }
439
440 bool WasmDebugInfo::HasBreakpoint(int func_index, int byte_offset) {
441 DCHECK_LE(0, func_index);
442 DCHECK_LE(0, byte_offset);
443 InterpreterHandle *handle = GetInterpreterHandleIfExists(this);
444 return handle &&
445 handle->interpreter.GetBreakpoint(static_cast<uint32_t>(func_index),
446 byte_offset);
447 }
448
123 Script *WasmDebugInfo::GetFunctionScript(Handle<WasmDebugInfo> debug_info, 449 Script *WasmDebugInfo::GetFunctionScript(Handle<WasmDebugInfo> debug_info,
124 int func_index) { 450 int func_index) {
125 Isolate *isolate = debug_info->GetIsolate(); 451 Isolate *isolate = debug_info->GetIsolate();
126 Object *scripts_obj = debug_info->get(kWasmDebugInfoFunctionScripts); 452 Object *scripts_obj = debug_info->get(kWasmDebugInfoFunctionScripts);
127 Handle<FixedArray> scripts; 453 Handle<FixedArray> scripts;
128 if (scripts_obj->IsUndefined(isolate)) { 454 if (scripts_obj->IsUndefined(isolate)) {
129 int num_functions = wasm::GetNumberOfFunctions(debug_info->wasm_object()); 455 int num_functions = wasm::GetNumberOfFunctions(debug_info->wasm_object());
130 scripts = isolate->factory()->NewFixedArray(num_functions, TENURED); 456 scripts = isolate->factory()->NewFixedArray(num_functions, TENURED);
131 debug_info->set(kWasmDebugInfoFunctionScripts, *scripts); 457 debug_info->set(kWasmDebugInfoFunctionScripts, *scripts);
132 } else { 458 } else {
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
221 int idx = 0; 547 int idx = 0;
222 for (std::tuple<uint32_t, int, int> elem : offset_table_vec) { 548 for (std::tuple<uint32_t, int, int> elem : offset_table_vec) {
223 offset_table->set(idx++, Smi::FromInt(std::get<0>(elem))); 549 offset_table->set(idx++, Smi::FromInt(std::get<0>(elem)));
224 offset_table->set(idx++, Smi::FromInt(std::get<1>(elem))); 550 offset_table->set(idx++, Smi::FromInt(std::get<1>(elem)));
225 offset_table->set(idx++, Smi::FromInt(std::get<2>(elem))); 551 offset_table->set(idx++, Smi::FromInt(std::get<2>(elem)));
226 } 552 }
227 DCHECK_EQ(idx, offset_table->length()); 553 DCHECK_EQ(idx, offset_table->length());
228 554
229 return offset_table; 555 return offset_table;
230 } 556 }
557
558 DebugInfo *WasmDebugInfo::GetDebugInfo(Handle<WasmDebugInfo> debug_info,
559 int func_index) {
560 Object *maybe_arr = debug_info->get(kWasmDebugInfoDebugInfos);
561 Isolate *isolate = debug_info->GetIsolate();
562 Handle<FixedArray> arr;
563 if (maybe_arr->IsUndefined(isolate)) {
564 arr = isolate->factory()->NewFixedArray(
565 wasm::GetNumberOfFunctions(debug_info->wasm_object()));
566 debug_info->set(kWasmDebugInfoDebugInfos, *arr);
567 } else {
568 arr = handle(FixedArray::cast(maybe_arr));
569 }
570
571 DCHECK_LE(func_index, static_cast<uint32_t>(arr->length()));
572 Object *maybe_info = arr->get(static_cast<int>(func_index));
573 if (!maybe_info->IsUndefined(isolate)) return DebugInfo::cast(maybe_info);
574
575 Handle<AbstractCode> code(AbstractCode::cast(
576 wasm::GetWasmFunctionCode(debug_info->wasm_object(), func_index)));
577 Handle<DebugInfo> new_debug_info = isolate->factory()->NewDebugInfo(code);
578 arr->set(static_cast<int>(func_index), *new_debug_info);
579 return *new_debug_info;
580 }
581
582 WasmDebugInfo::InstructionType WasmDebugInfo::GetInstructionType(
583 int func_index, int byte_offset) {
584 SeqOneByteString *bytes = wasm::GetWasmBytes(wasm_object());
585 DCHECK(byte_offset >= 0 && byte_offset < bytes->length());
586 switch (static_cast<WasmOpcode>(bytes->Get(byte_offset))) {
587 case WasmOpcode::kExprReturn:
588 return RETURN;
589 case WasmOpcode::kExprCallImport:
590 case WasmOpcode::kExprCallFunction:
591 case WasmOpcode::kExprCallIndirect:
592 return CALL;
593 default:
594 return OTHER;
595 }
596 }
597
598 WasmInstructionIterator WasmDebugInfo::GetInstructionIterator(
599 Handle<WasmDebugInfo> debug_info, int func_index) {
600 Vector<const uint8_t> function_bytes =
601 GetFunctionBytes(debug_info, func_index);
602
603 return WasmInstructionIterator(function_bytes.start(), function_bytes.end());
604 }
605
606 InterpreterFrameIterator WasmDebugInfo::GetInterpreterFrameIterator() {
607 return InterpreterFrameIterator(handle(this));
608 }
609
610 Object *WasmDebugInfo::GetInterpreterArgBuffer(int func_index) {
611 printf("GetInterpreterArgBuffer %d\n", func_index);
612 DCHECK_LE(0, func_index);
613 InterpreterHandle *interp_handle = GetOrCreateInterpreterHandle(this);
614 uint8_t *buf =
615 interp_handle->GetParameterBuffer(static_cast<uint32_t>(func_index));
616 Object *obj = reinterpret_cast<Object *>(buf);
617 DCHECK(!obj->IsHeapObject());
618 return obj;
619 }
620
621 void WasmDebugInfo::RunInterpreter(int func_index) {
622 printf("RunInterpreter %d\n", func_index);
623 DCHECK_LE(0, func_index);
624 InterpreterHandle *interp_handle = GetOrCreateInterpreterHandle(this);
625 interp_handle->Execute(static_cast<uint32_t>(func_index));
626 }
OLDNEW
« no previous file with comments | « src/wasm/wasm-debug.h ('k') | src/wasm/wasm-external-refs.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698