Index: src/wasm/wasm-module.cc |
diff --git a/src/wasm/wasm-module.cc b/src/wasm/wasm-module.cc |
index 4f0b885ee020c91fd12bc500dab0d8a9643b6aa2..67710bac0b6a584c2228fc06d33bc0bd0b71f4cf 100644 |
--- a/src/wasm/wasm-module.cc |
+++ b/src/wasm/wasm-module.cc |
@@ -1255,6 +1255,11 @@ MaybeHandle<JSObject> WasmModule::Instantiate(Isolate* isolate, |
Handle<FixedArray> code_table; |
Handle<FixedArray> old_code_table; |
Handle<JSObject> owner; |
+ // If we don't clone, this will be null(). Otherwise, this will |
+ // be a weak link to the original. If we lose the original to GC, |
+ // this will be a cleared. We'll link the instances chain last. |
+ MaybeHandle<WeakCell> link_to_original; |
+ |
{ |
Handle<FixedArray> original( |
FixedArray::cast(module_object->GetInternalField(0)), isolate); |
@@ -1265,20 +1270,24 @@ MaybeHandle<JSObject> WasmModule::Instantiate(Isolate* isolate, |
WeakCell* tmp = GetOwningInstance(*original); |
if (tmp != nullptr) { |
+ DCHECK(!tmp->cleared()); |
// There is already an owner, clone everything. |
owner = Handle<JSObject>(JSObject::cast(tmp->value()), isolate); |
// Insert the latest clone in front. |
compiled_module = factory->CopyFixedArray(original); |
+ // Replace the strong reference to point to the new instance here. |
+ // This allows any of the other instances, including the original, |
+ // to be collected. |
+ module_object->SetInternalField(0, *compiled_module); |
Handle<WeakCell> weak_link_to_wasm_obj = |
original->GetValueChecked<WeakCell>(isolate, kModuleObject); |
compiled_module->set(kModuleObject, *weak_link_to_wasm_obj); |
- Handle<WeakCell> link_to_original = factory->NewWeakCell(original); |
- compiled_module->set(kNextInstance, *link_to_original); |
- Handle<WeakCell> link_to_clone = factory->NewWeakCell(compiled_module); |
- original->set(kPrevInstance, *link_to_clone); |
- JSObject::cast(weak_link_to_wasm_obj->value()) |
- ->SetInternalField(0, *compiled_module); |
+ link_to_original = factory->NewWeakCell(original); |
+ // Don't link to original here. We remember the original |
+ // as a weak link. If that link isn't clear by the time we finish |
+ // instantiating this instance, then we link it at that time. |
+ compiled_module->set(kNextInstance, *factory->undefined_value()); |
// Clone the code for WASM functions and exports. |
for (int i = 0; i < code_table->length(); ++i) { |
@@ -1577,12 +1586,24 @@ MaybeHandle<JSObject> WasmModule::Instantiate(Isolate* isolate, |
if (!compiled_module->GetValue<WeakCell>(isolate, kModuleObject).is_null()) { |
instance->SetInternalField(kWasmCompiledModule, *compiled_module); |
Handle<WeakCell> link_to_owner = factory->NewWeakCell(instance); |
- compiled_module->set(kOwningInstance, *link_to_owner); |
Handle<Object> global_handle = isolate->global_handles()->Create(*instance); |
- GlobalHandles::MakeWeak(global_handle.location(), global_handle.location(), |
- &InstanceFinalizer, |
- v8::WeakCallbackType::kFinalizer); |
+ Handle<WeakCell> link_to_clone = factory->NewWeakCell(compiled_module); |
+ { |
+ DisallowHeapAllocation no_gc; |
+ compiled_module->set(kOwningInstance, *link_to_owner); |
+ Handle<WeakCell> next; |
+ if (link_to_original.ToHandle(&next) && !next->cleared()) { |
+ FixedArray* original = FixedArray::cast(next->value()); |
+ DCHECK_NOT_NULL(GetOwningInstance(original)); |
+ DCHECK(!GetOwningInstance(original)->cleared()); |
+ compiled_module->set(kNextInstance, *next); |
+ original->set(kPrevInstance, *link_to_clone); |
+ } |
+ GlobalHandles::MakeWeak(global_handle.location(), |
+ global_handle.location(), &InstanceFinalizer, |
+ v8::WeakCallbackType::kFinalizer); |
+ } |
} |
return instance; |