Title: [157413] trunk/Source/_javascript_Core
Revision
157413
Author
[email protected]
Date
2013-10-14 12:34:44 -0700 (Mon, 14 Oct 2013)

Log Message

llint_slow_path_put_by_id can deadlock on a ConcurrentJITLock
https://bugs.webkit.org/show_bug.cgi?id=122667

Reviewed by Filip Pizlo.

The issue this patch is attempting to fix is that there are places in our codebase
where we acquire the ConcurrentJITLock for a particular CodeBlock, then we do some
operations that can initiate a garbage collection. Garbage collection then calls 
some methods of CodeBlock that also take the ConcurrentJITLock (because they don't
always necessarily run during garbage collection). This causes a deadlock.

To fix this issue, this patch adds a new RAII-style object (DisallowGC) that stores 
into a thread-local field that indicates that it is unsafe to perform any operation 
that could trigger garbage collection on the current thread. In debug builds, 
ConcurrentJITLocker contains one of these DisallowGC objects so that we can eagerly 
detect deadlocks.

This patch also adds a new type of ConcurrentJITLocker, GCSafeConcurrentJITLocker,
which uses the DeferGC mechanism to prevent collections from occurring while the 
lock is held.

* CMakeLists.txt:
* GNUmakefile.list.am:
* _javascript_Core.vcxproj/_javascript_Core.vcxproj:
* _javascript_Core.vcxproj/_javascript_Core.vcxproj.filters:
* _javascript_Core.xcodeproj/project.pbxproj:
* heap/DeferGC.cpp: Added.
* heap/DeferGC.h:
(JSC::DisallowGC::DisallowGC):
(JSC::DisallowGC::~DisallowGC):
(JSC::DisallowGC::isGCDisallowedOnCurrentThread):
(JSC::DisallowGC::initialize):
* jit/JITStubs.cpp:
(JSC::tryCachePutByID):
(JSC::tryCacheGetByID):
(JSC::DEFINE_STUB_FUNCTION):
* llint/LLIntSlowPaths.cpp:
(JSC::LLInt::LLINT_SLOW_PATH_DECL):
* runtime/ConcurrentJITLock.h:
(JSC::ConcurrentJITLockerBase::ConcurrentJITLockerBase):
(JSC::ConcurrentJITLockerBase::~ConcurrentJITLockerBase):
(JSC::ConcurrentJITLockerBase::unlockEarly):
(JSC::GCSafeConcurrentJITLocker::GCSafeConcurrentJITLocker):
(JSC::ConcurrentJITLocker::ConcurrentJITLocker):
* runtime/InitializeThreading.cpp:
(JSC::initializeThreadingOnce):
* runtime/JSCellInlines.h:
(JSC::allocateCell):
* runtime/Structure.cpp:
(JSC::Structure::materializePropertyMap):
(JSC::Structure::putSpecificValue):
(JSC::Structure::createPropertyMap):
* runtime/Structure.h:

Modified Paths

Added Paths

Diff

Modified: trunk/Source/_javascript_Core/CMakeLists.txt (157412 => 157413)


--- trunk/Source/_javascript_Core/CMakeLists.txt	2013-10-14 19:24:09 UTC (rev 157412)
+++ trunk/Source/_javascript_Core/CMakeLists.txt	2013-10-14 19:34:44 UTC (rev 157413)
@@ -181,6 +181,7 @@
     heap/ConservativeRoots.cpp
     heap/CopiedSpace.cpp
     heap/CopyVisitor.cpp
+    heap/DeferGC.cpp
     heap/GCThread.cpp
     heap/GCThreadSharedData.cpp
     heap/HandleSet.cpp

Modified: trunk/Source/_javascript_Core/ChangeLog (157412 => 157413)


