Hello, GC experts. Recently I met a GC crash when PARRALLEL GC is enabled. Crash is like: #0 0x00007ffff72a1671 in isJSString (this=0x7fffeaec0cd8) at /home/oszi/WebKit/Source/JavaScriptCore/runtime/JSString.h:501 #1 visitChildren (this=0x7fffeaec0cd8) at /home/oszi/WebKit/Source/JavaScriptCore/heap/MarkStack.cpp:351 #2 JSC::SlotVisitor::drain (this=0x7fffeaec0cd8) at /home/oszi/WebKit/Source/JavaScriptCore/heap/MarkStack.cpp:405 #3 0x00007ffff72a19e4 in JSC::SlotVisitor::drainFromShared (this=0x7fffeaec0cd8, sharedDrainMode=JSC::SlotVisitor::MasterDrain) at /home/oszi/WebKit/Source/JavaScriptCore/heap/MarkStack.cpp:498 #4 0x00007ffff729dd38 in JSC::Heap::markRoots (this=0x7fffeaec0050, fullGC=<value optimized out>) at /home/oszi/WebKit/Source/JavaScriptCore/heap/Heap.cpp:555 #5 0x00007ffff729df8b in JSC::Heap::collect (this=0x7fffeaec0050, sweepToggle=JSC::Heap::DoNotSweep) at /home/oszi/WebKit/Source/JavaScriptCore/heap/Heap.cpp:717 #6 0x00007ffff72a410c in JSC::MarkedAllocator::allocateSlowCase (this=0x7fffeaec0158) at /home/oszi/WebKit/Source/JavaScriptCore/heap/MarkedAllocator.cpp:75 #7 0x00007ffff72e84ba in JSC::MarkedAllocator::allocate (exec=<value optimized out>) at /home/oszi/WebKit/Source/JavaScriptCore/heap/MarkedAllocator.h:77 #8 JSC::MarkedSpace::allocateWithDestructor (exec=<value optimized out>) at /home/oszi/WebKit/Source/JavaScriptCore/heap/MarkedSpace.h:191 #9 JSC::Heap::allocateWithDestructor (exec=<value optimized out>) at /home/oszi/WebKit/Source/JavaScriptCore/heap/Heap.h:362 #10 allocateCell<JSC::JSFinalObject> (exec=<value optimized out>) at /home/oszi/WebKit/Source/JavaScriptCore/runtime/JSCell.h:340 #11 JSC::JSFinalObject::create (exec=<value optimized out>) at /home/oszi/WebKit/Source/JavaScriptCore/runtime/JSObject.h:439 #12 constructEmptyObject (exec=<value optimized out>) at /home/oszi/WebKit/Source/JavaScriptCore/runtime/JSObject.h:515 #13 constructEmptyObject (exec=<value optimized out>) at /home/oszi/WebKit/Source/JavaScriptCore/runtime/JSGlobalObject.h:431 #14 constructEmptyObject (exec=<value optimized out>) at /home/oszi/WebKit/Source/JavaScriptCore/runtime/JSGlobalObject.h:436 #15 operationNewObject (exec=<value optimized out>) at /home/oszi/WebKit/Source/JavaScriptCore/dfg/DFGOperations.cpp:305 #16 0x00007fffaaf8880d in ?? () #17 0x0000000000000000 in ?? () I checked the code of JSCore GC. void SlotVisitor::drain() { StackStats::probe(); ASSERT(m_isInParallelMode); #if ENABLE(PARALLEL_GC) if (Options::numberOfGCMarkers() > 1) { while (!m_stack.isEmpty()) { m_stack.refill(); for (unsigned countdown = Options::minimumNumberOfScansBetweenRebalance(); m_stack.canRemoveLast() && countdown--;) visitChildren(*this, m_stack.removeLast()); donateKnownParallel(); } mergeOpaqueRootsIfNecessary(); return; } #endif while (!m_stack.isEmpty()) { m_stack.refill(); while (m_stack.canRemoveLast()) visitChildren(*this, m_stack.removeLast()); } } Why is m_shared.m_markingLock not added before m_stack.refill() and m_stack.removeLast(), just like inside the function void SlotVisitor::donateKnownParallel() ? It seems that m_stack is operated unsafely when PARRELLEL GC is enabled. What do you think?
The code you pasted is from some old version of WebKit, however the behavior you question is still present. I don't know if it's indeed a concern.
(In reply to comment #0) > Hello, GC experts. > > Recently I met a GC crash when PARRALLEL GC is enabled. Crash is like: > > #0 0x00007ffff72a1671 in isJSString (this=0x7fffeaec0cd8) at > /home/oszi/WebKit/Source/JavaScriptCore/runtime/JSString.h:501 > #1 visitChildren (this=0x7fffeaec0cd8) at > /home/oszi/WebKit/Source/JavaScriptCore/heap/MarkStack.cpp:351 > #2 JSC::SlotVisitor::drain (this=0x7fffeaec0cd8) at > /home/oszi/WebKit/Source/JavaScriptCore/heap/MarkStack.cpp:405 > #3 0x00007ffff72a19e4 in JSC::SlotVisitor::drainFromShared > (this=0x7fffeaec0cd8, sharedDrainMode=JSC::SlotVisitor::MasterDrain) at > /home/oszi/WebKit/Source/JavaScriptCore/heap/MarkStack.cpp:498 > #4 0x00007ffff729dd38 in JSC::Heap::markRoots (this=0x7fffeaec0050, > fullGC=<value optimized out>) at > /home/oszi/WebKit/Source/JavaScriptCore/heap/Heap.cpp:555 > #5 0x00007ffff729df8b in JSC::Heap::collect (this=0x7fffeaec0050, > sweepToggle=JSC::Heap::DoNotSweep) at > /home/oszi/WebKit/Source/JavaScriptCore/heap/Heap.cpp:717 > #6 0x00007ffff72a410c in JSC::MarkedAllocator::allocateSlowCase > (this=0x7fffeaec0158) at > /home/oszi/WebKit/Source/JavaScriptCore/heap/MarkedAllocator.cpp:75 > #7 0x00007ffff72e84ba in JSC::MarkedAllocator::allocate (exec=<value > optimized out>) at > /home/oszi/WebKit/Source/JavaScriptCore/heap/MarkedAllocator.h:77 > #8 JSC::MarkedSpace::allocateWithDestructor (exec=<value optimized out>) at > /home/oszi/WebKit/Source/JavaScriptCore/heap/MarkedSpace.h:191 > #9 JSC::Heap::allocateWithDestructor (exec=<value optimized out>) at > /home/oszi/WebKit/Source/JavaScriptCore/heap/Heap.h:362 > #10 allocateCell<JSC::JSFinalObject> (exec=<value optimized out>) at > /home/oszi/WebKit/Source/JavaScriptCore/runtime/JSCell.h:340 > #11 JSC::JSFinalObject::create (exec=<value optimized out>) at > /home/oszi/WebKit/Source/JavaScriptCore/runtime/JSObject.h:439 > #12 constructEmptyObject (exec=<value optimized out>) at > /home/oszi/WebKit/Source/JavaScriptCore/runtime/JSObject.h:515 > #13 constructEmptyObject (exec=<value optimized out>) at > /home/oszi/WebKit/Source/JavaScriptCore/runtime/JSGlobalObject.h:431 > #14 constructEmptyObject (exec=<value optimized out>) at > /home/oszi/WebKit/Source/JavaScriptCore/runtime/JSGlobalObject.h:436 > #15 operationNewObject (exec=<value optimized out>) at > /home/oszi/WebKit/Source/JavaScriptCore/dfg/DFGOperations.cpp:305 > #16 0x00007fffaaf8880d in ?? () > #17 0x0000000000000000 in ?? () > > > I checked the code of JSCore GC. > > void SlotVisitor::drain() > { > StackStats::probe(); > ASSERT(m_isInParallelMode); > > #if ENABLE(PARALLEL_GC) > if (Options::numberOfGCMarkers() > 1) { > while (!m_stack.isEmpty()) { > m_stack.refill(); > for (unsigned countdown = > Options::minimumNumberOfScansBetweenRebalance(); m_stack.canRemoveLast() && > countdown--;) > visitChildren(*this, m_stack.removeLast()); > donateKnownParallel(); > } > > mergeOpaqueRootsIfNecessary(); > return; > } > #endif > > while (!m_stack.isEmpty()) { > m_stack.refill(); > while (m_stack.canRemoveLast()) > visitChildren(*this, m_stack.removeLast()); > } > } > > Why is m_shared.m_markingLock not added before m_stack.refill() and > m_stack.removeLast(), just like inside the function void > SlotVisitor::donateKnownParallel() ? > > It seems that m_stack is operated unsafely when PARRELLEL GC is enabled. > > What do you think? Not a bug. m_stack is the thread-local stack.
Thanks a lot for your quickly response. m_stack is the thread-local stack, you are right. I made a mistake before. But we met some similar crashes like: #0 0x47dac0f0 in isJSString (v=...) at /usr/src/debug/webkit2-efl-tv-152340_0.10.193.0+tv/Source/JavaScriptCore/runtime/JSString.h:493 No locals. #1 visitChildren (cell=0xb3ad5018, visitor=...) at /usr/src/debug/webkit2-efl-tv-152340_0.10.193.0+tv/Source/JavaScriptCore/heap/SlotVisitor.cpp:80 No locals. #2 JSC::SlotVisitor::drain (this=this@entry=0xa54e8) at /usr/src/debug/webkit2-efl-tv-152340_0.10.193.0+tv/Source/JavaScriptCore/heap/SlotVisitor.cpp:136 countdown = 32 #3 0x47dac3a0 in JSC::SlotVisitor::drainFromShared (this=0xa54e8, sharedDrainMode=JSC::SlotVisitor::SlaveDrain) at /usr/src/debug/webkit2-efl-tv-152340_0.10.193.0+tv/Source/JavaScriptCore/heap/SlotVisitor.cpp:225 No locals. #4 0x47d9e2be in JSC::GCThread::gcThreadMain (this=0xa5550) at /usr/src/debug/webkit2-efl-tv-152340_0.10.193.0+tv/Source/JavaScriptCore/heap/GCThread.cpp:104 enabler = {m_stack = @0xa54e8} #5 0x47f4c2cc in WTF::wtfThreadEntryPoint (param=0xa5f98) at /usr/src/debug/webkit2-efl-tv-152340_0.10.193.0+tv/Source/WTF/wtf/ThreadingPthreads.cpp:195 invocation = {m_ptr = 0xa5f98} #6 0x42a56418 in start_thread (arg=0xb48ff070) at pthread_create.c:314 pd = 0xb48ff070 unwind_buf = {cancel_jmp_buf = {{jmp_buf = {-1081256549, 1235737603, -1265635216, 0, -1108857128, 338, -1238645568, 0, 0, -1265636436, 1, 0 <repeats 53 times>}, mask_was_saved = 0}}, priv = {pad = {0x0, 0x0, 0x0, 0x0}, data = {prev = 0x0, cleanup = 0x0, canceltype = 0}}} not_first_call = <optimized out> pagesize_m1 = <optimized out> sp = <optimized out> freesize = <optimized out> __PRETTY_FUNCTION__ = "start_thread" #7 0x429597c0 in ?? () at ../sysdeps/unix/sysv/linux/arm/clone.S:89 from ./symbols/lib/libc.so.6 No locals. Backtrace stopped: previous frame identical to this frame (corrupt stack?) Our codes that have crashes are a little old. Do you mean that the latest JavaScriptCore does not have this kind of crash? Is this crash PARALLEL GC's issue? If PARALLEL GC is disabled, could the crash be avoided? Because I have poor knowledge about GC, could you give me some suggestions? Thanks very much!