Commit b9eb9ee7 authored by mtrofin's avatar mtrofin Committed by Commit bot

[wasm] Use weak reference for wasm deopt data.

This unblocks moving off having to hold on to a compiled module
template.

Once we don't have the template, when we have a single instance, the
instance and wasm module share the same compiled code. We will want
to clear that code off instance-specific stuff, when the instance is
unreferenced and should be GC-ed (stuff like the instance heap, for
instance). However, the deopt data will maintain a strong reference,
blocking the GC: the module object strongly references the compiled
code, which strongly references the instance object through the deopt
data.

This change addresses that by making that last reference weak.

BUG=v8:5316

Review-Url: https://codereview.chromium.org/2284683005
Cr-Commit-Position: refs/heads/master@{#38990}
parent b42e12cd
......@@ -1461,9 +1461,8 @@ Address WasmFrame::GetCallerStackPointer() const {
}
Object* WasmFrame::wasm_obj() const {
FixedArray* deopt_data = LookupCode()->deoptimization_data();
DCHECK(deopt_data->length() == 2);
return deopt_data->get(0);
return wasm::GetOwningWasmInstance(*isolate()->factory()->undefined_value(),
LookupCode());
}
uint32_t WasmFrame::function_index() const {
......
......@@ -37,10 +37,11 @@ RUNTIME_FUNCTION(Runtime_WasmGrowMemory) {
Memory::Address_at(entry + StandardFrameConstants::kCallerPCOffset);
Code* code =
isolate->inner_pointer_to_code_cache()->GetCacheEntry(pc)->code;
FixedArray* deopt_data = code->deoptimization_data();
DCHECK(deopt_data->length() == 2);
module_object = Handle<JSObject>::cast(handle(deopt_data->get(0), isolate));
CHECK(!module_object->IsNull(isolate));
Object* undefined = *isolate->factory()->undefined_value();
Object* owning_instance = wasm::GetOwningWasmInstance(undefined, code);
CHECK_NOT_NULL(owning_instance);
CHECK_NE(owning_instance, undefined);
module_object = handle(JSObject::cast(owning_instance), isolate);
}
Address old_mem_start, new_mem_start;
......
......@@ -144,6 +144,18 @@ Handle<JSFunction> WrapExportCodeAsJSFunction(
return function;
}
Object* GetOwningWasmInstance(Object* undefined, Code* code) {
DCHECK(code->kind() == Code::WASM_FUNCTION);
DisallowHeapAllocation no_gc;
FixedArray* deopt_data = code->deoptimization_data();
DCHECK_NOT_NULL(deopt_data);
DCHECK(deopt_data->length() == 2);
Object* weak_link = deopt_data->get(0);
if (weak_link == undefined) return undefined;
WeakCell* cell = WeakCell::cast(weak_link);
return cell->value();
}
namespace {
// Internal constants for the layout of the module object.
const int kWasmModuleFunctionTable = 0;
......@@ -434,6 +446,24 @@ void FlushAssemblyCache(Isolate* isolate, Handle<FixedArray> functions) {
}
}
void SetRuntimeSupport(Isolate* isolate, Handle<JSObject> js_object) {
Handle<FixedArray> functions = Handle<FixedArray>(
FixedArray::cast(js_object->GetInternalField(kWasmModuleCodeTable)));
Handle<WeakCell> weak_link = isolate->factory()->NewWeakCell(js_object);
for (int i = FLAG_skip_compiling_wasm_funcs; i < functions->length(); ++i) {
Handle<Code> code = functions->GetValueChecked<Code>(isolate, i);
DCHECK(code->deoptimization_data() == nullptr ||
code->deoptimization_data()->length() == 0);
Handle<FixedArray> deopt_data =
isolate->factory()->NewFixedArray(2, TENURED);
deopt_data->set(0, *weak_link);
deopt_data->set(1, Smi::FromInt(static_cast<int>(i)));
deopt_data->set_length(2);
code->set_deoptimization_data(*deopt_data);
}
}
} // namespace
WasmModule::WasmModule(byte* module_start)
......@@ -873,21 +903,6 @@ void SetDebugSupport(Factory* factory, Handle<FixedArray> compiled_module,
js_object->SetInternalField(kWasmModuleBytesString,
*module_bytes_string.ToHandleChecked());
}
Handle<FixedArray> functions = Handle<FixedArray>(
FixedArray::cast(js_object->GetInternalField(kWasmModuleCodeTable)));
for (int i = FLAG_skip_compiling_wasm_funcs; i < functions->length(); ++i) {
Handle<Code> code = functions->GetValueChecked<Code>(isolate, i);
DCHECK(code->deoptimization_data() == nullptr ||
code->deoptimization_data()->length() == 0);
Handle<FixedArray> deopt_data = factory->NewFixedArray(2, TENURED);
if (!js_object.is_null()) {
deopt_data->set(0, *js_object);
}
deopt_data->set(1, Smi::FromInt(static_cast<int>(i)));
deopt_data->set_length(2);
code->set_deoptimization_data(*deopt_data);
}
MaybeHandle<ByteArray> function_name_table =
compiled_module->GetValue<ByteArray>(isolate, kFunctionNameTable);
......@@ -1397,6 +1412,7 @@ MaybeHandle<JSObject> WasmModule::Instantiate(
}
SetDebugSupport(factory, compiled_module, js_object);
SetRuntimeSupport(isolate, js_object);
FlushAssemblyCache(isolate, code_table);
......
......@@ -401,6 +401,13 @@ void PopulateFunctionTable(Handle<FixedArray> table, uint32_t table_size,
Handle<JSObject> CreateCompiledModuleObject(Isolate* isolate,
Handle<FixedArray> compiled_module);
// Assumed to be called with a code object associated to a wasm module instance.
// Intended to be called from runtime functions.
// Returns undefined if the runtime support was not setup, nullptr if the
// instance
// was collected, or the instance object owning the Code object
Object* GetOwningWasmInstance(Object* undefined, Code* code);
namespace testing {
// Decode, verify, and run the function labeled "main" in the
......
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