--- trunk/Source/_javascript_Core/ChangeLog	2013-10-14 19:24:09 UTC (rev 157412)
+++ trunk/Source/_javascript_Core/ChangeLog	2013-10-14 19:34:44 UTC (rev 157413)
@@ -1,3 +1,59 @@
+2013-10-11  Mark Hahnenberg  <[email protected]>
+
+        llint_slow_path_put_by_id can deadlock on a ConcurrentJITLock
+        https://bugs.webkit.org/show_bug.cgi?id=122667
+
+        Reviewed by Filip Pizlo.
+
+        The issue this patch is attempting to fix is that there are places in our codebase
+        where we acquire the ConcurrentJITLock for a particular CodeBlock, then we do some
+        operations that can initiate a garbage collection. Garbage collection then calls 
+        some methods of CodeBlock that also take the ConcurrentJITLock (because they don't
+        always necessarily run during garbage collection). This causes a deadlock.
+
+        To fix this issue, this patch adds a new RAII-style object (DisallowGC) that stores 
+        into a thread-local field that indicates that it is unsafe to perform any operation 
+        that could trigger garbage collection on the current thread. In debug builds, 
+        ConcurrentJITLocker contains one of these DisallowGC objects so that we can eagerly 
+        detect deadlocks.
+
+        This patch also adds a new type of ConcurrentJITLocker, GCSafeConcurrentJITLocker,
+        which uses the DeferGC mechanism to prevent collections from occurring while the 
+        lock is held.
+
+        * CMakeLists.txt:
+        * GNUmakefile.list.am:
+        * _javascript_Core.vcxproj/_javascript_Core.vcxproj:
+        * _javascript_Core.vcxproj/_javascript_Core.vcxproj.filters:
+        * _javascript_Core.xcodeproj/project.pbxproj:
+        * heap/DeferGC.cpp: Added.
+        * heap/DeferGC.h:
+        (JSC::DisallowGC::DisallowGC):
+        (JSC::DisallowGC::~DisallowGC):
+        (JSC::DisallowGC::isGCDisallowedOnCurrentThread):
+        (JSC::DisallowGC::initialize):
+        * jit/JITStubs.cpp:
+        (JSC::tryCachePutByID):
+        (JSC::tryCacheGetByID):
+        (JSC::DEFINE_STUB_FUNCTION):
+        * llint/LLIntSlowPaths.cpp:
+        (JSC::LLInt::LLINT_SLOW_PATH_DECL):
+        * runtime/ConcurrentJITLock.h:
+        (JSC::ConcurrentJITLockerBase::ConcurrentJITLockerBase):
+        (JSC::ConcurrentJITLockerBase::~ConcurrentJITLockerBase):
+        (JSC::ConcurrentJITLockerBase::unlockEarly):
+        (JSC::GCSafeConcurrentJITLocker::GCSafeConcurrentJITLocker):
+        (JSC::ConcurrentJITLocker::ConcurrentJITLocker):
+        * runtime/InitializeThreading.cpp:
+        (JSC::initializeThreadingOnce):
+        * runtime/JSCellInlines.h:
+        (JSC::allocateCell):
+        * runtime/Structure.cpp:
+        (JSC::Structure::materializePropertyMap):
+        (JSC::Structure::putSpecificValue):
+        (JSC::Structure::createPropertyMap):
+        * runtime/Structure.h:
+
 2013-10-14  Filip Pizlo  <[email protected]>
 
         Baseline JIT should use the DFG's PutById IC

Modified: trunk/Source/_javascript_Core/GNUmakefile.list.am (157412 => 157413)


--- trunk/Source/_javascript_Core/GNUmakefile.list.am	2013-10-14 19:24:09 UTC (rev 157412)
+++ trunk/Source/_javascript_Core/GNUmakefile.list.am	2013-10-14 19:34:44 UTC (rev 157413)
@@ -467,6 +467,7 @@
 	Source/_javascript_Core/heap/CopyWorkList.h \
 	Source/_javascript_Core/heap/ConservativeRoots.cpp \
 	Source/_javascript_Core/heap/ConservativeRoots.h \
+	Source/_javascript_Core/heap/DeferGC.cpp \
 	Source/_javascript_Core/heap/DeferGC.h \
 	Source/_javascript_Core/heap/GCAssertions.h \
 	Source/_javascript_Core/heap/GCIncomingRefCounted.h \

