Commit 96e83b78 authored by Ulan Degenbaev's avatar Ulan Degenbaev Committed by Commit Bot

[wasm] Use two-pass phantom callbacks for managed objects.

The phantom handle API requires that the first pass callback does not
invoke any V8 API. The current code breaks this requirement by invoking
AdjustAmountOfExternalAllocatedMemory, which can cause GC.

This patch splits the existing callback into two parts. The first part
only resets the handle and the second part performs native delete.

Bug: chromium:827806
Change-Id: I01eed09f94f5499cb9d13397066f4f908a0aa668
Reviewed-on: https://chromium-review.googlesource.com/995796
Commit-Queue: Ulan Degenbaev <ulan@chromium.org>
Reviewed-by: 's avatarClemens Hammacher <clemensh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#52366}
parent 125f8c81
...@@ -59,22 +59,30 @@ class Managed : public Foreign { ...@@ -59,22 +59,30 @@ class Managed : public Foreign {
isolate->factory()->NewForeign(reinterpret_cast<Address>(finalizer))); isolate->factory()->NewForeign(reinterpret_cast<Address>(finalizer)));
Handle<Object> global_handle = isolate->global_handles()->Create(*handle); Handle<Object> global_handle = isolate->global_handles()->Create(*handle);
finalizer->global_handle_location = global_handle.location(); finalizer->global_handle_location = global_handle.location();
GlobalHandles::MakeWeak(finalizer->global_handle_location, GlobalHandles::MakeWeak(
handle->GetFinalizer(), &Managed<CppType>::GCDelete, finalizer->global_handle_location, handle->GetFinalizer(),
v8::WeakCallbackType::kParameter); &ResetWeakAndScheduleGCDelete, v8::WeakCallbackType::kParameter);
return handle; return handle;
} }
private: private:
static void GCDelete(const v8::WeakCallbackInfo<void>& data) { static void ResetWeakAndScheduleGCDelete(
const v8::WeakCallbackInfo<void>& data) {
FinalizerWithHandle* finalizer = FinalizerWithHandle* finalizer =
reinterpret_cast<FinalizerWithHandle*>(data.GetParameter()); reinterpret_cast<FinalizerWithHandle*>(data.GetParameter());
GlobalHandles::Destroy(finalizer->global_handle_location);
Isolate* isolate = reinterpret_cast<Isolate*>(data.GetIsolate()); Isolate* isolate = reinterpret_cast<Isolate*>(data.GetIsolate());
isolate->UnregisterFromReleaseAtTeardown(finalizer); isolate->UnregisterFromReleaseAtTeardown(finalizer);
// We need to call GCDelete as a second pass callback because
// it can trigger garbage collection. The first pass callbacks
// are not allowed to invoke V8 API.
data.SetSecondPassCallback(&GCDelete);
}
GlobalHandles::Destroy(finalizer->global_handle_location); static void GCDelete(const v8::WeakCallbackInfo<void>& data) {
FinalizerWithHandle* finalizer =
reinterpret_cast<FinalizerWithHandle*>(data.GetParameter());
NativeDelete(finalizer); NativeDelete(finalizer);
} }
......
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