Changeset 157413 in webkit
- Timestamp:
- Oct 14, 2013, 12:34:44 PM (12 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 1 added
- 14 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/CMakeLists.txt
r157159 r157413 182 182 heap/CopiedSpace.cpp 183 183 heap/CopyVisitor.cpp 184 heap/DeferGC.cpp 184 185 heap/GCThread.cpp 185 186 heap/GCThreadSharedData.cpp -
trunk/Source/JavaScriptCore/ChangeLog
r157411 r157413 1 2013-10-11 Mark Hahnenberg <[email protected]> 2 3 llint_slow_path_put_by_id can deadlock on a ConcurrentJITLock 4 https://bugs.webkit.org/show_bug.cgi?id=122667 5 6 Reviewed by Filip Pizlo. 7 8 The issue this patch is attempting to fix is that there are places in our codebase 9 where we acquire the ConcurrentJITLock for a particular CodeBlock, then we do some 10 operations that can initiate a garbage collection. Garbage collection then calls 11 some methods of CodeBlock that also take the ConcurrentJITLock (because they don't 12 always necessarily run during garbage collection). This causes a deadlock. 13 14 To fix this issue, this patch adds a new RAII-style object (DisallowGC) that stores 15 into a thread-local field that indicates that it is unsafe to perform any operation 16 that could trigger garbage collection on the current thread. In debug builds, 17 ConcurrentJITLocker contains one of these DisallowGC objects so that we can eagerly 18 detect deadlocks. 19 20 This patch also adds a new type of ConcurrentJITLocker, GCSafeConcurrentJITLocker, 21 which uses the DeferGC mechanism to prevent collections from occurring while the 22 lock is held. 23 24 * CMakeLists.txt: 25 * GNUmakefile.list.am: 26 * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj: 27 * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters: 28 * JavaScriptCore.xcodeproj/project.pbxproj: 29 * heap/DeferGC.cpp: Added. 30 * heap/DeferGC.h: 31 (JSC::DisallowGC::DisallowGC): 32 (JSC::DisallowGC::~DisallowGC): 33 (JSC::DisallowGC::isGCDisallowedOnCurrentThread): 34 (JSC::DisallowGC::initialize): 35 * jit/JITStubs.cpp: 36 (JSC::tryCachePutByID): 37 (JSC::tryCacheGetByID): 38 (JSC::DEFINE_STUB_FUNCTION): 39 * llint/LLIntSlowPaths.cpp: 40 (JSC::LLInt::LLINT_SLOW_PATH_DECL): 41 * runtime/ConcurrentJITLock.h: 42 (JSC::ConcurrentJITLockerBase::ConcurrentJITLockerBase): 43 (JSC::ConcurrentJITLockerBase::~ConcurrentJITLockerBase): 44 (JSC::ConcurrentJITLockerBase::unlockEarly): 45 (JSC::GCSafeConcurrentJITLocker::GCSafeConcurrentJITLocker): 46 (JSC::ConcurrentJITLocker::ConcurrentJITLocker): 47 * runtime/InitializeThreading.cpp: 48 (JSC::initializeThreadingOnce): 49 * runtime/JSCellInlines.h: 50 (JSC::allocateCell): 51 * runtime/Structure.cpp: 52 (JSC::Structure::materializePropertyMap): 53 (JSC::Structure::putSpecificValue): 54 (JSC::Structure::createPropertyMap): 55 * runtime/Structure.h: 56 1 57 2013-10-14 Filip Pizlo <[email protected]> 2 58 -
trunk/Source/JavaScriptCore/GNUmakefile.list.am
r156984 r157413 468 468 Source/JavaScriptCore/heap/ConservativeRoots.cpp \ 469 469 Source/JavaScriptCore/heap/ConservativeRoots.h \ 470 Source/JavaScriptCore/heap/DeferGC.cpp \ 470 471 Source/JavaScriptCore/heap/DeferGC.h \ 471 472 Source/JavaScriptCore/heap/GCAssertions.h \ -
trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj
r156805 r157413 337 337 <ClCompile Include="..\heap\CopiedSpace.cpp" /> 338 338 <ClCompile Include="..\heap\CopyVisitor.cpp" /> 339 <ClCompile Include="..\heap\DeferGC.cpp" /> 339 340 <ClCompile Include="..\heap\GCThread.cpp" /> 340 341 <ClCompile Include="..\heap\GCThreadSharedData.cpp" /> … … 705 706 <ClInclude Include="..\heap\CopyVisitorInlines.h" /> 706 707 <ClInclude Include="..\heap\CopyWorkList.h" /> 708 <ClInclude Include="..\heap\DeferGC.h" /> 707 709 <ClInclude Include="..\heap\GCAssertions.h" /> 708 710 <ClInclude Include="..\heap\GCThread.h" /> -
trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters
r156863 r157413 874 874 <Filter>heap</Filter> 875 875 </ClCompile> 876 <ClCompile Include="..\heap\DeferGC.cpp"> 877 <Filter>heap</Filter> 878 </ClCompile> 876 879 <ClCompile Include="..\bytecode\DeferredCompilationCallback.cpp"> 877 880 <Filter>bytecode</Filter> … … 1222 1225 </ClInclude> 1223 1226 <ClInclude Include="..\heap\CopyWorkList.h"> 1227 <Filter>heap</Filter> 1228 </ClInclude> 1229 <ClInclude Include="..\heap\DeferGC.h"> 1224 1230 <Filter>heap</Filter> 1225 1231 </ClInclude> -
trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
r157264 r157413 374 374 0FC81516140511B500CFA603 /* VTableSpectrum.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FC815121405118600CFA603 /* VTableSpectrum.cpp */; }; 375 375 0FCCAE4516D0CF7400D0C65B /* ParserError.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FCCAE4316D0CF6E00D0C65B /* ParserError.h */; settings = {ATTRIBUTES = (Private, ); }; }; 376 0FCEFAAB1804C13E00472CE4 /* FTLSaveRestore.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FCEFAA91804C13E00472CE4 /* FTLSaveRestore.cpp */; }; 377 0FCEFAAC1804C13E00472CE4 /* FTLSaveRestore.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FCEFAAA1804C13E00472CE4 /* FTLSaveRestore.h */; settings = {ATTRIBUTES = (Private, ); }; }; 376 378 0FCEFAB01805CA6D00472CE4 /* InitializeLLVM.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FCEFAAE1805CA6D00472CE4 /* InitializeLLVM.h */; settings = {ATTRIBUTES = (Private, ); }; }; 377 379 0FCEFAB11805CA6D00472CE4 /* InitializeLLVMMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0FCEFAAF1805CA6D00472CE4 /* InitializeLLVMMac.mm */; }; … … 390 392 0FCEFADA180620DA00472CE4 /* LLVMAPI.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FCEFAC81805E75500472CE4 /* LLVMAPI.h */; }; 391 393 0FCEFADC18064A1400472CE4 /* config_llvm.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FCEFADB18064A1400472CE4 /* config_llvm.h */; }; 392 0FCEFAAB1804C13E00472CE4 /* FTLSaveRestore.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FCEFAA91804C13E00472CE4 /* FTLSaveRestore.cpp */; };393 0FCEFAAC1804C13E00472CE4 /* FTLSaveRestore.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FCEFAAA1804C13E00472CE4 /* FTLSaveRestore.h */; settings = {ATTRIBUTES = (Private, ); }; };394 394 0FCEFADF180738C000472CE4 /* FTLLocation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FCEFADD180738C000472CE4 /* FTLLocation.cpp */; }; 395 395 0FCEFAE0180738C000472CE4 /* FTLLocation.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FCEFADE180738C000472CE4 /* FTLLocation.h */; settings = {ATTRIBUTES = (Private, ); }; }; … … 685 685 2A48D1911772365B00C65A5F /* APICallbackFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = C211B574176A224D000E2A23 /* APICallbackFunction.h */; }; 686 686 2A6F462617E959CE00C45C98 /* HeapOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = 2A6F462517E959CE00C45C98 /* HeapOperation.h */; settings = {ATTRIBUTES = (Private, ); }; }; 687 2A7A58EF1808A4C40020BDF7 /* DeferGC.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2A7A58EE1808A4C40020BDF7 /* DeferGC.cpp */; }; 687 688 2AD8932B17E3868F00668276 /* HeapIterationScope.h in Headers */ = {isa = PBXBuildFile; fileRef = 2AD8932917E3868F00668276 /* HeapIterationScope.h */; }; 688 689 371D842D17C98B6E00ECF994 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 371D842C17C98B6E00ECF994 /* libz.dylib */; }; … … 1628 1629 0FCB408515C0A3C30048932B /* SlotVisitorInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SlotVisitorInlines.h; sourceTree = "<group>"; }; 1629 1630 0FCCAE4316D0CF6E00D0C65B /* ParserError.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ParserError.h; sourceTree = "<group>"; }; 1631 0FCEFAA91804C13E00472CE4 /* FTLSaveRestore.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FTLSaveRestore.cpp; path = ftl/FTLSaveRestore.cpp; sourceTree = "<group>"; }; 1632 0FCEFAAA1804C13E00472CE4 /* FTLSaveRestore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FTLSaveRestore.h; path = ftl/FTLSaveRestore.h; sourceTree = "<group>"; }; 1630 1633 0FCEFAAE1805CA6D00472CE4 /* InitializeLLVM.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = InitializeLLVM.h; path = llvm/InitializeLLVM.h; sourceTree = "<group>"; }; 1631 1634 0FCEFAAF1805CA6D00472CE4 /* InitializeLLVMMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = InitializeLLVMMac.mm; path = llvm/InitializeLLVMMac.mm; sourceTree = "<group>"; }; … … 1643 1646 0FCEFAD61806174600472CE4 /* LLVMAnchor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LLVMAnchor.cpp; sourceTree = "<group>"; }; 1644 1647 0FCEFADB18064A1400472CE4 /* config_llvm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = config_llvm.h; sourceTree = "<group>"; }; 1645 0FCEFAA91804C13E00472CE4 /* FTLSaveRestore.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FTLSaveRestore.cpp; path = ftl/FTLSaveRestore.cpp; sourceTree = "<group>"; };1646 0FCEFAAA1804C13E00472CE4 /* FTLSaveRestore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FTLSaveRestore.h; path = ftl/FTLSaveRestore.h; sourceTree = "<group>"; };1647 1648 0FCEFADD180738C000472CE4 /* FTLLocation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FTLLocation.cpp; path = ftl/FTLLocation.cpp; sourceTree = "<group>"; }; 1648 1649 0FCEFADE180738C000472CE4 /* FTLLocation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FTLLocation.h; path = ftl/FTLLocation.h; sourceTree = "<group>"; }; … … 1892 1893 2600B5A5152BAAA70091EE5F /* JSStringJoiner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSStringJoiner.h; sourceTree = "<group>"; }; 1893 1894 2A6F462517E959CE00C45C98 /* HeapOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HeapOperation.h; sourceTree = "<group>"; }; 1895 2A7A58EE1808A4C40020BDF7 /* DeferGC.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DeferGC.cpp; sourceTree = "<group>"; }; 1894 1896 2AD8932917E3868F00668276 /* HeapIterationScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HeapIterationScope.h; sourceTree = "<group>"; }; 1895 1897 371D842C17C98B6E00ECF994 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; }; … … 2917 2919 C218D13F1655CFD50062BB81 /* CopyWorkList.h */, 2918 2920 0F136D4B174AD69B0075B354 /* DeferGC.h */, 2921 2A7A58EE1808A4C40020BDF7 /* DeferGC.cpp */, 2919 2922 BCBE2CAD14E985AA000593AD /* GCAssertions.h */, 2920 2923 0F2B66A817B6B53D00A7AE3F /* GCIncomingRefCounted.h */, … … 5481 5484 A7386555118697B400540279 /* ThunkGenerators.cpp in Sources */, 5482 5485 0F2B670717B6B5AB00A7AE3F /* TypedArrayController.cpp in Sources */, 5486 2A7A58EF1808A4C40020BDF7 /* DeferGC.cpp in Sources */, 5483 5487 0F2B670A17B6B5AB00A7AE3F /* TypedArrayType.cpp in Sources */, 5484 5488 0FF4274A158EBE91004CB9FF /* udis86.c in Sources */, -
trunk/Source/JavaScriptCore/heap/DeferGC.h
r154127 r157413 29 29 #include "Heap.h" 30 30 #include <wtf/Noncopyable.h> 31 #include <wtf/ThreadSpecific.h> 31 32 32 33 namespace JSC { … … 68 69 }; 69 70 71 #ifndef NDEBUG 72 class DisallowGC { 73 WTF_MAKE_NONCOPYABLE(DisallowGC); 74 public: 75 DisallowGC() 76 { 77 WTF::threadSpecificSet(s_isGCDisallowedOnCurrentThread, reinterpret_cast<void*>(true)); 78 } 79 80 ~DisallowGC() 81 { 82 WTF::threadSpecificSet(s_isGCDisallowedOnCurrentThread, reinterpret_cast<void*>(false)); 83 } 84 85 static bool isGCDisallowedOnCurrentThread() 86 { 87 return !!WTF::threadSpecificGet(s_isGCDisallowedOnCurrentThread); 88 } 89 static void initialize() 90 { 91 WTF::threadSpecificKeyCreate(&s_isGCDisallowedOnCurrentThread, 0); 92 } 93 94 private: 95 JS_EXPORT_PRIVATE static WTF::ThreadSpecificKey s_isGCDisallowedOnCurrentThread; 96 }; 97 #endif // NDEBUG 98 70 99 } // namespace JSC 71 100 -
trunk/Source/JavaScriptCore/jit/JITStubs.cpp
r157411 r157413 126 126 NEVER_INLINE static void tryCacheGetByID(CallFrame* callFrame, CodeBlock* codeBlock, ReturnAddressPtr returnAddress, JSValue baseValue, const Identifier& propertyName, const PropertySlot& slot, StructureStubInfo* stubInfo) 127 127 { 128 ConcurrentJITLocker locker(codeBlock->m_lock);128 GCSafeConcurrentJITLocker locker(codeBlock->m_lock, callFrame->vm().heap); 129 129 130 130 // FIXME: Write a test that proves we need to check for recursion here just … … 556 556 } 557 557 558 ConcurrentJITLocker locker(codeBlock->m_lock);558 GCSafeConcurrentJITLocker locker(codeBlock->m_lock, callFrame->vm().heap); 559 559 560 560 Structure* structure = baseValue.asCell()->structure(); -
trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp
r156818 r157413 597 597 598 598 if (slot.type() == PutPropertySlot::NewProperty) { 599 ConcurrentJITLocker locker(codeBlock->m_lock);599 GCSafeConcurrentJITLocker locker(codeBlock->m_lock, vm.heap); 600 600 601 601 if (!structure->isDictionary() && structure->previousID()->outOfLineCapacity() == structure->outOfLineCapacity()) { -
trunk/Source/JavaScriptCore/runtime/ConcurrentJITLock.h
r153169 r157413 27 27 #define ConcurrentJITLock_h 28 28 29 #include "DeferGC.h" 29 30 #include <wtf/ByteSpinLock.h> 30 31 #include <wtf/NoLock.h> … … 34 35 #if ENABLE(CONCURRENT_JIT) 35 36 typedef ByteSpinLock ConcurrentJITLock; 36 typedef ByteSpinLocker ConcurrentJITLocker ;37 typedef ByteSpinLocker ConcurrentJITLockerImpl; 37 38 #else 38 39 typedef NoLock ConcurrentJITLock; 39 typedef NoLockLocker ConcurrentJITLocker ;40 typedef NoLockLocker ConcurrentJITLockerImpl; 40 41 #endif 42 43 class ConcurrentJITLockerBase { 44 WTF_MAKE_NONCOPYABLE(ConcurrentJITLockerBase); 45 public: 46 explicit ConcurrentJITLockerBase(ConcurrentJITLock& lockable) 47 : m_locker(&lockable) 48 { 49 } 50 explicit ConcurrentJITLockerBase(ConcurrentJITLock* lockable) 51 : m_locker(lockable) 52 { 53 } 54 55 ~ConcurrentJITLockerBase() 56 { 57 } 58 59 void unlockEarly() 60 { 61 m_locker.unlockEarly(); 62 } 63 64 private: 65 ConcurrentJITLockerImpl m_locker; 66 }; 67 68 class GCSafeConcurrentJITLocker : public ConcurrentJITLockerBase { 69 public: 70 GCSafeConcurrentJITLocker(ConcurrentJITLock& lockable, Heap& heap) 71 : ConcurrentJITLockerBase(lockable) 72 , m_deferGC(heap) 73 { 74 } 75 76 GCSafeConcurrentJITLocker(ConcurrentJITLock* lockable, Heap& heap) 77 : ConcurrentJITLockerBase(lockable) 78 , m_deferGC(heap) 79 { 80 } 81 82 private: 83 #if ENABLE(CONCURRENT_JIT) 84 DeferGC m_deferGC; 85 #else 86 struct NoDefer { 87 NoDefer(Heap& heap) : m_heap(heap) { } 88 Heap& m_heap; 89 }; 90 NoDefer m_deferGC; 91 #endif 92 }; 93 94 class ConcurrentJITLocker : public ConcurrentJITLockerBase { 95 public: 96 ConcurrentJITLocker(ConcurrentJITLock& lockable) 97 : ConcurrentJITLockerBase(lockable) 98 { 99 } 100 101 ConcurrentJITLocker(ConcurrentJITLock* lockable) 102 : ConcurrentJITLockerBase(lockable) 103 { 104 } 105 106 #if ENABLE(CONCURRENT_JIT) && !defined(NDEBUG) 107 private: 108 DisallowGC m_disallowGC; 109 #endif 110 }; 41 111 42 112 } // namespace JSC 43 113 44 114 #endif // ConcurrentJITLock_h 45 -
trunk/Source/JavaScriptCore/runtime/InitializeThreading.cpp
r157260 r157413 70 70 LLInt::initialize(); 71 71 #endif 72 #ifndef NDEBUG 73 DisallowGC::initialize(); 74 #endif 72 75 } 73 76 -
trunk/Source/JavaScriptCore/runtime/JSCellInlines.h
r154038 r157413 28 28 29 29 #include "CallFrame.h" 30 #include "DeferGC.h" 30 31 #include "Handle.h" 31 32 #include "JSCell.h" … … 86 87 void* allocateCell(Heap& heap, size_t size) 87 88 { 89 ASSERT(!DisallowGC::isGCDisallowedOnCurrentThread()); 88 90 ASSERT(size >= sizeof(T)); 89 91 #if ENABLE(GC_VALIDATION) -
trunk/Source/JavaScriptCore/runtime/Structure.cpp
r154426 r157413 281 281 // property map. We don't want getConcurrently() to see the property map in a half-baked 282 282 // state. 283 ConcurrentJITLocker locker(m_lock);283 GCSafeConcurrentJITLocker locker(m_lock, vm.heap); 284 284 if (!table) 285 285 createPropertyMap(locker, vm, numberOfSlotsForLastOffset(m_offset, m_inlineCapacity)); … … 882 882 PropertyOffset Structure::putSpecificValue(VM& vm, PropertyName propertyName, unsigned attributes, JSCell* specificValue) 883 883 { 884 ConcurrentJITLocker locker(m_lock);884 GCSafeConcurrentJITLocker locker(m_lock, vm.heap); 885 885 886 886 ASSERT(!JSC::isValidOffset(get(vm, propertyName))); … … 927 927 } 928 928 929 void Structure::createPropertyMap(const ConcurrentJITLocker&, VM& vm, unsigned capacity)929 void Structure::createPropertyMap(const GCSafeConcurrentJITLocker&, VM& vm, unsigned capacity) 930 930 { 931 931 ASSERT(!propertyTable()); -
trunk/Source/JavaScriptCore/runtime/Structure.h
r154199 r157413 394 394 PropertyOffset remove(PropertyName); 395 395 396 void createPropertyMap(const ConcurrentJITLocker&, VM&, unsigned keyCount = 0);396 void createPropertyMap(const GCSafeConcurrentJITLocker&, VM&, unsigned keyCount = 0); 397 397 void checkConsistency(); 398 398
Note:
See TracChangeset
for help on using the changeset viewer.