Modified: trunk/Source/_javascript_Core/_javascript_Core.vcxproj/_javascript_Core.vcxproj (157412 => 157413)


--- trunk/Source/_javascript_Core/_javascript_Core.vcxproj/_javascript_Core.vcxproj	2013-10-14 19:24:09 UTC (rev 157412)
+++ trunk/Source/_javascript_Core/_javascript_Core.vcxproj/_javascript_Core.vcxproj	2013-10-14 19:34:44 UTC (rev 157413)
@@ -336,6 +336,7 @@
     <ClCompile Include="..\heap\ConservativeRoots.cpp" />
     <ClCompile Include="..\heap\CopiedSpace.cpp" />
     <ClCompile Include="..\heap\CopyVisitor.cpp" />
+    <ClCompile Include="..\heap\DeferGC.cpp" />
     <ClCompile Include="..\heap\GCThread.cpp" />
     <ClCompile Include="..\heap\GCThreadSharedData.cpp" />
     <ClCompile Include="..\heap\HandleSet.cpp" />
@@ -704,6 +705,7 @@
     <ClInclude Include="..\heap\CopyVisitor.h" />
     <ClInclude Include="..\heap\CopyVisitorInlines.h" />
     <ClInclude Include="..\heap\CopyWorkList.h" />
+    <ClInclude Include="..\heap\DeferGC.h" />
     <ClInclude Include="..\heap\GCAssertions.h" />
     <ClInclude Include="..\heap\GCThread.h" />
     <ClInclude Include="..\heap\GCThreadSharedData.h" />

Modified: trunk/Source/_javascript_Core/_javascript_Core.vcxproj/_javascript_Core.vcxproj.filters (157412 => 157413)


--- trunk/Source/_javascript_Core/_javascript_Core.vcxproj/_javascript_Core.vcxproj.filters	2013-10-14 19:24:09 UTC (rev 157412)
+++ trunk/Source/_javascript_Core/_javascript_Core.vcxproj/_javascript_Core.vcxproj.filters	2013-10-14 19:34:44 UTC (rev 157413)
@@ -873,6 +873,9 @@
     <ClCompile Include="..\heap\CodeBlockSet.cpp">
       <Filter>heap</Filter>
     </ClCompile>
+    <ClCompile Include="..\heap\DeferGC.cpp">
+      <Filter>heap</Filter>
+    </ClCompile>
     <ClCompile Include="..\bytecode\DeferredCompilationCallback.cpp">
       <Filter>bytecode</Filter>
     </ClCompile>
@@ -1223,6 +1226,9 @@
     <ClInclude Include="..\heap\CopyWorkList.h">
       <Filter>heap</Filter>
     </ClInclude>
+    <ClInclude Include="..\heap\DeferGC.h">
+      <Filter>heap</Filter>
+    </ClInclude>
     <ClInclude Include="..\heap\GCAssertions.h">
       <Filter>heap</Filter>
     </ClInclude>
@@ -2381,4 +2387,4 @@
       <Filter>jit</Filter>
     </MASM>
   </ItemGroup>
-</Project>
\ No newline at end of file
+</Project>

Modified: trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (157412 => 157413)


--- trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2013-10-14 19:24:09 UTC (rev 157412)
+++ trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2013-10-14 19:34:44 UTC (rev 157413)
@@ -373,6 +373,8 @@
 		0FC815151405119B00CFA603 /* VTableSpectrum.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FC815141405118D00CFA603 /* VTableSpectrum.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		0FC81516140511B500CFA603 /* VTableSpectrum.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FC815121405118600CFA603 /* VTableSpectrum.cpp */; };
 		0FCCAE4516D0CF7400D0C65B /* ParserError.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FCCAE4316D0CF6E00D0C65B /* ParserError.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		0FCEFAAB1804C13E00472CE4 /* FTLSaveRestore.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FCEFAA91804C13E00472CE4 /* FTLSaveRestore.cpp */; };
