Commit 8a95dd3b authored by Michael Starzinger's avatar Michael Starzinger Committed by Commit Bot

[wasm] Add preliminary {WebAssembly.Function} constructor.

This adds a constructor function to be used as the base class for all
exported functions. With type reflection enabled exported functions are
instances of this new constructor. Using the constructor directly as
well as the 'type' property is still missing.

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

Change-Id: Id58359cf7866d24be0745abf36a839d3d86e5922
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1617253
Commit-Queue: Michael Starzinger <mstarzinger@chromium.org>
Reviewed-by: 's avatarJakob Kummerow <jkummerow@chromium.org>
Cr-Commit-Position: refs/heads/master@{#61614}
parent fdbb24a2
......@@ -300,7 +300,9 @@ enum ContextLookupFlags {
V(STRING_FUNCTION_INDEX, JSFunction, string_function) \
V(STRING_FUNCTION_PROTOTYPE_MAP_INDEX, Map, string_function_prototype_map) \
V(SYMBOL_FUNCTION_INDEX, JSFunction, symbol_function) \
V(WASM_EXPORTED_FUNCTION_MAP_INDEX, Map, wasm_exported_function_map) \
V(WASM_EXCEPTION_CONSTRUCTOR_INDEX, JSFunction, wasm_exception_constructor) \
V(WASM_FUNCTION_CONSTRUCTOR_INDEX, JSFunction, wasm_function_constructor) \
V(WASM_GLOBAL_CONSTRUCTOR_INDEX, JSFunction, wasm_global_constructor) \
V(WASM_INSTANCE_CONSTRUCTOR_INDEX, JSFunction, wasm_instance_constructor) \
V(WASM_MEMORY_CONSTRUCTOR_INDEX, JSFunction, wasm_memory_constructor) \
......
......@@ -2436,7 +2436,8 @@ Handle<JSFunction> Factory::NewFunction(const NewFunctionArgs& args) {
(*map == *isolate()->sloppy_function_without_prototype_map()) ||
(*map == *isolate()->sloppy_function_with_readonly_prototype_map()) ||
(*map == *isolate()->strict_function_map()) ||
(*map == *isolate()->strict_function_without_prototype_map()));
(*map == *isolate()->strict_function_without_prototype_map()) ||
(*map == *isolate()->wasm_exported_function_map()));
}
#endif
......
......@@ -1362,6 +1362,20 @@ void WebAssemblyException(const v8::FunctionCallbackInfo<v8::Value>& args) {
thrower.TypeError("WebAssembly.Exception cannot be called");
}
// WebAssembly.Function
void WebAssemblyFunction(const v8::FunctionCallbackInfo<v8::Value>& args) {
v8::Isolate* isolate = args.GetIsolate();
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
HandleScope scope(isolate);
ScheduledErrorThrower thrower(i_isolate, "WebAssembly.Function()");
if (!args.IsConstructCall()) {
thrower.TypeError("WebAssembly.Function must be invoked with 'new'");
return;
}
// TODO(7742): Implement ability to construct.
UNIMPLEMENTED();
}
constexpr const char* kName_WasmGlobalObject = "WebAssembly.Global";
constexpr const char* kName_WasmMemoryObject = "WebAssembly.Memory";
constexpr const char* kName_WasmInstanceObject = "WebAssembly.Instance";
......@@ -1962,7 +1976,7 @@ void WasmJs::Install(Isolate* isolate, bool exposed_on_global_object) {
JSFunction::EnsureHasInitialMap(module_constructor);
Handle<JSObject> module_proto(
JSObject::cast(module_constructor->instance_prototype()), isolate);
i::Handle<i::Map> module_map =
Handle<Map> module_map =
isolate->factory()->NewMap(i::WASM_MODULE_TYPE, WasmModuleObject::kSize);
JSFunction::SetInitialMap(module_constructor, module_map, module_proto);
InstallFunc(isolate, module_constructor, "imports", WebAssemblyModuleImports,
......@@ -1982,7 +1996,7 @@ void WasmJs::Install(Isolate* isolate, bool exposed_on_global_object) {
JSFunction::EnsureHasInitialMap(instance_constructor);
Handle<JSObject> instance_proto(
JSObject::cast(instance_constructor->instance_prototype()), isolate);
i::Handle<i::Map> instance_map = isolate->factory()->NewMap(
Handle<Map> instance_map = isolate->factory()->NewMap(
i::WASM_INSTANCE_TYPE, WasmInstanceObject::kSize);
JSFunction::SetInitialMap(instance_constructor, instance_map, instance_proto);
InstallGetter(isolate, instance_proto, "exports",
......@@ -2003,7 +2017,7 @@ void WasmJs::Install(Isolate* isolate, bool exposed_on_global_object) {
JSFunction::EnsureHasInitialMap(table_constructor);
Handle<JSObject> table_proto(
JSObject::cast(table_constructor->instance_prototype()), isolate);
i::Handle<i::Map> table_map =
Handle<Map> table_map =
isolate->factory()->NewMap(i::WASM_TABLE_TYPE, WasmTableObject::kSize);
JSFunction::SetInitialMap(table_constructor, table_map, table_proto);
InstallGetter(isolate, table_proto, "length", WebAssemblyTableGetLength);
......@@ -2024,7 +2038,7 @@ void WasmJs::Install(Isolate* isolate, bool exposed_on_global_object) {
JSFunction::EnsureHasInitialMap(memory_constructor);
Handle<JSObject> memory_proto(
JSObject::cast(memory_constructor->instance_prototype()), isolate);
i::Handle<i::Map> memory_map =
Handle<Map> memory_map =
isolate->factory()->NewMap(i::WASM_MEMORY_TYPE, WasmMemoryObject::kSize);
JSFunction::SetInitialMap(memory_constructor, memory_map, memory_proto);
InstallFunc(isolate, memory_proto, "grow", WebAssemblyMemoryGrow, 1);
......@@ -2044,7 +2058,7 @@ void WasmJs::Install(Isolate* isolate, bool exposed_on_global_object) {
JSFunction::EnsureHasInitialMap(global_constructor);
Handle<JSObject> global_proto(
JSObject::cast(global_constructor->instance_prototype()), isolate);
i::Handle<i::Map> global_map =
Handle<Map> global_map =
isolate->factory()->NewMap(i::WASM_GLOBAL_TYPE, WasmGlobalObject::kSize);
JSFunction::SetInitialMap(global_constructor, global_map, global_proto);
InstallFunc(isolate, global_proto, "valueOf", WebAssemblyGlobalValueOf, 0);
......@@ -2066,12 +2080,38 @@ void WasmJs::Install(Isolate* isolate, bool exposed_on_global_object) {
JSFunction::EnsureHasInitialMap(exception_constructor);
Handle<JSObject> exception_proto(
JSObject::cast(exception_constructor->instance_prototype()), isolate);
i::Handle<i::Map> exception_map = isolate->factory()->NewMap(
Handle<Map> exception_map = isolate->factory()->NewMap(
i::WASM_EXCEPTION_TYPE, WasmExceptionObject::kSize);
JSFunction::SetInitialMap(exception_constructor, exception_map,
exception_proto);
}
// Setup Function
if (enabled_features.type_reflection) {
Handle<JSFunction> function_constructor = InstallConstructorFunc(
isolate, webassembly, "Function", WebAssemblyFunction);
context->set_wasm_function_constructor(*function_constructor);
SetDummyInstanceTemplate(isolate, function_constructor);
JSFunction::EnsureHasInitialMap(function_constructor);
Handle<JSObject> function_proto(
JSObject::cast(function_constructor->instance_prototype()), isolate);
Handle<Map> function_map = isolate->factory()->CreateSloppyFunctionMap(
FUNCTION_WITHOUT_PROTOTYPE, MaybeHandle<JSFunction>());
CHECK(JSObject::SetPrototype(
function_proto,
handle(context->function_function()->prototype(), isolate), false,
kDontThrow)
.FromJust());
JSFunction::SetInitialMap(function_constructor, function_map,
function_proto);
// Make all exported functions an instance of {WebAssembly.Function}.
context->set_wasm_exported_function_map(*function_map);
} else {
// Make all exported functions an instance of {Function}.
Handle<Map> function_map = isolate->sloppy_function_without_prototype_map();
context->set_wasm_exported_function_map(*function_map);
}
// Setup errors
Handle<JSFunction> compile_error(
isolate->native_context()->wasm_compile_error_function(), isolate);
......
......@@ -2096,9 +2096,9 @@ Handle<WasmExportedFunction> WasmExportedFunction::New(
.ToHandleChecked();
}
bool is_asm_js_module = instance->module_object()->is_asm_js();
Handle<Map> function_map =
is_asm_js_module ? isolate->sloppy_function_map()
: isolate->sloppy_function_without_prototype_map();
Handle<Map> function_map = is_asm_js_module
? isolate->sloppy_function_map()
: isolate->wasm_exported_function_map();
NewFunctionArgs args =
NewFunctionArgs::ForWasm(name, function_data, function_map);
Handle<JSFunction> js_function = isolate->factory()->NewFunction(args);
......
......@@ -157,3 +157,33 @@ load('test/mjsunit/wasm/wasm-module-builder.js');
assertEquals('anyfunc', type.element);
assertEquals(3, Object.getOwnPropertyNames(type).length);
})();
(function TestFunctionConstructor() {
let desc = Object.getOwnPropertyDescriptor(WebAssembly, 'Function');
assertEquals(typeof desc.value, 'function');
assertTrue(desc.writable);
assertFalse(desc.enumerable);
assertTrue(desc.configurable);
// TODO(7742): The length should probably be 2 instead.
assertEquals(WebAssembly.Function.length, 1);
assertEquals(WebAssembly.Function.name, 'Function');
assertThrows(
() => WebAssembly.Function(), TypeError, /must be invoked with 'new'/);
// TODO(7742): Add tests for missing/bogus arguments.
})();
(function TestFunctionExportedFunctions() {
let builder = new WasmModuleBuilder();
builder.addFunction("fun", kSig_v_v).addBody([]).exportFunc();
let instance = builder.instantiate();
let fun = instance.exports.fun;
assertTrue(fun instanceof WebAssembly.Function);
assertTrue(fun instanceof Function);
assertTrue(fun instanceof Object);
assertSame(fun.__proto__, WebAssembly.Function.prototype);
assertSame(fun.__proto__.__proto__, Function.prototype);
assertSame(fun.__proto__.__proto__.__proto__, Object.prototype);
assertSame(fun.constructor, WebAssembly.Function);
assertEquals(typeof fun, 'function');
assertDoesNotThrow(() => fun());
})();
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