Title: [179728] trunk/Source/_javascript_Core
Revision
179728
Author
msab...@apple.com
Date
2015-02-05 17:12:00 -0800 (Thu, 05 Feb 2015)

Log Message

CodeCache is not thread safe when adding the same source from two different threads
https://bugs.webkit.org/show_bug.cgi?id=141275

Reviewed by Mark Lam.

The issue for this bug is that one thread, takes a cache miss in CodeCache::getGlobalCodeBlock,
but in the process creates a cache entry with a nullptr UnlinkedCodeBlockType* which it
will fill in later in the function.  During the body of that function, it allocates
objects that may garbage collect.  During that garbage collection, we drop the all locks.
While the locks are released by the first thread, another thread can enter the VM and might
have exactly the same source and enter CodeCache::getGlobalCodeBlock() itself.  When it
looks up the code block, it sees it as a cache it and uses the nullptr UnlinkedCodeBlockType*
and crashes.  This fixes the problem by not dropping the locks during garbage collection.
There are other likely scenarios where we have a data structure like this code cache in an
unsafe state for arbitrary reentrance.

Moved the functionality of DelayedReleaseScope directly into Heap.  Changed it into
a simple list that is cleared with the new function Heap::releaseDelayedReleasedObjects.
Now we accumulate objects to be released and release them when all locks are dropped or
when destroying the Heap.  This eliminated the dropping and reaquiring of locks associated
with the old scope form of this list.

Given that all functionality of DelayedReleaseScope is now used and referenced by Heap
and the lock management no longer needs to be done, just made the list a member of Heap.
We do need to guard against the case that releasing an object can create more objects
by calling into JS.  That is why releaseDelayedReleasedObjects() is written to remove
an object to release so that we aren't recursively in Vector code.  The other thing we
do in releaseDelayedReleasedObjects() is to guard against recursive calls to itself using
the m_delayedReleaseRecursionCount.  We only release at the first entry into the function.
This case is already tested by testapi.mm.

* heap/DelayedReleaseScope.h: Removed file

* API/JSAPIWrapperObject.mm:
* API/ObjCCallbackFunction.mm:
* _javascript_Core.vcxproj/_javascript_Core.vcxproj:
* _javascript_Core.vcxproj/_javascript_Core.vcxproj.filters:
* _javascript_Core.xcodeproj/project.pbxproj:
* heap/IncrementalSweeper.cpp:
(JSC::IncrementalSweeper::doSweep):
* heap/MarkedAllocator.cpp:
(JSC::MarkedAllocator::tryAllocateHelper):
(JSC::MarkedAllocator::tryAllocate):
* heap/MarkedBlock.cpp:
(JSC::MarkedBlock::sweep):
* heap/MarkedSpace.cpp:
(JSC::MarkedSpace::MarkedSpace):
(JSC::MarkedSpace::lastChanceToFinalize):
(JSC::MarkedSpace::didFinishIterating):
* heap/MarkedSpace.h:
* heap/Heap.cpp:
(JSC::Heap::collectAllGarbage):
(JSC::Heap::zombifyDeadObjects):
Removed references to DelayedReleaseScope and DelayedReleaseScope.h.

* heap/Heap.cpp:
(JSC::Heap::Heap): Initialized m_delayedReleaseRecursionCount.
(JSC::Heap::lastChanceToFinalize): Call releaseDelayedObjectsNow() as the VM is going away.
(JSC::Heap::releaseDelayedReleasedObjects): New function that released the accumulated
delayed release objects.

* heap/Heap.h:
(JSC::Heap::m_delayedReleaseObjects): List of objects to be released later.
(JSC::Heap::m_delayedReleaseRecursionCount): Counter to indicate that
releaseDelayedReleasedObjects is being called recursively.
* heap/HeapInlines.h:
(JSC::Heap::releaseSoon): Changed location of list to add delayed release objects.
        
* runtime/JSLock.cpp:
(JSC::JSLock::willReleaseLock):
Call Heap::releaseDelayedObjectsNow() when releasing the lock.

Modified Paths

Removed Paths

Diff

Modified: trunk/Source/_javascript_Core/API/JSAPIWrapperObject.mm (179727 => 179728)


