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) {
auto maybe_memory = GetFirstArgumentAsMemory(args, &thrower);
if (thrower.error()) return;
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);
size_t curr_size = buffer->byte_length() / i::wasm::kWasmPageSize;
DCHECK_LE(curr_size, std::numeric_limits<uint32_t>::max());
if (!ret->CreateDataProperty(isolate->GetCurrentContext(),
v8_str(isolate, "minimum"),
v8::Integer::NewFromUnsigned(
isolate, static_cast<uint32_t>(curr_size)))
.IsJust()) {
return;
}
uint32_t min_size = static_cast<uint32_t>(curr_size);
base::Optional<uint32_t> max_size;
if (memory->has_maximum_pages()) {
uint64_t max_size = memory->maximum_pages();
DCHECK_LE(max_size, std::numeric_limits<uint32_t>::max());
if (!ret->CreateDataProperty(isolate->GetCurrentContext(),
v8_str(isolate, "maximum"),
v8::Integer::NewFromUnsigned(
isolate, static_cast<uint32_t>(max_size)))
.IsJust()) {
return;
}
uint64_t max_size64 = memory->maximum_pages();
DCHECK_LE(max_size64, std::numeric_limits<uint32_t>::max());
max_size.emplace(static_cast<uint32_t>(max_size64));
}
v8::ReturnValue<v8::Value> return_value = args.GetReturnValue();
return_value.Set(ret);
auto type = i::wasm::GetTypeForMemory(i_isolate, min_size, max_size);
args.GetReturnValue().Set(Utils::ToLocal(type));
}
void WebAssemblyGlobalGetValueCommon(
......
......@@ -198,6 +198,24 @@ Handle<JSObject> GetTypeForGlobal(Isolate* isolate, bool is_mutable,
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,
uint32_t min_size,
base::Optional<uint32_t> max_size) {
......@@ -283,6 +301,15 @@ Handle<JSArray> GetImports(Isolate* isolate,
import_kind = table_string;
break;
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;
break;
case kExternalGlobal:
......@@ -374,6 +401,15 @@ Handle<JSArray> GetExports(Isolate* isolate,
export_kind = table_string;
break;
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;
break;
case kExternalGlobal:
......
......@@ -305,6 +305,8 @@ V8_EXPORT_PRIVATE bool IsWasmCodegenAllowed(Isolate* isolate,
Handle<JSObject> GetTypeForFunction(Isolate* isolate, FunctionSig* sig);
Handle<JSObject> GetTypeForGlobal(Isolate* isolate, bool is_mutable,
ValueType type);
Handle<JSObject> GetTypeForMemory(Isolate* isolate, uint32_t min_size,
base::Optional<uint32_t> max_size);
Handle<JSObject> GetTypeForTable(Isolate* isolate, ValueType type,
uint32_t min_size,
base::Optional<uint32_t> max_size);
......
......@@ -57,6 +57,52 @@ load('test/mjsunit/wasm/wasm-module-builder.js');
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() {
let table = new WebAssembly.Table({initial: 1, element: "anyfunc"});
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