On Tue, Oct 2, 2018 at 10:12 PM 'Kenton Varda' via v8-users < v8-users@googlegroups.com> wrote:
> On Tue, Oct 2, 2018 at 11:10 AM Michael Lippautz <mlippa...@chromium.org> > wrote: > >> 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. >> > > This is all for the Cloudflare Workers runtime. > https://developers.cloudflare.com/workers/about/ > > At present it is not open source. But, I'd very much like to release our > C++<->V8 glue layer at some point soon. We've used a lot of template/macro > magic to make it pretty painless to export a C++ interface to JavaScript. > Cool :) > > * 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? >> > > If I call RegisterExternalReference() without checking if a trace is in > progress, I pretty immediately get this unhelpful error dump: > > # > # Fatal error in , line 0 > # unreachable code > # > # > # > #FailureMessage Object: 0x7f638f70b980 > > Followed by a segfault with this stack trace: > > :? v8::internal::ConcurrentMarking::Run(int, > v8::internal::ConcurrentMarking::TaskState*) > ??:? v8::platform::WorkerThread::Run() > platform-posix.cc:? v8::base::ThreadEntry(void*) > glibc-2.24/nptl/pthread_create.c:333 start_thread > glibc-2.24/misc/../sysdeps/unix/sysv/linux/x86_64/clone.S:97 clone > > It looks like if make sure only to call it if a trace is in progress, then > it works fine. > Yes, that's correct. RegisterExternalReference() requires tracing to be in progress. However, you should be able to call it from anywhere on the main thread, e.g., also when V8 registers a reference through RegisterV8References <https://cs.chromium.org/chromium/src/v8/include/v8.h?q=EmbedderHeapTracer&sq=package:chromium&g=0&l=6961>. What I meant is that there's no need to *only* process the objects during AdvanceTracing <https://cs.chromium.org/chromium/src/v8/include/v8.h?q=EmbedderHeapTracer&sq=package:chromium&g=0&l=7001> . > > * 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. >> > > I may have misspoke slightly here: it appears the effect I was seeing is > *not* necessarily related to newly-created objects. Let me restate. > > It appears that it's possible that an object registered with > EmbedderHeapTracer::RegisterV8References() can actually be collected (i.e. > its weak callback is called) between then and > EmbedderHeapTracer::AdvanceTracing(). So, in RegisterV8References() I have > to make sure to put all the pointers in a map. When an object is destroyed > while tracing is active, I have to go remove it from the tracer's map. In > AdvanceTracing() I can then trace whatever is still in the map at that > point. > > I'm not sure what mechanism causes the object to be destroyed immediately > after it has been registered for tracing. But, AFAICT, the object is > legitimately no longer reachable -- I'm not seeing any objects being > destroyed that were still in-use. > > That should not be possible when everything is properly set up. Any object can only go away - on Scavenge, which should be prohibited by marking it as active in the prologue callbacks - on Mark-Compact, which should not be possible as tracing is still in progress. The only thing I can think of where this could happen is when V8 calls AdvanceTracing where it *must* trace all objects that are cached (indicated by completing actions in the old version, or with infinite as timeout in the new version) and the embedder does not follow this policy. The Mark-Compact collector implements various stages of weakness processing and an object could be collected if AdvanceTracing(infinity) does not fully process all objects on the embedder side. Then the next AdvanceTracing(infinity) call could see dead objects. Any chance that you are not completely draining all objects when it's required? 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.