Changeset 121098 in webkit for trunk/Source/JavaScriptCore
- Timestamp:
- Jun 23, 2012, 6:41:40 AM (13 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 23 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/API/APIShims.h
r121058 r121098 29 29 #include "CallFrame.h" 30 30 #include "GCActivityCallback.h" 31 #include "IncrementalSweeper.h"32 31 #include "JSLock.h" 33 32 #include <wtf/WTFThreadData.h> … … 36 35 37 36 class APIEntryShimWithoutLock { 38 public:39 enum RefGlobalDataTag { DontRefGlobalData = 0, RefGlobalData };40 41 37 protected: 42 APIEntryShimWithoutLock(JSGlobalData* globalData, bool registerThread, RefGlobalDataTag shouldRefGlobalData) 43 : m_shouldRefGlobalData(shouldRefGlobalData) 44 , m_globalData(globalData) 38 APIEntryShimWithoutLock(JSGlobalData* globalData, bool registerThread) 39 : m_globalData(globalData) 45 40 , m_entryIdentifierTable(wtfThreadData().setCurrentIdentifierTable(globalData->identifierTable)) 46 41 { 47 if (shouldRefGlobalData)48 m_globalData->ref();49 42 UNUSED_PARAM(registerThread); 50 43 if (registerThread) 51 44 globalData->heap.machineThreads().addCurrentThread(); 52 45 m_globalData->heap.activityCallback()->synchronize(); 53 m_globalData-> heap.sweeper()->synchronize();46 m_globalData->timeoutChecker.start(); 54 47 } 55 48 56 49 ~APIEntryShimWithoutLock() 57 50 { 51 m_globalData->timeoutChecker.stop(); 58 52 wtfThreadData().setCurrentIdentifierTable(m_entryIdentifierTable); 59 if (m_shouldRefGlobalData)60 m_globalData->deref();61 53 } 62 54 63 protected: 64 RefGlobalDataTag m_shouldRefGlobalData; 55 private: 65 56 JSGlobalData* m_globalData; 66 57 IdentifierTable* m_entryIdentifierTable; … … 71 62 // Normal API entry 72 63 APIEntryShim(ExecState* exec, bool registerThread = true) 73 : APIEntryShimWithoutLock(&exec->globalData(), registerThread, RefGlobalData) 64 : APIEntryShimWithoutLock(&exec->globalData(), registerThread) 65 , m_lock(exec) 74 66 { 75 init();76 }77 78 // This constructor is necessary for HeapTimer to prevent it from accidentally resurrecting79 // the ref count of a "dead" JSGlobalData.80 APIEntryShim(JSGlobalData* globalData, RefGlobalDataTag refGlobalData, bool registerThread = true)81 : APIEntryShimWithoutLock(globalData, registerThread, refGlobalData)82 {83 init();84 67 } 85 68 86 69 // JSPropertyNameAccumulator only has a globalData. 87 70 APIEntryShim(JSGlobalData* globalData, bool registerThread = true) 88 : APIEntryShimWithoutLock(globalData, registerThread, RefGlobalData) 71 : APIEntryShimWithoutLock(globalData, registerThread) 72 , m_lock(globalData->isSharedInstance() ? LockForReal : SilenceAssertionsOnly) 89 73 { 90 init();91 }92 93 ~APIEntryShim()94 {95 m_globalData->timeoutChecker.stop();96 m_globalData->apiLock().unlock();97 74 } 98 75 99 76 private: 100 void init() 101 { 102 m_globalData->apiLock().lock(); 103 m_globalData->timeoutChecker.start(); 104 } 77 JSLock m_lock; 105 78 }; 106 79 … … 116 89 ~APICallbackShim() 117 90 { 91 m_globalData->heap.activityCallback()->synchronize(); 118 92 wtfThreadData().setCurrentIdentifierTable(m_globalData->identifierTable); 119 93 } -
trunk/Source/JavaScriptCore/API/JSContextRef.cpp
r121058 r121098 79 79 // we use a shared one for backwards compatibility. 80 80 if (NSVersionOfLinkTimeLibrary("JavaScriptCore") <= webkitFirstVersionWithConcurrentGlobalContexts) { 81 JSLock lock(LockForReal); 81 82 return JSGlobalContextCreateInGroup(toRef(&JSGlobalData::sharedInstance()), globalObjectClass); 82 83 } … … 90 91 initializeThreading(); 91 92 93 JSLock lock(LockForReal); 92 94 RefPtr<JSGlobalData> globalData = group ? PassRefPtr<JSGlobalData>(toJS(group)) : JSGlobalData::createContextGroup(ThreadStackTypeSmall); 93 95 94 96 APIEntryShim entryShim(globalData.get(), false); 97 95 98 globalData->makeUsableFromMultipleThreads(); 96 99 … … 122 125 void JSGlobalContextRelease(JSGlobalContextRef ctx) 123 126 { 124 IdentifierTable* savedIdentifierTable; 125 ExecState* exec = toJS(ctx); 126 { 127 JSLockHolder lock(exec); 128 129 JSGlobalData& globalData = exec->globalData(); 130 savedIdentifierTable = wtfThreadData().setCurrentIdentifierTable(globalData.identifierTable); 131 132 bool protectCountIsZero = Heap::heap(exec->dynamicGlobalObject())->unprotect(exec->dynamicGlobalObject()); 133 if (protectCountIsZero) 134 globalData.heap.reportAbandonedObjectGraph(); 135 globalData.deref(); 136 } 127 ExecState* exec = toJS(ctx); 128 JSLock lock(exec); 129 130 JSGlobalData& globalData = exec->globalData(); 131 IdentifierTable* savedIdentifierTable = wtfThreadData().setCurrentIdentifierTable(globalData.identifierTable); 132 133 bool protectCountIsZero = Heap::heap(exec->dynamicGlobalObject())->unprotect(exec->dynamicGlobalObject()); 134 if (protectCountIsZero) { 135 globalData.heap.activityCallback()->synchronize(); 136 globalData.heap.reportAbandonedObjectGraph(); 137 } 138 globalData.deref(); 137 139 138 140 wtfThreadData().setCurrentIdentifierTable(savedIdentifierTable); … … 165 167 { 166 168 ExecState* exec = toJS(ctx); 167 JSLock Holderlock(exec);169 JSLock lock(exec); 168 170 169 171 unsigned count = 0; -
trunk/Source/JavaScriptCore/ChangeLog
r121083 r121098 1 2012-06-23 Sheriff Bot <[email protected]> 2 3 Unreviewed, rolling out r121058. 4 http://trac.webkit.org/changeset/121058 5 https://bugs.webkit.org/show_bug.cgi?id=89809 6 7 Patch causes plugins tests to crash in GTK debug builds 8 (Requested by zdobersek on #webkit). 9 10 * API/APIShims.h: 11 (JSC::APIEntryShimWithoutLock::APIEntryShimWithoutLock): 12 (JSC::APIEntryShimWithoutLock::~APIEntryShimWithoutLock): 13 (APIEntryShimWithoutLock): 14 (JSC::APIEntryShim::APIEntryShim): 15 (APIEntryShim): 16 (JSC::APICallbackShim::~APICallbackShim): 17 * API/JSContextRef.cpp: 18 (JSGlobalContextCreate): 19 (JSGlobalContextCreateInGroup): 20 (JSGlobalContextRelease): 21 (JSContextCreateBacktrace): 22 * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: 23 * heap/CopiedSpace.cpp: 24 (JSC::CopiedSpace::tryAllocateSlowCase): 25 * heap/Heap.cpp: 26 (JSC::Heap::protect): 27 (JSC::Heap::unprotect): 28 (JSC::Heap::collect): 29 (JSC::Heap::setActivityCallback): 30 (JSC::Heap::activityCallback): 31 (JSC::Heap::sweeper): 32 * heap/Heap.h: 33 (Heap): 34 * heap/HeapTimer.cpp: 35 (JSC::HeapTimer::~HeapTimer): 36 (JSC::HeapTimer::invalidate): 37 (JSC::HeapTimer::timerDidFire): 38 (JSC): 39 * heap/HeapTimer.h: 40 (HeapTimer): 41 * heap/IncrementalSweeper.cpp: 42 (JSC::IncrementalSweeper::doWork): 43 (JSC::IncrementalSweeper::create): 44 * heap/IncrementalSweeper.h: 45 (IncrementalSweeper): 46 * heap/MarkedAllocator.cpp: 47 (JSC::MarkedAllocator::allocateSlowCase): 48 * heap/WeakBlock.cpp: 49 (JSC::WeakBlock::reap): 50 * jsc.cpp: 51 (functionGC): 52 (functionReleaseExecutableMemory): 53 (jscmain): 54 * runtime/Completion.cpp: 55 (JSC::checkSyntax): 56 (JSC::evaluate): 57 * runtime/GCActivityCallback.h: 58 (DefaultGCActivityCallback): 59 (JSC::DefaultGCActivityCallback::create): 60 * runtime/JSGlobalData.cpp: 61 (JSC::JSGlobalData::JSGlobalData): 62 (JSC::JSGlobalData::~JSGlobalData): 63 (JSC::JSGlobalData::sharedInstance): 64 (JSC::JSGlobalData::sharedInstanceInternal): 65 * runtime/JSGlobalData.h: 66 (JSGlobalData): 67 * runtime/JSGlobalObject.cpp: 68 (JSC::JSGlobalObject::~JSGlobalObject): 69 (JSC::JSGlobalObject::init): 70 * runtime/JSLock.cpp: 71 (JSC): 72 (JSC::createJSLockCount): 73 (JSC::JSLock::lockCount): 74 (JSC::setLockCount): 75 (JSC::JSLock::JSLock): 76 (JSC::JSLock::lock): 77 (JSC::JSLock::unlock): 78 (JSC::JSLock::currentThreadIsHoldingLock): 79 (JSC::JSLock::DropAllLocks::DropAllLocks): 80 (JSC::JSLock::DropAllLocks::~DropAllLocks): 81 * runtime/JSLock.h: 82 (JSC): 83 (JSLock): 84 (JSC::JSLock::JSLock): 85 (JSC::JSLock::~JSLock): 86 (DropAllLocks): 87 * runtime/WeakGCMap.h: 88 (JSC::WeakGCMap::set): 89 * testRegExp.cpp: 90 (realMain): 91 1 92 2012-06-22 Alexandru Chiculita <[email protected]> 2 93 -
trunk/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def
r121058 r121098 7 7 ??0DateInstance@JSC@@IAE@PAVExecState@1@PAVStructure@1@@Z 8 8 ??0DefaultGCActivityCallback@JSC@@QAE@PAVHeap@1@@Z 9 ??0DropAllLocks@JSLock@JSC@@QAE@PAVExecState@2@@Z 10 ??0DropAllLocks@JSLock@JSC@@QAE@PAVJSGlobalData@2@@Z 9 ??0DropAllLocks@JSLock@JSC@@QAE@W4JSLockBehavior@2@@Z 11 10 ??0DynamicGlobalObjectScope@JSC@@QAE@AAVJSGlobalData@1@PAVJSGlobalObject@1@@Z 12 11 ??0InternalFunction@JSC@@IAE@PAVJSGlobalObject@1@PAVStructure@1@@Z 13 ??0JSLockHolder@JSC@@QAE@AAVJSGlobalData@1@@Z 14 ??0JSLockHolder@JSC@@QAE@PAVExecState@1@@Z 15 ??0JSLockHolder@JSC@@QAE@PAVJSGlobalData@1@@Z 12 ??0JSLock@JSC@@QAE@PAVExecState@1@@Z 16 13 ??0MD5@WTF@@QAE@XZ 17 14 ??0Mutex@WTF@@QAE@XZ … … 36 33 ??1JSGlobalData@JSC@@QAE@XZ 37 34 ??1JSGlobalObject@JSC@@QAE@XZ 38 ??1JSLockHolder@JSC@@QAE@XZ39 35 ??1Mutex@WTF@@QAE@XZ 40 36 ??1RefCountedLeakCounter@WTF@@QAE@XZ … … 128 124 ?cryptographicallyRandomValues@WTF@@YAXPAXI@Z 129 125 ?currentThread@WTF@@YAIXZ 126 ?currentThreadIsHoldingLock@JSLock@JSC@@SA_NXZ 130 127 ?currentTime@WTF@@YANXZ 131 128 ?data@CString@WTF@@QBEPBDXZ … … 239 236 ?jsString@JSC@@YAPAVJSString@1@PAVJSGlobalData@1@ABVUString@1@@Z 240 237 ?length@CString@WTF@@QBEIXZ 241 ?lock@JSLock@JSC@@ QAEXXZ238 ?lock@JSLock@JSC@@SAXW4JSLockBehavior@2@@Z 242 239 ?lock@Mutex@WTF@@QAEXXZ 243 240 ?lockAtomicallyInitializedStaticMutex@WTF@@YAXXZ 241 ?lockCount@JSLock@JSC@@SAHXZ 244 242 ?match@RegExp@JSC@@QAEHAAVJSGlobalData@2@ABVUString@2@IAAV?$Vector@H$0CA@@WTF@@@Z 245 243 ?materializePropertyMap@Structure@JSC@@AAEXAAVJSGlobalData@2@@Z … … 326 324 ?substringSharingImpl@UString@JSC@@QBE?AV12@II@Z 327 325 ?suggestedNewPropertyStorageSize@Structure@JSC@@QAEIXZ 328 ?sweeper@Heap@JSC@@QAEPAVIncrementalSweeper@2@XZ329 326 ?synthesizePrototype@JSValue@JSC@@QBEPAVJSObject@2@PAVExecState@2@@Z 330 327 ?thisObject@DebuggerCallFrame@JSC@@QBEPAVJSObject@2@XZ … … 356 353 ?tryLock@Mutex@WTF@@QAE_NXZ 357 354 ?type@DebuggerCallFrame@JSC@@QBE?AW4Type@12@XZ 358 ?unlock@JSLock@JSC@@ QAEXXZ355 ?unlock@JSLock@JSC@@SAXW4JSLockBehavior@2@@Z 359 356 ?unlock@Mutex@WTF@@QAEXXZ 360 357 ?unlockAtomicallyInitializedStaticMutex@WTF@@YAXXZ -
trunk/Source/JavaScriptCore/heap/CopiedSpace.cpp
r121058 r121098 67 67 return tryAllocateOversize(bytes, outPtr); 68 68 69 ASSERT(m_heap->globalData()->apiLock().currentThreadIsHoldingLock());70 69 m_heap->didAllocate(m_allocator.currentCapacity()); 71 70 -
trunk/Source/JavaScriptCore/heap/Heap.cpp
r121058 r121098 161 161 } 162 162 163 static inline bool isValidSharedInstanceThreadState(JSGlobalData* globalData) 164 { 165 return globalData->apiLock().currentThreadIsHoldingLock(); 163 static inline bool isValidSharedInstanceThreadState() 164 { 165 if (!JSLock::lockCount()) 166 return false; 167 168 if (!JSLock::currentThreadIsHoldingLock()) 169 return false; 170 171 return true; 166 172 } 167 173 … … 171 177 return false; 172 178 173 if (globalData->isSharedInstance() && !isValidSharedInstanceThreadState( globalData))179 if (globalData->isSharedInstance() && !isValidSharedInstanceThreadState()) 174 180 return false; 175 181 … … 322 328 { 323 329 ASSERT(k); 324 ASSERT( m_globalData->apiLock().currentThreadIsHoldingLock());330 ASSERT(JSLock::currentThreadIsHoldingLock() || !m_globalData->isSharedInstance()); 325 331 326 332 if (!k.isCell()) … … 333 339 { 334 340 ASSERT(k); 335 ASSERT( m_globalData->apiLock().currentThreadIsHoldingLock());341 ASSERT(JSLock::currentThreadIsHoldingLock() || !m_globalData->isSharedInstance()); 336 342 337 343 if (!k.isCell()) … … 687 693 688 694 GCPHASE(Collect); 689 ASSERT(globalData()->apiLock().currentThreadIsHoldingLock());690 695 ASSERT(globalData()->identifierTable == wtfThreadData().currentIdentifierTable()); 691 696 ASSERT(m_isSafeToCollect); … … 773 778 } 774 779 775 void Heap::setActivityCallback( GCActivityCallback*activityCallback)780 void Heap::setActivityCallback(PassOwnPtr<GCActivityCallback> activityCallback) 776 781 { 777 782 m_activityCallback = activityCallback; … … 780 785 GCActivityCallback* Heap::activityCallback() 781 786 { 782 return m_activityCallback ;787 return m_activityCallback.get(); 783 788 } 784 789 785 790 IncrementalSweeper* Heap::sweeper() 786 791 { 787 return m_sweeper ;792 return m_sweeper.get(); 788 793 } 789 794 -
trunk/Source/JavaScriptCore/heap/Heap.h
r121058 r121098 100 100 101 101 JS_EXPORT_PRIVATE GCActivityCallback* activityCallback(); 102 JS_EXPORT_PRIVATE void setActivityCallback( GCActivityCallback*);102 JS_EXPORT_PRIVATE void setActivityCallback(PassOwnPtr<GCActivityCallback>); 103 103 JS_EXPORT_PRIVATE void setGarbageCollectionTimerEnabled(bool); 104 104 105 JS_EXPORT_PRIVATEIncrementalSweeper* sweeper();105 IncrementalSweeper* sweeper(); 106 106 107 107 // true if an allocation or collection is in progress … … 238 238 double m_lastCodeDiscardTime; 239 239 240 OwnPtr<GCActivityCallback> m_activityCallback; 241 OwnPtr<IncrementalSweeper> m_sweeper; 242 240 243 DoublyLinkedList<ExecutableBase> m_compiledCode; 241 242 GCActivityCallback* m_activityCallback;243 IncrementalSweeper* m_sweeper;244 244 }; 245 245 -
trunk/Source/JavaScriptCore/heap/HeapTimer.cpp
r121058 r121098 27 27 #include "HeapTimer.h" 28 28 29 #include "APIShims.h"30 #include "JSObject.h"31 #include "JSString.h"32 #include "ScopeChain.h"33 29 #include <wtf/Threading.h> 34 30 … … 51 47 HeapTimer::~HeapTimer() 52 48 { 53 CFRunLoopRemoveTimer(m_runLoop.get(), m_timer.get(), kCFRunLoopCommonModes); 54 CFRunLoopTimerInvalidate(m_timer.get()); 49 invalidate(); 55 50 } 56 51 … … 66 61 void HeapTimer::invalidate() 67 62 { 68 m_globalData = 0; 69 CFRunLoopTimerSetNextFireDate(m_timer.get(), CFAbsoluteTimeGetCurrent() - s_decade); 70 } 71 72 void HeapTimer::didStartVMShutdown() 73 { 74 if (CFRunLoopGetCurrent() == m_runLoop.get()) { 75 invalidate(); 76 delete this; 77 return; 78 } 79 ASSERT(!m_globalData->apiLock().currentThreadIsHoldingLock()); 80 MutexLocker locker(m_shutdownMutex); 81 invalidate(); 63 CFRunLoopRemoveTimer(m_runLoop.get(), m_timer.get(), kCFRunLoopCommonModes); 64 CFRunLoopTimerInvalidate(m_timer.get()); 82 65 } 83 66 … … 85 68 { 86 69 HeapTimer* agent = static_cast<HeapTimer*>(info); 87 agent->m_shutdownMutex.lock(); 88 if (!agent->m_globalData) { 89 agent->m_shutdownMutex.unlock(); 90 delete agent; 91 return; 92 } 93 { 94 // We don't ref here to prevent us from resurrecting the ref count of a "dead" JSGlobalData. 95 APIEntryShim shim(agent->m_globalData, APIEntryShimWithoutLock::DontRefGlobalData); 96 agent->doWork(); 97 } 98 agent->m_shutdownMutex.unlock(); 70 agent->doWork(); 99 71 } 100 72 … … 110 82 } 111 83 112 void HeapTimer::didStartVMShutdown()113 {114 delete this;115 }116 117 84 void HeapTimer::synchronize() 118 85 { … … 123 90 } 124 91 92 125 93 #endif 126 94 -
trunk/Source/JavaScriptCore/heap/HeapTimer.h
r121058 r121098 28 28 29 29 #include <wtf/RetainPtr.h> 30 #include <wtf/Threading.h>31 30 32 31 #if USE(CF) … … 48 47 49 48 virtual ~HeapTimer(); 50 51 void didStartVMShutdown(); 49 52 50 virtual void synchronize(); 53 51 virtual void doWork() = 0; … … 62 60 RetainPtr<CFRunLoopRef> m_runLoop; 63 61 CFRunLoopTimerContext m_context; 64 65 Mutex m_shutdownMutex;66 62 #endif 67 63 -
trunk/Source/JavaScriptCore/heap/IncrementalSweeper.cpp
r121058 r121098 46 46 void IncrementalSweeper::doWork() 47 47 { 48 APIEntryShim shim(m_globalData); 48 49 doSweep(WTF::monotonicallyIncreasingTime()); 49 50 } … … 55 56 } 56 57 57 IncrementalSweeper*IncrementalSweeper::create(Heap* heap)58 PassOwnPtr<IncrementalSweeper> IncrementalSweeper::create(Heap* heap) 58 59 { 59 return new IncrementalSweeper(heap, CFRunLoopGetCurrent());60 return adoptPtr(new IncrementalSweeper(heap, CFRunLoopGetCurrent())); 60 61 } 61 62 … … 109 110 } 110 111 111 IncrementalSweeper*IncrementalSweeper::create(Heap* heap)112 PassOwnPtr<IncrementalSweeper> IncrementalSweeper::create(Heap* heap) 112 113 { 113 return new IncrementalSweeper(heap->globalData());114 return adoptPtr(new IncrementalSweeper(heap->globalData())); 114 115 } 115 116 -
trunk/Source/JavaScriptCore/heap/IncrementalSweeper.h
r121058 r121098 40 40 class IncrementalSweeper : public HeapTimer { 41 41 public: 42 static IncrementalSweeper*create(Heap*);42 static PassOwnPtr<IncrementalSweeper> create(Heap*); 43 43 void startSweeping(const HashSet<MarkedBlock*>& blockSnapshot); 44 44 virtual void doWork(); -
trunk/Source/JavaScriptCore/heap/MarkedAllocator.cpp
r121058 r121098 4 4 #include "GCActivityCallback.h" 5 5 #include "Heap.h" 6 #include "JSGlobalData.h"7 6 #include <wtf/CurrentTime.h> 8 7 … … 58 57 void* MarkedAllocator::allocateSlowCase() 59 58 { 60 ASSERT(m_heap->globalData()->apiLock().currentThreadIsHoldingLock());61 59 #if COLLECT_ON_EVERY_ALLOCATION 62 60 m_heap->collectAllGarbage(); -
trunk/Source/JavaScriptCore/heap/WeakBlock.cpp
r121058 r121098 128 128 continue; 129 129 130 if (Heap::isMarked(weakImpl->jsValue().asCell())) { 131 ASSERT(weakImpl->state() == WeakImpl::Live); 130 if (Heap::isMarked(weakImpl->jsValue().asCell())) 132 131 continue; 133 }134 132 135 133 weakImpl->setState(WeakImpl::Dead); -
trunk/Source/JavaScriptCore/jsc.cpp
r121058 r121098 300 300 EncodedJSValue JSC_HOST_CALL functionGC(ExecState* exec) 301 301 { 302 JSLock Holder lock(exec);302 JSLock lock(SilenceAssertionsOnly); 303 303 exec->heap()->collectAllGarbage(); 304 304 return JSValue::encode(jsUndefined()); … … 308 308 EncodedJSValue JSC_HOST_CALL functionReleaseExecutableMemory(ExecState* exec) 309 309 { 310 JSLock Holder lock(exec);310 JSLock lock(SilenceAssertionsOnly); 311 311 exec->globalData().releaseExecutableMemory(); 312 312 return JSValue::encode(jsUndefined()); … … 668 668 int jscmain(int argc, char** argv) 669 669 { 670 670 JSLock lock(SilenceAssertionsOnly); 671 671 672 RefPtr<JSGlobalData> globalData = JSGlobalData::create(ThreadStackTypeLarge, LargeHeap); 672 JSLockHolder lock(globalData.get());673 673 674 674 CommandLine options; -
trunk/Source/JavaScriptCore/runtime/Completion.cpp
r121058 r121098 38 38 bool checkSyntax(ExecState* exec, const SourceCode& source, JSValue* returnedException) 39 39 { 40 JSLock Holderlock(exec);40 JSLock lock(exec); 41 41 ASSERT(exec->globalData().identifierTable == wtfThreadData().currentIdentifierTable()); 42 42 … … 54 54 JSValue evaluate(ExecState* exec, ScopeChainNode* scopeChain, const SourceCode& source, JSValue thisValue, JSValue* returnedException) 55 55 { 56 JSLock Holderlock(exec);56 JSLock lock(exec); 57 57 ASSERT(exec->globalData().identifierTable == wtfThreadData().currentIdentifierTable()); 58 58 if (exec->globalData().isCollectorBusy()) -
trunk/Source/JavaScriptCore/runtime/GCActivityCallback.h
r121058 r121098 70 70 class DefaultGCActivityCallback : public GCActivityCallback { 71 71 public: 72 static DefaultGCActivityCallback*create(Heap*);72 static PassOwnPtr<DefaultGCActivityCallback> create(Heap*); 73 73 74 74 DefaultGCActivityCallback(Heap*); … … 92 92 }; 93 93 94 inline DefaultGCActivityCallback*DefaultGCActivityCallback::create(Heap* heap)94 inline PassOwnPtr<DefaultGCActivityCallback> DefaultGCActivityCallback::create(Heap* heap) 95 95 { 96 return new DefaultGCActivityCallback(heap);96 return adoptPtr(new DefaultGCActivityCallback(heap)); 97 97 } 98 98 -
trunk/Source/JavaScriptCore/runtime/JSGlobalData.cpp
r121058 r121098 35 35 #include "DebuggerActivation.h" 36 36 #include "FunctionConstructor.h" 37 #include "GCActivityCallback.h"38 37 #include "GetterSetter.h" 39 38 #include "HostCallReturnValue.h" 40 #include "IncrementalSweeper.h"41 39 #include "Interpreter.h" 42 40 #include "JSActivation.h" … … 181 179 interpreter = new Interpreter; 182 180 181 if (isSharedInstance()) 182 turnOffVerifier(); 183 183 184 // Need to be careful to keep everything consistent here 184 JSLockHolder lock(this);185 185 IdentifierTable* existingEntryIdentifierTable = wtfThreadData().setCurrentIdentifierTable(identifierTable); 186 JSLock lock(SilenceAssertionsOnly); 186 187 structureStructure.set(*this, Structure::createStructure(*this)); 187 188 debuggerActivationStructure.set(*this, DebuggerActivation::createStructure(*this, 0, jsNull())); … … 222 223 JSGlobalData::~JSGlobalData() 223 224 { 224 ASSERT(!m_apiLock.currentThreadIsHoldingLock());225 heap.activityCallback()->didStartVMShutdown();226 heap.sweeper()->didStartVMShutdown();227 225 heap.lastChanceToFinalize(); 228 226 … … 314 312 JSGlobalData& JSGlobalData::sharedInstance() 315 313 { 316 GlobalJSLock globalLock;317 314 JSGlobalData*& instance = sharedInstanceInternal(); 318 315 if (!instance) { … … 325 322 JSGlobalData*& JSGlobalData::sharedInstanceInternal() 326 323 { 324 ASSERT(JSLock::currentThreadIsHoldingLock()); 327 325 static JSGlobalData* sharedInstance; 328 326 return sharedInstance; -
trunk/Source/JavaScriptCore/runtime/JSGlobalData.h
r121058 r121098 36 36 #include "Intrinsic.h" 37 37 #include "JITStubs.h" 38 #include "JSLock.h"39 38 #include "JSValue.h" 40 39 #include "LLIntData.h" … … 48 47 #include <wtf/Forward.h> 49 48 #include <wtf/HashMap.h> 49 #include <wtf/RefCounted.h> 50 50 #include <wtf/SimpleStats.h> 51 #include <wtf/ThreadSafeRefCounted.h>52 51 #include <wtf/ThreadSpecific.h> 53 52 #include <wtf/WTFThreadData.h> … … 154 153 #endif 155 154 156 class JSGlobalData : public ThreadSafeRefCounted<JSGlobalData> {155 class JSGlobalData : public RefCounted<JSGlobalData> { 157 156 public: 158 157 // WebCore has a one-to-one mapping of threads to JSGlobalDatas; … … 182 181 void makeUsableFromMultipleThreads() { heap.machineThreads().makeUsableFromMultipleThreads(); } 183 182 184 private:185 JSLock m_apiLock;186 187 public:188 183 Heap heap; // The heap is our first data member to ensure that it's destructed after all the objects that reference it. 189 184 … … 415 410 #undef registerTypedArrayFunction 416 411 417 JSLock& apiLock() { return m_apiLock; }418 419 412 private: 420 413 friend class LLIntOffsetsExtractor; -
trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp
r121058 r121098 115 115 JSGlobalObject::~JSGlobalObject() 116 116 { 117 ASSERT(JSLock::currentThreadIsHoldingLock()); 118 117 119 if (m_debugger) 118 120 m_debugger->detach(this); … … 129 131 void JSGlobalObject::init(JSObject* thisValue) 130 132 { 131 ASSERT( globalData().apiLock().currentThreadIsHoldingLock());133 ASSERT(JSLock::currentThreadIsHoldingLock()); 132 134 133 135 m_globalScopeChain.set(globalData(), this, ScopeChainNode::create(0, this, &globalData(), this, thisValue)); -
trunk/Source/JavaScriptCore/runtime/JSLock.cpp
r121058 r121098 24 24 #include "Heap.h" 25 25 #include "CallFrame.h" 26 #include "JSGlobalObject.h"27 26 #include "JSObject.h" 28 27 #include "ScopeChain.h" … … 40 39 41 40 // Acquire this mutex before accessing lock-related data. 42 static pthread_mutex_t giantGlobalJSLock = PTHREAD_MUTEX_INITIALIZER; 43 44 GlobalJSLock::GlobalJSLock() 45 { 46 pthread_mutex_lock(&giantGlobalJSLock); 47 } 48 49 GlobalJSLock::~GlobalJSLock() 50 { 51 pthread_mutex_unlock(&giantGlobalJSLock); 52 } 53 54 JSLockHolder::JSLockHolder(ExecState* exec) 55 : m_globalData(&exec->globalData()) 56 { 57 m_globalData->apiLock().lock(); 58 } 59 60 JSLockHolder::JSLockHolder(JSGlobalData* globalData) 61 : m_globalData(globalData) 62 { 63 m_globalData->apiLock().lock(); 64 } 65 66 JSLockHolder::JSLockHolder(JSGlobalData& globalData) 67 : m_globalData(&globalData) 68 { 69 m_globalData->apiLock().lock(); 70 } 71 72 JSLockHolder::~JSLockHolder() 73 { 74 m_globalData->apiLock().unlock(); 75 } 76 77 JSLock::JSLock() 78 : m_lockCount(0) 79 { 80 m_spinLock.Init(); 81 } 82 83 JSLock::~JSLock() 84 { 85 } 86 87 void JSLock::lock() 88 { 89 ThreadIdentifier currentThread = WTF::currentThread(); 90 { 91 SpinLockHolder holder(&m_spinLock); 92 if (m_ownerThread == currentThread && m_lockCount) { 93 m_lockCount++; 94 return; 95 } 96 } 97 98 m_lock.lock(); 99 100 SpinLockHolder holder(&m_spinLock); 101 m_ownerThread = currentThread; 102 ASSERT(!m_lockCount); 103 m_lockCount = 1; 104 } 105 106 void JSLock::unlock() 107 { 108 ASSERT(currentThreadIsHoldingLock()); 109 110 SpinLockHolder holder(&m_spinLock); 111 m_lockCount--; 112 113 if (!m_lockCount) 114 m_lock.unlock(); 41 static pthread_mutex_t JSMutex = PTHREAD_MUTEX_INITIALIZER; 42 43 // Thread-specific key that tells whether a thread holds the JSMutex, and how many times it was taken recursively. 44 pthread_key_t JSLockCount; 45 46 static void createJSLockCount() 47 { 48 pthread_key_create(&JSLockCount, 0); 49 } 50 51 pthread_once_t createJSLockCountOnce = PTHREAD_ONCE_INIT; 52 53 // Lock nesting count. 54 intptr_t JSLock::lockCount() 55 { 56 pthread_once(&createJSLockCountOnce, createJSLockCount); 57 58 return reinterpret_cast<intptr_t>(pthread_getspecific(JSLockCount)); 59 } 60 61 static void setLockCount(intptr_t count) 62 { 63 ASSERT(count >= 0); 64 pthread_setspecific(JSLockCount, reinterpret_cast<void*>(count)); 65 } 66 67 JSLock::JSLock(ExecState* exec) 68 : m_lockBehavior(exec->globalData().isSharedInstance() ? LockForReal : SilenceAssertionsOnly) 69 { 70 lock(m_lockBehavior); 71 } 72 73 JSLock::JSLock(JSGlobalData* globalData) 74 : m_lockBehavior(globalData->isSharedInstance() ? LockForReal : SilenceAssertionsOnly) 75 { 76 lock(m_lockBehavior); 77 } 78 79 void JSLock::lock(JSLockBehavior lockBehavior) 80 { 81 #ifdef NDEBUG 82 // Locking "not for real" is a debug-only feature. 83 if (lockBehavior == SilenceAssertionsOnly) 84 return; 85 #endif 86 87 pthread_once(&createJSLockCountOnce, createJSLockCount); 88 89 intptr_t currentLockCount = lockCount(); 90 if (!currentLockCount && lockBehavior == LockForReal) { 91 int result = pthread_mutex_lock(&JSMutex); 92 ASSERT_UNUSED(result, !result); 93 } 94 setLockCount(currentLockCount + 1); 95 } 96 97 void JSLock::unlock(JSLockBehavior lockBehavior) 98 { 99 ASSERT(lockCount()); 100 101 #ifdef NDEBUG 102 // Locking "not for real" is a debug-only feature. 103 if (lockBehavior == SilenceAssertionsOnly) 104 return; 105 #endif 106 107 intptr_t newLockCount = lockCount() - 1; 108 setLockCount(newLockCount); 109 if (!newLockCount && lockBehavior == LockForReal) { 110 int result = pthread_mutex_unlock(&JSMutex); 111 ASSERT_UNUSED(result, !result); 112 } 115 113 } 116 114 117 115 void JSLock::lock(ExecState* exec) 118 116 { 119 exec->globalData().apiLock().lock();117 lock(exec->globalData().isSharedInstance() ? LockForReal : SilenceAssertionsOnly); 120 118 } 121 119 122 120 void JSLock::unlock(ExecState* exec) 123 121 { 124 exec->globalData().apiLock().unlock();122 unlock(exec->globalData().isSharedInstance() ? LockForReal : SilenceAssertionsOnly); 125 123 } 126 124 127 125 bool JSLock::currentThreadIsHoldingLock() 128 126 { 129 return m_lockCount && m_ownerThread == WTF::currentThread(); 127 pthread_once(&createJSLockCountOnce, createJSLockCount); 128 return !!pthread_getspecific(JSLockCount); 130 129 } 131 130 … … 151 150 // write over the second thread's call frames. 152 151 // 153 // Toavoid JS stack corruption we enforce a policy of only ever allowing two152 // In avoid JS stack corruption we enforce a policy of only ever allowing two 154 153 // threads to use a JS context concurrently, and only allowing the second of 155 154 // these threads to execute until it has completed and fully returned from its … … 160 159 // again through a callback, then the locks will not be dropped when DropAllLocks 161 160 // is called (since lockDropDepth is non-zero). Since this thread is still holding 162 // the locks, only it will be able to re-enter JSC (either be returning from the161 // the locks, only it will re able to re-enter JSC (either be returning from the 163 162 // callback, or by re-entering through another call to evaulate script or call 164 163 // function). … … 170 169 // would likely increase complexity and overhead. 171 170 // 172 173 // This function returns the number of locks that were dropped. 174 unsigned JSLock::dropAllLocks() 175 { 176 if (m_lockDropDepth++) 177 return 0; 178 179 return dropAllLocksUnconditionally(); 180 } 181 182 unsigned JSLock::dropAllLocksUnconditionally() 183 { 184 unsigned lockCount = m_lockCount; 185 for (unsigned i = 0; i < lockCount; i++) 186 unlock(); 187 188 return lockCount; 189 } 190 191 void JSLock::grabAllLocks(unsigned lockCount) 192 { 193 for (unsigned i = 0; i < lockCount; i++) 194 lock(); 195 196 m_lockDropDepth--; 197 } 171 static unsigned lockDropDepth = 0; 198 172 199 173 JSLock::DropAllLocks::DropAllLocks(ExecState* exec) 200 : m_lockCount(0) 201 , m_globalData(&exec->globalData()) 202 { 203 m_lockCount = m_globalData->apiLock().dropAllLocks(); 204 } 205 206 JSLock::DropAllLocks::DropAllLocks(JSGlobalData* globalData) 207 : m_lockCount(0) 208 , m_globalData(globalData) 209 { 210 m_lockCount = m_globalData->apiLock().dropAllLocks(); 174 : m_lockBehavior(exec->globalData().isSharedInstance() ? LockForReal : SilenceAssertionsOnly) 175 { 176 pthread_once(&createJSLockCountOnce, createJSLockCount); 177 178 if (lockDropDepth++) { 179 m_lockCount = 0; 180 return; 181 } 182 183 m_lockCount = JSLock::lockCount(); 184 for (intptr_t i = 0; i < m_lockCount; i++) 185 JSLock::unlock(m_lockBehavior); 186 } 187 188 JSLock::DropAllLocks::DropAllLocks(JSLockBehavior JSLockBehavior) 189 : m_lockBehavior(JSLockBehavior) 190 { 191 pthread_once(&createJSLockCountOnce, createJSLockCount); 192 193 if (lockDropDepth++) { 194 m_lockCount = 0; 195 return; 196 } 197 198 // It is necessary to drop even "unreal" locks, because having a non-zero lock count 199 // will prevent a real lock from being taken. 200 201 m_lockCount = JSLock::lockCount(); 202 for (intptr_t i = 0; i < m_lockCount; i++) 203 JSLock::unlock(m_lockBehavior); 211 204 } 212 205 213 206 JSLock::DropAllLocks::~DropAllLocks() 214 207 { 215 m_globalData->apiLock().grabAllLocks(m_lockCount); 208 for (intptr_t i = 0; i < m_lockCount; i++) 209 JSLock::lock(m_lockBehavior); 210 211 --lockDropDepth; 216 212 } 217 213 218 214 #else // (OS(DARWIN) || USE(PTHREADS)) 219 215 220 GlobalJSLock::GlobalJSLock() 221 { 222 } 223 224 GlobalJSLock::~GlobalJSLock() 225 { 226 } 227 228 JSLockHolder::JSLockHolder(JSGlobalData*) 229 { 230 } 231 232 JSLockHolder::JSLockHolder(JSGlobalData&) 233 { 234 } 235 236 JSLockHolder::JSLockHolder(ExecState*) 237 { 238 } 239 240 JSLockHolder::~JSLockHolder() 241 { 242 } 243 244 JSLock::JSLock() 245 { 246 } 247 248 JSLock::~JSLock() 249 { 216 JSLock::JSLock(ExecState*) 217 : m_lockBehavior(SilenceAssertionsOnly) 218 { 219 } 220 221 // If threading support is off, set the lock count to a constant value of 1 so ssertions 222 // that the lock is held don't fail 223 intptr_t JSLock::lockCount() 224 { 225 return 1; 250 226 } 251 227 … … 255 231 } 256 232 257 void JSLock::lock( )258 { 259 } 260 261 void JSLock::unlock( )233 void JSLock::lock(JSLockBehavior) 234 { 235 } 236 237 void JSLock::unlock(JSLockBehavior) 262 238 { 263 239 } … … 271 247 } 272 248 273 void JSLock::lock(JSGlobalData&)274 {275 }276 277 void JSLock::unlock(JSGlobalData&)278 {279 }280 281 unsigned JSLock::dropAllLocks()282 {283 return 0;284 }285 286 unsigned JSLock::dropAllLocksUnconditionally()287 {288 return 0;289 }290 291 void JSLock::grabAllLocks(unsigned)292 {293 }294 295 249 JSLock::DropAllLocks::DropAllLocks(ExecState*) 296 250 { 297 251 } 298 252 299 JSLock::DropAllLocks::DropAllLocks(JS GlobalData*)253 JSLock::DropAllLocks::DropAllLocks(JSLockBehavior) 300 254 { 301 255 } -
trunk/Source/JavaScriptCore/runtime/JSLock.h
r121058 r121098 24 24 #include <wtf/Assertions.h> 25 25 #include <wtf/Noncopyable.h> 26 #include <wtf/RefPtr.h>27 #include <wtf/TCSpinLock.h>28 #include <wtf/Threading.h>29 26 30 27 namespace JSC { … … 34 31 // JavaScript data structure or that interacts with shared state 35 32 // such as the protect count hash table. The simplest way to lock 36 // is to create a local JSLockHolder object in the scope where the lock 37 // must be held and pass it the context that requires protection. 38 // The lock is recursive so nesting is ok. The JSLock 33 // is to create a local JSLock object in the scope where the lock 34 // must be held. The lock is recursive so nesting is ok. The JSLock 39 35 // object also acts as a convenience short-hand for running important 40 36 // initialization routines. … … 49 45 // thread acquired it to begin with. 50 46 47 // For contexts other than the single shared one, implicit locking is not done, 48 // but we still need to perform all the counting in order to keep debug 49 // assertions working, so that clients that use the shared context don't break. 50 51 51 class ExecState; 52 52 class JSGlobalData; 53 53 54 // This class is used to protect the initialization of the legacy single 55 // shared JSGlobalData. 56 class GlobalJSLock { 57 WTF_MAKE_NONCOPYABLE(GlobalJSLock); 58 public: 59 JS_EXPORT_PRIVATE GlobalJSLock(); 60 JS_EXPORT_PRIVATE ~GlobalJSLock(); 61 }; 62 63 class JSLockHolder { 64 public: 65 JS_EXPORT_PRIVATE JSLockHolder(JSGlobalData*); 66 JS_EXPORT_PRIVATE JSLockHolder(JSGlobalData&); 67 JS_EXPORT_PRIVATE JSLockHolder(ExecState*); 68 69 JS_EXPORT_PRIVATE ~JSLockHolder(); 70 private: 71 RefPtr<JSGlobalData> m_globalData; 72 }; 54 enum JSLockBehavior { SilenceAssertionsOnly, LockForReal }; 73 55 74 56 class JSLock { 75 57 WTF_MAKE_NONCOPYABLE(JSLock); 76 58 public: 77 JS Lock();78 JS _EXPORT_PRIVATE ~JSLock();59 JS_EXPORT_PRIVATE JSLock(ExecState*); 60 JSLock(JSGlobalData*); 79 61 80 JS_EXPORT_PRIVATE void lock(); 81 JS_EXPORT_PRIVATE void unlock(); 62 JSLock(JSLockBehavior lockBehavior) 63 : m_lockBehavior(lockBehavior) 64 { 65 #ifdef NDEBUG 66 // Locking "not for real" is a debug-only feature. 67 if (lockBehavior == SilenceAssertionsOnly) 68 return; 69 #endif 70 lock(lockBehavior); 71 } 82 72 73 ~JSLock() 74 { 75 #ifdef NDEBUG 76 // Locking "not for real" is a debug-only feature. 77 if (m_lockBehavior == SilenceAssertionsOnly) 78 return; 79 #endif 80 unlock(m_lockBehavior); 81 } 82 83 JS_EXPORT_PRIVATE static void lock(JSLockBehavior); 84 JS_EXPORT_PRIVATE static void unlock(JSLockBehavior); 83 85 static void lock(ExecState*); 84 86 static void unlock(ExecState*); 85 static void lock(JSGlobalData&);86 static void unlock(JSGlobalData&);87 87 88 JS_EXPORT_PRIVATE bool currentThreadIsHoldingLock(); 88 JS_EXPORT_PRIVATE static intptr_t lockCount(); 89 JS_EXPORT_PRIVATE static bool currentThreadIsHoldingLock(); 89 90 90 unsigned dropAllLocks(); 91 unsigned dropAllLocksUnconditionally(); 92 void grabAllLocks(unsigned lockCount); 93 94 SpinLock m_spinLock; 95 Mutex m_lock; 96 ThreadIdentifier m_ownerThread; 97 intptr_t m_lockCount; 98 unsigned m_lockDropDepth; 91 JSLockBehavior m_lockBehavior; 99 92 100 93 class DropAllLocks { … … 102 95 public: 103 96 JS_EXPORT_PRIVATE DropAllLocks(ExecState* exec); 104 JS_EXPORT_PRIVATE DropAllLocks(JS GlobalData*);97 JS_EXPORT_PRIVATE DropAllLocks(JSLockBehavior); 105 98 JS_EXPORT_PRIVATE ~DropAllLocks(); 106 99 107 100 private: 108 101 intptr_t m_lockCount; 109 RefPtr<JSGlobalData> m_globalData;102 JSLockBehavior m_lockBehavior; 110 103 }; 111 104 }; -
trunk/Source/JavaScriptCore/runtime/WeakGCMap.h
r121058 r121098 76 76 } 77 77 78 void set(JSGlobalData& globalData, const KeyType& key, ExternalType value)78 void set(JSGlobalData&, const KeyType& key, ExternalType value) 79 79 { 80 ASSERT_UNUSED(globalData, globalData.apiLock().currentThreadIsHoldingLock());81 80 typename MapType::AddResult result = m_map.add(key, 0); 82 81 if (!result.isNewEntry) -
trunk/Source/JavaScriptCore/testRegExp.cpp
r121058 r121098 496 496 int realMain(int argc, char** argv) 497 497 { 498 JSLock lock(SilenceAssertionsOnly); 499 498 500 RefPtr<JSGlobalData> globalData = JSGlobalData::create(ThreadStackTypeLarge, LargeHeap); 499 JSLockHolder lock(globalData.get());500 501 501 502 CommandLine options;
Note:
See TracChangeset
for help on using the changeset viewer.