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.

Reply via email to