Commit fd8fe873 authored by Michael Starzinger's avatar Michael Starzinger Committed by Commit Bot

[wasm] Add WebAssembly.Module type reflection of memories.

This adds type reflection support to the {WebAssembly.Module.exports} as
well as {WebAssembly.Module.imports} method. It also refactors existing
reflective code to use the internal instead of the public embedder API,
which is slightly more efficient anyways.

R=ahaas@chromium.org
TEST=mjsunit/wasm/type-reflection
BUG=v8:7742

Change-Id: I88a6c7e9236a549808707c72e40a63302b7747a9
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1763527Reviewed-by: 's avatarAndreas Haas <ahaas@chromium.org>
Commit-Queue: Michael Starzinger <mstarzinger@chromium.org>
Cr-Commit-Position: refs/heads/master@{#63312}
parent df76f1e5
...@@ -1731,33 +1731,18 @@ void WebAssemblyMemoryType(const v8::FunctionCallbackInfo<v8::Value>& args) { ...@@ -1731,33 +1731,18 @@ void WebAssemblyMemoryType(const v8::FunctionCallbackInfo<v8::Value>& args) {
auto maybe_memory = GetFirstArgumentAsMemory(args, &thrower); auto maybe_memory = GetFirstArgumentAsMemory(args, &thrower);
if (thrower.error()) return; if (thrower.error()) return;
i::Handle<i::WasmMemoryObject> memory = maybe_memory.ToHandleChecked(); i::Handle<i::WasmMemoryObject> memory = maybe_memory.ToHandleChecked();
v8::Local<v8::Object> ret = v8::Object::New(isolate);
i::Handle<i::JSArrayBuffer> buffer(memory->array_buffer(), i_isolate); i::Handle<i::JSArrayBuffer> buffer(memory->array_buffer(), i_isolate);
size_t curr_size = buffer->byte_length() / i::wasm::kWasmPageSize; size_t curr_size = buffer->byte_length() / i::wasm::kWasmPageSize;
DCHECK_LE(curr_size, std::numeric_limits<uint32_t>::max()); DCHECK_LE(curr_size, std::numeric_limits<uint32_t>::max());
if (!ret->CreateDataProperty(isolate->GetCurrentContext(), uint32_t min_size = static_cast<uint32_t>(curr_size);
v8_str(isolate, "minimum"), base::Optional<uint32_t> max_size;
v8::Integer::NewFromUnsigned(
isolate, static_cast<uint32_t>(curr_size)))
.IsJust()) {
return;
}
if (memory->has_maximum_pages()) { if (memory->has_maximum_pages()) {
uint64_t max_size = memory->maximum_pages(); uint64_t max_size64 = memory->maximum_pages();
DCHECK_LE(max_size, std::numeric_limits<uint32_t>::max()); DCHECK_LE(max_size64, std::numeric_limits<uint32_t>::max());
if (!ret->CreateDataProperty(isolate->GetCurrentContext(), max_size.emplace(static_cast<uint32_t>(max_size64));
v8_str(isolate, "maximum"),
v8::Integer::NewFromUnsigned(
isolate, static_cast<uint32_t>(max_size)))
.IsJust()) {
return;
}
} }
auto type = i::wasm::GetTypeForMemory(i_isolate, min_size, max_size);
v8::ReturnValue<v8::Value> return_value = args.GetReturnValue(); args.GetReturnValue().Set(Utils::ToLocal(type));
return_value.Set(ret);
} }
void WebAssemblyGlobalGetValueCommon( void WebAssemblyGlobalGetValueCommon(
......
...@@ -198,6 +198,24 @@ Handle<JSObject> GetTypeForGlobal(Isolate* isolate, bool is_mutable, ...@@ -198,6 +198,24 @@ Handle<JSObject> GetTypeForGlobal(Isolate* isolate, bool is_mutable,
return object; return object;
} }
Handle<JSObject> GetTypeForMemory(Isolate* isolate, uint32_t min_size,
base::Optional<uint32_t> max_size) {
Factory* factory = isolate->factory();
Handle<JSFunction> object_function = isolate->object_function();
Handle<JSObject> object = factory->NewJSObject(object_function);
Handle<String> minimum_string = factory->InternalizeUtf8String("minimum");
Handle<String> maximum_string = factory->InternalizeUtf8String("maximum");
JSObject::AddProperty(isolate, object, minimum_string,
factory->NewNumberFromUint(min_size), NONE);
if (max_size.has_value()) {
JSObject::AddProperty(isolate, object, maximum_string,
factory->NewNumberFromUint(max_size.value()), NONE);
}
return object;
}
Handle<JSObject> GetTypeForTable(Isolate* isolate, ValueType type, Handle<JSObject> GetTypeForTable(Isolate* isolate, ValueType type,
uint32_t min_size, uint32_t min_size,
base::Optional<uint32_t> max_size) { base::Optional<uint32_t> max_size) {
...@@ -283,6 +301,15 @@ Handle<JSArray> GetImports(Isolate* isolate, ...@@ -283,6 +301,15 @@ Handle<JSArray> GetImports(Isolate* isolate,
import_kind = table_string; import_kind = table_string;
break; break;
case kExternalMemory: case kExternalMemory:
if (enabled_features.type_reflection) {
DCHECK_EQ(0, import.index); // Only one memory supported.
base::Optional<uint32_t> maximum_size;
if (module->has_maximum_pages) {
maximum_size.emplace(module->maximum_pages);
}
type_value =
GetTypeForMemory(isolate, module->initial_pages, maximum_size);
}
import_kind = memory_string; import_kind = memory_string;
break; break;
case kExternalGlobal: case kExternalGlobal:
...@@ -374,6 +401,15 @@ Handle<JSArray> GetExports(Isolate* isolate, ...@@ -374,6 +401,15 @@ Handle<JSArray> GetExports(Isolate* isolate,
export_kind = table_string; export_kind = table_string;
break; break;
case kExternalMemory: case kExternalMemory:
if (enabled_features.type_reflection) {
DCHECK_EQ(0, exp.index); // Only one memory supported.
base::Optional<uint32_t> maximum_size;
if (module->has_maximum_pages) {
maximum_size.emplace(module->maximum_pages);
}
type_value =
GetTypeForMemory(isolate, module->initial_pages, maximum_size);
}
export_kind = memory_string; export_kind = memory_string;
break; break;
case kExternalGlobal: case kExternalGlobal:
......
...@@ -305,6 +305,8 @@ V8_EXPORT_PRIVATE bool IsWasmCodegenAllowed(Isolate* isolate, ...@@ -305,6 +305,8 @@ V8_EXPORT_PRIVATE bool IsWasmCodegenAllowed(Isolate* isolate,
Handle<JSObject> GetTypeForFunction(Isolate* isolate, FunctionSig* sig); Handle<JSObject> GetTypeForFunction(Isolate* isolate, FunctionSig* sig);
Handle<JSObject> GetTypeForGlobal(Isolate* isolate, bool is_mutable, Handle<JSObject> GetTypeForGlobal(Isolate* isolate, bool is_mutable,
ValueType type); ValueType type);
Handle<JSObject> GetTypeForMemory(Isolate* isolate, uint32_t min_size,
base::Optional<uint32_t> max_size);
Handle<JSObject> GetTypeForTable(Isolate* isolate, ValueType type, Handle<JSObject> GetTypeForTable(Isolate* isolate, ValueType type,
uint32_t min_size, uint32_t min_size,
base::Optional<uint32_t> max_size); base::Optional<uint32_t> max_size);
......
...@@ -57,6 +57,52 @@ load('test/mjsunit/wasm/wasm-module-builder.js'); ...@@ -57,6 +57,52 @@ load('test/mjsunit/wasm/wasm-module-builder.js');
assertEquals(2, Object.getOwnPropertyNames(type).length); assertEquals(2, Object.getOwnPropertyNames(type).length);
})(); })();
(function TestMemoryExports() {
let builder = new WasmModuleBuilder();
builder.addMemory(1).exportMemoryAs("a")
let module = new WebAssembly.Module(builder.toBuffer());
let exports = WebAssembly.Module.exports(module);
assertEquals("a", exports[0].name);
assertTrue("type" in exports[0]);
assertEquals(1, exports[0].type.minimum);
assertFalse("maximum" in exports[0].type);
builder = new WasmModuleBuilder();
builder.addMemory(2, 16).exportMemoryAs("b")
module = new WebAssembly.Module(builder.toBuffer());
exports = WebAssembly.Module.exports(module);
assertEquals("b", exports[0].name);
assertTrue("type" in exports[0]);
assertEquals(2, exports[0].type.minimum);
assertEquals(16, exports[0].type.maximum);
})();
(function TestMemoryImports() {
let builder = new WasmModuleBuilder();
builder.addImportedMemory("m", "a", 1);
let module = new WebAssembly.Module(builder.toBuffer());
let imports = WebAssembly.Module.imports(module);
assertEquals("a", imports[0].name);
assertEquals("m", imports[0].module);
assertTrue("type" in imports[0]);
assertEquals(1, imports[0].type.minimum);
assertFalse("maximum" in imports[0].type);
builder = new WasmModuleBuilder();
builder.addImportedMemory("m", "b", 2, 16);
module = new WebAssembly.Module(builder.toBuffer());
imports = WebAssembly.Module.imports(module);
assertEquals("b", imports[0].name);
assertEquals("m", imports[0].module);
assertTrue("type" in imports[0]);
assertEquals(2, imports[0].type.minimum);
assertEquals(16, imports[0].type.maximum);
})();
(function TestTableType() { (function TestTableType() {
let table = new WebAssembly.Table({initial: 1, element: "anyfunc"}); let table = new WebAssembly.Table({initial: 1, element: "anyfunc"});
let type = WebAssembly.Table.type(table); let type = WebAssembly.Table.type(table);
......
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