Changeset 179728 in webkit
- Timestamp:
- Feb 5, 2015, 5:12:00 PM (12 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 1 deleted
- 15 edited
-
API/JSAPIWrapperObject.mm (modified) (1 diff)
-
API/ObjCCallbackFunction.mm (modified) (1 diff)
-
ChangeLog (modified) (1 diff)
-
JavaScriptCore.vcxproj/JavaScriptCore.vcxproj (modified) (1 diff)
-
JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters (modified) (1 diff)
-
JavaScriptCore.xcodeproj/project.pbxproj (modified) (4 diffs)
-
heap/DelayedReleaseScope.h (deleted)
-
heap/Heap.cpp (modified) (5 diffs)
-
heap/Heap.h (modified) (3 diffs)
-
heap/HeapInlines.h (modified) (1 diff)
-
heap/IncrementalSweeper.cpp (modified) (2 diffs)
-
heap/MarkedAllocator.cpp (modified) (3 diffs)
-
heap/MarkedBlock.cpp (modified) (2 diffs)
-
heap/MarkedSpace.cpp (modified) (4 diffs)
-
heap/MarkedSpace.h (modified) (3 diffs)
-
runtime/JSLock.cpp (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/API/JSAPIWrapperObject.mm
r171939 r179728 27 27 #include "JSAPIWrapperObject.h" 28 28 29 #include "DelayedReleaseScope.h"30 29 #include "JSCInlines.h" 31 30 #include "JSCallbackObject.h" -
trunk/Source/JavaScriptCore/API/ObjCCallbackFunction.mm
r173410 r179728 31 31 #import "APICallbackFunction.h" 32 32 #import "APICast.h" 33 #import "DelayedReleaseScope.h"34 33 #import "Error.h" 35 34 #import "JSCJSValueInlines.h" -
trunk/Source/JavaScriptCore/ChangeLog
r179687 r179728 1 2015-02-05 Michael Saboff <msaboff@apple.com> 2 3 CodeCache is not thread safe when adding the same source from two different threads 4 https://bugs.webkit.org/show_bug.cgi?id=141275 5 6 Reviewed by Mark Lam. 7 8 The issue for this bug is that one thread, takes a cache miss in CodeCache::getGlobalCodeBlock, 9 but in the process creates a cache entry with a nullptr UnlinkedCodeBlockType* which it 10 will fill in later in the function. During the body of that function, it allocates 11 objects that may garbage collect. During that garbage collection, we drop the all locks. 12 While the locks are released by the first thread, another thread can enter the VM and might 13 have exactly the same source and enter CodeCache::getGlobalCodeBlock() itself. When it 14 looks up the code block, it sees it as a cache it and uses the nullptr UnlinkedCodeBlockType* 15 and crashes. This fixes the problem by not dropping the locks during garbage collection. 16 There are other likely scenarios where we have a data structure like this code cache in an 17 unsafe state for arbitrary reentrance. 18 19 Moved the functionality of DelayedReleaseScope directly into Heap. Changed it into 20 a simple list that is cleared with the new function Heap::releaseDelayedReleasedObjects. 21 Now we accumulate objects to be released and release them when all locks are dropped or 22 when destroying the Heap. This eliminated the dropping and reaquiring of locks associated 23 with the old scope form of this list. 24 25 Given that all functionality of DelayedReleaseScope is now used and referenced by Heap 26 and the lock management no longer needs to be done, just made the list a member of Heap. 27 We do need to guard against the case that releasing an object can create more objects 28 by calling into JS. That is why releaseDelayedReleasedObjects() is written to remove 29 an object to release so that we aren't recursively in Vector code. The other thing we 30 do in releaseDelayedReleasedObjects() is to guard against recursive calls to itself using 31 the m_delayedReleaseRecursionCount. We only release at the first entry into the function. 32 This case is already tested by testapi.mm. 33 34 * heap/DelayedReleaseScope.h: Removed file 35 36 * API/JSAPIWrapperObject.mm: 37 * API/ObjCCallbackFunction.mm: 38 * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj: 39 * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters: 40 * JavaScriptCore.xcodeproj/project.pbxproj: 41 * heap/IncrementalSweeper.cpp: 42 (JSC::IncrementalSweeper::doSweep): 43 * heap/MarkedAllocator.cpp: 44 (JSC::MarkedAllocator::tryAllocateHelper): 45 (JSC::MarkedAllocator::tryAllocate): 46 * heap/MarkedBlock.cpp: 47 (JSC::MarkedBlock::sweep): 48 * heap/MarkedSpace.cpp: 49 (JSC::MarkedSpace::MarkedSpace): 50 (JSC::MarkedSpace::lastChanceToFinalize): 51 (JSC::MarkedSpace::didFinishIterating): 52 * heap/MarkedSpace.h: 53 * heap/Heap.cpp: 54 (JSC::Heap::collectAllGarbage): 55 (JSC::Heap::zombifyDeadObjects): 56 Removed references to DelayedReleaseScope and DelayedReleaseScope.h. 57 58 * heap/Heap.cpp: 59 (JSC::Heap::Heap): Initialized m_delayedReleaseRecursionCount. 60 (JSC::Heap::lastChanceToFinalize): Call releaseDelayedObjectsNow() as the VM is going away. 61 (JSC::Heap::releaseDelayedReleasedObjects): New function that released the accumulated 62 delayed release objects. 63 64 * heap/Heap.h: 65 (JSC::Heap::m_delayedReleaseObjects): List of objects to be released later. 66 (JSC::Heap::m_delayedReleaseRecursionCount): Counter to indicate that 67 releaseDelayedReleasedObjects is being called recursively. 68 * heap/HeapInlines.h: 69 (JSC::Heap::releaseSoon): Changed location of list to add delayed release objects. 70 71 * runtime/JSLock.cpp: 72 (JSC::JSLock::willReleaseLock): 73 Call Heap::releaseDelayedObjectsNow() when releasing the lock. 74 1 75 2015-02-05 Youenn Fablet <youenn.fablet@crf.canon.fr> and Xabier Rodriguez Calvar <calvaris@igalia.com> 2 76 -
trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj
r179552 r179728 1231 1231 <ClInclude Include="..\heap\CopyWriteBarrier.h" /> 1232 1232 <ClInclude Include="..\heap\DeferGC.h" /> 1233 <ClInclude Include="..\heap\DelayedReleaseScope.h" />1234 1233 <ClInclude Include="..\heap\EdenGCActivityCallback.h" /> 1235 1234 <ClInclude Include="..\heap\FullGCActivityCallback.h" /> -
trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters
r179552 r179728 3769 3769 <Filter>runtime</Filter> 3770 3770 </ClInclude> 3771 <ClInclude Include="..\heap\DelayedReleaseScope.h">3772 <Filter>heap</Filter>3773 </ClInclude>3774 3771 <ClInclude Include="..\bytecode\VariableWatchpointSet.h"> 3775 3772 <Filter>bytecode</Filter> -
trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
r179503 r179728 865 865 2A111245192FCE79005EE18D /* CustomGetterSetter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2A111243192FCE79005EE18D /* CustomGetterSetter.cpp */; }; 866 866 2A111246192FCE79005EE18D /* CustomGetterSetter.h in Headers */ = {isa = PBXBuildFile; fileRef = 2A111244192FCE79005EE18D /* CustomGetterSetter.h */; settings = {ATTRIBUTES = (Private, ); }; }; 867 2A2825D018341F2D0087FBA9 /* DelayedReleaseScope.h in Headers */ = {isa = PBXBuildFile; fileRef = 2A2825CF18341F2D0087FBA9 /* DelayedReleaseScope.h */; };868 867 2A48D1911772365B00C65A5F /* APICallbackFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = C211B574176A224D000E2A23 /* APICallbackFunction.h */; }; 869 868 2A4BB7F318A41179008A0FCD /* JSManagedValueInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 2A4BB7F218A41179008A0FCD /* JSManagedValueInternal.h */; }; … … 2500 2499 2A111243192FCE79005EE18D /* CustomGetterSetter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CustomGetterSetter.cpp; sourceTree = "<group>"; }; 2501 2500 2A111244192FCE79005EE18D /* CustomGetterSetter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CustomGetterSetter.h; sourceTree = "<group>"; }; 2502 2A2825CF18341F2D0087FBA9 /* DelayedReleaseScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DelayedReleaseScope.h; sourceTree = "<group>"; };2503 2501 2A343F7418A1748B0039B085 /* GCSegmentedArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GCSegmentedArray.h; sourceTree = "<group>"; }; 2504 2502 2A343F7718A1749D0039B085 /* GCSegmentedArrayInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GCSegmentedArrayInlines.h; sourceTree = "<group>"; }; … … 3849 3847 2A7A58EE1808A4C40020BDF7 /* DeferGC.cpp */, 3850 3848 0F136D4B174AD69B0075B354 /* DeferGC.h */, 3851 2A2825CF18341F2D0087FBA9 /* DelayedReleaseScope.h */,3852 3849 BCBE2CAD14E985AA000593AD /* GCAssertions.h */, 3853 3850 0F2B66A817B6B53D00A7AE3F /* GCIncomingRefCounted.h */, … … 5536 5533 0F136D4D174AD69E0075B354 /* DeferGC.h in Headers */, 5537 5534 0FC712DF17CD877C008CC93C /* DeferredCompilationCallback.h in Headers */, 5538 2A2825D018341F2D0087FBA9 /* DelayedReleaseScope.h in Headers */,5539 5535 A77A423E17A0BBFD00A8DB81 /* DFGAbstractHeap.h in Headers */, 5540 5536 A5EA70E819F5B1010098F5EC /* AugmentableInspectorControllerClient.h in Headers */, -
trunk/Source/JavaScriptCore/heap/Heap.cpp
r179478 r179728 28 28 #include "CopyVisitorInlines.h" 29 29 #include "DFGWorklist.h" 30 #include "DelayedReleaseScope.h"31 30 #include "EdenGCActivityCallback.h" 32 31 #include "FullGCActivityCallback.h" … … 338 337 #endif 339 338 , m_deferralDepth(0) 339 #if USE(CF) 340 , m_delayedReleaseRecursionCount(0) 341 #endif 340 342 { 341 343 m_storageSpace.init(); … … 361 363 362 364 m_objectSpace.lastChanceToFinalize(); 365 releaseDelayedReleasedObjects(); 366 } 367 368 void Heap::releaseDelayedReleasedObjects() 369 { 370 #if USE(CF) 371 if (!m_delayedReleaseRecursionCount++) { 372 while (!m_delayedReleaseObjects.isEmpty()) { 373 RetainPtr<CFTypeRef> objectToRelease = m_delayedReleaseObjects.takeLast(); 374 objectToRelease.clear(); 375 } 376 } 377 m_delayedReleaseRecursionCount--; 378 #endif 363 379 } 364 380 … … 967 983 968 984 SamplingRegion samplingRegion("Garbage Collection: Sweeping"); 969 DelayedReleaseScope delayedReleaseScope(m_objectSpace);970 985 m_objectSpace.sweep(); 971 986 m_objectSpace.shrink(); … … 1379 1394 { 1380 1395 SamplingRegion samplingRegion("Garbage Collection: Sweeping"); 1381 DelayedReleaseScope delayedReleaseScope(m_objectSpace);1382 1396 m_objectSpace.zombifySweep(); 1383 1397 } -
trunk/Source/JavaScriptCore/heap/Heap.h
r179211 r179728 116 116 ~Heap(); 117 117 JS_EXPORT_PRIVATE void lastChanceToFinalize(); 118 void releaseDelayedReleasedObjects(); 118 119 119 120 VM* vm() const { return m_vm; } … … 232 233 friend class DeferGC; 233 234 friend class DeferGCForAWhile; 234 friend class DelayedReleaseScope;235 235 friend class GCAwareJITStubRoutine; 236 236 friend class GCLogging; … … 388 388 389 389 std::unique_ptr<HeapVerifier> m_verifier; 390 #if USE(CF) 391 Vector<RetainPtr<CFTypeRef>> m_delayedReleaseObjects; 392 unsigned m_delayedReleaseRecursionCount; 393 #endif 390 394 }; 391 395 -
trunk/Source/JavaScriptCore/heap/HeapInlines.h
r179211 r179728 250 250 inline void Heap::releaseSoon(RetainPtr<T>&& object) 251 251 { 252 m_ objectSpace.releaseSoon(WTF::move(object));252 m_delayedReleaseObjects.append(WTF::move(object)); 253 253 } 254 254 #endif -
trunk/Source/JavaScriptCore/heap/IncrementalSweeper.cpp
r176000 r179728 27 27 #include "IncrementalSweeper.h" 28 28 29 #include "DelayedReleaseScope.h"30 29 #include "Heap.h" 31 30 #include "JSObject.h" … … 69 68 void IncrementalSweeper::doSweep(double sweepBeginTime) 70 69 { 71 DelayedReleaseScope scope(m_vm->heap.m_objectSpace);72 70 while (m_currentBlockToSweepIndex < m_blocksToSweep.size()) { 73 71 sweepNextBlock(); -
trunk/Source/JavaScriptCore/heap/MarkedAllocator.cpp
r179211 r179728 27 27 #include "MarkedAllocator.h" 28 28 29 #include "DelayedReleaseScope.h"30 29 #include "GCActivityCallback.h" 31 30 #include "Heap.h" … … 63 62 inline void* MarkedAllocator::tryAllocateHelper(size_t bytes) 64 63 { 65 // We need a while loop to check the free list because the DelayedReleaseScope 66 // could cause arbitrary code to execute and exhaust the free list that we 67 // thought had elements in it. 68 while (!m_freeList.head) { 69 DelayedReleaseScope delayedReleaseScope(*m_markedSpace); 70 if (m_currentBlock) { 71 ASSERT(m_currentBlock == m_nextBlockToSweep); 72 m_currentBlock->didConsumeFreeList(); 73 m_nextBlockToSweep = m_currentBlock->next(); 64 if (m_currentBlock) { 65 ASSERT(m_currentBlock == m_nextBlockToSweep); 66 m_currentBlock->didConsumeFreeList(); 67 m_nextBlockToSweep = m_currentBlock->next(); 68 } 69 70 MarkedBlock* next; 71 for (MarkedBlock*& block = m_nextBlockToSweep; block; block = next) { 72 next = block->next(); 73 74 MarkedBlock::FreeList freeList = block->sweep(MarkedBlock::SweepToFreeList); 75 76 double utilization = ((double)MarkedBlock::blockSize - (double)freeList.bytes) / (double)MarkedBlock::blockSize; 77 if (utilization >= Options::minMarkedBlockUtilization()) { 78 ASSERT(freeList.bytes || !freeList.head); 79 m_blockList.remove(block); 80 m_retiredBlocks.push(block); 81 block->didRetireBlock(freeList); 82 continue; 74 83 } 75 84 76 MarkedBlock* next; 77 for (MarkedBlock*& block = m_nextBlockToSweep; block; block = next) { 78 next = block->next(); 79 80 MarkedBlock::FreeList freeList = block->sweep(MarkedBlock::SweepToFreeList); 81 82 double utilization = ((double)MarkedBlock::blockSize - (double)freeList.bytes) / (double)MarkedBlock::blockSize; 83 if (utilization >= Options::minMarkedBlockUtilization()) { 84 ASSERT(freeList.bytes || !freeList.head); 85 m_blockList.remove(block); 86 m_retiredBlocks.push(block); 87 block->didRetireBlock(freeList); 88 continue; 89 } 90 91 if (bytes > block->cellSize()) { 92 block->stopAllocating(freeList); 93 continue; 94 } 95 96 m_currentBlock = block; 97 m_freeList = freeList; 98 break; 85 if (bytes > block->cellSize()) { 86 block->stopAllocating(freeList); 87 continue; 99 88 } 100 101 if (!m_freeList.head) { 102 m_currentBlock = 0; 103 return 0; 104 } 89 90 m_currentBlock = block; 91 m_freeList = freeList; 92 break; 93 } 94 95 if (!m_freeList.head) { 96 m_currentBlock = 0; 97 return 0; 105 98 } 106 99 … … 128 121 m_heap->m_operationInProgress = Allocation; 129 122 void* result = tryAllocateHelper(bytes); 130 131 // Due to the DelayedReleaseScope in tryAllocateHelper, some other thread might have132 // created a new block after we thought we didn't find any free cells.133 while (!result && m_currentBlock) {134 // A new block was added by another thread so try popping the free list.135 result = tryPopFreeList(bytes);136 if (result)137 break;138 // The free list was empty, so call tryAllocateHelper to do the normal sweeping stuff.139 result = tryAllocateHelper(bytes);140 }141 123 142 124 m_heap->m_operationInProgress = NoOperation; -
trunk/Source/JavaScriptCore/heap/MarkedBlock.cpp
r179211 r179728 27 27 #include "MarkedBlock.h" 28 28 29 #include "DelayedReleaseScope.h"30 29 #include "IncrementalSweeper.h" 31 30 #include "JSCell.h" … … 111 110 MarkedBlock::FreeList MarkedBlock::sweep(SweepMode sweepMode) 112 111 { 113 ASSERT(DelayedReleaseScope::isInEffectFor(heap()->m_objectSpace));114 112 HEAP_LOG_BLOCK_STATE_TRANSITION(this); 115 113 -
trunk/Source/JavaScriptCore/heap/MarkedSpace.cpp
r179211 r179728 22 22 #include "MarkedSpace.h" 23 23 24 #include "DelayedReleaseScope.h"25 24 #include "IncrementalSweeper.h" 26 25 #include "JSGlobalObject.h" … … 83 82 , m_capacity(0) 84 83 , m_isIterating(false) 85 , m_currentDelayedReleaseScope(nullptr)86 84 { 87 85 for (size_t cellSize = preciseStep; cellSize <= preciseCutoff; cellSize += preciseStep) { … … 115 113 void MarkedSpace::lastChanceToFinalize() 116 114 { 117 DelayedReleaseScope delayedReleaseScope(*this);118 115 stopAllocating(); 119 116 forEachAllocator<LastChanceToFinalize>(); … … 363 360 { 364 361 ASSERT(isIterating()); 365 DelayedReleaseScope scope(*this);366 362 resumeAllocating(); 367 363 m_isIterating = false; -
trunk/Source/JavaScriptCore/heap/MarkedSpace.h
r179211 r179728 37 37 namespace JSC { 38 38 39 class DelayedReleaseScope;40 39 class Heap; 41 40 class HeapIterationScope; … … 162 161 163 162 private: 164 friend class DelayedReleaseScope;165 163 friend class LLIntOffsetsExtractor; 166 164 friend class JIT; … … 178 176 MarkedBlockSet m_blocks; 179 177 Vector<MarkedBlock*> m_blocksWithNewObjects; 180 181 DelayedReleaseScope* m_currentDelayedReleaseScope;182 178 }; 183 179 -
trunk/Source/JavaScriptCore/runtime/JSLock.cpp
r171558 r179728 172 172 void JSLock::willReleaseLock() 173 173 { 174 if (m_vm) 174 if (m_vm) { 175 m_vm->heap.releaseDelayedReleasedObjects(); 175 176 m_vm->setStackPointerAtVMEntry(nullptr); 177 } 176 178 177 179 if (m_entryAtomicStringTable) {
Note:
See TracChangeset
for help on using the changeset viewer.