--- trunk/Source/_javascript_Core/API/JSAPIWrapperObject.mm	2015-02-06 01:07:51 UTC (rev 179727)
+++ trunk/Source/_javascript_Core/API/JSAPIWrapperObject.mm	2015-02-06 01:12:00 UTC (rev 179728)
@@ -26,7 +26,6 @@
 #include "config.h"
 #include "JSAPIWrapperObject.h"
 
-#include "DelayedReleaseScope.h"
 #include "JSCInlines.h"
 #include "JSCallbackObject.h"
 #include "JSVirtualMachineInternal.h"

Modified: trunk/Source/_javascript_Core/API/ObjCCallbackFunction.mm (179727 => 179728)


--- trunk/Source/_javascript_Core/API/ObjCCallbackFunction.mm	2015-02-06 01:07:51 UTC (rev 179727)
+++ trunk/Source/_javascript_Core/API/ObjCCallbackFunction.mm	2015-02-06 01:12:00 UTC (rev 179728)
@@ -30,7 +30,6 @@
 
 #import "APICallbackFunction.h"
 #import "APICast.h"
-#import "DelayedReleaseScope.h"
 #import "Error.h"
 #import "JSCJSValueInlines.h"
 #import "JSCell.h"

Modified: trunk/Source/_javascript_Core/ChangeLog (179727 => 179728)


--- trunk/Source/_javascript_Core/ChangeLog	2015-02-06 01:07:51 UTC (rev 179727)
+++ trunk/Source/_javascript_Core/ChangeLog	2015-02-06 01:12:00 UTC (rev 179728)
@@ -1,3 +1,77 @@
+2015-02-05  Michael Saboff  <msab...@apple.com>
+
+        CodeCache is not thread safe when adding the same source from two different threads
+        https://bugs.webkit.org/show_bug.cgi?id=141275
+
+        Reviewed by Mark Lam.
+
+        The issue for this bug is that one thread, takes a cache miss in CodeCache::getGlobalCodeBlock,
+        but in the process creates a cache entry with a nullptr UnlinkedCodeBlockType* which it
+        will fill in later in the function.  During the body of that function, it allocates
+        objects that may garbage collect.  During that garbage collection, we drop the all locks.
+        While the locks are released by the first thread, another thread can enter the VM and might
+        have exactly the same source and enter CodeCache::getGlobalCodeBlock() itself.  When it
+        looks up the code block, it sees it as a cache it and uses the nullptr UnlinkedCodeBlockType*
+        and crashes.  This fixes the problem by not dropping the locks during garbage collection.
+        There are other likely scenarios where we have a data structure like this code cache in an
+        unsafe state for arbitrary reentrance.
+
+        Moved the functionality of DelayedReleaseScope directly into Heap.  Changed it into
+        a simple list that is cleared with the new function Heap::releaseDelayedReleasedObjects.
+        Now we accumulate objects to be released and release them when all locks are dropped or
+        when destroying the Heap.  This eliminated the dropping and reaquiring of locks associated
+        with the old scope form of this list.
+
+        Given that all functionality of DelayedReleaseScope is now used and referenced by Heap
+        and the lock management no longer needs to be done, just made the list a member of Heap.
+        We do need to guard against the case that releasing an object can create more objects
+        by calling into JS.  That is why releaseDelayedReleasedObjects() is written to remove
+        an object to release so that we aren't recursively in Vector code.  The other thing we
+        do in releaseDelayedReleasedObjects() is to guard against recursive calls to itself using
+        the m_delayedReleaseRecursionCount.  We only release at the first entry into the function.
+        This case is already tested by testapi.mm.
+
+        * heap/DelayedReleaseScope.h: Removed file
+
+        * API/JSAPIWrapperObject.mm:
+        * API/ObjCCallbackFunction.mm:
+        * _javascript_Core.vcxproj/_javascript_Core.vcxproj:
+        * _javascript_Core.vcxproj/_javascript_Core.vcxproj.filters:
+        * _javascript_Core.xcodeproj/project.pbxproj:
+        * heap/IncrementalSweeper.cpp:
+        (JSC::IncrementalSweeper::doSweep):
+        * heap/MarkedAllocator.cpp:
+        (JSC::MarkedAllocator::tryAllocateHelper):
+        (JSC::MarkedAllocator::tryAllocate):
+        * heap/MarkedBlock.cpp:
+        (JSC::MarkedBlock::sweep):
+        * heap/MarkedSpace.cpp:
+        (JSC::MarkedSpace::MarkedSpace):
+        (JSC::MarkedSpace::lastChanceToFinalize):
+        (JSC::MarkedSpace::didFinishIterating):
+        * heap/MarkedSpace.h:
+        * heap/Heap.cpp:
+        (JSC::Heap::collectAllGarbage):
+        (JSC::Heap::zombifyDeadObjects):
+        Removed references to DelayedReleaseScope and DelayedReleaseScope.h.
+
+        * heap/Heap.cpp:
+        (JSC::Heap::Heap): Initialized m_delayedReleaseRecursionCount.
+        (JSC::Heap::lastChanceToFinalize): Call releaseDelayedObjectsNow() as the VM is going away.
+        (JSC::Heap::releaseDelayedReleasedObjects): New function that released the accumulated
+        delayed release objects.
+
+        * heap/Heap.h:
+        (JSC::Heap::m_delayedReleaseObjects): List of objects to be released later.
+        (JSC::Heap::m_delayedReleaseRecursionCount): Counter to indicate that
+        releaseDelayedReleasedObjects is being called recursively.
+        * heap/HeapInlines.h:
+        (JSC::Heap::releaseSoon): Changed location of list to add delayed release objects.
+        
+        * runtime/JSLock.cpp:
+        (JSC::JSLock::willReleaseLock):
+        Call Heap::releaseDelayedObjectsNow() when releasing the lock.
+
 2015-02-05  Youenn Fablet  <youenn.fab...@crf.canon.fr> and Xabier Rodriguez Calvar <calva...@igalia.com>
 
         [Streams API] Implement a barebone ReadableStream interface

