[wasm] Avoid internal implicit receivers for API functions.

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: I3c81d8dc3ae4a38e650b390a04170585cb31ec77
Reviewed-on: https://chromium-review.googlesource.com/1170685
Reviewed-by: Clemens Hammacher <clemensh@chromium.org>
Commit-Queue: Michael Starzinger <mstarzinger@chromium.org>
Cr-Commit-Position: refs/heads/master@{#55037}
This commit is contained in:
Michael Starzinger 2018-08-10 10:16:12 +02:00 committed by Commit Bot
parent f4ca3fc56e
commit 2392fd87b0
3 changed files with 39 additions and 13 deletions

View File

@ -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;
@ -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);

View File

@ -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());
@ -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);
@ -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);
@ -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);
@ -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);
@ -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);
@ -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);

View File

@ -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.
@ -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;
}