+		0FCEFAAC1804C13E00472CE4 /* FTLSaveRestore.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FCEFAAA1804C13E00472CE4 /* FTLSaveRestore.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		0FCEFAB01805CA6D00472CE4 /* InitializeLLVM.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FCEFAAE1805CA6D00472CE4 /* InitializeLLVM.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		0FCEFAB11805CA6D00472CE4 /* InitializeLLVMMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0FCEFAAF1805CA6D00472CE4 /* InitializeLLVMMac.mm */; };
 		0FCEFAC11805D94E00472CE4 /* LLVMOverrides.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FCEFAC01805D94100472CE4 /* LLVMOverrides.cpp */; };
@@ -389,8 +391,6 @@
 		0FCEFAD71806174600472CE4 /* LLVMAnchor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FCEFAD61806174600472CE4 /* LLVMAnchor.cpp */; };
 		0FCEFADA180620DA00472CE4 /* LLVMAPI.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FCEFAC81805E75500472CE4 /* LLVMAPI.h */; };
 		0FCEFADC18064A1400472CE4 /* config_llvm.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FCEFADB18064A1400472CE4 /* config_llvm.h */; };
-		0FCEFAAB1804C13E00472CE4 /* FTLSaveRestore.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FCEFAA91804C13E00472CE4 /* FTLSaveRestore.cpp */; };
-		0FCEFAAC1804C13E00472CE4 /* FTLSaveRestore.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FCEFAAA1804C13E00472CE4 /* FTLSaveRestore.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		0FCEFADF180738C000472CE4 /* FTLLocation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FCEFADD180738C000472CE4 /* FTLLocation.cpp */; };
 		0FCEFAE0180738C000472CE4 /* FTLLocation.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FCEFADE180738C000472CE4 /* FTLLocation.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		0FD2C92416D01EE900C7803F /* StructureInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD2C92316D01EE900C7803F /* StructureInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -684,6 +684,7 @@
 		2600B5A7152BAAA70091EE5F /* JSStringJoiner.h in Headers */ = {isa = PBXBuildFile; fileRef = 2600B5A5152BAAA70091EE5F /* JSStringJoiner.h */; };
 		2A48D1911772365B00C65A5F /* APICallbackFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = C211B574176A224D000E2A23 /* APICallbackFunction.h */; };
 		2A6F462617E959CE00C45C98 /* HeapOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = 2A6F462517E959CE00C45C98 /* HeapOperation.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		2A7A58EF1808A4C40020BDF7 /* DeferGC.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2A7A58EE1808A4C40020BDF7 /* DeferGC.cpp */; };
 		2AD8932B17E3868F00668276 /* HeapIterationScope.h in Headers */ = {isa = PBXBuildFile; fileRef = 2AD8932917E3868F00668276 /* HeapIterationScope.h */; };
 		371D842D17C98B6E00ECF994 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 371D842C17C98B6E00ECF994 /* libz.dylib */; };
 		41359CF30FDD89AD00206180 /* DateConversion.h in Headers */ = {isa = PBXBuildFile; fileRef = D21202290AD4310C00ED79B6 /* DateConversion.h */; };