Modified: trunk/Source/_javascript_Core/_javascript_Core.vcxproj/_javascript_Core.vcxproj (179727 => 179728)


--- trunk/Source/_javascript_Core/_javascript_Core.vcxproj/_javascript_Core.vcxproj	2015-02-06 01:07:51 UTC (rev 179727)
+++ trunk/Source/_javascript_Core/_javascript_Core.vcxproj/_javascript_Core.vcxproj	2015-02-06 01:12:00 UTC (rev 179728)
@@ -1230,7 +1230,6 @@
     <ClInclude Include="..\heap\CopyWorkList.h" />
     <ClInclude Include="..\heap\CopyWriteBarrier.h" />
     <ClInclude Include="..\heap\DeferGC.h" />
-    <ClInclude Include="..\heap\DelayedReleaseScope.h" />
     <ClInclude Include="..\heap\EdenGCActivityCallback.h" />
     <ClInclude Include="..\heap\FullGCActivityCallback.h" />
     <ClInclude Include="..\heap\GCActivityCallback.h" />

Modified: trunk/Source/_javascript_Core/_javascript_Core.vcxproj/_javascript_Core.vcxproj.filters (179727 => 179728)


--- trunk/Source/_javascript_Core/_javascript_Core.vcxproj/_javascript_Core.vcxproj.filters	2015-02-06 01:07:51 UTC (rev 179727)
+++ trunk/Source/_javascript_Core/_javascript_Core.vcxproj/_javascript_Core.vcxproj.filters	2015-02-06 01:12:00 UTC (rev 179728)
@@ -3768,9 +3768,6 @@
     <ClInclude Include="..\runtime\StackAlignment.h">
       <Filter>runtime</Filter>
     </ClInclude>
-    <ClInclude Include="..\heap\DelayedReleaseScope.h">
-      <Filter>heap</Filter>
-    </ClInclude>
     <ClInclude Include="..\bytecode\VariableWatchpointSet.h">
       <Filter>bytecode</Filter>
     </ClInclude>

Modified: trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (179727 => 179728)


--- trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2015-02-06 01:07:51 UTC (rev 179727)
+++ trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2015-02-06 01:12:00 UTC (rev 179728)
@@ -864,7 +864,6 @@
 		2A05ABD61961DF2400341750 /* JSPropertyNameEnumerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 2A05ABD41961DF2400341750 /* JSPropertyNameEnumerator.h */; };
 		2A111245192FCE79005EE18D /* CustomGetterSetter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2A111243192FCE79005EE18D /* CustomGetterSetter.cpp */; };
 		2A111246192FCE79005EE18D /* CustomGetterSetter.h in Headers */ = {isa = PBXBuildFile; fileRef = 2A111244192FCE79005EE18D /* CustomGetterSetter.h */; settings = {ATTRIBUTES = (Private, ); }; };
-		2A2825D018341F2D0087FBA9 /* DelayedReleaseScope.h in Headers */ = {isa = PBXBuildFile; fileRef = 2A2825CF18341F2D0087FBA9 /* DelayedReleaseScope.h */; };
 		2A48D1911772365B00C65A5F /* APICallbackFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = C211B574176A224D000E2A23 /* APICallbackFunction.h */; };
 		2A4BB7F318A41179008A0FCD /* JSManagedValueInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 2A4BB7F218A41179008A0FCD /* JSManagedValueInternal.h */; };
 		2A4EC90B1860D6C20094F782 /* WriteBarrierBuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2A4EC9091860D6C20094F782 /* WriteBarrierBuffer.cpp */; };
@@ -2499,7 +2498,6 @@
 		2A05ABD41961DF2400341750 /* JSPropertyNameEnumerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSPropertyNameEnumerator.h; sourceTree = "<group>"; };
 		2A111243192FCE79005EE18D /* CustomGetterSetter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CustomGetterSetter.cpp; sourceTree = "<group>"; };
 		2A111244192FCE79005EE18D /* CustomGetterSetter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CustomGetterSetter.h; sourceTree = "<group>"; };
-		2A2825CF18341F2D0087FBA9 /* DelayedReleaseScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DelayedReleaseScope.h; sourceTree = "<group>"; };
 		2A343F7418A1748B0039B085 /* GCSegmentedArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GCSegmentedArray.h; sourceTree = "<group>"; };
 		2A343F7718A1749D0039B085 /* GCSegmentedArrayInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GCSegmentedArrayInlines.h; sourceTree = "<group>"; };
 		2A4BB7F218A41179008A0FCD /* JSManagedValueInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSManagedValueInternal.h; sourceTree = "<group>"; };
@@ -3848,7 +3846,6 @@
 				2A68295A1875F80500B6C3E2 /* CopyWriteBarrier.h */,
 				2A7A58EE1808A4C40020BDF7 /* DeferGC.cpp */,
 				0F136D4B174AD69B0075B354 /* DeferGC.h */,
-				2A2825CF18341F2D0087FBA9 /* DelayedReleaseScope.h */,
 				BCBE2CAD14E985AA000593AD /* GCAssertions.h */,
 				0F2B66A817B6B53D00A7AE3F /* GCIncomingRefCounted.h */,
 				0F2B66A917B6B53D00A7AE3F /* GCIncomingRefCountedInlines.h */,
@@ -5535,7 +5532,6 @@
 				FEA08621182B7A0400F6D851 /* DebuggerPrimitives.h in Headers */,
 				0F136D4D174AD69E0075B354 /* DeferGC.h in Headers */,
 				0FC712DF17CD877C008CC93C /* DeferredCompilationCallback.h in Headers */,
-				2A2825D018341F2D0087FBA9 /* DelayedReleaseScope.h in Headers */,
 				A77A423E17A0BBFD00A8DB81 /* DFGAbstractHeap.h in Headers */,
 				A5EA70E819F5B1010098F5EC /* AugmentableInspectorControllerClient.h in Headers */,
 				A704D90317A0BAA8006BA554 /* DFGAbstractInterpreter.h in Headers */,

Deleted: trunk/Source/_javascript_Core/heap/DelayedReleaseScope.h (179727 => 179728)


