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