@@ -1627,6 +1628,8 @@
 		0FC815141405118D00CFA603 /* VTableSpectrum.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VTableSpectrum.h; sourceTree = "<group>"; };
 		0FCB408515C0A3C30048932B /* SlotVisitorInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SlotVisitorInlines.h; sourceTree = "<group>"; };
 		0FCCAE4316D0CF6E00D0C65B /* ParserError.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ParserError.h; sourceTree = "<group>"; };
+		0FCEFAA91804C13E00472CE4 /* FTLSaveRestore.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FTLSaveRestore.cpp; path = ftl/FTLSaveRestore.cpp; sourceTree = "<group>"; };
+		0FCEFAAA1804C13E00472CE4 /* FTLSaveRestore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FTLSaveRestore.h; path = ftl/FTLSaveRestore.h; sourceTree = "<group>"; };
 		0FCEFAAE1805CA6D00472CE4 /* InitializeLLVM.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = InitializeLLVM.h; path = llvm/InitializeLLVM.h; sourceTree = "<group>"; };
 		0FCEFAAF1805CA6D00472CE4 /* InitializeLLVMMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = InitializeLLVMMac.mm; path = llvm/InitializeLLVMMac.mm; sourceTree = "<group>"; };
 		0FCEFAB61805D61600472CE4 /* libllvmForJSC.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libllvmForJSC.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -1642,8 +1645,6 @@
 		0FCEFAD21805EDCC00472CE4 /* LLVMHeaders.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LLVMHeaders.h; path = llvm/LLVMHeaders.h; sourceTree = "<group>"; };
 		0FCEFAD61806174600472CE4 /* LLVMAnchor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LLVMAnchor.cpp; sourceTree = "<group>"; };
 		0FCEFADB18064A1400472CE4 /* config_llvm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = config_llvm.h; sourceTree = "<group>"; };
-		0FCEFAA91804C13E00472CE4 /* FTLSaveRestore.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FTLSaveRestore.cpp; path = ftl/FTLSaveRestore.cpp; sourceTree = "<group>"; };
-		0FCEFAAA1804C13E00472CE4 /* FTLSaveRestore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FTLSaveRestore.h; path = ftl/FTLSaveRestore.h; sourceTree = "<group>"; };
 		0FCEFADD180738C000472CE4 /* FTLLocation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FTLLocation.cpp; path = ftl/FTLLocation.cpp; sourceTree = "<group>"; };
 		0FCEFADE180738C000472CE4 /* FTLLocation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FTLLocation.h; path = ftl/FTLLocation.h; sourceTree = "<group>"; };
 		0FD2C92316D01EE900C7803F /* StructureInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StructureInlines.h; sourceTree = "<group>"; };
@@ -1891,6 +1892,7 @@
 		2600B5A4152BAAA70091EE5F /* JSStringJoiner.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSStringJoiner.cpp; sourceTree = "<group>"; };
 		2600B5A5152BAAA70091EE5F /* JSStringJoiner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSStringJoiner.h; sourceTree = "<group>"; };
 		2A6F462517E959CE00C45C98 /* HeapOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HeapOperation.h; sourceTree = "<group>"; };
+		2A7A58EE1808A4C40020BDF7 /* DeferGC.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DeferGC.cpp; sourceTree = "<group>"; };
 		2AD8932917E3868F00668276 /* HeapIterationScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HeapIterationScope.h; sourceTree = "<group>"; };
 		371D842C17C98B6E00ECF994 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; };
 		449097EE0F8F81B50076A327 /* FeatureDefines.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = FeatureDefines.xcconfig; sourceTree = "<group>"; };
@@ -2916,6 +2918,7 @@
 				C2239D1416262BDD005AC5FD /* CopyVisitorInlines.h */,
 				C218D13F1655CFD50062BB81 /* CopyWorkList.h */,
 				0F136D4B174AD69B0075B354 /* DeferGC.h */,
+				2A7A58EE1808A4C40020BDF7 /* DeferGC.cpp */,
 				BCBE2CAD14E985AA000593AD /* GCAssertions.h */,
 				0F2B66A817B6B53D00A7AE3F /* GCIncomingRefCounted.h */,
 				0F2B66A917B6B53D00A7AE3F /* GCIncomingRefCountedInlines.h */,
@@ -5480,6 +5483,7 @@
 				0FD8A32517D51F5700CA2C40 /* DFGOSREntrypointCreationPhase.cpp in Sources */,
 				A7386555118697B400540279 /* ThunkGenerators.cpp in Sources */,
 				0F2B670717B6B5AB00A7AE3F /* TypedArrayController.cpp in Sources */,
+				2A7A58EF1808A4C40020BDF7 /* DeferGC.cpp in Sources */,
 				0F2B670A17B6B5AB00A7AE3F /* TypedArrayType.cpp in Sources */,
 				0FF4274A158EBE91004CB9FF /* udis86.c in Sources */,
 				0FF42740158EBE8B004CB9FF /* udis86_decode.c in Sources */,