--- trunk/Source/_javascript_Core/heap/DelayedReleaseScope.h	2015-02-06 01:07:51 UTC (rev 179727)
+++ trunk/Source/_javascript_Core/heap/DelayedReleaseScope.h	2015-02-06 01:12:00 UTC (rev 179728)
@@ -1,103 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef DelayedReleaseScope_h
-#define DelayedReleaseScope_h
-
-#include "Heap.h"
-#include "JSLock.h"
-#include "MarkedSpace.h"
-
-namespace JSC {
-
-#if USE(CF)
-
-class DelayedReleaseScope {
-public:
-    DelayedReleaseScope(MarkedSpace& markedSpace)
-        : m_markedSpace(markedSpace)
-    {
-        ASSERT(!m_markedSpace.m_currentDelayedReleaseScope);
-        m_markedSpace.m_currentDelayedReleaseScope = this;
-    }
-
-    ~DelayedReleaseScope()
-    {
-        ASSERT(m_markedSpace.m_currentDelayedReleaseScope == this);
-        m_markedSpace.m_currentDelayedReleaseScope = nullptr;
-
-        HeapOperation operationInProgress = NoOperation;
-        std::swap(operationInProgress, m_markedSpace.m_heap->m_operationInProgress);
-
-        {
-            JSLock::DropAllLocks dropAllLocks(*m_markedSpace.m_heap->vm());
-            m_delayedReleaseObjects.clear();
-        }
-
-        std::swap(operationInProgress, m_markedSpace.m_heap->m_operationInProgress);
-    }
-
-    template <typename T>
-    void releaseSoon(RetainPtr<T>&& object)
-    {
-        m_delayedReleaseObjects.append(WTF::move(object));
-    }
-
-    static bool isInEffectFor(MarkedSpace& markedSpace)
-    {
-        return markedSpace.m_currentDelayedReleaseScope;
-    }
-
-private:
-    MarkedSpace& m_markedSpace;
-    Vector<RetainPtr<CFTypeRef>> m_delayedReleaseObjects;
-};
-
-template <typename T>
-inline void MarkedSpace::releaseSoon(RetainPtr<T>&& object)
-{
-    ASSERT(m_currentDelayedReleaseScope);
-    m_currentDelayedReleaseScope->releaseSoon(WTF::move(object));
-}
-
-#else // USE(CF)
-
-class DelayedReleaseScope {
-public:
-    DelayedReleaseScope(MarkedSpace&)
-    {
-    }
-
-    static bool isInEffectFor(MarkedSpace&)
-    {
-        return true;
-    }
-};
-
-#endif // USE(CF)
-
-} // namespace JSC
-
-#endif // DelayedReleaseScope_h

Modified: trunk/Source/_javascript_Core/heap/Heap.cpp (179727 => 179728)


--- trunk/Source/_javascript_Core/heap/Heap.cpp	2015-02-06 01:07:51 UTC (rev 179727)
+++ trunk/Source/_javascript_Core/heap/Heap.cpp	2015-02-06 01:12:00 UTC (rev 179728)
@@ -27,7 +27,6 @@
 #include "CopiedSpaceInlines.h"
 #include "CopyVisitorInlines.h"
 #include "DFGWorklist.h"
-#include "DelayedReleaseScope.h"
 #include "EdenGCActivityCallback.h"
 #include "FullGCActivityCallback.h"
 #include "GCActivityCallback.h"
@@ -337,6 +336,9 @@
     , m_sweeper(std::make_unique<IncrementalSweeper>(this->vm()))
 #endif
     , m_deferralDepth(0)
+#if USE(CF)
+    , m_delayedReleaseRecursionCount(0)
+#endif
 {
     m_storageSpace.init();
     if (Options::verifyHeap())
@@ -360,8 +362,22 @@
     RELEASE_ASSERT(m_operationInProgress == NoOperation);
 
     m_objectSpace.lastChanceToFinalize();
+    releaseDelayedReleasedObjects();
 }
 
+void Heap::releaseDelayedReleasedObjects()
+{
+#if USE(CF)
+    if (!m_delayedReleaseRecursionCount++) {
+        while (!m_delayedReleaseObjects.isEmpty()) {
+            RetainPtr<CFTypeRef> objectToRelease = m_delayedReleaseObjects.takeLast();
+            objectToRelease.clear();
+        }
+    }
+    m_delayedReleaseRecursionCount--;
+#endif
+}
+
 void Heap::reportExtraMemoryCostSlowCase(size_t cost)
 {
     // Our frequency of garbage collection tries to balance memory use against speed
@@ -966,7 +982,6 @@
     collect(FullCollection);
 
     SamplingRegion samplingRegion("Garbage Collection: Sweeping");
-    DelayedReleaseScope delayedReleaseScope(m_objectSpace);
     m_objectSpace.sweep();
     m_objectSpace.shrink();
 }
