Skip to content

Commit

Permalink
[wasm] Avoid internal implicit receivers for API functions.
Browse files Browse the repository at this point in the history
This assigns dummy instance templates to all WebAssembly API functions
used as constructors. It hence avoids implicit receivers from having the
internal instance types. These objects would never be fully initialized
and causes heap iterations to stumble over these objects.

R=clemensh@chromium.org
BUG=v8:8003

Change-Id: I9d9da9a2c2202252353429b39c21ee23debe3c86
Reviewed-on: https://chromium-review.googlesource.com/1169057
Reviewed-by: Clemens Hammacher <clemensh@chromium.org>
  • Loading branch information
Michael Starzinger committed Aug 9, 2018
1 parent 3c1f40d commit 5821a7a
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 13 deletions.
6 changes: 5 additions & 1 deletion src/objects-debug.cc
Expand Up @@ -223,10 +223,12 @@ void HeapObject::HeapObjectVerify(Isolate* isolate) {
case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
case WASM_GLOBAL_TYPE:
case WASM_MEMORY_TYPE:
case WASM_MODULE_TYPE:
case WASM_TABLE_TYPE:
JSObject::cast(this)->JSObjectVerify(isolate);
break;
case WASM_MODULE_TYPE:
WasmModuleObject::cast(this)->WasmModuleObjectVerify(isolate);
break;
case WASM_INSTANCE_TYPE:
WasmInstanceObject::cast(this)->WasmInstanceObjectVerify(isolate);
break;
Expand Down Expand Up @@ -1678,7 +1680,9 @@ void WasmExportedFunctionData::WasmExportedFunctionDataVerify(
void WasmModuleObject::WasmModuleObjectVerify(Isolate* isolate) {
CHECK(IsWasmModuleObject());
VerifyObjectField(isolate, kNativeModuleOffset);
CHECK(managed_native_module()->IsForeign());
VerifyObjectField(isolate, kExportWrappersOffset);
CHECK(export_wrappers()->IsFixedArray());
VerifyObjectField(isolate, kScriptOffset);
VerifyObjectField(isolate, kAsmJsOffsetTableOffset);
VerifyObjectField(isolate, kBreakPointInfosOffset);
Expand Down
27 changes: 24 additions & 3 deletions src/wasm/wasm-js.cc
Expand Up @@ -1296,19 +1296,26 @@ void WebAssemblyGlobalSetValue(

// TODO(titzer): we use the API to create the function template because the
// internal guts are too ugly to replicate here.
static i::Handle<i::FunctionTemplateInfo> NewTemplate(i::Isolate* i_isolate,
FunctionCallback func) {
static i::Handle<i::FunctionTemplateInfo> NewFunctionTemplate(
i::Isolate* i_isolate, FunctionCallback func) {
Isolate* isolate = reinterpret_cast<Isolate*>(i_isolate);
Local<FunctionTemplate> templ = FunctionTemplate::New(isolate, func);
templ->ReadOnlyPrototype();
return v8::Utils::OpenHandle(*templ);
}

static i::Handle<i::ObjectTemplateInfo> NewObjectTemplate(
i::Isolate* i_isolate) {
Isolate* isolate = reinterpret_cast<Isolate*>(i_isolate);
Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
return v8::Utils::OpenHandle(*templ);
}

namespace internal {

Handle<JSFunction> CreateFunc(Isolate* isolate, Handle<String> name,
FunctionCallback func) {
Handle<FunctionTemplateInfo> temp = NewTemplate(isolate, func);
Handle<FunctionTemplateInfo> temp = NewFunctionTemplate(isolate, func);
Handle<JSFunction> function =
ApiNatives::InstantiateFunction(temp, name).ToHandleChecked();
DCHECK(function->shared()->HasSharedName());
Expand Down Expand Up @@ -1367,6 +1374,15 @@ void InstallGetterSetter(Isolate* isolate, Handle<JSObject> object,
Utils::ToLocal(setter_func), attributes);
}

// Assigns a dummy instance template to the given constructor function. Used to
// make sure the implicit receivers for the constructors in this file have an
// instance type different from the internal one, they allocate the resulting
// object explicitly and ignore implicit receiver.
void SetDummyInstanceTemplate(Isolate* isolate, Handle<JSFunction> fun) {
Handle<ObjectTemplateInfo> instance_template = NewObjectTemplate(isolate);
fun->shared()->get_api_func_data()->set_instance_template(*instance_template);
}

void WasmJs::Install(Isolate* isolate, bool exposed_on_global_object) {
Handle<JSGlobalObject> global = isolate->global_object();
Handle<Context> context(global->native_context(), isolate);
Expand Down Expand Up @@ -1412,6 +1428,7 @@ void WasmJs::Install(Isolate* isolate, bool exposed_on_global_object) {
Handle<JSFunction> module_constructor =
InstallFunc(isolate, webassembly, "Module", WebAssemblyModule, 1);
context->set_wasm_module_constructor(*module_constructor);
SetDummyInstanceTemplate(isolate, module_constructor);
JSFunction::EnsureHasInitialMap(module_constructor);
Handle<JSObject> module_proto(
JSObject::cast(module_constructor->instance_prototype()), isolate);
Expand All @@ -1431,6 +1448,7 @@ void WasmJs::Install(Isolate* isolate, bool exposed_on_global_object) {
Handle<JSFunction> instance_constructor =
InstallFunc(isolate, webassembly, "Instance", WebAssemblyInstance, 1);
context->set_wasm_instance_constructor(*instance_constructor);
SetDummyInstanceTemplate(isolate, instance_constructor);
JSFunction::EnsureHasInitialMap(instance_constructor);
Handle<JSObject> instance_proto(
JSObject::cast(instance_constructor->instance_prototype()), isolate);
Expand All @@ -1447,6 +1465,7 @@ void WasmJs::Install(Isolate* isolate, bool exposed_on_global_object) {
Handle<JSFunction> table_constructor =
InstallFunc(isolate, webassembly, "Table", WebAssemblyTable, 1);
context->set_wasm_table_constructor(*table_constructor);
SetDummyInstanceTemplate(isolate, table_constructor);
JSFunction::EnsureHasInitialMap(table_constructor);
Handle<JSObject> table_proto(
JSObject::cast(table_constructor->instance_prototype()), isolate);
Expand All @@ -1464,6 +1483,7 @@ void WasmJs::Install(Isolate* isolate, bool exposed_on_global_object) {
Handle<JSFunction> memory_constructor =
InstallFunc(isolate, webassembly, "Memory", WebAssemblyMemory, 1);
context->set_wasm_memory_constructor(*memory_constructor);
SetDummyInstanceTemplate(isolate, memory_constructor);
JSFunction::EnsureHasInitialMap(memory_constructor);
Handle<JSObject> memory_proto(
JSObject::cast(memory_constructor->instance_prototype()), isolate);
Expand All @@ -1481,6 +1501,7 @@ void WasmJs::Install(Isolate* isolate, bool exposed_on_global_object) {
Handle<JSFunction> global_constructor =
InstallFunc(isolate, webassembly, "Global", WebAssemblyGlobal, 1);
context->set_wasm_global_constructor(*global_constructor);
SetDummyInstanceTemplate(isolate, global_constructor);
JSFunction::EnsureHasInitialMap(global_constructor);
Handle<JSObject> global_proto(
JSObject::cast(global_constructor->instance_prototype()), isolate);
Expand Down
19 changes: 10 additions & 9 deletions src/wasm/wasm-objects.cc
Expand Up @@ -212,15 +212,6 @@ Handle<WasmModuleObject> WasmModuleObject::New(
static_cast<int>(native_module->module()->num_exported_functions);
Handle<FixedArray> export_wrappers =
isolate->factory()->NewFixedArray(export_wrapper_size, TENURED);
Handle<WasmModuleObject> module_object = Handle<WasmModuleObject>::cast(
isolate->factory()->NewJSObject(isolate->wasm_module_constructor()));
module_object->set_export_wrappers(*export_wrappers);
if (script->type() == Script::TYPE_WASM) {
script->set_wasm_module_object(*module_object);
}
module_object->set_script(*script);
module_object->set_weak_instance_list(
ReadOnlyRoots(isolate).empty_weak_array_list());

// Use the given shared {NativeModule}, but increase its reference count by
// allocating a new {Managed<T>} that the {WasmModuleObject} references.
Expand All @@ -232,6 +223,16 @@ Handle<WasmModuleObject> WasmModuleObject::New(
Handle<Managed<wasm::NativeModule>> managed_native_module =
Managed<wasm::NativeModule>::FromSharedPtr(isolate, memory_estimate,
std::move(native_module));

Handle<WasmModuleObject> module_object = Handle<WasmModuleObject>::cast(
isolate->factory()->NewJSObject(isolate->wasm_module_constructor()));
module_object->set_export_wrappers(*export_wrappers);
if (script->type() == Script::TYPE_WASM) {
script->set_wasm_module_object(*module_object);
}
module_object->set_script(*script);
module_object->set_weak_instance_list(
ReadOnlyRoots(isolate).empty_weak_array_list());
module_object->set_managed_native_module(*managed_native_module);
return module_object;
}
Expand Down

0 comments on commit 5821a7a

Please sign in to comment.