Commit f10edd09 authored by Benedikt Meurer's avatar Benedikt Meurer Committed by Commit Bot

[inspector][wasm] Re-add WasmValue as JSObject subclass.

BREAKING CHANGE: The values of Wasm locals, stack, and globals are now
represented as objects instead of holding the (primitive) values
directly, and SIMD128 values are no longer represented as Uint8Arrays.
The DWARF extension has been prepared for this breaking change.

The new `WasmValue` comes with `type` and `value` properties that hold
its contents. The motivation here is that this is a more extensible
approach. In case of SIMD128, the `value` property holds the canonical
string representation, which has the additional advantage that these
values can be compared with `===` (and `==`).

This partially reverts https://crrev.com/c/2614428, the main difference
here being that WasmValue is now a proper JSObject that can be exposed
on the DebugEvaluate proxy API.

Screenshot: https://imgur.com/rcahNKM.png
Bug: chromium:1170282, chromium:1071432, chromium:1159402
Change-Id: Iea304e3680775123c41deb4c3d172ac949da1b98
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2643384Reviewed-by: 's avatarPhilip Pfaffe <pfaffe@chromium.org>
Reviewed-by: 's avatarZhi An Ng <zhin@chromium.org>
Reviewed-by: 's avatarYang Guo <yangguo@chromium.org>
Commit-Queue: Benedikt Meurer <bmeurer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#72570}
parent 3af1d7c3
......@@ -1359,6 +1359,7 @@ torque_files = [
"src/builtins/typed-array.tq",
"src/builtins/wasm.tq",
"src/builtins/weak-ref.tq",
"src/debug/debug-wasm-objects.tq",
"src/ic/handler-configuration.tq",
"src/objects/allocation-site.tq",
"src/objects/api-callbacks.tq",
......@@ -2652,8 +2653,9 @@ v8_source_set("v8_base_without_compiler") {
"src/debug/debug-stack-trace-iterator.h",
"src/debug/debug-type-profile.cc",
"src/debug/debug-type-profile.h",
"src/debug/debug-wasm-support.cc",
"src/debug/debug-wasm-support.h",
"src/debug/debug-wasm-objects-inl.h",
"src/debug/debug-wasm-objects.cc",
"src/debug/debug-wasm-objects.h",
"src/debug/debug.cc",
"src/debug/debug.h",
"src/debug/interface-types.h",
......
......@@ -1030,6 +1030,7 @@ domain Runtime
arraybuffer
dataview
webassemblymemory
wasmvalue
# Object class (constructor) name. Specified for `object` type values only.
optional string className
# Remote object value in case of primitive values or JSON values (if it was requested).
......
......@@ -263,6 +263,7 @@ Type::bitset BitsetType::Lub(const MapRefLike& map) {
case WASM_MODULE_OBJECT_TYPE:
case WASM_STRUCT_TYPE:
case WASM_TABLE_OBJECT_TYPE:
case WASM_VALUE_OBJECT_TYPE:
case WEAK_CELL_TYPE:
DCHECK(!map.is_callable());
DCHECK(!map.is_undetectable());
......
......@@ -10,7 +10,7 @@
#include "src/common/globals.h"
#include "src/debug/debug-frames.h"
#include "src/debug/debug-scopes.h"
#include "src/debug/debug-wasm-support.h"
#include "src/debug/debug-wasm-objects.h"
#include "src/debug/debug.h"
#include "src/execution/frames-inl.h"
#include "src/execution/isolate-inl.h"
......
......@@ -9,6 +9,7 @@
#include "src/debug/debug-evaluate.h"
#include "src/debug/debug-property-iterator.h"
#include "src/debug/debug-type-profile.h"
#include "src/debug/debug-wasm-objects-inl.h"
#include "src/debug/debug.h"
#include "src/execution/vm-state-inl.h"
#include "src/objects/js-generator-inl.h"
......@@ -740,6 +741,12 @@ void AccessorPair::CheckCast(Value* that) {
"Value is not a v8::debug::AccessorPair");
}
void WasmValueObject::CheckCast(Value* that) {
i::Handle<i::Object> obj = Utils::OpenHandle(that);
Utils::ApiCheck(obj->IsWasmValueObject(), "v8::debug::WasmValueObject::Cast",
"Value is not a v8::debug::WasmValueObject");
}
Local<Function> GetBuiltin(Isolate* v8_isolate, Builtin builtin) {
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate);
......@@ -1102,6 +1109,27 @@ bool AccessorPair::IsAccessorPair(Local<Value> that) {
return obj->IsAccessorPair();
}
bool WasmValueObject::IsWasmValueObject(Local<Value> that) {
i::Handle<i::Object> obj = Utils::OpenHandle(*that);
return obj->IsWasmValueObject();
}
Local<String> WasmValueObject::type() const {
i::Handle<i::WasmValueObject> object =
i::Handle<i::WasmValueObject>::cast(Utils::OpenHandle(this));
i::Isolate* isolate = object->GetIsolate();
i::Handle<i::String> type(object->type(), isolate);
return Utils::ToLocal(type);
}
Local<Value> WasmValueObject::value() const {
i::Handle<i::WasmValueObject> object =
i::Handle<i::WasmValueObject>::cast(Utils::OpenHandle(this));
i::Isolate* isolate = object->GetIsolate();
i::Handle<i::Object> value(object->value(), isolate);
return Utils::ToLocal(value);
}
MaybeLocal<Message> GetMessageFromPromise(Local<Promise> p) {
i::Handle<i::JSPromise> promise = Utils::OpenHandle(*p);
i::Isolate* isolate = promise->GetIsolate();
......
......@@ -616,6 +616,19 @@ class PropertyIterator {
virtual bool is_array_index() = 0;
};
class V8_EXPORT_PRIVATE WasmValueObject : public v8::Object {
public:
WasmValueObject() = delete;
static bool IsWasmValueObject(v8::Local<v8::Value> obj);
V8_INLINE static WasmValueObject* Cast(v8::Value* obj);
v8::Local<v8::String> type() const;
v8::Local<v8::Value> value() const;
private:
static void CheckCast(v8::Value* obj);
};
AccessorPair* AccessorPair::Cast(v8::Value* value) {
#ifdef V8_ENABLE_CHECKS
CheckCast(value);
......@@ -623,6 +636,13 @@ AccessorPair* AccessorPair::Cast(v8::Value* value) {
return static_cast<AccessorPair*>(value);
}
WasmValueObject* WasmValueObject::Cast(v8::Value* value) {
#ifdef V8_ENABLE_CHECKS
CheckCast(value);
#endif
return static_cast<WasmValueObject*>(value);
}
MaybeLocal<Message> GetMessageFromPromise(Local<Promise> promise);
} // namespace debug
......
......@@ -7,7 +7,7 @@
#include "src/api/api-inl.h"
#include "src/debug/debug-evaluate.h"
#include "src/debug/debug-scope-iterator.h"
#include "src/debug/debug-wasm-support.h"
#include "src/debug/debug-wasm-objects.h"
#include "src/debug/debug.h"
#include "src/debug/liveedit.h"
#include "src/execution/frames-inl.h"
......
// Copyright 2021 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_DEBUG_DEBUG_WASM_OBJECTS_INL_H_
#define V8_DEBUG_DEBUG_WASM_OBJECTS_INL_H_
#include "src/debug/debug-wasm-objects.h"
#include "src/objects/js-objects-inl.h"
// Has to be the last include (doesn't have include guards):
#include "src/objects/object-macros.h"
namespace v8 {
namespace internal {
#include "torque-generated/src/debug/debug-wasm-objects-tq-inl.inc"
OBJECT_CONSTRUCTORS_IMPL(WasmValueObject, JSObject)
CAST_ACCESSOR(WasmValueObject)
ACCESSORS(WasmValueObject, type, String, kTypeOffset)
ACCESSORS(WasmValueObject, value, Object, kValueOffset)
} // namespace internal
} // namespace v8
#include "src/objects/object-macros-undef.h"
#endif // V8_DEBUG_DEBUG_WASM_OBJECTS_INL_H_
......@@ -2,10 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/debug/debug-wasm-support.h"
#include "src/debug/debug-wasm-objects.h"
#include "src/api/api-inl.h"
#include "src/api/api-natives.h"
#include "src/debug/debug-wasm-objects-inl.h"
#include "src/execution/frames-inl.h"
#include "src/objects/property-descriptor.h"
#include "src/wasm/wasm-debug.h"
......@@ -16,49 +17,6 @@ namespace v8 {
namespace internal {
namespace {
// Convert a WasmValue to an appropriate JS representation.
Handle<Object> WasmValueToObject(Isolate* isolate, wasm::WasmValue value) {
auto* factory = isolate->factory();
switch (value.type().kind()) {
case wasm::ValueType::kI32:
return factory->NewNumberFromInt(value.to_i32());
case wasm::ValueType::kI64:
return BigInt::FromInt64(isolate, value.to_i64());
case wasm::ValueType::kF32:
return factory->NewNumber(value.to_f32());
case wasm::ValueType::kF64:
return factory->NewNumber(value.to_f64());
case wasm::ValueType::kS128: {
wasm::Simd128 s128 = value.to_s128();
Handle<JSArrayBuffer> buffer;
if (!factory
->NewJSArrayBufferAndBackingStore(
kSimd128Size, InitializedFlag::kUninitialized)
.ToHandle(&buffer)) {
isolate->FatalProcessOutOfHeapMemory(
"failed to allocate backing store");
}
base::Memcpy(buffer->allocation_base(), s128.bytes(),
buffer->byte_length());
auto array = factory->NewJSTypedArray(kExternalUint8Array, buffer, 0,
kSimd128Size);
JSObject::SetPrototype(array, factory->null_value(), false, kDontThrow)
.Check();
return array;
}
case wasm::ValueType::kRef:
return value.to_externref();
default:
break;
}
return factory->undefined_value();
}
} // namespace
namespace {
// Helper for unpacking a maybe name that makes a default with an index if
// the name is empty. If the name is not empty, it's prefixed with a $.
Handle<String> GetNameOrDefault(Isolate* isolate,
......@@ -124,6 +82,18 @@ enum DebugProxyId {
kNumInstanceProxies = kLastInstanceProxyId + 1
};
constexpr int kWasmValueMapIndex = kNumProxies;
constexpr int kNumDebugMaps = kWasmValueMapIndex + 1;
Handle<FixedArray> GetOrCreateDebugMaps(Isolate* isolate) {
Handle<FixedArray> maps = isolate->wasm_debug_maps();
if (maps->length() == 0) {
maps = isolate->factory()->NewFixedArrayWithHoles(kNumDebugMaps);
isolate->native_context()->set_wasm_debug_maps(*maps);
}
return maps;
}
// Creates a Map for the given debug proxy |id| using the |create_template_fn|
// on-demand and caches this map in the global object. The map is derived from
// the FunctionTemplate returned by |create_template_fn| and has it's prototype
......@@ -131,12 +101,8 @@ enum DebugProxyId {
Handle<Map> GetOrCreateDebugProxyMap(
Isolate* isolate, DebugProxyId id,
v8::Local<v8::FunctionTemplate> (*create_template_fn)(v8::Isolate*)) {
Handle<FixedArray> maps = isolate->wasm_debug_proxy_maps();
if (maps->length() == 0) {
maps = isolate->factory()->NewFixedArrayWithHoles(kNumProxies);
isolate->native_context()->set_wasm_debug_proxy_maps(*maps);
}
CHECK_EQ(kNumProxies, maps->length());
auto maps = GetOrCreateDebugMaps(isolate);
CHECK_LE(kNumProxies, maps->length());
if (!maps->is_the_hole(isolate, id)) {
return handle(Map::cast(maps->get(id)), isolate);
}
......@@ -372,9 +338,9 @@ struct GlobalsProxy : NamedDebugProxy<GlobalsProxy, kGlobalsProxy> {
static Handle<Object> Get(Isolate* isolate,
Handle<WasmInstanceObject> instance,
uint32_t index) {
return WasmValueToObject(isolate,
WasmInstanceObject::GetGlobalValue(
instance, instance->module()->globals[index]));
return WasmValueObject::New(
isolate, WasmInstanceObject::GetGlobalValue(
instance, instance->module()->globals[index]));
}
static Handle<String> GetName(Isolate* isolate,
......@@ -453,7 +419,7 @@ struct LocalsProxy : NamedDebugProxy<LocalsProxy, kLocalsProxy, FixedArray> {
auto function = debug_info->GetFunctionAtAddress(frame->pc());
auto values = isolate->factory()->NewFixedArray(count + 2);
for (int i = 0; i < count; ++i) {
auto value = WasmValueToObject(
auto value = WasmValueObject::New(
isolate, debug_info->GetLocalValue(i, frame->pc(), frame->fp(),
frame->callee_fp()));
values->set(i, *value);
......@@ -500,7 +466,7 @@ struct StackProxy : IndexedDebugProxy<StackProxy, kStackProxy, FixedArray> {
int count = debug_info->GetStackDepth(frame->pc());
auto values = isolate->factory()->NewFixedArray(count);
for (int i = 0; i < count; ++i) {
auto value = WasmValueToObject(
auto value = WasmValueObject::New(
isolate, debug_info->GetStackValue(i, frame->pc(), frame->fp(),
frame->callee_fp()));
values->set(i, *value);
......@@ -555,8 +521,10 @@ Handle<JSObject> GetOrCreateInstanceProxy(Isolate* isolate,
// and extensions to inspect the WebAssembly engine state from JavaScript.
// The proxy provides the following interface:
//
// type WasmSimdValue = Uint8Array;
// type WasmValue = number | bigint | object | WasmSimdValue;
// type WasmValue = {
// type: string;
// value: number | bigint | object | string;
// };
// type WasmFunction = (... args : WasmValue[]) = > WasmValue;
// interface WasmInterface {
// $globalX: WasmValue;
......@@ -773,8 +741,97 @@ class DebugWasmScopeIterator final : public debug::ScopeIterator {
ScopeType type_;
};
Handle<String> WasmSimd128ToString(Isolate* isolate, wasm::Simd128 s128) {
// We use the canonical format as described in:
// https://github.com/WebAssembly/simd/blob/master/proposals/simd/TextSIMD.md
EmbeddedVector<char, 50> buffer;
auto i32x4 = s128.to_i32x4();
SNPrintF(buffer, "i32x4 0x%08X 0x%08X 0x%08X 0x%08X", i32x4.val[0],
i32x4.val[1], i32x4.val[2], i32x4.val[3]);
return isolate->factory()->NewStringFromAsciiChecked(buffer.data());
}
} // namespace
// static
Handle<WasmValueObject> WasmValueObject::New(Isolate* isolate,
Handle<String> type,
Handle<Object> value) {
auto maps = GetOrCreateDebugMaps(isolate);
if (maps->is_the_hole(isolate, kWasmValueMapIndex)) {
Handle<Map> map = isolate->factory()->NewMap(
WASM_VALUE_OBJECT_TYPE, WasmValueObject::kSize,
TERMINAL_FAST_ELEMENTS_KIND, 2);
Map::EnsureDescriptorSlack(isolate, map, 2);
{ // type
Descriptor d = Descriptor::DataField(
isolate,
isolate->factory()->InternalizeString(StaticCharVector("type")),
WasmValueObject::kTypeIndex, FROZEN, Representation::Tagged());
map->AppendDescriptor(isolate, &d);
}
{ // value
Descriptor d = Descriptor::DataField(
isolate,
isolate->factory()->InternalizeString(StaticCharVector("value")),
WasmValueObject::kValueIndex, FROZEN, Representation::Tagged());
map->AppendDescriptor(isolate, &d);
}
map->set_is_extensible(false);
maps->set(kWasmValueMapIndex, *map);
}
Handle<Map> value_map =
handle(Map::cast(maps->get(kWasmValueMapIndex)), isolate);
Handle<WasmValueObject> object = Handle<WasmValueObject>::cast(
isolate->factory()->NewJSObjectFromMap(value_map));
object->set_type(*type);
object->set_value(*value);
return object;
}
// static
Handle<WasmValueObject> WasmValueObject::New(Isolate* isolate,
const wasm::WasmValue& value) {
Handle<String> t;
Handle<Object> v;
switch (value.type().kind()) {
case wasm::ValueType::kI32: {
t = isolate->factory()->InternalizeString(StaticCharVector("i32"));
v = isolate->factory()->NewNumberFromInt(value.to_i32_unchecked());
break;
}
case wasm::ValueType::kI64: {
t = isolate->factory()->InternalizeString(StaticCharVector("i64"));
v = BigInt::FromInt64(isolate, value.to_i64_unchecked());
break;
}
case wasm::ValueType::kF32: {
t = isolate->factory()->InternalizeString(StaticCharVector("f32"));
v = isolate->factory()->NewNumber(value.to_f32_unchecked());
break;
}
case wasm::ValueType::kF64: {
t = isolate->factory()->InternalizeString(StaticCharVector("f64"));
v = isolate->factory()->NewNumber(value.to_f64_unchecked());
break;
}
case wasm::ValueType::kS128: {
t = isolate->factory()->InternalizeString(StaticCharVector("v128"));
v = WasmSimd128ToString(isolate, value.to_s128_unchecked());
break;
}
case wasm::ValueType::kRef: {
t = isolate->factory()->InternalizeString(StaticCharVector("externref"));
v = value.to_externref();
break;
}
default:
UNREACHABLE();
}
return New(isolate, t, v);
}
Handle<JSObject> GetWasmDebugProxy(WasmFrame* frame) {
return ContextProxy::Create(frame);
}
......
......@@ -2,26 +2,63 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_DEBUG_DEBUG_WASM_SUPPORT_H_
#define V8_DEBUG_DEBUG_WASM_SUPPORT_H_
#ifndef V8_DEBUG_DEBUG_WASM_OBJECTS_H_
#define V8_DEBUG_DEBUG_WASM_OBJECTS_H_
#include <memory>
#include "src/objects/js-objects.h"
// Has to be the last include (doesn't have include guards):
#include "src/objects/object-macros.h"
namespace v8 {
namespace debug {
class ScopeIterator;
} // namespace debug
namespace internal {
namespace wasm {
class WasmValue;
} // namespace wasm
#include "torque-generated/src/debug/debug-wasm-objects-tq.inc"
template <typename T>
class Handle;
class JSArray;
class JSObject;
class WasmFrame;
class WasmInstanceObject;
class WasmModuleObject;
class WasmValueObject : public JSObject {
public:
DECL_CAST(WasmValueObject)
DECL_ACCESSORS(type, String)
DECL_ACCESSORS(value, Object)
// Dispatched behavior.
DECL_PRINTER(WasmValueObject)
DECL_VERIFIER(WasmValueObject)
// Layout description.
#define WASM_VALUE_FIELDS(V) \
V(kTypeOffset, kTaggedSize) \
V(kValueOffset, kTaggedSize) \
V(kSize, 0)
DEFINE_FIELD_OFFSET_CONSTANTS(JSObject::kHeaderSize, WASM_VALUE_FIELDS)
#undef WASM_VALUE_FIELDS
// Indices of in-object properties.
static constexpr int kTypeIndex = 0;
static constexpr int kValueIndex = 1;
static Handle<WasmValueObject> New(Isolate* isolate, Handle<String> type,
Handle<Object> value);
static Handle<WasmValueObject> New(Isolate* isolate,
const wasm::WasmValue& value);
OBJECT_CONSTRUCTORS(WasmValueObject, JSObject);
};
Handle<JSObject> GetWasmDebugProxy(WasmFrame* frame);
std::unique_ptr<debug::ScopeIterator> GetWasmScopeIterator(WasmFrame* frame);
......@@ -34,4 +71,6 @@ Handle<JSArray> GetWasmModuleObjectInternalProperties(
} // namespace internal
} // namespace v8
#endif // V8_DEBUG_DEBUG_WASM_SUPPORT_H_
#include "src/objects/object-macros-undef.h"
#endif // V8_DEBUG_DEBUG_WASM_OBJECTS_H_
// Copyright 2021 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include 'src/debug/debug-wasm-objects.h'
extern class WasmValueObject extends JSObject;
......@@ -5,6 +5,7 @@
#include "src/codegen/assembler-inl.h"
#include "src/common/globals.h"
#include "src/date/date.h"
#include "src/debug/debug-wasm-objects-inl.h"
#include "src/diagnostics/disasm.h"
#include "src/diagnostics/disassembler.h"
#include "src/heap/combined-heap.h"
......@@ -228,6 +229,9 @@ void HeapObject::HeapObjectVerify(Isolate* isolate) {
case WASM_INSTANCE_OBJECT_TYPE:
WasmInstanceObject::cast(*this).WasmInstanceObjectVerify(isolate);
break;
case WASM_VALUE_OBJECT_TYPE:
WasmValueObject::cast(*this).WasmValueObjectVerify(isolate);
break;
case JS_SET_KEY_VALUE_ITERATOR_TYPE:
case JS_SET_VALUE_ITERATOR_TYPE:
JSSetIterator::cast(*this).JSSetIteratorVerify(isolate);
......@@ -1539,6 +1543,12 @@ void WasmInstanceObject::WasmInstanceObjectVerify(Isolate* isolate) {
}
}
void WasmValueObject::WasmValueObjectVerify(Isolate* isolate) {
JSObjectVerify(isolate);
CHECK(IsWasmValueObject());
CHECK(type().IsString());
}
void WasmExportedFunctionData::WasmExportedFunctionDataVerify(
Isolate* isolate) {
TorqueGeneratedClassVerifiers::WasmExportedFunctionDataVerify(*this, isolate);
......
......@@ -7,6 +7,7 @@
#include "src/common/globals.h"
#include "src/compiler/node.h"
#include "src/debug/debug-wasm-objects-inl.h"
#include "src/diagnostics/disasm.h"
#include "src/diagnostics/disassembler.h"
#include "src/heap/heap-inl.h" // For InOldSpace.
......@@ -175,6 +176,9 @@ void HeapObject::HeapObjectPrint(std::ostream& os) { // NOLINT
case WASM_INSTANCE_OBJECT_TYPE:
WasmInstanceObject::cast(*this).WasmInstanceObjectPrint(os);
break;
case WASM_VALUE_OBJECT_TYPE:
WasmValueObject::cast(*this).WasmValueObjectPrint(os);
break;
case CODE_TYPE:
Code::cast(*this).CodePrint(os);
break;
......@@ -1895,6 +1899,13 @@ void WasmTableObject::WasmTableObjectPrint(std::ostream& os) { // NOLINT
os << "\n";
}
void WasmValueObject::WasmValueObjectPrint(std::ostream& os) { // NOLINT
PrintHeader(os, "WasmValueObject");
os << "\n - type: " << Brief(type());
os << "\n - value: " << Brief(value());
os << "\n";
}
void WasmGlobalObject::WasmGlobalObjectPrint(std::ostream& os) { // NOLINT
PrintHeader(os, "WasmGlobalObject");
if (type().is_reference_type()) {
......
......@@ -4594,8 +4594,8 @@ bool Genesis::InstallABunchOfRandomThings() {
native_context()->set_slow_template_instantiations_cache(
*slow_template_instantiations_cache);
auto wasm_debug_proxy_maps = isolate()->factory()->empty_fixed_array();
native_context()->set_wasm_debug_proxy_maps(*wasm_debug_proxy_maps);
auto wasm_debug_maps = isolate()->factory()->empty_fixed_array();
native_context()->set_wasm_debug_maps(*wasm_debug_maps);
// Store the map for the %ObjectPrototype% after the natives has been compiled
// and the Object function has been set up.
......
......@@ -43,26 +43,6 @@ V8InternalValueType v8InternalValueTypeFrom(v8::Local<v8::Context> context,
return inspectedContext->getInternalType(value.As<v8::Object>());
}
template <typename ResultType>
ResultType unpackWasmValue(v8::Local<v8::Context> context,
v8::Local<v8::Array> array) {
ResultType result;
constexpr int kSize = sizeof(result);
uint8_t buffer[kSize];
for (int i = 0; i < kSize; i++) {
v8::Local<v8::Int32> i32 =
array->Get(context, i).ToLocalChecked().As<v8::Int32>();
buffer[i] = static_cast<uint8_t>(i32->Value());
}
memcpy(&result, buffer, kSize);
return result;
}
// Partial list of Wasm's ValueType, copied here to avoid including internal
// header. Using an unscoped enumeration here to allow implicit conversions from
// int. Keep in sync with ValueType::Kind in wasm/value-type.h.
enum WasmValueType { kStmt, kI32, kI64, kF32, kF64, kS128, kExternRef };
Response toProtocolValue(v8::Local<v8::Context> context,
v8::Local<v8::Value> value, int maxDepth,
std::unique_ptr<protocol::Value>* result) {
......@@ -325,6 +305,22 @@ String16 descriptionForCollection(v8::Isolate* isolate,
return String16::concat(className, '(', String16::fromInteger(length), ')');
}
String16 descriptionForWasmValueObject(
v8::Local<v8::Context> context,
v8::Local<v8::debug::WasmValueObject> object) {
v8::Isolate* isolate = context->GetIsolate();
auto type = toProtocolString(isolate, object->type());
auto value = object->value();
if (type == "i32" || type == "f32" || type == "f64") {
return String16::fromDouble(v8::Local<v8::Number>::Cast(value)->Value());
} else if (type == "i64") {
return descriptionForBigInt(context, v8::Local<v8::BigInt>::Cast(value));
} else if (type == "v128") {
return toProtocolString(isolate, v8::Local<v8::String>::Cast(value));
}
return type;
}
String16 descriptionForEntry(v8::Local<v8::Context> context,
v8::Local<v8::Object> object) {
v8::Isolate* isolate = context->GetIsolate();
......@@ -1711,6 +1707,13 @@ std::unique_ptr<ValueMirror> ValueMirror::create(v8::Local<v8::Context> context,
descriptionForCollection(
isolate, memory, memory->Buffer()->ByteLength() / kWasmPageSize));
}
if (v8::debug::WasmValueObject::IsWasmValueObject(value)) {
v8::Local<v8::debug::WasmValueObject> v =
value.As<v8::debug::WasmValueObject>();
return std::make_unique<ObjectMirror>(
value, RemoteObject::SubtypeEnum::Wasmvalue,
descriptionForWasmValueObject(context, v));
}
V8InternalValueType internalType =
v8InternalValueTypeFrom(context, value.As<v8::Object>());
if (value->IsArray() && internalType == V8InternalValueType::kScopeList) {
......
......@@ -237,7 +237,7 @@ enum ContextLookupFlags {
V(SLOW_TEMPLATE_INSTANTIATIONS_CACHE_INDEX, SimpleNumberDictionary, \
slow_template_instantiations_cache) \
V(ATOMICS_WAITASYNC_PROMISES, OrderedHashSet, atomics_waitasync_promises) \
V(WASM_DEBUG_PROXY_MAPS, FixedArray, wasm_debug_proxy_maps) \
V(WASM_DEBUG_MAPS, FixedArray, wasm_debug_maps) \
/* Fast Path Protectors */ \
V(REGEXP_SPECIES_PROTECTOR_INDEX, PropertyCell, regexp_species_protector) \
/* All *_FUNCTION_MAP_INDEX definitions used by Context::FunctionMapIndex */ \
......
......@@ -596,6 +596,7 @@ bool CanSubclassHaveInobjectProperties(InstanceType instance_type) {
case WASM_MEMORY_OBJECT_TYPE:
case WASM_MODULE_OBJECT_TYPE:
case WASM_TABLE_OBJECT_TYPE:
case WASM_VALUE_OBJECT_TYPE:
return true;
case BIGINT_TYPE:
......
......@@ -7,6 +7,7 @@
#include "src/api/api-arguments-inl.h"
#include "src/common/globals.h"
#include "src/date/date.h"
#include "src/debug/debug-wasm-objects.h"
#include "src/execution/arguments.h"
#include "src/execution/frames.h"
#include "src/execution/isolate.h"
......@@ -2301,6 +2302,8 @@ int JSObject::GetHeaderSize(InstanceType type,
return WasmModuleObject::kHeaderSize;
case WASM_TABLE_OBJECT_TYPE:
return WasmTableObject::kHeaderSize;
case WASM_VALUE_OBJECT_TYPE:
return WasmValueObject::kHeaderSize;
case WASM_EXCEPTION_OBJECT_TYPE:
return WasmExceptionObject::kHeaderSize;
default:
......
......@@ -309,6 +309,7 @@ VisitorId Map::GetVisitorId(Map map) {
case WASM_MEMORY_OBJECT_TYPE:
case WASM_MODULE_OBJECT_TYPE:
case WASM_TABLE_OBJECT_TYPE:
case WASM_VALUE_OBJECT_TYPE:
case JS_BOUND_FUNCTION_TYPE: {
const bool has_raw_data_fields =
(FLAG_unbox_double_fields && !map.HasFastPointerLayout()) ||
......
......@@ -226,6 +226,7 @@ class ZoneForwardList;
V(WasmStruct) \
V(WasmTypeInfo) \
V(WasmTableObject) \
V(WasmValueObject) \
V(WeakFixedArray) \
V(WeakArrayList) \
V(WeakCell) \
......
......@@ -994,6 +994,7 @@ ReturnType BodyDescriptorApply(InstanceType type, T1 p1, T2 p2, T3 p3, T4 p4) {
case WASM_MEMORY_OBJECT_TYPE:
case WASM_MODULE_OBJECT_TYPE:
case WASM_TABLE_OBJECT_TYPE:
case WASM_VALUE_OBJECT_TYPE:
return Op::template apply<JSObject::BodyDescriptor>(p1, p2, p3, p4);
case WASM_INSTANCE_OBJECT_TYPE:
return Op::template apply<WasmInstanceObject::BodyDescriptor>(p1, p2, p3,
......
......@@ -10,7 +10,7 @@
#include "src/debug/debug-evaluate.h"
#include "src/debug/debug-frames.h"
#include "src/debug/debug-scopes.h"
#include "src/debug/debug-wasm-support.h"
#include "src/debug/debug-wasm-objects.h"
#include "src/debug/debug.h"
#include "src/debug/liveedit.h"
#include "src/execution/arguments-inl.h"
......
......@@ -8,7 +8,6 @@ type PodArrayOfWasmValueType extends ByteArray
@useParentTypeChecker
type ManagedWasmNativeModule extends Foreign
constexpr 'Managed<wasm::NativeModule>';
type WasmValueType extends uint8 constexpr 'wasm::ValueType::Kind';
extern class WasmInstanceObject extends JSObject;
......
......@@ -28,7 +28,7 @@ Setting breakpoint at offset 41, condition "true"
breakpointId : <breakpointId>
}
}
Setting breakpoint at offset 46, condition "$var0==3"
Setting breakpoint at offset 46, condition "$var0.value==3"
{
id : <messageId>
result : {
......@@ -42,25 +42,25 @@ Setting breakpoint at offset 46, condition "$var0==3"
}
Calling fib(5)
Script wasm://wasm/f00dbc56 byte offset 41: Wasm opcode 0x0d (kExprBrIf)
$var0: 5
$var0: 5 (i32)
Script wasm://wasm/f00dbc56 byte offset 41: Wasm opcode 0x0d (kExprBrIf)
$var0: 4
$var0: 4 (i32)
Script wasm://wasm/f00dbc56 byte offset 41: Wasm opcode 0x0d (kExprBrIf)
$var0: 3
$var0: 3 (i32)
Script wasm://wasm/f00dbc56 byte offset 46: Wasm opcode 0x10 (kExprCallFunction)
$var0: 3
$var0: 3 (i32)
Script wasm://wasm/f00dbc56 byte offset 41: Wasm opcode 0x0d (kExprBrIf)
$var0: 2
$var0: 2 (i32)
Script wasm://wasm/f00dbc56 byte offset 41: Wasm opcode 0x0d (kExprBrIf)
$var0: 1
$var0: 1 (i32)
Script wasm://wasm/f00dbc56 byte offset 41: Wasm opcode 0x0d (kExprBrIf)
$var0: 2
$var0: 2 (i32)
Script wasm://wasm/f00dbc56 byte offset 41: Wasm opcode 0x0d (kExprBrIf)
$var0: 3
$var0: 3 (i32)
Script wasm://wasm/f00dbc56 byte offset 46: Wasm opcode 0x10 (kExprCallFunction)
$var0: 3
$var0: 3 (i32)
Script wasm://wasm/f00dbc56 byte offset 41: Wasm opcode 0x0d (kExprBrIf)
$var0: 2
$var0: 2 (i32)
Script wasm://wasm/f00dbc56 byte offset 41: Wasm opcode 0x0d (kExprBrIf)
$var0: 1
$var0: 1 (i32)
fib returned!
......@@ -29,7 +29,7 @@ const find_offset = opcode => fib.body_offset + fib_body.indexOf(opcode);
const breakpoints = [
{loc: find_offset(kExprLocalGet), cond: 'false'},
{loc: find_offset(kExprBrIf), cond: 'true'},
{loc: find_offset(kExprCallFunction), cond: '$var0==3'}
{loc: find_offset(kExprCallFunction), cond: '$var0.value==3'}
];
Protocol.Debugger.onPaused(async msg => {
......@@ -40,8 +40,10 @@ Protocol.Debugger.onPaused(async msg => {
if (scope.type != 'local') continue;
var properties = await Protocol.Runtime.getProperties(
{'objectId': scope.object.objectId});
InspectorTest.log(properties.result.result.map(
value => `${value.name}: ${value.value.value}`));
for (var {name, value} of properties.result.result) {
value = await WasmInspectorTest.getWasmValue(value);
InspectorTest.log(`${name}: ${value}`);
}
}
Protocol.Debugger.resume();
});
......
......@@ -24,8 +24,9 @@ Protocol.Debugger.onPaused(async msg => {
if (scope.type == 'module') continue;
var scope_properties =
await Protocol.Runtime.getProperties({objectId: scope.object.objectId});
let str = scope_properties.result.result.map(
elem => WasmInspectorTest.getWasmValue(elem.value)).join(', ');
let str = (await Promise.all(scope_properties.result.result.map(
elem => WasmInspectorTest.getWasmValue(elem.value))))
.join(', ');
line.push(`${scope.type}: [${str}]`);
}
InspectorTest.log(line.join('; '));
......
......@@ -6,8 +6,8 @@ Wait for script
Got wasm script: wasm://wasm/c84b7cde
Run
Expecting to pause at 61
Paused at offset 61; wasm-expression-stack: []; local: [12]
Paused at offset 62; wasm-expression-stack: []; local: [12]
Paused at offset 64; wasm-expression-stack: [12]; local: [12]
Paused at offset 66; wasm-expression-stack: [12, 1]; local: [12]
Paused at offset 67; wasm-expression-stack: [13]; local: [12]
Paused at offset 61; wasm-expression-stack: []; local: [12 (i32)]
Paused at offset 62; wasm-expression-stack: []; local: [12 (i32)]
Paused at offset 64; wasm-expression-stack: [12 (i32)]; local: [12 (i32)]
Paused at offset 66; wasm-expression-stack: [12 (i32), 1 (i32)]; local: [12 (i32)]
Paused at offset 67; wasm-expression-stack: [13 (i32)]; local: [12 (i32)]
......@@ -70,8 +70,9 @@ async function inspect(frame) {
if (scope.type == 'module') continue;
var scope_properties =
await Protocol.Runtime.getProperties({objectId: scope.object.objectId});
let str = scope_properties.result.result.map(
elem => WasmInspectorTest.getWasmValue(elem.value)).join(', ');
let str = (await Promise.all(scope_properties.result.result.map(
elem => WasmInspectorTest.getWasmValue(elem.value))))
.join(', ');
line.push(`${scope.type}: [${str}]`);
}
InspectorTest.log(line.join('; '));
......
......@@ -7,11 +7,11 @@ Paused at:
--- 0 ---
Script wasm://wasm/a9a86c5e byte offset 46: Wasm opcode 0x6d (kExprI32DivS)
scope at div (0:46):
$a: 1
$b: 0
$unused: 4711
$local_zero: 0
$local_const_11: 11
$a: 1 (i32)
$b: 0 (i32)
$unused: 4711 (i32)
$local_zero: 0 (i32)
$local_const_11: 11 (i32)
--- 1 ---
try {
instance.exports.#div(1, 0, 4711); // traps (div by zero)
......@@ -37,11 +37,11 @@ Paused at:
--- 0 ---
Script wasm://wasm/a9a86c5e byte offset 46: Wasm opcode 0x6d (kExprI32DivS)
scope at div (0:46):
$a: -2147483648
$b: -1
$unused: 4711
$local_zero: 0
$local_const_11: 11
$a: -2147483648 (i32)
$b: -1 (i32)
$unused: 4711 (i32)
$local_zero: 0 (i32)
$local_const_11: 11 (i32)
--- 1 ---
try {
instance.exports.#div(0x80000000, -1, 4711); // traps (unrepresentable)
......
......@@ -80,8 +80,9 @@ async function printLocalScope(frame) {
if (scope.type != 'local') continue;
let properties = await Protocol.Runtime.getProperties(
{'objectId': scope.object.objectId});
for (let value of properties.result.result) {
InspectorTest.log(` ${value.name}: ${value.value.value}`);
for (let {name, value} of properties.result.result) {
value = await WasmInspectorTest.getWasmValue(value);
InspectorTest.log(` ${name}: ${value}`);
}
}
}
......@@ -2,14 +2,14 @@ Tests that Liftoff does not merge opcodes while stepping
Running test: test
Setting breakpoint at offset 33.
Paused at offset 33: [0]
Paused at offset 35: [0, 0]
Paused at offset 36: [0, 1]
Paused at offset 33: [-1]
Paused at offset 35: [-1, -1]
Paused at offset 36: [-1, 0]
Paused at offset 38: [-1]
Paused at offset 33: [13]
Paused at offset 35: [13, 13]
Paused at offset 36: [13, 0]
Paused at offset 38: [13]
Paused at offset 33: [0 (i32)]
Paused at offset 35: [0 (i32), 0 (i32)]
Paused at offset 36: [0 (i32), 1 (i32)]
Paused at offset 33: [-1 (i32)]
Paused at offset 35: [-1 (i32), -1 (i32)]
Paused at offset 36: [-1 (i32), 0 (i32)]
Paused at offset 38: [-1 (i32)]
Paused at offset 33: [13 (i32)]
Paused at offset 35: [13 (i32), 13 (i32)]
Paused at offset 36: [13 (i32), 0 (i32)]
Paused at offset 38: [13 (i32)]
......@@ -56,8 +56,8 @@ async function printPauseLocationAndStep(msg) {
if (scope.type == 'module') continue;
let scope_properties =
await Protocol.Runtime.getProperties({objectId: scope.object.objectId});
scopes[scope.type] = scope_properties.result.result.map(
elem => WasmInspectorTest.getWasmValue(elem.value));
scopes[scope.type] = await Promise.all(scope_properties.result.result.map(
elem => WasmInspectorTest.getWasmValue(elem.value)));
}
let values = scopes['local'].concat(scopes['wasm-expression-stack']).join(', ');
InspectorTest.log(`Paused at offset ${loc.columnNumber}: [${values}]`);
......
......@@ -14,9 +14,9 @@ Setting breakpoint on offset 54 (on the setlocal before the call), url wasm://wa
Script wasm://wasm/9b4bf87e byte offset 54: Wasm opcode 0x21 (kExprLocalSet)
at wasm_B (0:54):
- scope (wasm-expression-stack):
{"0":3}
0: 3 (i32)
- scope (local):
{"$var0":4}
$var0: 4 (i32)
- scope (module):
-- skipped
at (anonymous) (0:17):
......@@ -26,9 +26,8 @@ Debugger.stepInto called
Script wasm://wasm/9b4bf87e byte offset 56: Wasm opcode 0x10 (kExprCallFunction)
at wasm_B (0:56):
- scope (wasm-expression-stack):
{}
- scope (local):
{"$var0":3}
$var0: 3 (i32)
- scope (module):
-- skipped
at (anonymous) (0:17):
......@@ -38,16 +37,13 @@ Debugger.stepInto called
Script wasm://wasm/9b4bf87e byte offset 38: Wasm opcode 0x01 (kExprNop)
at wasm_A (0:38):
- scope (wasm-expression-stack):
{}
- scope (local):
{}
- scope (module):
-- skipped
at wasm_B (0:56):
- scope (wasm-expression-stack):
{}
- scope (local):
{"$var0":3}
$var0: 3 (i32)
- scope (module):
-- skipped
at (anonymous) (0:17):
......@@ -57,16 +53,13 @@ Debugger.stepOver called
Script wasm://wasm/9b4bf87e byte offset 39: Wasm opcode 0x01 (kExprNop)
at wasm_A (0:39):
- scope (wasm-expression-stack):
{}
- scope (local):
{}
- scope (module):
-- skipped
at wasm_B (0:56):
- scope (wasm-expression-stack):
{}
- scope (local):
{"$var0":3}
$var0: 3 (i32)
- scope (module):
-- skipped
at (anonymous) (0:17):
......@@ -76,9 +69,8 @@ Debugger.stepOut called
Script wasm://wasm/9b4bf87e byte offset 58: Wasm opcode 0x0c (kExprBr)
at wasm_B (0:58):
- scope (wasm-expression-stack):
{}
- scope (local):
{"$var0":3}
$var0: 3 (i32)
- scope (module):
-- skipped
at (anonymous) (0:17):
......@@ -88,9 +80,9 @@ Debugger.stepOut called
Script wasm://wasm/9b4bf87e byte offset 54: Wasm opcode 0x21 (kExprLocalSet)
at wasm_B (0:54):
- scope (wasm-expression-stack):
{"0":2}
0: 2 (i32)
- scope (local):
{"$var0":3}
$var0: 3 (i32)
- scope (module):
-- skipped
at (anonymous) (0:17):
......@@ -100,9 +92,8 @@ Debugger.stepOver called
Script wasm://wasm/9b4bf87e byte offset 56: Wasm opcode 0x10 (kExprCallFunction)
at wasm_B (0:56):
- scope (wasm-expression-stack):
{}
- scope (local):
{"$var0":2}
$var0: 2 (i32)
- scope (module):
-- skipped
at (anonymous) (0:17):
......@@ -112,9 +103,8 @@ Debugger.stepOver called
Script wasm://wasm/9b4bf87e byte offset 58: Wasm opcode 0x0c (kExprBr)
at wasm_B (0:58):
- scope (wasm-expression-stack):
{}
- scope (local):
{"$var0":2}
$var0: 2 (i32)
- scope (module):
-- skipped
at (anonymous) (0:17):
......@@ -124,9 +114,9 @@ Debugger.resume called
Script wasm://wasm/9b4bf87e byte offset 54: Wasm opcode 0x21 (kExprLocalSet)
at wasm_B (0:54):
- scope (wasm-expression-stack):
{"0":1}
0: 1 (i32)
- scope (local):
{"$var0":2}
$var0: 2 (i32)
- scope (module):
-- skipped
at (anonymous) (0:17):
......@@ -136,9 +126,8 @@ Debugger.stepInto called
Script wasm://wasm/9b4bf87e byte offset 56: Wasm opcode 0x10 (kExprCallFunction)
at wasm_B (0:56):
- scope (wasm-expression-stack):
{}
- scope (local):
{"$var0":1}
$var0: 1 (i32)
- scope (module):
-- skipped
at (anonymous) (0:17):
......@@ -148,16 +137,13 @@ Debugger.stepInto called
Script wasm://wasm/9b4bf87e byte offset 38: Wasm opcode 0x01 (kExprNop)
at wasm_A (0:38):
- scope (wasm-expression-stack):
{}
- scope (local):
{}
- scope (module):
-- skipped
at wasm_B (0:56):
- scope (wasm-expression-stack):
{}
- scope (local):
{"$var0":1}
$var0: 1 (i32)
- scope (module):
-- skipped
at (anonymous) (0:17):
......@@ -167,9 +153,8 @@ Debugger.stepOut called
Script wasm://wasm/9b4bf87e byte offset 58: Wasm opcode 0x0c (kExprBr)
at wasm_B (0:58):
- scope (wasm-expression-stack):
{}
- scope (local):
{"$var0":1}
$var0: 1 (i32)
- scope (module):
-- skipped
at (anonymous) (0:17):
......@@ -179,9 +164,8 @@ Debugger.stepInto called
Script wasm://wasm/9b4bf87e byte offset 45: Wasm opcode 0x20 (kExprLocalGet)
at wasm_B (0:45):
- scope (wasm-expression-stack):
{}
- scope (local):
{"$var0":1}
$var0: 1 (i32)
- scope (module):
-- skipped
at (anonymous) (0:17):
......@@ -191,9 +175,9 @@ Debugger.stepInto called
Script wasm://wasm/9b4bf87e byte offset 47: Wasm opcode 0x04 (kExprIf)
at wasm_B (0:47):
- scope (wasm-expression-stack):
{"0":1}
0: 1 (i32)
- scope (local):
{"$var0":1}
$var0: 1 (i32)
- scope (module):
-- skipped
at (anonymous) (0:17):
......@@ -203,9 +187,8 @@ Debugger.stepInto called
Script wasm://wasm/9b4bf87e byte offset 49: Wasm opcode 0x20 (kExprLocalGet)
at wasm_B (0:49):
- scope (wasm-expression-stack):
{}
- scope (local):
{"$var0":1}
$var0: 1 (i32)
- scope (module):
-- skipped
at (anonymous) (0:17):
......@@ -215,9 +198,9 @@ Debugger.stepInto called
Script wasm://wasm/9b4bf87e byte offset 51: Wasm opcode 0x41 (kExprI32Const)
at wasm_B (0:51):
- scope (wasm-expression-stack):
{"0":1}
0: 1 (i32)
- scope (local):
{"$var0":1}
$var0: 1 (i32)
- scope (module):
-- skipped
at (anonymous) (0:17):
......@@ -227,9 +210,10 @@ Debugger.stepInto called
Script wasm://wasm/9b4bf87e byte offset 53: Wasm opcode 0x6b (kExprI32Sub)
at wasm_B (0:53):
- scope (wasm-expression-stack):
{"0":1,"1":1}
0: 1 (i32)
1: 1 (i32)
- scope (local):
{"$var0":1}
$var0: 1 (i32)
- scope (module):
-- skipped
at (anonymous) (0:17):
......@@ -239,9 +223,9 @@ Debugger.stepInto called
Script wasm://wasm/9b4bf87e byte offset 54: Wasm opcode 0x21 (kExprLocalSet)
at wasm_B (0:54):
- scope (wasm-expression-stack):
{"0":0}
0: 0 (i32)
- scope (local):
{"$var0":1}
$var0: 1 (i32)
- scope (module):
-- skipped
at (anonymous) (0:17):
......@@ -251,9 +235,8 @@ Debugger.stepInto called
Script wasm://wasm/9b4bf87e byte offset 56: Wasm opcode 0x10 (kExprCallFunction)
at wasm_B (0:56):
- scope (wasm-expression-stack):
{}
- scope (local):
{"$var0":0}
$var0: 0 (i32)
- scope (module):
-- skipped
at (anonymous) (0:17):
......@@ -263,16 +246,13 @@ Debugger.stepInto called
Script wasm://wasm/9b4bf87e byte offset 38: Wasm opcode 0x01 (kExprNop)
at wasm_A (0:38):
- scope (wasm-expression-stack):
{}
- scope (local):
{}
- scope (module):
-- skipped
at wasm_B (0:56):
- scope (wasm-expression-stack):
{}
- scope (local):
{"$var0":0}
$var0: 0 (i32)
- scope (module):
-- skipped
at (anonymous) (0:17):
......@@ -282,16 +262,13 @@ Debugger.stepInto called
Script wasm://wasm/9b4bf87e byte offset 39: Wasm opcode 0x01 (kExprNop)
at wasm_A (0:39):
- scope (wasm-expression-stack):
{}
- scope (local):
{}
- scope (module):
-- skipped
at wasm_B (0:56):
- scope (wasm-expression-stack):
{}
- scope (local):
{"$var0":0}
$var0: 0 (i32)
- scope (module):
-- skipped
at (anonymous) (0:17):
......@@ -301,16 +278,13 @@ Debugger.stepInto called
Script wasm://wasm/9b4bf87e byte offset 40: Wasm opcode 0x0b (kExprEnd)
at wasm_A (0:40):
- scope (wasm-expression-stack):
{}
- scope (local):
{}
- scope (module):
-- skipped
at wasm_B (0:56):
- scope (wasm-expression-stack):
{}
- scope (local):
{"$var0":0}
$var0: 0 (i32)
- scope (module):
-- skipped
at (anonymous) (0:17):
......@@ -320,9 +294,8 @@ Debugger.stepInto called
Script wasm://wasm/9b4bf87e byte offset 58: Wasm opcode 0x0c (kExprBr)
at wasm_B (0:58):
- scope (wasm-expression-stack):
{}
- scope (local):
{"$var0":0}
$var0: 0 (i32)
- scope (module):
-- skipped
at (anonymous) (0:17):
......
......@@ -91,15 +91,12 @@ async function waitForPauseAndStep(stepAction) {
if (scope.type === 'global' || scope.type === 'module') {
InspectorTest.logObject(' -- skipped');
} else {
const object = {};
const {result: {result: properties}} =
await Protocol.Runtime.getProperties({
objectId: scope.object.objectId
});
for (const {name, value: {value}} of properties) {
object[name] = value;
let properties = await Protocol.Runtime.getProperties(
{objectId: scope.object.objectId});
for (let {name, value} of properties.result.result) {
value = await WasmInspectorTest.getWasmValue(value);
InspectorTest.log(` ${name}: ${value}`);
}
InspectorTest.log(` ${JSON.stringify(object)}`);
}
}
}
......
......@@ -7,10 +7,11 @@ utils.load('test/mjsunit/wasm/wasm-module-builder.js');
WasmInspectorTest = {}
InspectorTest.getWasmOpcodeName = getOpcodeName;
WasmInspectorTest.evalWithUrl = (code, url) =>
Protocol.Runtime
.evaluate({'expression': code + '\n//# sourceURL=v8://test/' + url})
.then(printIfFailure);
WasmInspectorTest.evalWithUrl = async function(code, url) {
return await Protocol.Runtime
.evaluate({'expression': code + '\n//# sourceURL=v8://test/' + url})
.then(printIfFailure);
};
WasmInspectorTest.instantiateFromBuffer = function(bytes, imports) {
var buffer = new ArrayBuffer(bytes.length);
......@@ -20,12 +21,14 @@ WasmInspectorTest.instantiateFromBuffer = function(bytes, imports) {
}
const module = new WebAssembly.Module(buffer);
return new WebAssembly.Instance(module, imports);
}
};
WasmInspectorTest.instantiate = async function(bytes, instance_name = 'instance') {
const instantiate_code = `var ${instance_name} = (${WasmInspectorTest.instantiateFromBuffer})(${JSON.stringify(bytes)});`;
WasmInspectorTest.instantiate =
async function(bytes, instance_name = 'instance') {
const instantiate_code = `var ${instance_name} = (${
WasmInspectorTest.instantiateFromBuffer})(${JSON.stringify(bytes)});`;
await WasmInspectorTest.evalWithUrl(instantiate_code, 'instantiate');
}
};
WasmInspectorTest.dumpScopeProperties = async function(message) {
printIfFailure(message);
......@@ -33,11 +36,17 @@ WasmInspectorTest.dumpScopeProperties = async function(message) {
var value_str = await getScopeValues(value.name, value.value);
InspectorTest.log(' ' + value.name + ': ' + value_str);
}
}
};
WasmInspectorTest.getWasmValue = value => {
return value.unserializableValue ?? value.value;
}
WasmInspectorTest.getWasmValue = async function(value) {
let msg = await Protocol.Runtime.getProperties({objectId: value.objectId});
printIfFailure(msg);
const value_type = msg.result.result.find(({name}) => name === 'type');
const value_value = msg.result.result.find(({name}) => name === 'value');
return `${
value_value.value.unserializableValue ??
value_value.value.value} (${value_type.value.value})`;
};
function printIfFailure(message) {
if (!message.result) {
......@@ -47,22 +56,29 @@ function printIfFailure(message) {
}
async function getScopeValues(name, value) {
if (value.type === 'object') {
if (value.subtype === 'typedarray' || value.subtype == 'webassemblymemory') return value.description;
async function printValue(value) {
if (value.type === 'object' && value.subtype === 'wasmvalue') {
return await WasmInspectorTest.getWasmValue(value);
} else if ('className' in value) {
return `(${value.className})`;
}
return `${value.unserializableValue ?? value.value} (${
value.subtype ?? value.type})`;
}
if (value.type === 'object' && value.subtype !== 'wasmvalue') {
if (value.subtype === 'typedarray' || value.subtype == 'webassemblymemory')
return value.description;
if (name === 'instance') return dumpInstanceProperties(value);
if (name === 'module') return value.description;
let msg = await Protocol.Runtime.getProperties({objectId: value.objectId});
printIfFailure(msg);
const printProperty = function({name, value}) {
if ('className' in value) {
return `"${name}" (${value.className})`;
}
return `"${name}": ${WasmInspectorTest.getWasmValue(value)} (${value.subtype ?? value.type})`;
async function printProperty({name, value}) {
return `"${name}": ${await printValue(value)}`;
}
return msg.result.result.map(printProperty).join(', ');
return (await Promise.all(msg.result.result.map(printProperty))).join(', ');
}
return `${WasmInspectorTest.getWasmValue(value)} (${value.subtype ?? value.type})`;
return await printValue(value);
}
function recursiveGetPropertiesWrapper(value, depth) {
......@@ -71,10 +87,12 @@ function recursiveGetPropertiesWrapper(value, depth) {
async function recursiveGetProperties(value, depth) {
if (depth > 0) {
const properties = await Promise.all(value.result.result.map(
x => {return Protocol.Runtime.getProperties({objectId: x.value.objectId});}));
const recursiveProperties = await Promise.all(properties.map(
x => {return recursiveGetProperties(x, depth - 1);}));
const properties = await Promise.all(value.result.result.map(x => {
return Protocol.Runtime.getProperties({objectId: x.value.objectId});
}));
const recursiveProperties = await Promise.all(properties.map(x => {
return recursiveGetProperties(x, depth - 1);
}));
return recursiveProperties.flat();
}
return value;
......@@ -86,17 +104,17 @@ async function dumpInstanceProperties(instanceObj) {
}
const exportsName = 'exports';
let exportsObj = await Protocol.Runtime.callFunctionOn(
{objectId: instanceObj.objectId,
functionDeclaration: invokeGetter.toString(),
arguments: [{value: JSON.stringify(exportsName)}]
});
let exportsObj = await Protocol.Runtime.callFunctionOn({
objectId: instanceObj.objectId,
functionDeclaration: invokeGetter.toString(),
arguments: [{value: JSON.stringify(exportsName)}]
});
printIfFailure(exportsObj);
let exports = await Protocol.Runtime.getProperties(
{objectId: exportsObj.result.result.objectId});
printIfFailure(exports);
const printExports = function(value) {
function printExports(value) {
return `"${value.name}" (${value.value.className})`;
}
const formattedExports = exports.result.result.map(printExports).join(', ');
......
......@@ -227,6 +227,7 @@ INSTANCE_TYPES = {
1114: "WASM_MEMORY_OBJECT_TYPE",
1115: "WASM_MODULE_OBJECT_TYPE",
1116: "WASM_TABLE_OBJECT_TYPE",
1117: "WASM_VALUE_OBJECT_TYPE",
}
# List of known V8 maps.
......
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