@@ -1378,7 +1393,6 @@
     // Sweep now because destructors will crash once we're zombified.
     {
         SamplingRegion samplingRegion("Garbage Collection: Sweeping");
-        DelayedReleaseScope delayedReleaseScope(m_objectSpace);
         m_objectSpace.zombifySweep();
     }
     HeapIterationScope iterationScope(*this);

Modified: trunk/Source/_javascript_Core/heap/Heap.h (179727 => 179728)


--- trunk/Source/_javascript_Core/heap/Heap.h	2015-02-06 01:07:51 UTC (rev 179727)
+++ trunk/Source/_javascript_Core/heap/Heap.h	2015-02-06 01:12:00 UTC (rev 179728)
@@ -115,6 +115,7 @@
     Heap(VM*, HeapType);
     ~Heap();
     JS_EXPORT_PRIVATE void lastChanceToFinalize();
+    void releaseDelayedReleasedObjects();
 
     VM* vm() const { return m_vm; }
     MarkedSpace& objectSpace() { return m_objectSpace; }
@@ -231,7 +232,6 @@
     friend class CopiedBlock;
     friend class DeferGC;
     friend class DeferGCForAWhile;
-    friend class DelayedReleaseScope;
     friend class GCAwareJITStubRoutine;
     friend class GCLogging;
     friend class HandleSet;
@@ -387,6 +387,10 @@
     Vector<DFG::Worklist*> m_suspendedCompilerWorklists;
 
     std::unique_ptr<HeapVerifier> m_verifier;
+#if USE(CF)
+    Vector<RetainPtr<CFTypeRef>> m_delayedReleaseObjects;
+    unsigned m_delayedReleaseRecursionCount;
+#endif
 };
 
 } // namespace JSC

Modified: trunk/Source/_javascript_Core/heap/HeapInlines.h (179727 => 179728)


--- trunk/Source/_javascript_Core/heap/HeapInlines.h	2015-02-06 01:07:51 UTC (rev 179727)
+++ trunk/Source/_javascript_Core/heap/HeapInlines.h	2015-02-06 01:12:00 UTC (rev 179728)
@@ -249,7 +249,7 @@
 template <typename T>
 inline void Heap::releaseSoon(RetainPtr<T>&& object)
 {
-    m_objectSpace.releaseSoon(WTF::move(object));
+    m_delayedReleaseObjects.append(WTF::move(object));
 }
 #endif
 

Modified: trunk/Source/_javascript_Core/heap/IncrementalSweeper.cpp (179727 => 179728)


--- trunk/Source/_javascript_Core/heap/IncrementalSweeper.cpp	2015-02-06 01:07:51 UTC (rev 179727)
+++ trunk/Source/_javascript_Core/heap/IncrementalSweeper.cpp	2015-02-06 01:12:00 UTC (rev 179728)
@@ -26,7 +26,6 @@
 #include "config.h"
 #include "IncrementalSweeper.h"
 
-#include "DelayedReleaseScope.h"
 #include "Heap.h"
 #include "JSObject.h"
 #include "JSString.h"
