Glad that your setup works for you now. Is your project open source? In any case, let us know if you encounter any further issues.
I also have a few followup questions below to make sure nothing is wrong and potentially improve V8's handling there. On Tue, Oct 2, 2018 at 6:34 PM 'Kenton Varda' via v8-users < v8-users@googlegroups.com> wrote: > I figured this out. > > First, some misunderstandings: > > 1) --predictable was a red herring. It fixed the specific reproduction > case I had (seemingly by accident), but did not actually fix the general > problem (and had some negative side-effects). > That's what I thought, yeah. > > 2) The term "write barrier" was confusing me because I'm not well-read in > GC literature and I was thinking of a write barrier between threads. So I > was assuming you were telling me that I was missing some thread > synchronization, but given that only scavenges are multi-threaded and they > don't trace through native objects, I didn't get it. But now I've figured > out that this is actually a garbage collection term that is not necessarily > related to threading. > > Yes, I should've been more specific. Glad you figured it out. > 3) I didn't fully realize that GC being incremental means that V8 > interleaves calls to the tracer with regular code execution, meaning that > new objects could be created while a trace is in progress. This has almost > all the same implications as being multi-threaded, without the actual > threading. > > It's slightly simpler as it avoids concurrent access on objects and all the challenges that come with that. > > So, here's specifically what I did (in the hopes that it helps someone in > the future): > > * When allocating a new native object, I check if a trace pass is in > progress (i.e. TracePrologue() has been called but TraceEpilogue() has > not). If so, I add the object to the list of objects that needs to be > traced. This handles the specific case that you mentioned, where the object > is allocated already-marked, and hence won't otherwise be traced as part of > the current tracing pass. It looks like I can't actually do the trace > synchronously when the object is created -- V8 doesn't expect > RegisterExternalReference() to be called at this time and crashes. Instead, > by adding it to the list, my tracer's IsTracingDone() now returns false, > which leads V8 to call AdvanceTracing() at some future point, which is > where I can then trace the object. > Delaying is usually better as depending on scheduling and idleness it has the potential to run in a less-busy phase of execution. That depends on the kind of platform you are running on though. On a first look, the synchronous call to RegisterExternalReference should also work though. Any chance you can pass along what's happening via bug or email? > * It's possible that a newly-created object will be destroyed before > tracing progresses, if all handles go out-of-scope. Hence, the object's > weak callback must also check if a trace is in progress, and must then > remove the object from the list of objects to be traced. Otherwise, > AdvanceTracing() will end up tracing a dangling pointer. > How can it go away? IIRC, then you set up the Scavenger correctly so that it would be strong and the currently running Mark-Compact GC should not be able to finish without tracing it. > > * If a native object can be modified after creation to add new weak > handles, then of course we run into a similar problem: The parent object > may already have been traced during the current cycle, and so the child > needs to be traced immediately. At present this case does not actually come > up in the objects we've instrumented, but it will at some point. I guess I > will either need to re-queue the parent object to be traced again, or I'll > need to specifically record that the new handle needs to have > RegisterExternalRefreence() called when tracing next advances. > > The is the problem of graph mutation during incremental (or concurrent) garbage collections. As already said, we rely on write barriers to re-visit such objects. You can follow the Blink implementation here <https://cs.chromium.org/chromium/src/third_party/blink/renderer/platform/bindings/trace_wrapper_member.h?q=TraceWrapperMEmber&sq=package:chromium&dr=CSs&l=53>. It uses a wrapping type that intercepts each write as manually instrumenting code with write barriers is way too error prone for us. Cheers, -Michael -- -- 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.