[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/+/1763527 Reviewed-by: Andreas Haas <ahaas@chromium.org> Commit-Queue: Michael Starzinger <mstarzinger@chromium.org> Cr-Commit-Position: refs/heads/master@{#63312}
This commit is contained in:
parent
df76f1e55a
commit
fd8fe87387
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user