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.