It seems that one of the following is occurring:

   - v8 is materializing a strong edge to an object whose weak finalizer 
   callback it has called
   - v8 is calling a weak finalizer callback on something with strong edges

Exactly which we have been unable to determine.  Given that neither 
Chromium nor Node seem to be using kFinalizer, I guess that this code 
doesn't get much in the way of a workout, so I guess we'll just stop using 
kFinalizer also.

On Friday, 3 August 2018 15:59:54 UTC-4, Daryl Haresign wrote:
>
> Hi all,
>
> We have recently started using the EmbedderHeapTracer APIs (upgrading to 
> v8 6.2), and we've started to see some odd behavior.  I was hoping someone 
> would be able to say what it is that's going on.
>
> We have a C++ Wrapper class for hosted and marshaled objects.  Internally 
> it stores two v8::Persistent<v8::Object> handles, both of which are weak, 
> with a registered finalizer callback.  The first handle's finalizer 
> callback Reset()s the handle, and adds the Wrapper to a list of wrappers 
> to be deleted in the GC epilogue.  The second handle's finalizer callback 
> ClearWeak()s the handle.  When the GC epilogue happens, we walk the list 
> of wrappers to delete and call the Wrapper destructor.  This destructor 
> Reset()s the second handle.
>
> The v8::Object the Wrapper wraps has two embedder fields, with the second 
> one being a pointer to the Wrapper.
>
> What we are seeing is that, infrequently (once in maybe 600,000 created 
> Wrapper objects), the following sequence of events occurs:
>
>
>    1. A Wrapper is created at address A
>    2. Several scavenge GCs occur, where we unconditionally mark all 
>    Wrappers as active
>    3. Mark/Sweep GC prologue
>       1. Trace prologue
>          1. V8 informs us of an object with its second embedder field 
>          pointing to address A
>       2. Trace epilogue
>       3. Weak finalizer callbacks are called for this object, we queue up 
>       the Wrapper for deletion
>    4. Mark/Sweep GC epilogue
>       1. We delete the Wrapper
>    5. Mark/Sweep GC prologue
>       1. Trace prologue
>          1. V8 informs us of an object with its second embedder field 
>          pointing to address A
>       
> At this point, the Wrapper at address A has been deleted, so we access 
> garbage memory.
>
> We've looked into the GC code, and it seems that objects with weak 
> finalizer handles pointing at them are kept alive until the end of the 
> current GC cycle.  Additionally our second weak handle which we make strong 
> until the destructor is called in the GC epilogue ensures that this is the 
> case.  But in that GC cycle we clear out the last handle to this object on 
> our side, so we were under the impression that the object would no longer 
> be reachable.  It seems as though somehow v8 is materializing a reference 
> to this object after we remove our final reference, causing it to be 
> retraced after we have deleted the associated Wrapper.  Is there any 
> reason why v8 might be doing this?
>
> As a work-around, we are now clearing the embedder fields in the first 
> weak finalizer callback where we add the object to the list of wrappers to 
> delete.  This means that even if v8 decides to keep a reference, it will 
> not see it as a wrapper which should be traced, so we won't ever hear about 
> it again.  But we'd like to understand what the root issue is so that we 
> can adjust our assumptions if necessary.
>
> Thanks,
> Daryl.
>

-- 
-- 
v8-users mailing list
v8-users@googlegroups.com
http://groups.google.com/group/v8-users
--- 
You received this message because you are subscribed to the Google Groups 
"v8-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to v8-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to