Commit 058299a8 authored by Benedikt Meurer's avatar Benedikt Meurer Committed by Commit Bot

[wasm] Use WebAssembly.Memory objects in the scope chain.

Previously V8 would wrap the WebAssembly.Memory backing stores into
Uint8Arrays and report that as memories, but that's confusing to the
developer, since that's not what's really being used. The way that
DevTools presents the backing stores of memories, it's still perfectly
possible to get hold of an Uint8Array if that's what the developer is
looking for.

To make it possible to easily identify the WebAssembly.Memory objects
in the DevTools front-end (in particular for the memory inspector) we
add a 'webassemblymemory' subtype to the Chrome DevTools Protocol. We
also improve the description for the memories to include the number
of active pages.

Fixed: chromium:1155566
Screenshot: https://imgur.com/8enx57u.png
Change-Id: I63dbabe0e372e9ad6dcc8e6642cdb743147a620c
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2574699Reviewed-by: 's avatarClemens Backes <clemensb@chromium.org>
Reviewed-by: 's avatarYang Guo <yangguo@chromium.org>
Commit-Queue: Benedikt Meurer <bmeurer@chromium.org>
Auto-Submit: Benedikt Meurer <bmeurer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#71641}
parent a69b442b
......@@ -1043,6 +1043,7 @@ domain Runtime
typedarray
arraybuffer
dataview
webassemblymemory
i32
i64
f32
......
......@@ -91,6 +91,7 @@ class Private;
class Uint32;
class Utils;
class Value;
class WasmMemoryObject;
class WasmModuleObject;
template <class T> class Local;
template <class T>
......@@ -2962,6 +2963,11 @@ class V8_EXPORT Value : public Data {
*/
bool IsProxy() const;
/**
* Returns true if this value is a WasmMemoryObject.
*/
bool IsWasmMemoryObject() const;
/**
* Returns true if this value is a WasmModuleObject.
*/
......@@ -4980,6 +4986,22 @@ class V8_EXPORT CompiledWasmModule {
const std::string source_url_;
};
// An instance of WebAssembly.Memory.
class V8_EXPORT WasmMemoryObject : public Object {
public:
WasmMemoryObject() = delete;
/**
* Returns underlying ArrayBuffer.
*/
Local<ArrayBuffer> Buffer();
V8_INLINE static WasmMemoryObject* Cast(Value* obj);
private:
static void CheckCast(Value* object);
};
// An instance of WebAssembly.Module.
class V8_EXPORT WasmModuleObject : public Object {
public:
......@@ -11956,6 +11978,13 @@ Proxy* Proxy::Cast(v8::Value* value) {
return static_cast<Proxy*>(value);
}
WasmMemoryObject* WasmMemoryObject::Cast(v8::Value* value) {
#ifdef V8_ENABLE_CHECKS
CheckCast(value);
#endif
return static_cast<WasmMemoryObject*>(value);
}
WasmModuleObject* WasmModuleObject::Cast(v8::Value* value) {
#ifdef V8_ENABLE_CHECKS
CheckCast(value);
......
......@@ -3583,6 +3583,7 @@ VALUE_IS_SPECIFIC_TYPE(SymbolObject, SymbolWrapper)
VALUE_IS_SPECIFIC_TYPE(Date, JSDate)
VALUE_IS_SPECIFIC_TYPE(Map, JSMap)
VALUE_IS_SPECIFIC_TYPE(Set, JSSet)
VALUE_IS_SPECIFIC_TYPE(WasmMemoryObject, WasmMemoryObject)
VALUE_IS_SPECIFIC_TYPE(WasmModuleObject, WasmModuleObject)
VALUE_IS_SPECIFIC_TYPE(WeakMap, JSWeakMap)
VALUE_IS_SPECIFIC_TYPE(WeakSet, JSWeakSet)
......@@ -3903,6 +3904,11 @@ void v8::Proxy::CheckCast(Value* that) {
Utils::ApiCheck(that->IsProxy(), "v8::Proxy::Cast", "Value is not a Proxy");
}
void v8::WasmMemoryObject::CheckCast(Value* that) {
Utils::ApiCheck(that->IsWasmMemoryObject(), "v8::WasmMemoryObject::Cast",
"Value is not a WasmMemoryObject");
}
void v8::WasmModuleObject::CheckCast(Value* that) {
Utils::ApiCheck(that->IsWasmModuleObject(), "v8::WasmModuleObject::Cast",
"Value is not a WasmModuleObject");
......@@ -7502,6 +7508,12 @@ MemorySpan<const uint8_t> CompiledWasmModule::GetWireBytesRef() {
return {bytes_vec.begin(), bytes_vec.size()};
}
Local<ArrayBuffer> v8::WasmMemoryObject::Buffer() {
i::Handle<i::WasmMemoryObject> obj = Utils::OpenHandle(this);
i::Handle<i::JSArrayBuffer> buffer(obj->array_buffer(), obj->GetIsolate());
return Utils::ToLocal(buffer);
}
CompiledWasmModule WasmModuleObject::GetCompiledModule() {
i::Handle<i::WasmModuleObject> obj =
i::Handle<i::WasmModuleObject>::cast(Utils::OpenHandle(this));
......
......@@ -136,7 +136,8 @@ class RegisteredExtension {
V(BigInt, BigInt) \
V(ScriptOrModule, Script) \
V(FixedArray, FixedArray) \
V(ModuleRequest, ModuleRequest)
V(ModuleRequest, ModuleRequest) \
V(WasmMemoryObject, WasmMemoryObject)
class Utils {
public:
......
......@@ -22,6 +22,10 @@ using protocol::Runtime::PropertyPreview;
using protocol::Runtime::RemoteObject;
namespace {
// WebAssembly memory is organized in pages of size 64KiB.
const size_t kWasmPageSize = 64 * 1024;
V8InspectorClient* clientFor(v8::Local<v8::Context> context) {
return static_cast<V8InspectorImpl*>(
v8::debug::GetInspector(context->GetIsolate()))
......@@ -1909,6 +1913,13 @@ std::unique_ptr<ValueMirror> ValueMirror::create(v8::Local<v8::Context> context,
value, RemoteObject::SubtypeEnum::Dataview,
descriptionForCollection(isolate, view, view->ByteLength()));
}
if (value->IsWasmMemoryObject()) {
v8::Local<v8::WasmMemoryObject> memory = value.As<v8::WasmMemoryObject>();
return std::make_unique<ObjectMirror>(
value, RemoteObject::SubtypeEnum::Webassemblymemory,
descriptionForCollection(
isolate, memory, memory->Buffer()->ByteLength() / kWasmPageSize));
}
V8InternalValueType internalType =
v8InternalValueTypeFrom(context, value.As<v8::Object>());
if (value->IsArray() && internalType == V8InternalValueType::kScopeList) {
......
......@@ -211,11 +211,8 @@ Handle<JSObject> GetModuleScopeObject(Handle<WasmInstanceObject> instance) {
const char* label = "memory%d";
name = PrintFToOneByteString<true>(isolate, label, memory_index);
}
Handle<JSArrayBuffer> memory_buffer(
instance->memory_object().array_buffer(), isolate);
Handle<JSTypedArray> uint8_array = isolate->factory()->NewJSTypedArray(
kExternalUint8Array, memory_buffer, 0, memory_buffer->byte_length());
JSObject::AddProperty(isolate, module_scope_object, name, uint8_array,
Handle<WasmMemoryObject> memory_object(instance->memory_object(), isolate);
JSObject::AddProperty(isolate, module_scope_object, name, memory_object,
NONE);
}
......
......@@ -14,7 +14,7 @@ Scope:
at C (interpreted) (0:169):
- scope (module):
instance: exports: "exported_global" (Global), "exported_memory" (Memory), "exported_table" (Table), "main" (Function)
exported_memory: Uint8Array(65536)
exported_memory: Memory(1)
globals: "exported_global": 0 (i32)
- scope (local):
i32_arg: 42 (i32)
......@@ -24,7 +24,7 @@ at C (interpreted) (0:169):
at B (liftoff) (0:158):
- scope (module):
instance: exports: "exported_global" (Global), "exported_memory" (Memory), "exported_table" (Table), "main" (Function)
exported_memory: Uint8Array(65536)
exported_memory: Memory(1)
globals: "exported_global": 0 (i32)
- scope (local):
0: 0 (f32)
......@@ -39,7 +39,7 @@ at B (liftoff) (0:158):
at A (liftoff) (0:128):
- scope (module):
instance: exports: "exported_global" (Global), "exported_memory" (Memory), "exported_table" (Table), "main" (Function)
exported_memory: Uint8Array(65536)
exported_memory: Memory(1)
globals: "exported_global": 0 (i32)
- scope (local):
var0: 42 (i32)
......@@ -54,7 +54,7 @@ Scope:
at C (interpreted) (0:171):
- scope (module):
instance: exports: "exported_global" (Global), "exported_memory" (Memory), "exported_table" (Table), "main" (Function)
exported_memory: Uint8Array(65536)
exported_memory: Memory(1)
globals: "exported_global": 0 (i32)
- scope (local):
i32_arg: 42 (i32)
......@@ -65,7 +65,7 @@ at C (interpreted) (0:171):
at B (liftoff) (0:158):
- scope (module):
instance: exports: "exported_global" (Global), "exported_memory" (Memory), "exported_table" (Table), "main" (Function)
exported_memory: Uint8Array(65536)
exported_memory: Memory(1)
globals: "exported_global": 0 (i32)
- scope (local):
0: 0 (f32)
......@@ -80,7 +80,7 @@ at B (liftoff) (0:158):
at A (liftoff) (0:128):
- scope (module):
instance: exports: "exported_global" (Global), "exported_memory" (Memory), "exported_table" (Table), "main" (Function)
exported_memory: Uint8Array(65536)
exported_memory: Memory(1)
globals: "exported_global": 0 (i32)
- scope (local):
var0: 42 (i32)
......@@ -95,7 +95,7 @@ Scope:
at C (interpreted) (0:173):
- scope (module):
instance: exports: "exported_global" (Global), "exported_memory" (Memory), "exported_table" (Table), "main" (Function)
exported_memory: Uint8Array(65536)
exported_memory: Memory(1)
globals: "exported_global": 42 (i32)
- scope (local):
i32_arg: 42 (i32)
......@@ -105,7 +105,7 @@ at C (interpreted) (0:173):
at B (liftoff) (0:158):
- scope (module):
instance: exports: "exported_global" (Global), "exported_memory" (Memory), "exported_table" (Table), "main" (Function)
exported_memory: Uint8Array(65536)
exported_memory: Memory(1)
globals: "exported_global": 42 (i32)
- scope (local):
0: 0 (f32)
......@@ -120,7 +120,7 @@ at B (liftoff) (0:158):
at A (liftoff) (0:128):
- scope (module):
instance: exports: "exported_global" (Global), "exported_memory" (Memory), "exported_table" (Table), "main" (Function)
exported_memory: Uint8Array(65536)
exported_memory: Memory(1)
globals: "exported_global": 42 (i32)
- scope (local):
var0: 42 (i32)
......@@ -135,7 +135,7 @@ Scope:
at C (interpreted) (0:175):
- scope (module):
instance: exports: "exported_global" (Global), "exported_memory" (Memory), "exported_table" (Table), "main" (Function)
exported_memory: Uint8Array(65536)
exported_memory: Memory(1)
globals: "exported_global": 42 (i32)
- scope (local):
i32_arg: 42 (i32)
......@@ -146,7 +146,7 @@ at C (interpreted) (0:175):
at B (liftoff) (0:158):
- scope (module):
instance: exports: "exported_global" (Global), "exported_memory" (Memory), "exported_table" (Table), "main" (Function)
exported_memory: Uint8Array(65536)
exported_memory: Memory(1)
globals: "exported_global": 42 (i32)
- scope (local):
0: 0 (f32)
......@@ -161,7 +161,7 @@ at B (liftoff) (0:158):
at A (liftoff) (0:128):
- scope (module):
instance: exports: "exported_global" (Global), "exported_memory" (Memory), "exported_table" (Table), "main" (Function)
exported_memory: Uint8Array(65536)
exported_memory: Memory(1)
globals: "exported_global": 42 (i32)
- scope (local):
var0: 42 (i32)
......@@ -176,7 +176,7 @@ Scope:
at C (interpreted) (0:177):
- scope (module):
instance: exports: "exported_global" (Global), "exported_memory" (Memory), "exported_table" (Table), "main" (Function)
exported_memory: Uint8Array(65536)
exported_memory: Memory(1)
globals: "exported_global": 42 (i32)
- scope (local):
i32_arg: 42 (i32)
......@@ -186,7 +186,7 @@ at C (interpreted) (0:177):
at B (liftoff) (0:158):
- scope (module):
instance: exports: "exported_global" (Global), "exported_memory" (Memory), "exported_table" (Table), "main" (Function)
exported_memory: Uint8Array(65536)
exported_memory: Memory(1)
globals: "exported_global": 42 (i32)
- scope (local):
0: 0 (f32)
......@@ -201,7 +201,7 @@ at B (liftoff) (0:158):
at A (liftoff) (0:128):
- scope (module):
instance: exports: "exported_global" (Global), "exported_memory" (Memory), "exported_table" (Table), "main" (Function)
exported_memory: Uint8Array(65536)
exported_memory: Memory(1)
globals: "exported_global": 42 (i32)
- scope (local):
var0: 42 (i32)
......@@ -216,7 +216,7 @@ Scope:
at B (liftoff) (0:160):
- scope (module):
instance: exports: "exported_global" (Global), "exported_memory" (Memory), "exported_table" (Table), "main" (Function)
exported_memory: Uint8Array(65536)
exported_memory: Memory(1)
globals: "exported_global": 42 (i32)
- scope (local):
0: 0 (f32)
......@@ -231,7 +231,7 @@ at B (liftoff) (0:160):
at A (liftoff) (0:128):
- scope (module):
instance: exports: "exported_global" (Global), "exported_memory" (Memory), "exported_table" (Table), "main" (Function)
exported_memory: Uint8Array(65536)
exported_memory: Memory(1)
globals: "exported_global": 42 (i32)
- scope (local):
var0: 42 (i32)
......@@ -246,7 +246,7 @@ Scope:
at B (liftoff) (0:161):
- scope (module):
instance: exports: "exported_global" (Global), "exported_memory" (Memory), "exported_table" (Table), "main" (Function)
exported_memory: Uint8Array(65536)
exported_memory: Memory(1)
globals: "exported_global": 42 (i32)
- scope (local):
0: 0 (f32)
......@@ -260,7 +260,7 @@ at B (liftoff) (0:161):
at A (liftoff) (0:128):
- scope (module):
instance: exports: "exported_global" (Global), "exported_memory" (Memory), "exported_table" (Table), "main" (Function)
exported_memory: Uint8Array(65536)
exported_memory: Memory(1)
globals: "exported_global": 42 (i32)
- scope (local):
var0: 42 (i32)
......@@ -275,7 +275,7 @@ Scope:
at B (liftoff) (0:162):
- scope (module):
instance: exports: "exported_global" (Global), "exported_memory" (Memory), "exported_table" (Table), "main" (Function)
exported_memory: Uint8Array(65536)
exported_memory: Memory(1)
globals: "exported_global": 42 (i32)
- scope (local):
0: 0 (f32)
......@@ -288,7 +288,7 @@ at B (liftoff) (0:162):
at A (liftoff) (0:128):
- scope (module):
instance: exports: "exported_global" (Global), "exported_memory" (Memory), "exported_table" (Table), "main" (Function)
exported_memory: Uint8Array(65536)
exported_memory: Memory(1)
globals: "exported_global": 42 (i32)
- scope (local):
var0: 42 (i32)
......@@ -303,7 +303,7 @@ Scope:
at A (liftoff) (0:130):
- scope (module):
instance: exports: "exported_global" (Global), "exported_memory" (Memory), "exported_table" (Table), "main" (Function)
exported_memory: Uint8Array(65536)
exported_memory: Memory(1)
globals: "exported_global": 42 (i32)
- scope (local):
var0: 42 (i32)
......
......@@ -50,7 +50,7 @@ function printIfFailure(message) {
async function getScopeValues(name, value) {
if (value.type == 'object') {
if (value.subtype == 'typedarray') return value.description;
if (value.subtype === 'typedarray' || value.subtype == 'webassemblymemory') return value.description;
if (name == 'instance') return dumpInstanceProperties(value);
let msg = await Protocol.Runtime.getProperties({objectId: value.objectId});
......
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