Added: trunk/Source/_javascript_Core/heap/DeferGC.cpp (0 => 157413)


--- trunk/Source/_javascript_Core/heap/DeferGC.cpp	                        (rev 0)
+++ trunk/Source/_javascript_Core/heap/DeferGC.cpp	2013-10-14 19:34:44 UTC (rev 157413)
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2013 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "DeferGC.h"
+
+namespace JSC {
+
+#ifndef NDEBUG
+WTF::ThreadSpecificKey DisallowGC::s_isGCDisallowedOnCurrentThread = 0;
+#endif
+
+} // namespace JSC

Modified: trunk/Source/_javascript_Core/heap/DeferGC.h (157412 => 157413)


--- trunk/Source/_javascript_Core/heap/DeferGC.h	2013-10-14 19:24:09 UTC (rev 157412)
+++ trunk/Source/_javascript_Core/heap/DeferGC.h	2013-10-14 19:34:44 UTC (rev 157413)
@@ -28,6 +28,7 @@
 
 #include "Heap.h"
 #include <wtf/Noncopyable.h>
+#include <wtf/ThreadSpecific.h>
 
 namespace JSC {
 
@@ -67,6 +68,34 @@
     Heap& m_heap;
 };
 
+#ifndef NDEBUG
+class DisallowGC {
+    WTF_MAKE_NONCOPYABLE(DisallowGC);
+public:
+    DisallowGC()
+    {
+        WTF::threadSpecificSet(s_isGCDisallowedOnCurrentThread, reinterpret_cast<void*>(true));
+    }
+
+    ~DisallowGC()
+    {
+        WTF::threadSpecificSet(s_isGCDisallowedOnCurrentThread, reinterpret_cast<void*>(false));
+    }
+
+    static bool isGCDisallowedOnCurrentThread()
+    {
+        return !!WTF::threadSpecificGet(s_isGCDisallowedOnCurrentThread);
+    }
+    static void initialize()
+    {
+        WTF::threadSpecificKeyCreate(&s_isGCDisallowedOnCurrentThread, 0);
+    }
+
+private:
+    JS_EXPORT_PRIVATE static WTF::ThreadSpecificKey s_isGCDisallowedOnCurrentThread;
+};
+#endif // NDEBUG
+
 } // namespace JSC
 
 #endif // DeferGC_h

Modified: trunk/Source/_javascript_Core/jit/JITStubs.cpp (157412 => 157413)


--- trunk/Source/_javascript_Core/jit/JITStubs.cpp	2013-10-14 19:24:09 UTC (rev 157412)
+++ trunk/Source/_javascript_Core/jit/JITStubs.cpp	2013-10-14 19:34:44 UTC (rev 157413)
@@ -125,7 +125,7 @@
 
 NEVER_INLINE static void tryCacheGetByID(CallFrame* callFrame, CodeBlock* codeBlock, ReturnAddressPtr returnAddress, JSValue baseValue, const Identifier& propertyName, const PropertySlot& slot, StructureStubInfo* stubInfo)
 {
-    ConcurrentJITLocker locker(codeBlock->m_lock);
+    GCSafeConcurrentJITLocker locker(codeBlock->m_lock, callFrame->vm().heap);
     
     // FIXME: Write a test that proves we need to check for recursion here just
     // like the interpreter does, then add a check for recursion.
@@ -555,7 +555,7 @@
         return JSValue::encode(result);
     }
 
-    ConcurrentJITLocker locker(codeBlock->m_lock);
+    GCSafeConcurrentJITLocker locker(codeBlock->m_lock, callFrame->vm().heap);
     
     Structure* structure = baseValue.asCell()->structure();
 

Modified: trunk/Source/_javascript_Core/llint/LLIntSlowPaths.cpp (157412 => 157413)