@@ -68,7 +67,6 @@
 
 void IncrementalSweeper::doSweep(double sweepBeginTime)
 {
-    DelayedReleaseScope scope(m_vm->heap.m_objectSpace);
     while (m_currentBlockToSweepIndex < m_blocksToSweep.size()) {
         sweepNextBlock();
 

Modified: trunk/Source/_javascript_Core/heap/MarkedAllocator.cpp (179727 => 179728)


--- trunk/Source/_javascript_Core/heap/MarkedAllocator.cpp	2015-02-06 01:07:51 UTC (rev 179727)
+++ trunk/Source/_javascript_Core/heap/MarkedAllocator.cpp	2015-02-06 01:12:00 UTC (rev 179728)
@@ -26,7 +26,6 @@
 #include "config.h"
 #include "MarkedAllocator.h"
 
-#include "DelayedReleaseScope.h"
 #include "GCActivityCallback.h"
 #include "Heap.h"
 #include "IncrementalSweeper.h"
@@ -62,47 +61,41 @@
 
 inline void* MarkedAllocator::tryAllocateHelper(size_t bytes)
 {
-    // We need a while loop to check the free list because the DelayedReleaseScope 
-    // could cause arbitrary code to execute and exhaust the free list that we 
-    // thought had elements in it.
-    while (!m_freeList.head) {
-        DelayedReleaseScope delayedReleaseScope(*m_markedSpace);
-        if (m_currentBlock) {
-            ASSERT(m_currentBlock == m_nextBlockToSweep);
-            m_currentBlock->didConsumeFreeList();
-            m_nextBlockToSweep = m_currentBlock->next();
-        }
+    if (m_currentBlock) {
+        ASSERT(m_currentBlock == m_nextBlockToSweep);
+        m_currentBlock->didConsumeFreeList();
+        m_nextBlockToSweep = m_currentBlock->next();
+    }
 
-        MarkedBlock* next;
-        for (MarkedBlock*& block = m_nextBlockToSweep; block; block = next) {
-            next = block->next();
+    MarkedBlock* next;
+    for (MarkedBlock*& block = m_nextBlockToSweep; block; block = next) {
+        next = block->next();
 
-            MarkedBlock::FreeList freeList = block->sweep(MarkedBlock::SweepToFreeList);
-            
-            double utilization = ((double)MarkedBlock::blockSize - (double)freeList.bytes) / (double)MarkedBlock::blockSize;
-            if (utilization >= Options::minMarkedBlockUtilization()) {
-                ASSERT(freeList.bytes || !freeList.head);
-                m_blockList.remove(block);
-                m_retiredBlocks.push(block);
-                block->didRetireBlock(freeList);
-                continue;
-            }
-
-            if (bytes > block->cellSize()) {
-                block->stopAllocating(freeList);
-                continue;
-            }
-
-            m_currentBlock = block;
-            m_freeList = freeList;
-            break;
-        }
+        MarkedBlock::FreeList freeList = block->sweep(MarkedBlock::SweepToFreeList);
         
-        if (!m_freeList.head) {
-            m_currentBlock = 0;
-            return 0;
+        double utilization = ((double)MarkedBlock::blockSize - (double)freeList.bytes) / (double)MarkedBlock::blockSize;
+        if (utilization >= Options::minMarkedBlockUtilization()) {
+            ASSERT(freeList.bytes || !freeList.head);
+            m_blockList.remove(block);
+            m_retiredBlocks.push(block);
+            block->didRetireBlock(freeList);
+            continue;
         }
+
+        if (bytes > block->cellSize()) {
+            block->stopAllocating(freeList);
+            continue;
+        }
+
+        m_currentBlock = block;
+        m_freeList = freeList;
+        break;
     }
+    
+    if (!m_freeList.head) {
+        m_currentBlock = 0;
+        return 0;
+    }
 
     ASSERT(m_freeList.head);
     void* head = tryPopFreeList(bytes);
@@ -128,17 +121,6 @@
     m_heap->m_operationInProgress = Allocation;
     void* result = tryAllocateHelper(bytes);
 
-    // Due to the DelayedReleaseScope in tryAllocateHelper, some other thread might have
-    // created a new block after we thought we didn't find any free cells. 
-    while (!result && m_currentBlock) {
-        // A new block was added by another thread so try popping the free list.
-        result = tryPopFreeList(bytes);
-        if (result)
-            break;
-        // The free list was empty, so call tryAllocateHelper to do the normal sweeping stuff.
-        result = tryAllocateHelper(bytes);
-    }
-
     m_heap->m_operationInProgress = NoOperation;
     ASSERT(result || !m_currentBlock);
     return result;

Modified: trunk/Source/_javascript_Core/heap/MarkedBlock.cpp (179727 => 179728)


--- trunk/Source/_javascript_Core/heap/MarkedBlock.cpp	2015-02-06 01:07:51 UTC (rev 179727)
+++ trunk/Source/_javascript_Core/heap/MarkedBlock.cpp	2015-02-06 01:12:00 UTC (rev 179728)
@@ -26,7 +26,6 @@
 #include "config.h"
 #include "MarkedBlock.h"
 
-#include "DelayedReleaseScope.h"
 #include "IncrementalSweeper.h"
 #include "JSCell.h"
 #include "JSDestructibleObject.h"
@@ -110,7 +109,6 @@
 
 MarkedBlock::FreeList MarkedBlock::sweep(SweepMode sweepMode)
 {
-    ASSERT(DelayedReleaseScope::isInEffectFor(heap()->m_objectSpace));
     HEAP_LOG_BLOCK_STATE_TRANSITION(this);
 
     m_weakSet.sweep();

Modified: trunk/Source/_javascript_Core/heap/MarkedSpace.cpp (179727 => 179728)


--- trunk/Source/_javascript_Core/heap/MarkedSpace.cpp	2015-02-06 01:07:51 UTC (rev 179727)
+++ trunk/Source/_javascript_Core/heap/MarkedSpace.cpp	2015-02-06 01:12:00 UTC (rev 179728)
@@ -21,7 +21,6 @@
 #include "config.h"
 #include "MarkedSpace.h"
 
-#include "DelayedReleaseScope.h"
 #include "IncrementalSweeper.h"
 #include "JSGlobalObject.h"
 #include "JSLock.h"
@@ -82,7 +81,6 @@
     : m_heap(heap)
     , m_capacity(0)
     , m_isIterating(false)
-    , m_currentDelayedReleaseScope(nullptr)
 {
     for (size_t cellSize = preciseStep; cellSize <= preciseCutoff; cellSize += preciseStep) {
         allocatorFor(cellSize).init(heap, this, cellSize, MarkedBlock::None);
@@ -114,7 +112,6 @@
 
 void MarkedSpace::lastChanceToFinalize()
 {
-    DelayedReleaseScope delayedReleaseScope(*this);
     stopAllocating();
     forEachAllocator<LastChanceToFinalize>();
 }
@@ -362,7 +359,6 @@
 void MarkedSpace::didFinishIterating()
 {
     ASSERT(isIterating());
-    DelayedReleaseScope scope(*this);
     resumeAllocating();
     m_isIterating = false;
 }

Modified: trunk/Source/_javascript_Core/heap/MarkedSpace.h (179727 => 179728)


--- trunk/Source/_javascript_Core/heap/MarkedSpace.h	2015-02-06 01:07:51 UTC (rev 179727)
+++ trunk/Source/_javascript_Core/heap/MarkedSpace.h	2015-02-06 01:12:00 UTC (rev 179728)
@@ -36,7 +36,6 @@
 
 namespace JSC {
 
-class DelayedReleaseScope;
 class Heap;
 class HeapIterationScope;
 class JSCell;
@@ -161,7 +160,6 @@
 #endif
 
 private:
-    friend class DelayedReleaseScope;
     friend class LLIntOffsetsExtractor;
     friend class JIT;
 
@@ -177,8 +175,6 @@
     bool m_isIterating;
     MarkedBlockSet m_blocks;
     Vector<MarkedBlock*> m_blocksWithNewObjects;
-
-    DelayedReleaseScope* m_currentDelayedReleaseScope;
 };
 
 template<typename Functor> inline typename Functor::ReturnType MarkedSpace::forEachLiveCell(HeapIterationScope&, Functor& functor)

Modified: trunk/Source/_javascript_Core/runtime/JSLock.cpp (179727 => 179728)


--- trunk/Source/_javascript_Core/runtime/JSLock.cpp	2015-02-06 01:07:51 UTC (rev 179727)
+++ trunk/Source/_javascript_Core/runtime/JSLock.cpp	2015-02-06 01:12:00 UTC (rev 179728)
@@ -171,8 +171,10 @@
 
 void JSLock::willReleaseLock()
 {
-    if (m_vm)
+    if (m_vm) {
+        m_vm->heap.releaseDelayedReleasedObjects();
         m_vm->setStackPointerAtVMEntry(nullptr);
+    }
 
     if (m_entryAtomicStringTable) {
         wtfThreadData().setCurrentAtomicStringTable(m_entryAtomicStringTable);
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to