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).

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.

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.


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.

* 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.

* 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.

In any case, my GC issues seem now to be fixed without any special flags.
Hooray!

-Kenton

On Wed, Sep 26, 2018 at 4:08 AM Michael Lippautz <mlippa...@chromium.org>
wrote:

> Two more ideas:
> - V8 is using incremental marking for such wrappers which means that the
> C++ graph should either (a) be immutable during marking or (b) should keep
> the marking state consistent with e.g. write barriers.
> - Specific issue: When creating an API object while marking is running, V8
> may allocate the object as already marked (called black allocation). This
> means that RegisterV8References() will not be called as the objects are not
> discovered by the marker. In Blink, we thus issue a write barrier for such
> objects when establishing a new link
> <https://cs.chromium.org/chromium/src/third_party/blink/renderer/platform/bindings/v8_dom_wrapper.h?type=cs&q=SetNativeInfoInternal&sq=package:chromium&g=0&l=118>
> .
>
> We've some embedders that don't want to implement the incremental version
> and they thus set the flag incremental_marking_wrappers
> <https://cs.chromium.org/chromium/src/v8/src/flag-definitions.h?q=incremental_marking_wrappers&sq=package:chromium&g=0&l=712>
> to false. You could try disabling that flag but also dropping predictable.
>
> On Tue, Sep 25, 2018 at 6:36 PM 'Kenton Varda' via v8-users <
> v8-users@googlegroups.com> wrote:
>
>> Hi Michael,
>>
>> Thanks for commenting!
>>
>> On Tue, Sep 25, 2018 at 6:37 AM Michael Lippautz <mlippa...@chromium.org>
>> wrote:
>>
>>> Looks like Isolate::VisitWeakHandles
>>> <https://cs.chromium.org/chromium/src/v8/src/api.cc?q=Isolate::VisitWeakHandles&sq=package:chromium&g=0&l=8852>
>>> only iterates over weak handles with a non-zero class id. Any chance that
>>> this one is still 0?
>>>
>>
>> No, I set class ID to 1 just before calling SetWeak() -- for no other
>> purpose than this requirement. :)
>>
>>
>
> Ack.
>
>
>> The symptom described here hints to the Scavenger collecting objects.
>>> From the above description it looks like you wanted to preserve those
>>> objects on Scavenge.
>>>
>>> Some ideas:
>>> - Maybe class id is 0 (see above)?
>>> - Maybe the handle are not SetWeak
>>> <https://cs.chromium.org/chromium/src/v8/include/v8.h?type=cs&q=v8::PersistentBase::SetWeak&sq=package:chromium&g=0&l=514>
>>> immediately but only after some time where a Scavenge could've happened?
>>>
>>
>> But before calling SetWeak(), the handle would be strong, and therefore
>> not collected, right? Do I need to call MarkActive() at the same time as
>> SetWeak() to make sure any currently-running scavenges don't collect it?
>>
>>
> Yip, didn't think about this one. That all should work.
>
>
> --
> --
> v8-users mailing list
> v8-users@googlegroups.com
> http://groups.google.com/group/v8-users
> ---
> You received this message because you are subscribed to a topic in the
> Google Groups "v8-users" group.
> To unsubscribe from this topic, visit
> https://groups.google.com/d/topic/v8-users/e8LsFC-LNGE/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to
> v8-users+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>

-- 
-- 
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