--- trunk/Source/_javascript_Core/llint/LLIntSlowPaths.cpp	2013-10-14 19:24:09 UTC (rev 157412)
+++ trunk/Source/_javascript_Core/llint/LLIntSlowPaths.cpp	2013-10-14 19:34:44 UTC (rev 157413)
@@ -596,7 +596,7 @@
             && baseCell == slot.base()) {
             
             if (slot.type() == PutPropertySlot::NewProperty) {
-                ConcurrentJITLocker locker(codeBlock->m_lock);
+                GCSafeConcurrentJITLocker locker(codeBlock->m_lock, vm.heap);
             
                 if (!structure->isDictionary() && structure->previousID()->outOfLineCapacity() == structure->outOfLineCapacity()) {
                     ASSERT(structure->previousID()->transitionWatchpointSetHasBeenInvalidated());

Modified: trunk/Source/_javascript_Core/runtime/ConcurrentJITLock.h (157412 => 157413)


--- trunk/Source/_javascript_Core/runtime/ConcurrentJITLock.h	2013-10-14 19:24:09 UTC (rev 157412)
+++ trunk/Source/_javascript_Core/runtime/ConcurrentJITLock.h	2013-10-14 19:34:44 UTC (rev 157413)
@@ -26,6 +26,7 @@
 #ifndef ConcurrentJITLock_h
 #define ConcurrentJITLock_h
 
+#include "DeferGC.h"
 #include <wtf/ByteSpinLock.h>
 #include <wtf/NoLock.h>
 
@@ -33,13 +34,81 @@
 
 #if ENABLE(CONCURRENT_JIT)
 typedef ByteSpinLock ConcurrentJITLock;
-typedef ByteSpinLocker ConcurrentJITLocker;
+typedef ByteSpinLocker ConcurrentJITLockerImpl;
 #else
 typedef NoLock ConcurrentJITLock;
-typedef NoLockLocker ConcurrentJITLocker;
+typedef NoLockLocker ConcurrentJITLockerImpl;
 #endif
 
+class ConcurrentJITLockerBase {
+    WTF_MAKE_NONCOPYABLE(ConcurrentJITLockerBase);
+public:
+    explicit ConcurrentJITLockerBase(ConcurrentJITLock& lockable)
+        : m_locker(&lockable)
+    {
+    }
+    explicit ConcurrentJITLockerBase(ConcurrentJITLock* lockable)
+        : m_locker(lockable)
+    {
+    }
+
+    ~ConcurrentJITLockerBase()
+    {
+    }
+    
+    void unlockEarly()
+    {
+        m_locker.unlockEarly();
+    }
+
+private:
+    ConcurrentJITLockerImpl m_locker;
+};
+
+class GCSafeConcurrentJITLocker : public ConcurrentJITLockerBase {
+public:
+    GCSafeConcurrentJITLocker(ConcurrentJITLock& lockable, Heap& heap)
+        : ConcurrentJITLockerBase(lockable)
+        , m_deferGC(heap)
+    {
+    }
+
+    GCSafeConcurrentJITLocker(ConcurrentJITLock* lockable, Heap& heap)
+        : ConcurrentJITLockerBase(lockable)
+        , m_deferGC(heap)
+    {
+    }
+
+private:
+#if ENABLE(CONCURRENT_JIT)
+    DeferGC m_deferGC;
+#else
+    struct NoDefer {
+        NoDefer(Heap& heap) : m_heap(heap) { }
+        Heap& m_heap;
+    };
+    NoDefer m_deferGC;
+#endif
+};
+
+class ConcurrentJITLocker : public ConcurrentJITLockerBase {
+public:
+    ConcurrentJITLocker(ConcurrentJITLock& lockable)
+        : ConcurrentJITLockerBase(lockable)
+    {
+    }
+
+    ConcurrentJITLocker(ConcurrentJITLock* lockable)
+        : ConcurrentJITLockerBase(lockable)
+    {
+    }
+
+#if ENABLE(CONCURRENT_JIT) && !defined(NDEBUG)
+private:
+    DisallowGC m_disallowGC;
+#endif
+};
+
 } // namespace JSC
 
 #endif // ConcurrentJITLock_h
-

Modified: trunk/Source/_javascript_Core/runtime/InitializeThreading.cpp (157412 => 157413)


--- trunk/Source/_javascript_Core/runtime/InitializeThreading.cpp	2013-10-14 19:24:09 UTC (rev 157412)
+++ trunk/Source/_javascript_Core/runtime/InitializeThreading.cpp	2013-10-14 19:34:44 UTC (rev 157413)
@@ -69,6 +69,9 @@
 #if ENABLE(LLINT)
     LLInt::initialize();
 #endif
+#ifndef NDEBUG
+    DisallowGC::initialize();
+#endif
 }
 
 void initializeThreading()

Modified: trunk/Source/_javascript_Core/runtime/JSCellInlines.h (157412 => 157413)


--- trunk/Source/_javascript_Core/runtime/JSCellInlines.h	2013-10-14 19:24:09 UTC (rev 157412)
+++ trunk/Source/_javascript_Core/runtime/JSCellInlines.h	2013-10-14 19:34:44 UTC (rev 157413)
@@ -27,6 +27,7 @@
 #define JSCellInlines_h
 
 #include "CallFrame.h"
+#include "DeferGC.h"
 #include "Handle.h"
 #include "JSCell.h"
 #include "JSObject.h"
@@ -85,6 +86,7 @@
 template<typename T>
 void* allocateCell(Heap& heap, size_t size)
 {
+    ASSERT(!DisallowGC::isGCDisallowedOnCurrentThread());
     ASSERT(size >= sizeof(T));
 #if ENABLE(GC_VALIDATION)
     ASSERT(!heap.vm()->isInitializingObject());

Modified: trunk/Source/_javascript_Core/runtime/Structure.cpp (157412 => 157413)


--- trunk/Source/_javascript_Core/runtime/Structure.cpp	2013-10-14 19:24:09 UTC (rev 157412)
+++ trunk/Source/_javascript_Core/runtime/Structure.cpp	2013-10-14 19:34:44 UTC (rev 157413)
@@ -280,7 +280,7 @@
     // Must hold the lock on this structure, since we will be modifying this structure's
     // property map. We don't want getConcurrently() to see the property map in a half-baked
     // state.
-    ConcurrentJITLocker locker(m_lock);
+    GCSafeConcurrentJITLocker locker(m_lock, vm.heap);
     if (!table)
         createPropertyMap(locker, vm, numberOfSlotsForLastOffset(m_offset, m_inlineCapacity));
     else
@@ -881,7 +881,7 @@
 
 PropertyOffset Structure::putSpecificValue(VM& vm, PropertyName propertyName, unsigned attributes, JSCell* specificValue)
 {
-    ConcurrentJITLocker locker(m_lock);
+    GCSafeConcurrentJITLocker locker(m_lock, vm.heap);
     
     ASSERT(!JSC::isValidOffset(get(vm, propertyName)));
 
@@ -926,7 +926,7 @@
     return offset;
 }
 
-void Structure::createPropertyMap(const ConcurrentJITLocker&, VM& vm, unsigned capacity)
+void Structure::createPropertyMap(const GCSafeConcurrentJITLocker&, VM& vm, unsigned capacity)
 {
     ASSERT(!propertyTable());
 

Modified: trunk/Source/_javascript_Core/runtime/Structure.h (157412 => 157413)


--- trunk/Source/_javascript_Core/runtime/Structure.h	2013-10-14 19:24:09 UTC (rev 157412)
+++ trunk/Source/_javascript_Core/runtime/Structure.h	2013-10-14 19:34:44 UTC (rev 157413)
@@ -393,7 +393,7 @@
     PropertyOffset putSpecificValue(VM&, PropertyName, unsigned attributes, JSCell* specificValue);
     PropertyOffset remove(PropertyName);
 
-    void createPropertyMap(const ConcurrentJITLocker&, VM&, unsigned keyCount = 0);
+    void createPropertyMap(const GCSafeConcurrentJITLocker&, VM&, unsigned keyCount = 0);
     void checkConsistency();
 
     bool despecifyFunction(VM&, PropertyName);
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to