Commit 6e70425b authored by Clemens Hammacher's avatar Clemens Hammacher Committed by Commit Bot

[wasm] Provide scope information via inspector

This CL implements the proposed change to show information about
WebAssembly values and call frames via the inspector interface.
Each interpreted WebAssembly frame will have two scopes: A global scope
showing information about the memory (to be extended for globals), and
a local scope showing information about parameters, local variables, and
stack values.
Names of local variables will be added later.

R=ahaas@chromium.org, yangguo@chromium.org
BUG=v8:6245,v8:5822

Change-Id: I0a35fddd0a353933c86adf62083233b08098a2c7
Reviewed-on: https://chromium-review.googlesource.com/474865
Commit-Queue: Clemens Hammacher <clemensh@chromium.org>
Reviewed-by: 's avatarAleksey Kozyatinskiy <kozyatinskiy@chromium.org>
Reviewed-by: 's avatarAndreas Haas <ahaas@chromium.org>
Cr-Commit-Position: refs/heads/master@{#44633}
parent 68b047d0
...@@ -1833,6 +1833,10 @@ int WasmInterpreterEntryFrame::position() const { ...@@ -1833,6 +1833,10 @@ int WasmInterpreterEntryFrame::position() const {
return FrameSummary::GetBottom(this).AsWasmInterpreted().SourcePosition(); return FrameSummary::GetBottom(this).AsWasmInterpreted().SourcePosition();
} }
Object* WasmInterpreterEntryFrame::context() const {
return wasm_instance()->compiled_module()->ptr_to_native_context();
}
Address WasmInterpreterEntryFrame::GetCallerStackPointer() const { Address WasmInterpreterEntryFrame::GetCallerStackPointer() const {
return fp() + ExitFrameConstants::kCallerSPOffset; return fp() + ExitFrameConstants::kCallerSPOffset;
} }
......
...@@ -1350,6 +1350,7 @@ class WasmInterpreterEntryFrame final : public StandardFrame { ...@@ -1350,6 +1350,7 @@ class WasmInterpreterEntryFrame final : public StandardFrame {
WasmInstanceObject* wasm_instance() const; WasmInstanceObject* wasm_instance() const;
Script* script() const override; Script* script() const override;
int position() const override; int position() const override;
Object* context() const override;
static WasmInterpreterEntryFrame* cast(StackFrame* frame) { static WasmInterpreterEntryFrame* cast(StackFrame* frame) {
DCHECK(frame->is_wasm_interpreter_entry()); DCHECK(frame->is_wasm_interpreter_entry());
......
...@@ -402,10 +402,9 @@ DebuggerScript._frameMirrorToJSCallFrame = function(frameMirror) ...@@ -402,10 +402,9 @@ DebuggerScript._frameMirrorToJSCallFrame = function(frameMirror)
*/ */
function contextId() function contextId()
{ {
var mirror = ensureFuncMirror(); var context =
var context = mirror.context(); ensureFuncMirror().context() || ensureScriptMirror().context();
if (context && context.data()) if (context && context.data()) return Number(context.data());
return Number(context.data());
return 0; return 0;
} }
......
...@@ -355,6 +355,9 @@ ScriptMirror.prototype.value = function() {} ...@@ -355,6 +355,9 @@ ScriptMirror.prototype.value = function() {}
/** @return {number} */ /** @return {number} */
ScriptMirror.prototype.id = function() {} ScriptMirror.prototype.id = function() {}
/** @return {ContextMirror} */
ScriptMirror.prototype.context = function() {}
/** /**
* @param {number} position * @param {number} position
* @param {boolean=} includeResourceOffset * @param {boolean=} includeResourceOffset
......
...@@ -551,7 +551,7 @@ RUNTIME_FUNCTION(Runtime_GetFrameDetails) { ...@@ -551,7 +551,7 @@ RUNTIME_FUNCTION(Runtime_GetFrameDetails) {
// bit 0: invoked in the debugger context. // bit 0: invoked in the debugger context.
// bit 1: optimized frame. // bit 1: optimized frame.
// bit 2: inlined in optimized frame // bit 2: inlined in optimized frame
int flags = 0; int flags = inlined_frame_index << 2;
if (*save->context() == *isolate->debug()->debug_context()) { if (*save->context() == *isolate->debug()->debug_context()) {
flags |= 1 << 0; flags |= 1 << 0;
} }
...@@ -830,7 +830,7 @@ RUNTIME_FUNCTION(Runtime_GetAllScopesDetails) { ...@@ -830,7 +830,7 @@ RUNTIME_FUNCTION(Runtime_GetAllScopesDetails) {
CHECK(isolate->debug()->CheckExecutionState(break_id)); CHECK(isolate->debug()->CheckExecutionState(break_id));
CONVERT_SMI_ARG_CHECKED(wrapped_id, 1); CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]); CONVERT_NUMBER_CHECKED(int, inlined_frame_index, Int32, args[2]);
ScopeIterator::Option option = ScopeIterator::DEFAULT; ScopeIterator::Option option = ScopeIterator::DEFAULT;
if (args.length() == 4) { if (args.length() == 4) {
...@@ -842,9 +842,19 @@ RUNTIME_FUNCTION(Runtime_GetAllScopesDetails) { ...@@ -842,9 +842,19 @@ RUNTIME_FUNCTION(Runtime_GetAllScopesDetails) {
StackFrame::Id id = DebugFrameHelper::UnwrapFrameId(wrapped_id); StackFrame::Id id = DebugFrameHelper::UnwrapFrameId(wrapped_id);
StackTraceFrameIterator frame_it(isolate, id); StackTraceFrameIterator frame_it(isolate, id);
StandardFrame* frame = frame_it.frame(); StandardFrame* frame = frame_it.frame();
FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate);
List<Handle<JSObject> > result(4); // Handle wasm frames specially. They provide exactly two scopes (global /
// local).
if (frame->is_wasm_interpreter_entry()) {
Handle<WasmDebugInfo> debug_info(
WasmInterpreterEntryFrame::cast(frame)->wasm_instance()->debug_info(),
isolate);
return *WasmDebugInfo::GetScopeDetails(debug_info, frame->fp(),
inlined_frame_index);
}
FrameInspector frame_inspector(frame, inlined_frame_index, isolate);
List<Handle<JSObject>> result(4);
ScopeIterator it(isolate, &frame_inspector, option); ScopeIterator it(isolate, &frame_inspector, option);
for (; !it.Done(); it.Next()) { for (; !it.Done(); it.Next()) {
Handle<JSObject> details; Handle<JSObject> details;
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include "src/assembler-inl.h" #include "src/assembler-inl.h"
#include "src/assert-scope.h" #include "src/assert-scope.h"
#include "src/compiler/wasm-compiler.h" #include "src/compiler/wasm-compiler.h"
#include "src/debug/debug-scopes.h"
#include "src/debug/debug.h" #include "src/debug/debug.h"
#include "src/factory.h" #include "src/factory.h"
#include "src/frames-inl.h" #include "src/frames-inl.h"
...@@ -24,6 +25,42 @@ using namespace v8::internal::wasm; ...@@ -24,6 +25,42 @@ using namespace v8::internal::wasm;
namespace { namespace {
template <bool internal, typename... Args>
Handle<String> PrintFToOneByteString(Isolate* isolate, const char* format,
Args... args) {
// Maximum length of a formatted value name ("param#%d", "local#%d",
// "global#%d").
constexpr int kMaxStrLen = 18;
EmbeddedVector<char, kMaxStrLen> value;
int len = SNPrintF(value, format, args...);
CHECK(len > 0 && len < value.length());
Vector<uint8_t> name = Vector<uint8_t>::cast(value.SubVector(0, len));
return internal
? isolate->factory()->InternalizeOneByteString(name)
: isolate->factory()->NewStringFromOneByte(name).ToHandleChecked();
}
Handle<Object> WasmValToValueObject(Isolate* isolate, WasmVal value) {
switch (value.type) {
case kWasmI32:
if (Smi::IsValid(value.to<int32_t>()))
return handle(Smi::FromInt(value.to<int32_t>()), isolate);
return PrintFToOneByteString<false>(isolate, "%d", value.to<int32_t>());
case kWasmI64:
if (Smi::IsValid(value.to<int64_t>()))
return handle(Smi::FromIntptr(value.to<int64_t>()), isolate);
return PrintFToOneByteString<false>(isolate, "%" PRId64,
value.to<int64_t>());
case kWasmF32:
return isolate->factory()->NewNumber(value.to<float>());
case kWasmF64:
return isolate->factory()->NewNumber(value.to<double>());
default:
UNIMPLEMENTED();
return isolate->factory()->undefined_value();
}
}
// Forward declaration. // Forward declaration.
class InterpreterHandle; class InterpreterHandle;
InterpreterHandle* GetInterpreterHandle(WasmDebugInfo* debug_info); InterpreterHandle* GetInterpreterHandle(WasmDebugInfo* debug_info);
...@@ -367,6 +404,88 @@ class InterpreterHandle { ...@@ -367,6 +404,88 @@ class InterpreterHandle {
instance_.mem_start = reinterpret_cast<byte*>(new_memory->backing_store()); instance_.mem_start = reinterpret_cast<byte*>(new_memory->backing_store());
CHECK(new_memory->byte_length()->ToUint32(&instance_.mem_size)); CHECK(new_memory->byte_length()->ToUint32(&instance_.mem_size));
} }
Handle<JSArray> GetScopeDetails(Address frame_pointer, int frame_index,
Handle<WasmInstanceObject> instance) {
auto frame = GetInterpretedFrame(frame_pointer, frame_index);
Handle<FixedArray> global_scope =
isolate_->factory()->NewFixedArray(ScopeIterator::kScopeDetailsSize);
global_scope->set(ScopeIterator::kScopeDetailsTypeIndex,
Smi::FromInt(ScopeIterator::ScopeTypeGlobal));
Handle<JSObject> global_scope_object =
isolate_->factory()->NewJSObjectWithNullProto();
global_scope->set(ScopeIterator::kScopeDetailsObjectIndex,
*global_scope_object);
// TODO(clemensh): Add globals to the global scope.
if (instance->has_memory_buffer()) {
Handle<String> name = isolate_->factory()->InternalizeOneByteString(
STATIC_CHAR_VECTOR("memory"));
Handle<JSArrayBuffer> memory_buffer(instance->memory_buffer(), isolate_);
uint32_t byte_length;
CHECK(memory_buffer->byte_length()->ToUint32(&byte_length));
Handle<JSTypedArray> uint8_array = isolate_->factory()->NewJSTypedArray(
kExternalUint8Array, memory_buffer, 0, byte_length);
JSObject::SetOwnPropertyIgnoreAttributes(global_scope_object, name,
uint8_array, NONE)
.Check();
}
Handle<FixedArray> local_scope =
isolate_->factory()->NewFixedArray(ScopeIterator::kScopeDetailsSize);
local_scope->set(ScopeIterator::kScopeDetailsTypeIndex,
Smi::FromInt(ScopeIterator::ScopeTypeLocal));
Handle<JSObject> local_scope_object =
isolate_->factory()->NewJSObjectWithNullProto();
local_scope->set(ScopeIterator::kScopeDetailsObjectIndex,
*local_scope_object);
// Fill parameters and locals.
int num_params = frame->GetParameterCount();
int num_locals = frame->GetLocalCount();
DCHECK_LE(num_params, num_locals);
for (int i = 0; i < num_locals; ++i) {
// TODO(clemensh): Use names from name section if present.
const char* label = i < num_params ? "param#%d" : "local#%d";
Handle<String> name = PrintFToOneByteString<true>(isolate_, label, i);
WasmVal value = frame->GetLocalValue(i);
Handle<Object> value_obj = WasmValToValueObject(isolate_, value);
JSObject::SetOwnPropertyIgnoreAttributes(local_scope_object, name,
value_obj, NONE)
.Check();
}
// Fill stack values.
int stack_count = frame->GetStackHeight();
// Use an object without prototype instead of an Array, for nicer displaying
// in DevTools. For Arrays, the length field and prototype is displayed,
// which does not make too much sense here.
Handle<JSObject> stack_obj =
isolate_->factory()->NewJSObjectWithNullProto();
for (int i = 0; i < stack_count; ++i) {
WasmVal value = frame->GetStackValue(i);
Handle<Object> value_obj = WasmValToValueObject(isolate_, value);
JSObject::SetOwnElementIgnoreAttributes(
stack_obj, static_cast<uint32_t>(i), value_obj, NONE)
.Check();
}
Handle<String> stack_name = isolate_->factory()->InternalizeOneByteString(
STATIC_CHAR_VECTOR("stack"));
JSObject::SetOwnPropertyIgnoreAttributes(local_scope_object, stack_name,
stack_obj, NONE)
.Check();
Handle<JSArray> global_jsarr =
isolate_->factory()->NewJSArrayWithElements(global_scope);
Handle<JSArray> local_jsarr =
isolate_->factory()->NewJSArrayWithElements(local_scope);
Handle<FixedArray> all_scopes = isolate_->factory()->NewFixedArray(2);
all_scopes->set(0, *global_jsarr);
all_scopes->set(1, *local_jsarr);
return isolate_->factory()->NewJSArrayWithElements(all_scopes);
}
}; };
InterpreterHandle* GetOrCreateInterpreterHandle( InterpreterHandle* GetOrCreateInterpreterHandle(
...@@ -553,3 +672,12 @@ void WasmDebugInfo::UpdateMemory(JSArrayBuffer* new_memory) { ...@@ -553,3 +672,12 @@ void WasmDebugInfo::UpdateMemory(JSArrayBuffer* new_memory) {
if (!interp_handle) return; if (!interp_handle) return;
interp_handle->UpdateMemory(new_memory); interp_handle->UpdateMemory(new_memory);
} }
// static
Handle<JSArray> WasmDebugInfo::GetScopeDetails(Handle<WasmDebugInfo> debug_info,
Address frame_pointer,
int frame_index) {
InterpreterHandle* interp_handle = GetInterpreterHandle(*debug_info);
Handle<WasmInstanceObject> instance(debug_info->wasm_instance());
return interp_handle->GetScopeDetails(frame_pointer, frame_index, instance);
}
...@@ -2259,8 +2259,10 @@ class InterpretedFrameImpl { ...@@ -2259,8 +2259,10 @@ class InterpretedFrameImpl {
static_cast<size_t>(index_) + 1 == thread_->frames_.size(); static_cast<size_t>(index_) + 1 == thread_->frames_.size();
size_t stack_limit = size_t stack_limit =
is_top_frame ? thread_->stack_.size() : thread_->frames_[index_ + 1].sp; is_top_frame ? thread_->stack_.size() : thread_->frames_[index_ + 1].sp;
DCHECK_LE(GetLocalCount(), stack_limit); DCHECK_LE(frame()->sp, stack_limit);
return static_cast<int>(stack_limit) - GetLocalCount(); size_t frame_size = stack_limit - frame()->sp;
DCHECK_LE(GetLocalCount(), frame_size);
return static_cast<int>(frame_size) - GetLocalCount();
} }
WasmVal GetLocalValue(int index) const { WasmVal GetLocalValue(int index) const {
......
...@@ -593,6 +593,17 @@ class WasmDebugInfo : public FixedArray { ...@@ -593,6 +593,17 @@ class WasmDebugInfo : public FixedArray {
// Update the memory view of the interpreter after executing GrowMemory in // Update the memory view of the interpreter after executing GrowMemory in
// compiled code. // compiled code.
void UpdateMemory(JSArrayBuffer* new_memory); void UpdateMemory(JSArrayBuffer* new_memory);
// Get scope details for a specific interpreted frame.
// This returns a JSArray of length two: One entry for the global scope, one
// for the local scope. Both elements are JSArrays of size
// ScopeIterator::kScopeDetailsSize and layout as described in debug-scopes.h.
// The global scope contains information about globals and the memory.
// The local scope contains information about parameters, locals, and stack
// values.
static Handle<JSArray> GetScopeDetails(Handle<WasmDebugInfo>,
Address frame_pointer,
int frame_index);
}; };
class WasmInstanceWrapper : public FixedArray { class WasmInstanceWrapper : public FixedArray {
......
...@@ -32,52 +32,298 @@ Setting breakpoint on line 7 (on the setlocal before the call), url wasm://wasm/ ...@@ -32,52 +32,298 @@ Setting breakpoint on line 7 (on the setlocal before the call), url wasm://wasm/
scriptId : <scriptId> scriptId : <scriptId>
} }
Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1:7:6: >set_local 0 Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1:7:6: >set_local 0
Step action: stepInto at wasm_B (7:6):
- scope (global):
-- skipped
- scope (local):
param#0: 4 (number)
stack: {"0":3} (Object)
at (anonymous) (0:17):
- scope (global):
-- skipped
Debugger.stepInto called
Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1:8:6: >call 0 Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1:8:6: >call 0
Step action: stepInto at wasm_B (8:6):
- scope (global):
-- skipped
- scope (local):
param#0: 3 (number)
stack: {} (Object)
at (anonymous) (0:17):
- scope (global):
-- skipped
Debugger.stepInto called
Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-0:1:2: >nop Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-0:1:2: >nop
Step action: stepOver at wasm_A (1:2):
- scope (global):
-- skipped
- scope (local):
stack: {} (Object)
at wasm_B (8:6):
- scope (global):
-- skipped
- scope (local):
param#0: 3 (number)
stack: {} (Object)
at (anonymous) (0:17):
- scope (global):
-- skipped
Debugger.stepOver called
Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-0:2:2: >nop Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-0:2:2: >nop
Step action: stepOut at wasm_A (2:2):
- scope (global):
-- skipped
- scope (local):
stack: {} (Object)
at wasm_B (8:6):
- scope (global):
-- skipped
- scope (local):
param#0: 3 (number)
stack: {} (Object)
at (anonymous) (0:17):
- scope (global):
-- skipped
Debugger.stepOut called
Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1:9:6: >br 1 Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1:9:6: >br 1
Step action: stepOut at wasm_B (9:6):
- scope (global):
-- skipped
- scope (local):
param#0: 3 (number)
stack: {} (Object)
at (anonymous) (0:17):
- scope (global):
-- skipped
Debugger.stepOut called
Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1:7:6: >set_local 0 Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1:7:6: >set_local 0
Step action: stepOver at wasm_B (7:6):
- scope (global):
-- skipped
- scope (local):
param#0: 3 (number)
stack: {"0":2} (Object)
at (anonymous) (0:17):
- scope (global):
-- skipped
Debugger.stepOver called
Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1:8:6: >call 0 Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1:8:6: >call 0
Step action: stepOver at wasm_B (8:6):
- scope (global):
-- skipped
- scope (local):
param#0: 2 (number)
stack: {} (Object)
at (anonymous) (0:17):
- scope (global):
-- skipped
Debugger.stepOver called
Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1:9:6: >br 1 Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1:9:6: >br 1
Step action: resume at wasm_B (9:6):
- scope (global):
-- skipped
- scope (local):
param#0: 2 (number)
stack: {} (Object)
at (anonymous) (0:17):
- scope (global):
-- skipped
Debugger.resume called
Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1:7:6: >set_local 0 Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1:7:6: >set_local 0
Step action: stepInto at wasm_B (7:6):
- scope (global):
-- skipped
- scope (local):
param#0: 2 (number)
stack: {"0":1} (Object)
at (anonymous) (0:17):
- scope (global):
-- skipped
Debugger.stepInto called
Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1:8:6: >call 0 Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1:8:6: >call 0
Step action: stepInto at wasm_B (8:6):
- scope (global):
-- skipped
- scope (local):
param#0: 1 (number)
stack: {} (Object)
at (anonymous) (0:17):
- scope (global):
-- skipped
Debugger.stepInto called
Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-0:1:2: >nop Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-0:1:2: >nop
Step action: stepOut at wasm_A (1:2):
- scope (global):
-- skipped
- scope (local):
stack: {} (Object)
at wasm_B (8:6):
- scope (global):
-- skipped
- scope (local):
param#0: 1 (number)
stack: {} (Object)
at (anonymous) (0:17):
- scope (global):
-- skipped
Debugger.stepOut called
Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1:9:6: >br 1 Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1:9:6: >br 1
Step action: stepInto at wasm_B (9:6):
- scope (global):
-- skipped
- scope (local):
param#0: 1 (number)
stack: {} (Object)
at (anonymous) (0:17):
- scope (global):
-- skipped
Debugger.stepInto called
Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1:1:2: >loop Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1:1:2: >loop
Step action: stepInto at wasm_B (1:2):
- scope (global):
-- skipped
- scope (local):
param#0: 1 (number)
stack: {} (Object)
at (anonymous) (0:17):
- scope (global):
-- skipped
Debugger.stepInto called
Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1:2:4: >get_local 0 Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1:2:4: >get_local 0
Step action: stepInto at wasm_B (2:4):
- scope (global):
-- skipped
- scope (local):
param#0: 1 (number)
stack: {} (Object)
at (anonymous) (0:17):
- scope (global):
-- skipped
Debugger.stepInto called
Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1:3:4: >if Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1:3:4: >if
Step action: stepInto at wasm_B (3:4):
- scope (global):
-- skipped
- scope (local):
param#0: 1 (number)
stack: {"0":1} (Object)
at (anonymous) (0:17):
- scope (global):
-- skipped
Debugger.stepInto called
Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1:4:6: >get_local 0 Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1:4:6: >get_local 0
Step action: stepInto at wasm_B (4:6):
- scope (global):
-- skipped
- scope (local):
param#0: 1 (number)
stack: {} (Object)
at (anonymous) (0:17):
- scope (global):
-- skipped
Debugger.stepInto called
Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1:5:6: >i32.const 1 Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1:5:6: >i32.const 1
Step action: stepInto at wasm_B (5:6):
- scope (global):
-- skipped
- scope (local):
param#0: 1 (number)
stack: {"0":1} (Object)
at (anonymous) (0:17):
- scope (global):
-- skipped
Debugger.stepInto called
Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1:6:6: >i32.sub Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1:6:6: >i32.sub
Step action: stepInto at wasm_B (6:6):
- scope (global):
-- skipped
- scope (local):
param#0: 1 (number)
stack: {"0":1,"1":1} (Object)
at (anonymous) (0:17):
- scope (global):
-- skipped
Debugger.stepInto called
Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1:7:6: >set_local 0 Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1:7:6: >set_local 0
Step action: stepInto at wasm_B (7:6):
- scope (global):
-- skipped
- scope (local):
param#0: 1 (number)
stack: {"0":0} (Object)
at (anonymous) (0:17):
- scope (global):
-- skipped
Debugger.stepInto called
Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1:8:6: >call 0 Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1:8:6: >call 0
Step action: stepInto at wasm_B (8:6):
- scope (global):
-- skipped
- scope (local):
param#0: 0 (number)
stack: {} (Object)
at (anonymous) (0:17):
- scope (global):
-- skipped
Debugger.stepInto called
Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-0:1:2: >nop Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-0:1:2: >nop
Step action: stepInto at wasm_A (1:2):
- scope (global):
-- skipped
- scope (local):
stack: {} (Object)
at wasm_B (8:6):
- scope (global):
-- skipped
- scope (local):
param#0: 0 (number)
stack: {} (Object)
at (anonymous) (0:17):
- scope (global):
-- skipped
Debugger.stepInto called
Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-0:2:2: >nop Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-0:2:2: >nop
Step action: stepInto at wasm_A (2:2):
- scope (global):
-- skipped
- scope (local):
stack: {} (Object)
at wasm_B (8:6):
- scope (global):
-- skipped
- scope (local):
param#0: 0 (number)
stack: {} (Object)
at (anonymous) (0:17):
- scope (global):
-- skipped
Debugger.stepInto called
Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-0:3:0: >end Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-0:3:0: >end
Step action: stepInto at wasm_A (3:0):
- scope (global):
-- skipped
- scope (local):
stack: {} (Object)
at wasm_B (8:6):
- scope (global):
-- skipped
- scope (local):
param#0: 0 (number)
stack: {} (Object)
at (anonymous) (0:17):
- scope (global):
-- skipped
Debugger.stepInto called
Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1:9:6: >br 1 Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1:9:6: >br 1
Step action: resume at wasm_B (9:6):
- scope (global):
-- skipped
- scope (local):
param#0: 0 (number)
stack: {} (Object)
at (anonymous) (0:17):
- scope (global):
-- skipped
Debugger.resume called
exports.main returned! exports.main returned!
Finished! Finished!
...@@ -68,6 +68,9 @@ var step_actions = [ ...@@ -68,6 +68,9 @@ var step_actions = [
// then just resume. // then just resume.
'resume' 'resume'
]; ];
for (var action of step_actions) {
InspectorTest.logProtocolCommandCalls('Debugger.' + action)
}
var sources = {}; var sources = {};
var urls = {}; var urls = {};
var afterTwoSourcesCallback; var afterTwoSourcesCallback;
...@@ -151,10 +154,48 @@ function printPauseLocation(scriptId, lineNr, columnNr) { ...@@ -151,10 +154,48 @@ function printPauseLocation(scriptId, lineNr, columnNr) {
line); line);
} }
async function getValueString(value) {
if (value.type == 'object') {
var msg = await Protocol.Runtime.callFunctionOn({
objectId: value.objectId,
functionDeclaration: 'function () { return JSON.stringify(this); }'
});
printFailure(msg);
return msg.result.result.value + ' (' + value.description + ')';
}
return value.value + ' (' + value.type + ')';
}
async function dumpProperties(message) {
printFailure(message);
for (var value of message.result.result) {
var value_str = await getValueString(value.value);
InspectorTest.log(' ' + value.name + ': ' + value_str);
}
}
async function dumpScopeChainsOnPause(message) {
for (var frame of message.params.callFrames) {
var functionName = frame.functionName || '(anonymous)';
var lineNumber = frame.location ? frame.location.lineNumber : frame.lineNumber;
var columnNumber = frame.location ? frame.location.columnNumber : frame.columnNumber;
InspectorTest.log(`at ${functionName} (${lineNumber}:${columnNumber}):`);
for (var scope of frame.scopeChain) {
InspectorTest.logObject(' - scope (' + scope.type + '):');
if (scope.type == 'global') {
InspectorTest.logObject(' -- skipped');
} else {
var properties = await Protocol.Runtime.getProperties(
{'objectId': scope.object.objectId});
await dumpProperties(properties);
}
}
}
}
function handlePaused(msg) { function handlePaused(msg) {
var loc = msg.params.callFrames[0].location; var loc = msg.params.callFrames[0].location;
printPauseLocation(loc.scriptId, loc.lineNumber, loc.columnNumber); printPauseLocation(loc.scriptId, loc.lineNumber, loc.columnNumber);
var action = step_actions.shift(); dumpScopeChainsOnPause(msg)
InspectorTest.log('Step action: ' + action); .then(Protocol.Debugger[step_actions.shift() || 'resume']);
Protocol.Debugger[action]();
} }
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