Changeset 121058 in webkit for trunk/Source/JavaScriptCore


Ignore:
Timestamp:
Jun 22, 2012, 2:42:46 PM (13 years ago)
Author:
[email protected]
Message:

JSLock should be per-JSGlobalData
https://bugs.webkit.org/show_bug.cgi?id=89123

Reviewed by Gavin Barraclough.

Source/JavaScriptCore:

  • JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def:
  • API/APIShims.h:

(APIEntryShimWithoutLock):
(JSC::APIEntryShimWithoutLock::APIEntryShimWithoutLock): Added an extra parameter to the constructor to
determine whether we should ref the JSGlobalData or not. We want to ref all the time except for in the
HeapTimer class because timerDidFire could run after somebody has started to tear down that particular
JSGlobalData, so we wouldn't want to resurrect the ref count of that JSGlobalData from 0 back to 1 after
its destruction has begun.
(JSC::APIEntryShimWithoutLock::~APIEntryShimWithoutLock): Now derefs if it also refed.
(JSC::APIEntryShim::APIEntryShim):
(APIEntryShim):
(JSC::APIEntryShim::~APIEntryShim):
(JSC::APIEntryShim::init): Factored out common initialization code for the various APIEntryShim constructors.
Also moved the timeoutChecker stop and start here because we need to start after we've grabbed the API lock
and before we've released it, which can only done in APIEntryShim.
(JSC::APICallbackShim::~APICallbackShim): We no longer need to synchronize here.

  • API/JSContextRef.cpp:

(JSGlobalContextCreate):
(JSGlobalContextCreateInGroup):
(JSGlobalContextRelease):
(JSContextCreateBacktrace):

  • heap/CopiedSpace.cpp:

(JSC::CopiedSpace::tryAllocateSlowCase):

  • heap/Heap.cpp:

(JSC::Heap::protect):
(JSC::Heap::unprotect):
(JSC::Heap::collect):
(JSC::Heap::setActivityCallback):
(JSC::Heap::activityCallback):
(JSC::Heap::sweeper):

  • heap/Heap.h: Changed m_activityCallback and m_sweeper to be raw pointers rather than OwnPtrs because they

are now responsible for their own lifetime. Also changed the order of declaration of the GCActivityCallback
and the IncrementalSweeper to make sure they're the last things that get initialized during construction to
prevent any issues with uninitialized memory in the JSGlobalData/Heap they might care about.
(Heap):

  • heap/HeapTimer.cpp: Refactored to allow for thread-safe operation and shutdown.

(JSC::HeapTimer::~HeapTimer):
(JSC::HeapTimer::invalidate):
(JSC):
(JSC::HeapTimer::didStartVMShutdown): Called at the beginning of ~JSGlobalData. If we're on the same thread
that the HeapTimer is running on, we kill the HeapTimer ourselves. If not, then we set some state in the
HeapTimer and schedule it to fire immediately so that it can notice and kill itself.
(JSC::HeapTimer::timerDidFire): We grab our mutex and check our JSGlobalData pointer. If it has been zero-ed
out, then we know the VM has started to shutdown and we should kill ourselves. Otherwise, grab the APIEntryShim,
but without ref-ing the JSGlobalData (we don't want to bring the JSGlobalData's ref-count from 0 to 1) in case
we were interrupted between releasing our mutex and trying to grab the APILock.

  • heap/HeapTimer.h:

(HeapTimer):

  • heap/IncrementalSweeper.cpp:

(JSC::IncrementalSweeper::doWork): We no longer need the API shim here since HeapTimer::timerDidFire handles
all of that for us.
(JSC::IncrementalSweeper::create):

  • heap/IncrementalSweeper.h:

(IncrementalSweeper):

  • heap/MarkedAllocator.cpp:

(JSC::MarkedAllocator::allocateSlowCase):

  • heap/WeakBlock.cpp:

(JSC::WeakBlock::reap):

  • jsc.cpp:

(functionGC):
(functionReleaseExecutableMemory):
(jscmain):

  • runtime/Completion.cpp:

(JSC::checkSyntax):
(JSC::evaluate):

  • runtime/GCActivityCallback.h:

(DefaultGCActivityCallback):
(JSC::DefaultGCActivityCallback::create):

  • runtime/JSGlobalData.cpp:

(JSC::JSGlobalData::JSGlobalData):
(JSC::JSGlobalData::~JSGlobalData): Signals to the two HeapTimers (GCActivityCallback and IncrementalSweeper)
that the VM has started shutting down. It then waits until the HeapTimer is done with whatever activity
it needs to do before continuing with any further destruction. Also asserts that we do not currently hold the
APILock because this could potentially cause deadlock when we try to signal to the HeapTimers using their mutexes.
(JSC::JSGlobalData::sharedInstance): Protect the initialization for the shared instance with the GlobalJSLock.
(JSC::JSGlobalData::sharedInstanceInternal):

  • runtime/JSGlobalData.h: Change to be ThreadSafeRefCounted so that we don't have to worry about refing and

de-refing JSGlobalDatas on separate threads since we don't do it that often anyways.
(JSGlobalData):
(JSC::JSGlobalData::apiLock):

  • runtime/JSGlobalObject.cpp:

(JSC::JSGlobalObject::~JSGlobalObject):
(JSC::JSGlobalObject::init):

  • runtime/JSLock.cpp:

(JSC):
(JSC::GlobalJSLock::GlobalJSLock): For accessing the shared instance.
(JSC::GlobalJSLock::~GlobalJSLock):
(JSC::JSLockHolder::JSLockHolder): MutexLocker for JSLock. Also refs the JSGlobalData to keep it alive so that
it can successfully unlock it later without it disappearing from underneath it.
(JSC::JSLockHolder::~JSLockHolder):
(JSC::JSLock::JSLock):
(JSC::JSLock::~JSLock):
(JSC::JSLock::lock): Uses the spin lock for guarding the lock count and owner thread fields. Uses the mutex for
actually waiting for long periods.
(JSC::JSLock::unlock):
(JSC::JSLock::currentThreadIsHoldingLock):
(JSC::JSLock::dropAllLocks):
(JSC::JSLock::dropAllLocksUnconditionally):
(JSC::JSLock::grabAllLocks):
(JSC::JSLock::DropAllLocks::DropAllLocks):
(JSC::JSLock::DropAllLocks::~DropAllLocks):

  • runtime/JSLock.h:

(JSC):
(GlobalJSLock):
(JSLockHolder):
(JSLock):
(DropAllLocks):

  • runtime/WeakGCMap.h:

(JSC::WeakGCMap::set):

  • testRegExp.cpp:

(realMain):

Source/WebCore:

No new tests. Current regression tests are sufficient.

Changed all sites that used JSLock to instead use the new JSLockHolder
and pass in the correct JS context that the code is about to interact with that
needs protection. Also added a couple JSLocks to places that didn't already
have it that needed it.

  • bindings/js/GCController.cpp:

(WebCore::collect):
(WebCore::GCController::garbageCollectSoon):
(WebCore::GCController::garbageCollectNow):
(WebCore::GCController::discardAllCompiledCode):

  • bindings/js/JSCustomSQLStatementErrorCallback.cpp:

(WebCore::JSSQLStatementErrorCallback::handleEvent):

  • bindings/js/JSCustomVoidCallback.cpp:

(WebCore::JSCustomVoidCallback::handleEvent):

  • bindings/js/JSCustomXPathNSResolver.cpp:

(WebCore::JSCustomXPathNSResolver::lookupNamespaceURI):

  • bindings/js/JSErrorHandler.cpp:

(WebCore::JSErrorHandler::handleEvent):

  • bindings/js/JSEventCustom.cpp:

(WebCore::toJS):

  • bindings/js/JSEventListener.cpp:

(WebCore::JSEventListener::handleEvent):

  • bindings/js/JSInjectedScriptHostCustom.cpp:

(WebCore::InjectedScriptHost::nodeAsScriptValue):
(WebCore::JSInjectedScriptHost::inspectedObject):

  • bindings/js/JSInjectedScriptManager.cpp:

(WebCore::InjectedScriptManager::createInjectedScript):
(WebCore::InjectedScriptManager::canAccessInspectedWindow):

  • bindings/js/JSLazyEventListener.cpp:

(WebCore::JSLazyEventListener::initializeJSFunction):

  • bindings/js/JSMainThreadExecState.h:

(WebCore::JSMainThreadExecState::evaluate):

  • bindings/js/JSMutationCallbackCustom.cpp:

(WebCore::JSMutationCallback::handleEvent):

  • bindings/js/JSNodeFilterCondition.cpp:

(WebCore::JSNodeFilterCondition::acceptNode):

  • bindings/js/JSRequestAnimationFrameCallbackCustom.cpp:

(WebCore::JSRequestAnimationFrameCallback::handleEvent):

  • bindings/js/JavaScriptCallFrame.cpp:

(WebCore::JavaScriptCallFrame::evaluate):

  • bindings/js/PageScriptDebugServer.cpp:

(WebCore::PageScriptDebugServer::recompileAllJSFunctions):

  • bindings/js/ScheduledAction.cpp:

(WebCore::ScheduledAction::executeFunctionInContext):

  • bindings/js/ScriptCachedFrameData.cpp:

(WebCore::ScriptCachedFrameData::ScriptCachedFrameData):
(WebCore::ScriptCachedFrameData::restore):
(WebCore::ScriptCachedFrameData::clear):

  • bindings/js/ScriptController.cpp:

(WebCore::ScriptController::evaluateInWorld):
(WebCore::ScriptController::clearWindowShell):
(WebCore::ScriptController::initScript):
(WebCore::ScriptController::updateDocument):
(WebCore::ScriptController::cacheableBindingRootObject):
(WebCore::ScriptController::bindingRootObject):
(WebCore::ScriptController::windowScriptNPObject):
(WebCore::ScriptController::jsObjectForPluginElement):
(WebCore::ScriptController::clearScriptObjects):

  • bindings/js/ScriptControllerMac.mm:

(WebCore::ScriptController::windowScriptObject):

  • bindings/js/ScriptDebugServer.cpp:

(WebCore::ScriptDebugServer::dispatchDidPause):

  • bindings/js/ScriptEventListener.cpp:

(WebCore::eventListenerHandlerBody):
(WebCore::eventListenerHandlerLocation):

  • bindings/js/ScriptFunctionCall.cpp:

(WebCore::ScriptCallArgumentHandler::appendArgument):
(WebCore::ScriptFunctionCall::call):
(WebCore::ScriptFunctionCall::construct):
(WebCore::ScriptCallback::call):

  • bindings/js/ScriptObject.cpp:

(WebCore::ScriptGlobalObject::set):
(WebCore::ScriptGlobalObject::get):
(WebCore::ScriptGlobalObject::remove):

  • bindings/js/ScriptValue.cpp:

(WebCore::ScriptValue::getString):
(WebCore::ScriptValue::toInspectorValue):

  • bindings/js/WorkerScriptController.cpp:

(WebCore::WorkerScriptController::~WorkerScriptController):
(WebCore::WorkerScriptController::initScript):
(WebCore::WorkerScriptController::evaluate):
(WebCore::WorkerScriptController::disableEval):

  • bindings/objc/WebScriptObject.mm:

(_didExecute):
(-[WebScriptObject _setImp:originRootObject:rootObject:]):
(-[WebScriptObject _setOriginRootObject:andRootObject:]):
(-[WebScriptObject dealloc]):
(-[WebScriptObject finalize]):
(-[WebScriptObject callWebScriptMethod:withArguments:]):
(-[WebScriptObject evaluateWebScript:]):
(-[WebScriptObject setValue:forKey:]):
(-[WebScriptObject valueForKey:]):
(-[WebScriptObject removeWebScriptKey:]):
(-[WebScriptObject hasWebScriptKey:]):
(-[WebScriptObject stringRepresentation]):
(-[WebScriptObject webScriptValueAtIndex:]):
(-[WebScriptObject setWebScriptValueAtIndex:value:]):
(+[WebScriptObject _convertValueToObjcValue:originRootObject:rootObject:]):

  • bindings/scripts/CodeGeneratorJS.pm:

(GenerateCallbackImplementation):

  • bindings/scripts/test/JS/JSTestCallback.cpp:

(WebCore::JSTestCallback::callbackWithNoParam):
(WebCore::JSTestCallback::callbackWithClass1Param):
(WebCore::JSTestCallback::callbackWithClass2Param):
(WebCore::JSTestCallback::callbackWithStringList):
(WebCore::JSTestCallback::callbackWithBoolean):
(WebCore::JSTestCallback::callbackRequiresThisToPass):

  • bridge/NP_jsobject.cpp:

(_NPN_InvokeDefault):
(_NPN_Invoke):
(_NPN_Evaluate):
(_NPN_GetProperty):
(_NPN_SetProperty):
(_NPN_RemoveProperty):
(_NPN_HasProperty):
(_NPN_HasMethod):
(_NPN_Enumerate):
(_NPN_Construct):

  • bridge/c/c_class.cpp:

(JSC::Bindings::CClass::~CClass):
(JSC::Bindings::CClass::methodsNamed):
(JSC::Bindings::CClass::fieldNamed):

  • bridge/c/c_instance.cpp:

(JSC::Bindings::CInstance::moveGlobalExceptionToExecState):
(JSC::Bindings::CInstance::invokeMethod):
(JSC::Bindings::CInstance::invokeDefaultMethod):
(JSC::Bindings::CInstance::invokeConstruct):
(JSC::Bindings::CInstance::getPropertyNames):

  • bridge/c/c_runtime.cpp:

(JSC::Bindings::CField::valueFromInstance):
(JSC::Bindings::CField::setValueToInstance):

  • bridge/c/c_utility.cpp:

(JSC::Bindings::convertValueToNPVariant):
(JSC::Bindings::convertNPVariantToValue):

  • bridge/jni/jni_jsobject.mm:

(JavaJSObject::call):
(JavaJSObject::eval):
(JavaJSObject::getMember):
(JavaJSObject::setMember):
(JavaJSObject::removeMember):
(JavaJSObject::getSlot):
(JavaJSObject::setSlot):
(JavaJSObject::toString):
(JavaJSObject::convertValueToJObject):
(JavaJSObject::convertJObjectToValue):

  • bridge/jni/jni_objc.mm:

(JSC::Bindings::dispatchJNICall):

  • bridge/jni/jsc/JNIUtilityPrivate.cpp:

(JSC::Bindings::convertValueToJValue):

  • bridge/jni/jsc/JavaClassJSC.cpp:

(JavaClass::JavaClass):
(JavaClass::~JavaClass):

  • bridge/jni/jsc/JavaInstanceJSC.cpp:

(JavaInstance::stringValue):

  • bridge/jni/jsc/JavaMethodJSC.cpp:

(appendClassName):
(JavaMethod::signature):

  • bridge/jni/jsc/JavaStringJSC.h:

(JSC::Bindings::JavaString::JavaString):
(JSC::Bindings::JavaString::~JavaString):
(JSC::Bindings::JavaString::utf8):
(JSC::Bindings::JavaString::init):

  • bridge/jsc/BridgeJSC.cpp:

(JSC::Bindings::Instance::createRuntimeObject):
(JSC::Bindings::Instance::newRuntimeObject):

  • bridge/objc/objc_instance.mm:

(ObjcInstance::moveGlobalExceptionToExecState):
(ObjcInstance::invokeObjcMethod):
(ObjcInstance::invokeDefaultMethod):
(ObjcInstance::setValueOfUndefinedField):
(ObjcInstance::getValueOfUndefinedField):

  • bridge/objc/objc_runtime.mm:

(JSC::Bindings::ObjcField::valueFromInstance):
(JSC::Bindings::ObjcField::setValueToInstance):

  • bridge/objc/objc_utility.mm:

(JSC::Bindings::convertValueToObjcValue):
(JSC::Bindings::convertNSStringToString):
(JSC::Bindings::convertObjcValueToValue):

  • bridge/qt/qt_instance.cpp:

(JSC::Bindings::QtInstance::~QtInstance):
(JSC::Bindings::QtInstance::getQtInstance):
(JSC::Bindings::QtInstance::newRuntimeObject):

  • bridge/qt/qt_pixmapruntime.cpp:

(JSC::Bindings::QtPixmapInstance::createPixmapRuntimeObject):

  • bridge/qt/qt_runtime.cpp:

(JSC::Bindings::convertValueToQVariant):
(JSC::Bindings::convertQVariantToValue):
(JSC::Bindings::QtRuntimeMetaMethod::call):
(JSC::Bindings::QtRuntimeConnectionMethod::call):

  • bridge/qt/qt_runtime_qt4.cpp:

(JSC::Bindings::convertValueToQVariant):
(JSC::Bindings::convertQVariantToValue):
(JSC::Bindings::QtRuntimeMetaMethod::call):
(JSC::Bindings::QtRuntimeConnectionMethod::call):

  • html/HTMLCanvasElement.cpp:

(WebCore::HTMLCanvasElement::createImageBuffer):

  • html/HTMLImageLoader.cpp:

(WebCore::HTMLImageLoader::notifyFinished):

  • plugins/PluginView.cpp:

(WebCore::PluginView::start):
(WebCore::PluginView::stop):
(WebCore::PluginView::performRequest):
(WebCore::PluginView::npObject):
(WebCore::PluginView::privateBrowsingStateChanged):

  • plugins/blackberry/PluginViewBlackBerry.cpp:

(WebCore::PluginView::dispatchNPEvent):
(WebCore::PluginView::setNPWindowIfNeeded):
(WebCore::PluginView::platformStart):
(WebCore::PluginView::getWindowInfo):

  • plugins/efl/PluginViewEfl.cpp:

(WebCore::PluginView::dispatchNPEvent):

  • plugins/gtk/PluginViewGtk.cpp:

(WebCore::PluginView::dispatchNPEvent):
(WebCore::PluginView::handleKeyboardEvent):
(WebCore::PluginView::handleMouseEvent):
(WebCore::PluginView::setNPWindowIfNeeded):
(WebCore::PluginView::platformStart):

  • plugins/mac/PluginViewMac.mm:

(WebCore::PluginView::setNPWindowIfNeeded):
(WebCore::PluginView::dispatchNPEvent):

  • plugins/qt/PluginViewQt.cpp:

(WebCore::PluginView::dispatchNPEvent):
(WebCore::PluginView::setNPWindowIfNeeded):
(WebCore::PluginView::platformStart):

  • plugins/win/PluginViewWin.cpp:

(WebCore::PluginView::dispatchNPEvent):
(WebCore::PluginView::handleKeyboardEvent):
(WebCore::PluginView::handleMouseEvent):
(WebCore::PluginView::setNPWindowRect):

  • testing/js/WebCoreTestSupport.cpp:

(WebCoreTestSupport::injectInternalsObject):
(WebCoreTestSupport::resetInternalsObject):

  • xml/XMLHttpRequest.cpp:

(WebCore::XMLHttpRequest::dropProtection):

Source/WebKit/blackberry:

Changed all sites that used JSLock to instead use the new JSLockHolder
and pass in the correct JS context that the code is about to interact with that
needs protection.

  • Api/BlackBerryGlobal.cpp:

(BlackBerry::WebKit::clearMemoryCaches):

  • WebCoreSupport/ClientExtension.cpp:
  • WebCoreSupport/PagePopupBlackBerry.cpp:

(WebCore::PagePopupBlackBerry::installDomFunction):

  • WebKitSupport/DumpRenderTreeSupport.cpp:

(DumpRenderTreeSupport::computedStyleIncludingVisitedInfo):

Source/WebKit/efl:

Changed all sites that used JSLock to instead use the new JSLockHolder
and pass in the correct JS context that the code is about to interact with that
needs protection.

  • ewk/ewk_frame.cpp:

(ewk_frame_script_execute):

  • ewk/ewk_view.cpp:

(ewk_view_js_object_add):

Source/WebKit/gtk:

Changed all sites that used JSLock to instead use the new JSLockHolder
and pass in the correct JS context that the code is about to interact with that
needs protection.

  • WebCoreSupport/DumpRenderTreeSupportGtk.cpp:

(DumpRenderTreeSupportGtk::gcCountJavascriptObjects):

Source/WebKit/mac:

Changed all sites that used JSLock to instead use the new JSLockHolder
and pass in the correct JS context that the code is about to interact with that
needs protection.

  • DOM/WebDOMOperations.mm:

(JSC):

  • Misc/WebCoreStatistics.mm:

(+[WebCoreStatistics javaScriptObjectsCount]):
(+[WebCoreStatistics javaScriptGlobalObjectsCount]):
(+[WebCoreStatistics javaScriptProtectedObjectsCount]):
(+[WebCoreStatistics javaScriptProtectedGlobalObjectsCount]):
(+[WebCoreStatistics javaScriptProtectedObjectTypeCounts]):
(+[WebCoreStatistics javaScriptObjectTypeCounts]):
(+[WebCoreStatistics shouldPrintExceptions]):
(+[WebCoreStatistics setShouldPrintExceptions:]):
(+[WebCoreStatistics memoryStatistics]):
(+[WebCoreStatistics javaScriptReferencedObjectsCount]):

  • Plugins/Hosted/NetscapePluginInstanceProxy.mm:

(WebKit::NetscapePluginInstanceProxy::evaluate):
(WebKit::NetscapePluginInstanceProxy::invoke):
(WebKit::NetscapePluginInstanceProxy::invokeDefault):
(WebKit::NetscapePluginInstanceProxy::construct):
(WebKit::NetscapePluginInstanceProxy::getProperty):
(WebKit::NetscapePluginInstanceProxy::setProperty):
(WebKit::NetscapePluginInstanceProxy::removeProperty):
(WebKit::NetscapePluginInstanceProxy::hasMethod):
(WebKit::NetscapePluginInstanceProxy::enumerate):
(WebKit::NetscapePluginInstanceProxy::addValueToArray):
(WebKit::NetscapePluginInstanceProxy::moveGlobalExceptionToExecState):

  • Plugins/WebNetscapePluginStream.mm:

(WebNetscapePluginStream::wantsAllStreams):

  • Plugins/WebNetscapePluginView.mm:

(-[WebNetscapePluginView sendEvent:isDrawRect:]):
(-[WebNetscapePluginView privateBrowsingModeDidChange]):
(-[WebNetscapePluginView setWindowIfNecessary]):
(-[WebNetscapePluginView createPluginScriptableObject]):
(-[WebNetscapePluginView getFormValue:]):
(-[WebNetscapePluginView evaluateJavaScriptPluginRequest:]):
(-[WebNetscapePluginView webFrame:didFinishLoadWithReason:]):
(-[WebNetscapePluginView loadPluginRequest:]):
(-[WebNetscapePluginView _printedPluginBitmap]):

  • Plugins/WebPluginController.mm:

(+[WebPluginController plugInViewWithArguments:fromPluginPackage:]):
(-[WebPluginController stopOnePlugin:]):
(-[WebPluginController destroyOnePlugin:]):
(-[WebPluginController startAllPlugins]):
(-[WebPluginController addPlugin:]):

  • WebView/WebFrame.mm:

(-[WebFrame _stringByEvaluatingJavaScriptFromString:forceUserGesture:]):
(-[WebFrame _stringByEvaluatingJavaScriptFromString:withGlobalObject:inScriptWorld:]):

  • WebView/WebScriptDebugDelegate.mm:

(-[WebScriptCallFrame scopeChain]):
(-[WebScriptCallFrame evaluateWebScript:]):

  • WebView/WebView.mm:

(+[WebView _reportException:inContext:]):
(-[WebView aeDescByEvaluatingJavaScriptFromString:]):
(-[WebView _computedStyleIncludingVisitedInfo:forElement:]):

Source/WebKit/qt:

Changed all sites that used JSLock to instead use the new JSLockHolder
and pass in the correct JS context that the code is about to interact with that
needs protection.

  • Api/qwebframe.cpp:

(QWebFramePrivate::addQtSenderToGlobalObject):
(QWebFrame::addToJavaScriptWindowObject):

  • WebCoreSupport/DumpRenderTreeSupportQt.cpp:

(DumpRenderTreeSupportQt::injectInternalsObject):
(DumpRenderTreeSupportQt::resetInternalsObject):

Source/WebKit/win:

Changed all sites that used JSLock to instead use the new JSLockHolder
and pass in the correct JS context that the code is about to interact with that
needs protection.

  • WebCoreStatistics.cpp:

(WebCoreStatistics::javaScriptObjectsCount):
(WebCoreStatistics::javaScriptGlobalObjectsCount):
(WebCoreStatistics::javaScriptProtectedObjectsCount):
(WebCoreStatistics::javaScriptProtectedGlobalObjectsCount):
(WebCoreStatistics::javaScriptProtectedObjectTypeCounts):

  • WebFrame.cpp:

(WebFrame::stringByEvaluatingJavaScriptInScriptWorld):

  • WebJavaScriptCollector.cpp:

(WebJavaScriptCollector::objectCount):

  • WebView.cpp:

(WebView::stringByEvaluatingJavaScriptFromString):
(WebView::reportException):
(WebView::elementFromJS):

Source/WebKit2:

Changed all sites that used JSLock to instead use the new JSLockHolder
and pass in the correct JS context that the code is about to interact with that
needs protection.

  • Shared/mac/WebMemorySampler.mac.mm:

(WebKit::WebMemorySampler::sampleWebKit):

  • WebProcess/InjectedBundle/InjectedBundle.cpp:

(WebKit::InjectedBundle::javaScriptObjectsCount):
(WebKit::InjectedBundle::reportException):

  • WebProcess/Plugins/Netscape/JSNPObject.cpp:

(WebKit::JSNPObject::callMethod):
(WebKit::JSNPObject::callObject):
(WebKit::JSNPObject::callConstructor):
(WebKit::JSNPObject::put):
(WebKit::JSNPObject::deleteProperty):
(WebKit::JSNPObject::getOwnPropertyNames):
(WebKit::JSNPObject::propertyGetter):

  • WebProcess/Plugins/Netscape/NPJSObject.cpp:

(WebKit::NPJSObject::hasMethod):
(WebKit::NPJSObject::invoke):
(WebKit::NPJSObject::invokeDefault):
(WebKit::NPJSObject::hasProperty):
(WebKit::NPJSObject::getProperty):
(WebKit::NPJSObject::setProperty):
(WebKit::NPJSObject::removeProperty):
(WebKit::NPJSObject::enumerate):
(WebKit::NPJSObject::construct):

  • WebProcess/Plugins/Netscape/NPRuntimeObjectMap.cpp:

(WebKit::NPRuntimeObjectMap::convertJSValueToNPVariant):
(WebKit::NPRuntimeObjectMap::evaluate):
(WebKit::NPRuntimeObjectMap::moveGlobalExceptionToExecState):

  • WebProcess/WebPage/WebFrame.cpp:

(WebKit::WebFrame::jsWrapperForWorld):
(WebKit::WebFrame::computedStyleIncludingVisitedInfo):

  • WebProcess/WebPage/WebPage.cpp:

(WebKit::WebPage::runJavaScriptInMainFrame):

  • WebProcess/WebProcess.cpp:

(WebKit::WebProcess::getWebCoreStatistics):

Location:
trunk/Source/JavaScriptCore
Files:
23 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/API/APIShims.h

    r95901 r121058  
    2929#include "CallFrame.h"
    3030#include "GCActivityCallback.h"
     31#include "IncrementalSweeper.h"
    3132#include "JSLock.h"
    3233#include <wtf/WTFThreadData.h>
     
    3536
    3637class APIEntryShimWithoutLock {
     38public:
     39    enum RefGlobalDataTag { DontRefGlobalData = 0, RefGlobalData };
     40
    3741protected:
    38     APIEntryShimWithoutLock(JSGlobalData* globalData, bool registerThread)
    39         : m_globalData(globalData)
     42    APIEntryShimWithoutLock(JSGlobalData* globalData, bool registerThread, RefGlobalDataTag shouldRefGlobalData)
     43        : m_shouldRefGlobalData(shouldRefGlobalData)
     44        , m_globalData(globalData)
    4045        , m_entryIdentifierTable(wtfThreadData().setCurrentIdentifierTable(globalData->identifierTable))
    4146    {
     47        if (shouldRefGlobalData)
     48            m_globalData->ref();
    4249        UNUSED_PARAM(registerThread);
    4350        if (registerThread)
    4451            globalData->heap.machineThreads().addCurrentThread();
    4552        m_globalData->heap.activityCallback()->synchronize();
    46         m_globalData->timeoutChecker.start();
     53        m_globalData->heap.sweeper()->synchronize();
    4754    }
    4855
    4956    ~APIEntryShimWithoutLock()
    5057    {
    51         m_globalData->timeoutChecker.stop();
    5258        wtfThreadData().setCurrentIdentifierTable(m_entryIdentifierTable);
     59        if (m_shouldRefGlobalData)
     60            m_globalData->deref();
    5361    }
    5462
    55 private:
     63protected:
     64    RefGlobalDataTag m_shouldRefGlobalData;
    5665    JSGlobalData* m_globalData;
    5766    IdentifierTable* m_entryIdentifierTable;
     
    6271    // Normal API entry
    6372    APIEntryShim(ExecState* exec, bool registerThread = true)
    64         : APIEntryShimWithoutLock(&exec->globalData(), registerThread)
    65         , m_lock(exec)
     73        : APIEntryShimWithoutLock(&exec->globalData(), registerThread, RefGlobalData)
    6674    {
     75        init();
     76    }
     77
     78    // This constructor is necessary for HeapTimer to prevent it from accidentally resurrecting
     79    // the ref count of a "dead" JSGlobalData.
     80    APIEntryShim(JSGlobalData* globalData, RefGlobalDataTag refGlobalData, bool registerThread = true)
     81        : APIEntryShimWithoutLock(globalData, registerThread, refGlobalData)
     82    {
     83        init();
    6784    }
    6885
    6986    // JSPropertyNameAccumulator only has a globalData.
    7087    APIEntryShim(JSGlobalData* globalData, bool registerThread = true)
    71         : APIEntryShimWithoutLock(globalData, registerThread)
    72         , m_lock(globalData->isSharedInstance() ? LockForReal : SilenceAssertionsOnly)
     88        : APIEntryShimWithoutLock(globalData, registerThread, RefGlobalData)
    7389    {
     90        init();
     91    }
     92
     93    ~APIEntryShim()
     94    {
     95        m_globalData->timeoutChecker.stop();
     96        m_globalData->apiLock().unlock();
    7497    }
    7598
    7699private:
    77     JSLock m_lock;
     100    void init()
     101    {
     102        m_globalData->apiLock().lock();
     103        m_globalData->timeoutChecker.start();
     104    }
    78105};
    79106
     
    89116    ~APICallbackShim()
    90117    {
    91         m_globalData->heap.activityCallback()->synchronize();
    92118        wtfThreadData().setCurrentIdentifierTable(m_globalData->identifierTable);
    93119    }
  • trunk/Source/JavaScriptCore/API/JSContextRef.cpp

    r116809 r121058  
    7979    // we use a shared one for backwards compatibility.
    8080    if (NSVersionOfLinkTimeLibrary("JavaScriptCore") <= webkitFirstVersionWithConcurrentGlobalContexts) {
    81         JSLock lock(LockForReal);
    8281        return JSGlobalContextCreateInGroup(toRef(&JSGlobalData::sharedInstance()), globalObjectClass);
    8382    }
     
    9190    initializeThreading();
    9291
    93     JSLock lock(LockForReal);
    9492    RefPtr<JSGlobalData> globalData = group ? PassRefPtr<JSGlobalData>(toJS(group)) : JSGlobalData::createContextGroup(ThreadStackTypeSmall);
    9593
    9694    APIEntryShim entryShim(globalData.get(), false);
    97 
    9895    globalData->makeUsableFromMultipleThreads();
    9996
     
    125122void JSGlobalContextRelease(JSGlobalContextRef ctx)
    126123{
    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();
     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    }
    139137
    140138    wtfThreadData().setCurrentIdentifierTable(savedIdentifierTable);
     
    167165{
    168166    ExecState* exec = toJS(ctx);
    169     JSLock lock(exec);
     167    JSLockHolder lock(exec);
    170168
    171169    unsigned count = 0;
  • trunk/Source/JavaScriptCore/ChangeLog

    r121028 r121058  
     12012-06-20  Mark Hahnenberg  <[email protected]>
     2
     3        JSLock should be per-JSGlobalData
     4        https://bugs.webkit.org/show_bug.cgi?id=89123
     5
     6        Reviewed by Gavin Barraclough.
     7
     8        * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def:
     9        * API/APIShims.h:
     10        (APIEntryShimWithoutLock):
     11        (JSC::APIEntryShimWithoutLock::APIEntryShimWithoutLock): Added an extra parameter to the constructor to
     12        determine whether we should ref the JSGlobalData or not. We want to ref all the time except for in the
     13        HeapTimer class because timerDidFire could run after somebody has started to tear down that particular
     14        JSGlobalData, so we wouldn't want to resurrect the ref count of that JSGlobalData from 0 back to 1 after
     15        its destruction has begun.
     16        (JSC::APIEntryShimWithoutLock::~APIEntryShimWithoutLock): Now derefs if it also refed.
     17        (JSC::APIEntryShim::APIEntryShim):
     18        (APIEntryShim):
     19        (JSC::APIEntryShim::~APIEntryShim):
     20        (JSC::APIEntryShim::init): Factored out common initialization code for the various APIEntryShim constructors.
     21        Also moved the timeoutChecker stop and start here because we need to start after we've grabbed the API lock
     22        and before we've released it, which can only done in APIEntryShim.
     23        (JSC::APICallbackShim::~APICallbackShim): We no longer need to synchronize here.
     24        * API/JSContextRef.cpp:
     25        (JSGlobalContextCreate):
     26        (JSGlobalContextCreateInGroup):
     27        (JSGlobalContextRelease):
     28        (JSContextCreateBacktrace):
     29        * heap/CopiedSpace.cpp:
     30        (JSC::CopiedSpace::tryAllocateSlowCase):
     31        * heap/Heap.cpp:
     32        (JSC::Heap::protect):
     33        (JSC::Heap::unprotect):
     34        (JSC::Heap::collect):
     35        (JSC::Heap::setActivityCallback):
     36        (JSC::Heap::activityCallback):
     37        (JSC::Heap::sweeper):
     38        * heap/Heap.h: Changed m_activityCallback and m_sweeper to be raw pointers rather than OwnPtrs because they
     39        are now responsible for their own lifetime. Also changed the order of declaration of the GCActivityCallback
     40        and the IncrementalSweeper to make sure they're the last things that get initialized during construction to
     41        prevent any issues with uninitialized memory in the JSGlobalData/Heap they might care about.
     42        (Heap):
     43        * heap/HeapTimer.cpp: Refactored to allow for thread-safe operation and shutdown.
     44        (JSC::HeapTimer::~HeapTimer):
     45        (JSC::HeapTimer::invalidate):
     46        (JSC):
     47        (JSC::HeapTimer::didStartVMShutdown): Called at the beginning of ~JSGlobalData. If we're on the same thread
     48        that the HeapTimer is running on, we kill the HeapTimer ourselves. If not, then we set some state in the
     49        HeapTimer and schedule it to fire immediately so that it can notice and kill itself.
     50        (JSC::HeapTimer::timerDidFire): We grab our mutex and check our JSGlobalData pointer. If it has been zero-ed
     51        out, then we know the VM has started to shutdown and we should kill ourselves. Otherwise, grab the APIEntryShim,
     52        but without ref-ing the JSGlobalData (we don't want to bring the JSGlobalData's ref-count from 0 to 1) in case
     53        we were interrupted between releasing our mutex and trying to grab the APILock.
     54        * heap/HeapTimer.h:
     55        (HeapTimer):
     56        * heap/IncrementalSweeper.cpp:
     57        (JSC::IncrementalSweeper::doWork): We no longer need the API shim here since HeapTimer::timerDidFire handles
     58        all of that for us.
     59        (JSC::IncrementalSweeper::create):
     60        * heap/IncrementalSweeper.h:
     61        (IncrementalSweeper):
     62        * heap/MarkedAllocator.cpp:
     63        (JSC::MarkedAllocator::allocateSlowCase):
     64        * heap/WeakBlock.cpp:
     65        (JSC::WeakBlock::reap):
     66        * jsc.cpp:
     67        (functionGC):
     68        (functionReleaseExecutableMemory):
     69        (jscmain):
     70        * runtime/Completion.cpp:
     71        (JSC::checkSyntax):
     72        (JSC::evaluate):
     73        * runtime/GCActivityCallback.h:
     74        (DefaultGCActivityCallback):
     75        (JSC::DefaultGCActivityCallback::create):
     76        * runtime/JSGlobalData.cpp:
     77        (JSC::JSGlobalData::JSGlobalData):
     78        (JSC::JSGlobalData::~JSGlobalData): Signals to the two HeapTimers (GCActivityCallback and IncrementalSweeper)
     79        that the VM has started shutting down. It then waits until the HeapTimer is done with whatever activity
     80        it needs to do before continuing with any further destruction. Also asserts that we do not currently hold the
     81        APILock because this could potentially cause deadlock when we try to signal to the HeapTimers using their mutexes.
     82        (JSC::JSGlobalData::sharedInstance): Protect the initialization for the shared instance with the GlobalJSLock.
     83        (JSC::JSGlobalData::sharedInstanceInternal):
     84        * runtime/JSGlobalData.h: Change to be ThreadSafeRefCounted so that we don't have to worry about refing and
     85        de-refing JSGlobalDatas on separate threads since we don't do it that often anyways.
     86        (JSGlobalData):
     87        (JSC::JSGlobalData::apiLock):
     88        * runtime/JSGlobalObject.cpp:
     89        (JSC::JSGlobalObject::~JSGlobalObject):
     90        (JSC::JSGlobalObject::init):
     91        * runtime/JSLock.cpp:
     92        (JSC):
     93        (JSC::GlobalJSLock::GlobalJSLock): For accessing the shared instance.
     94        (JSC::GlobalJSLock::~GlobalJSLock):
     95        (JSC::JSLockHolder::JSLockHolder): MutexLocker for JSLock. Also refs the JSGlobalData to keep it alive so that
     96        it can successfully unlock it later without it disappearing from underneath it.
     97        (JSC::JSLockHolder::~JSLockHolder):
     98        (JSC::JSLock::JSLock):
     99        (JSC::JSLock::~JSLock):
     100        (JSC::JSLock::lock): Uses the spin lock for guarding the lock count and owner thread fields. Uses the mutex for
     101        actually waiting for long periods.
     102        (JSC::JSLock::unlock):
     103        (JSC::JSLock::currentThreadIsHoldingLock):
     104        (JSC::JSLock::dropAllLocks):
     105        (JSC::JSLock::dropAllLocksUnconditionally):
     106        (JSC::JSLock::grabAllLocks):
     107        (JSC::JSLock::DropAllLocks::DropAllLocks):
     108        (JSC::JSLock::DropAllLocks::~DropAllLocks):
     109        * runtime/JSLock.h:
     110        (JSC):
     111        (GlobalJSLock):
     112        (JSLockHolder):
     113        (JSLock):
     114        (DropAllLocks):
     115        * runtime/WeakGCMap.h:
     116        (JSC::WeakGCMap::set):
     117        * testRegExp.cpp:
     118        (realMain):
     119
    11202012-06-22  Peter Beverloo  <[email protected]>
    2121
  • trunk/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def

    r120897 r121058  
    77    ??0DateInstance@JSC@@IAE@PAVExecState@1@PAVStructure@1@@Z
    88    ??0DefaultGCActivityCallback@JSC@@QAE@PAVHeap@1@@Z
    9     ??0DropAllLocks@JSLock@JSC@@QAE@W4JSLockBehavior@2@@Z
     9    ??0DropAllLocks@JSLock@JSC@@QAE@PAVExecState@2@@Z
     10    ??0DropAllLocks@JSLock@JSC@@QAE@PAVJSGlobalData@2@@Z
    1011    ??0DynamicGlobalObjectScope@JSC@@QAE@AAVJSGlobalData@1@PAVJSGlobalObject@1@@Z
    1112    ??0InternalFunction@JSC@@IAE@PAVJSGlobalObject@1@PAVStructure@1@@Z
    12     ??0JSLock@JSC@@QAE@PAVExecState@1@@Z
     13    ??0JSLockHolder@JSC@@QAE@AAVJSGlobalData@1@@Z
     14    ??0JSLockHolder@JSC@@QAE@PAVExecState@1@@Z
     15    ??0JSLockHolder@JSC@@QAE@PAVJSGlobalData@1@@Z
    1316    ??0MD5@WTF@@QAE@XZ
    1417    ??0Mutex@WTF@@QAE@XZ
     
    3336    ??1JSGlobalData@JSC@@QAE@XZ
    3437    ??1JSGlobalObject@JSC@@QAE@XZ
     38    ??1JSLockHolder@JSC@@QAE@XZ
    3539    ??1Mutex@WTF@@QAE@XZ
    3640    ??1RefCountedLeakCounter@WTF@@QAE@XZ
     
    124128    ?cryptographicallyRandomValues@WTF@@YAXPAXI@Z
    125129    ?currentThread@WTF@@YAIXZ
    126     ?currentThreadIsHoldingLock@JSLock@JSC@@SA_NXZ
    127130    ?currentTime@WTF@@YANXZ
    128131    ?data@CString@WTF@@QBEPBDXZ
     
    236239    ?jsString@JSC@@YAPAVJSString@1@PAVJSGlobalData@1@ABVUString@1@@Z
    237240    ?length@CString@WTF@@QBEIXZ
    238     ?lock@JSLock@JSC@@SAXW4JSLockBehavior@2@@Z
     241    ?lock@JSLock@JSC@@QAEXXZ
    239242    ?lock@Mutex@WTF@@QAEXXZ
    240243    ?lockAtomicallyInitializedStaticMutex@WTF@@YAXXZ
    241     ?lockCount@JSLock@JSC@@SAHXZ
    242244    ?match@RegExp@JSC@@QAEHAAVJSGlobalData@2@ABVUString@2@IAAV?$Vector@H$0CA@@WTF@@@Z
    243245    ?materializePropertyMap@Structure@JSC@@AAEXAAVJSGlobalData@2@@Z
     
    324326    ?substringSharingImpl@UString@JSC@@QBE?AV12@II@Z
    325327    ?suggestedNewPropertyStorageSize@Structure@JSC@@QAEIXZ
     328    ?sweeper@Heap@JSC@@QAEPAVIncrementalSweeper@2@XZ
    326329    ?synthesizePrototype@JSValue@JSC@@QBEPAVJSObject@2@PAVExecState@2@@Z
    327330    ?thisObject@DebuggerCallFrame@JSC@@QBEPAVJSObject@2@XZ
     
    353356    ?tryLock@Mutex@WTF@@QAE_NXZ
    354357    ?type@DebuggerCallFrame@JSC@@QBE?AW4Type@12@XZ
    355     ?unlock@JSLock@JSC@@SAXW4JSLockBehavior@2@@Z
     358    ?unlock@JSLock@JSC@@QAEXXZ
    356359    ?unlock@Mutex@WTF@@QAEXXZ
    357360    ?unlockAtomicallyInitializedStaticMutex@WTF@@YAXXZ
  • trunk/Source/JavaScriptCore/heap/CopiedSpace.cpp

    r120568 r121058  
    6767        return tryAllocateOversize(bytes, outPtr);
    6868   
     69    ASSERT(m_heap->globalData()->apiLock().currentThreadIsHoldingLock());
    6970    m_heap->didAllocate(m_allocator.currentCapacity());
    7071
  • trunk/Source/JavaScriptCore/heap/Heap.cpp

    r120742 r121058  
    161161}
    162162
    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;
     163static inline bool isValidSharedInstanceThreadState(JSGlobalData* globalData)
     164{
     165    return globalData->apiLock().currentThreadIsHoldingLock();
    172166}
    173167
     
    177171        return false;
    178172
    179     if (globalData->isSharedInstance() && !isValidSharedInstanceThreadState())
     173    if (globalData->isSharedInstance() && !isValidSharedInstanceThreadState(globalData))
    180174        return false;
    181175
     
    328322{
    329323    ASSERT(k);
    330     ASSERT(JSLock::currentThreadIsHoldingLock() || !m_globalData->isSharedInstance());
     324    ASSERT(m_globalData->apiLock().currentThreadIsHoldingLock());
    331325
    332326    if (!k.isCell())
     
    339333{
    340334    ASSERT(k);
    341     ASSERT(JSLock::currentThreadIsHoldingLock() || !m_globalData->isSharedInstance());
     335    ASSERT(m_globalData->apiLock().currentThreadIsHoldingLock());
    342336
    343337    if (!k.isCell())
     
    693687   
    694688    GCPHASE(Collect);
     689    ASSERT(globalData()->apiLock().currentThreadIsHoldingLock());
    695690    ASSERT(globalData()->identifierTable == wtfThreadData().currentIdentifierTable());
    696691    ASSERT(m_isSafeToCollect);
     
    778773}
    779774
    780 void Heap::setActivityCallback(PassOwnPtr<GCActivityCallback> activityCallback)
     775void Heap::setActivityCallback(GCActivityCallback* activityCallback)
    781776{
    782777    m_activityCallback = activityCallback;
     
    785780GCActivityCallback* Heap::activityCallback()
    786781{
    787     return m_activityCallback.get();
     782    return m_activityCallback;
    788783}
    789784
    790785IncrementalSweeper* Heap::sweeper()
    791786{
    792     return m_sweeper.get();
     787    return m_sweeper;
    793788}
    794789
  • trunk/Source/JavaScriptCore/heap/Heap.h

    r120742 r121058  
    100100
    101101        JS_EXPORT_PRIVATE GCActivityCallback* activityCallback();
    102         JS_EXPORT_PRIVATE void setActivityCallback(PassOwnPtr<GCActivityCallback>);
     102        JS_EXPORT_PRIVATE void setActivityCallback(GCActivityCallback*);
    103103        JS_EXPORT_PRIVATE void setGarbageCollectionTimerEnabled(bool);
    104104
    105         IncrementalSweeper* sweeper();
     105        JS_EXPORT_PRIVATE IncrementalSweeper* sweeper();
    106106
    107107        // true if an allocation or collection is in progress
     
    238238        double m_lastCodeDiscardTime;
    239239
    240         OwnPtr<GCActivityCallback> m_activityCallback;
    241         OwnPtr<IncrementalSweeper> m_sweeper;
    242        
    243240        DoublyLinkedList<ExecutableBase> m_compiledCode;
     241       
     242        GCActivityCallback* m_activityCallback;
     243        IncrementalSweeper* m_sweeper;
    244244    };
    245245
  • trunk/Source/JavaScriptCore/heap/HeapTimer.cpp

    r120970 r121058  
    2727#include "HeapTimer.h"
    2828
     29#include "APIShims.h"
     30#include "JSObject.h"
     31#include "JSString.h"
     32#include "ScopeChain.h"
    2933#include <wtf/Threading.h>
    3034
     
    4751HeapTimer::~HeapTimer()
    4852{
    49     invalidate();
     53    CFRunLoopRemoveTimer(m_runLoop.get(), m_timer.get(), kCFRunLoopCommonModes);
     54    CFRunLoopTimerInvalidate(m_timer.get());
    5055}
    5156
     
    6166void HeapTimer::invalidate()
    6267{
    63     CFRunLoopRemoveTimer(m_runLoop.get(), m_timer.get(), kCFRunLoopCommonModes);
    64     CFRunLoopTimerInvalidate(m_timer.get());
     68    m_globalData = 0;
     69    CFRunLoopTimerSetNextFireDate(m_timer.get(), CFAbsoluteTimeGetCurrent() - s_decade);
     70}
     71
     72void 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();
    6582}
    6683
     
    6885{
    6986    HeapTimer* agent = static_cast<HeapTimer*>(info);
    70     agent->doWork();
     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();
    7199}
    72100
     
    82110}
    83111
     112void HeapTimer::didStartVMShutdown()
     113{
     114    delete this;
     115}
     116
    84117void HeapTimer::synchronize()
    85118{
     
    90123}
    91124
    92 
    93125#endif
    94126   
  • trunk/Source/JavaScriptCore/heap/HeapTimer.h

    r120970 r121058  
    2828
    2929#include <wtf/RetainPtr.h>
     30#include <wtf/Threading.h>
    3031
    3132#if USE(CF)
     
    4748   
    4849    virtual ~HeapTimer();
    49    
     50
     51    void didStartVMShutdown();
    5052    virtual void synchronize();
    5153    virtual void doWork() = 0;
     
    6062    RetainPtr<CFRunLoopRef> m_runLoop;
    6163    CFRunLoopTimerContext m_context;
     64
     65    Mutex m_shutdownMutex;
    6266#endif
    6367   
  • trunk/Source/JavaScriptCore/heap/IncrementalSweeper.cpp

    r120970 r121058  
    4646void IncrementalSweeper::doWork()
    4747{
    48     APIEntryShim shim(m_globalData);
    4948    doSweep(WTF::monotonicallyIncreasingTime());
    5049}
     
    5655}
    5756
    58 PassOwnPtr<IncrementalSweeper> IncrementalSweeper::create(Heap* heap)
     57IncrementalSweeper* IncrementalSweeper::create(Heap* heap)
    5958{
    60     return adoptPtr(new IncrementalSweeper(heap, CFRunLoopGetCurrent()));
     59    return new IncrementalSweeper(heap, CFRunLoopGetCurrent());
    6160}
    6261
     
    110109}
    111110
    112 PassOwnPtr<IncrementalSweeper> IncrementalSweeper::create(Heap* heap)
     111IncrementalSweeper* IncrementalSweeper::create(Heap* heap)
    113112{
    114     return adoptPtr(new IncrementalSweeper(heap->globalData()));
     113    return new IncrementalSweeper(heap->globalData());
    115114}
    116115
  • trunk/Source/JavaScriptCore/heap/IncrementalSweeper.h

    r120970 r121058  
    4040class IncrementalSweeper : public HeapTimer {
    4141public:
    42     static PassOwnPtr<IncrementalSweeper> create(Heap*);
     42    static IncrementalSweeper* create(Heap*);
    4343    void startSweeping(const HashSet<MarkedBlock*>& blockSnapshot);
    4444    virtual void doWork();
  • trunk/Source/JavaScriptCore/heap/MarkedAllocator.cpp

    r120898 r121058  
    44#include "GCActivityCallback.h"
    55#include "Heap.h"
     6#include "JSGlobalData.h"
    67#include <wtf/CurrentTime.h>
    78
     
    5758void* MarkedAllocator::allocateSlowCase()
    5859{
     60    ASSERT(m_heap->globalData()->apiLock().currentThreadIsHoldingLock());
    5961#if COLLECT_ON_EVERY_ALLOCATION
    6062    m_heap->collectAllGarbage();
  • trunk/Source/JavaScriptCore/heap/WeakBlock.cpp

    r119878 r121058  
    128128            continue;
    129129
    130         if (Heap::isMarked(weakImpl->jsValue().asCell()))
     130        if (Heap::isMarked(weakImpl->jsValue().asCell())) {
     131            ASSERT(weakImpl->state() == WeakImpl::Live);
    131132            continue;
     133        }
    132134
    133135        weakImpl->setState(WeakImpl::Dead);
  • trunk/Source/JavaScriptCore/jsc.cpp

    r118018 r121058  
    300300EncodedJSValue JSC_HOST_CALL functionGC(ExecState* exec)
    301301{
    302     JSLock lock(SilenceAssertionsOnly);
     302    JSLockHolder lock(exec);
    303303    exec->heap()->collectAllGarbage();
    304304    return JSValue::encode(jsUndefined());
     
    308308EncodedJSValue JSC_HOST_CALL functionReleaseExecutableMemory(ExecState* exec)
    309309{
    310     JSLock lock(SilenceAssertionsOnly);
     310    JSLockHolder lock(exec);
    311311    exec->globalData().releaseExecutableMemory();
    312312    return JSValue::encode(jsUndefined());
     
    668668int jscmain(int argc, char** argv)
    669669{
    670     JSLock lock(SilenceAssertionsOnly);
    671 
     670   
    672671    RefPtr<JSGlobalData> globalData = JSGlobalData::create(ThreadStackTypeLarge, LargeHeap);
     672    JSLockHolder lock(globalData.get());
    673673
    674674    CommandLine options;
  • trunk/Source/JavaScriptCore/runtime/Completion.cpp

    r119518 r121058  
    3838bool checkSyntax(ExecState* exec, const SourceCode& source, JSValue* returnedException)
    3939{
    40     JSLock lock(exec);
     40    JSLockHolder lock(exec);
    4141    ASSERT(exec->globalData().identifierTable == wtfThreadData().currentIdentifierTable());
    4242
     
    5454JSValue evaluate(ExecState* exec, ScopeChainNode* scopeChain, const SourceCode& source, JSValue thisValue, JSValue* returnedException)
    5555{
    56     JSLock lock(exec);
     56    JSLockHolder lock(exec);
    5757    ASSERT(exec->globalData().identifierTable == wtfThreadData().currentIdentifierTable());
    5858    if (exec->globalData().isCollectorBusy())
  • trunk/Source/JavaScriptCore/runtime/GCActivityCallback.h

    r120742 r121058  
    7070class DefaultGCActivityCallback : public GCActivityCallback {
    7171public:
    72     static PassOwnPtr<DefaultGCActivityCallback> create(Heap*);
     72    static DefaultGCActivityCallback* create(Heap*);
    7373
    7474    DefaultGCActivityCallback(Heap*);
     
    9292};
    9393
    94 inline PassOwnPtr<DefaultGCActivityCallback> DefaultGCActivityCallback::create(Heap* heap)
     94inline DefaultGCActivityCallback* DefaultGCActivityCallback::create(Heap* heap)
    9595{
    96     return adoptPtr(new DefaultGCActivityCallback(heap));
     96    return new DefaultGCActivityCallback(heap);
    9797}
    9898
  • trunk/Source/JavaScriptCore/runtime/JSGlobalData.cpp

    r120664 r121058  
    3535#include "DebuggerActivation.h"
    3636#include "FunctionConstructor.h"
     37#include "GCActivityCallback.h"
    3738#include "GetterSetter.h"
    3839#include "HostCallReturnValue.h"
     40#include "IncrementalSweeper.h"
    3941#include "Interpreter.h"
    4042#include "JSActivation.h"
     
    179181    interpreter = new Interpreter;
    180182
    181     if (isSharedInstance())
    182         turnOffVerifier();
    183 
    184183    // Need to be careful to keep everything consistent here
     184    JSLockHolder lock(this);
    185185    IdentifierTable* existingEntryIdentifierTable = wtfThreadData().setCurrentIdentifierTable(identifierTable);
    186     JSLock lock(SilenceAssertionsOnly);
    187186    structureStructure.set(*this, Structure::createStructure(*this));
    188187    debuggerActivationStructure.set(*this, DebuggerActivation::createStructure(*this, 0, jsNull()));
     
    223222JSGlobalData::~JSGlobalData()
    224223{
     224    ASSERT(!m_apiLock.currentThreadIsHoldingLock());
     225    heap.activityCallback()->didStartVMShutdown();
     226    heap.sweeper()->didStartVMShutdown();
    225227    heap.lastChanceToFinalize();
    226228
     
    312314JSGlobalData& JSGlobalData::sharedInstance()
    313315{
     316    GlobalJSLock globalLock;
    314317    JSGlobalData*& instance = sharedInstanceInternal();
    315318    if (!instance) {
     
    322325JSGlobalData*& JSGlobalData::sharedInstanceInternal()
    323326{
    324     ASSERT(JSLock::currentThreadIsHoldingLock());
    325327    static JSGlobalData* sharedInstance;
    326328    return sharedInstance;
  • trunk/Source/JavaScriptCore/runtime/JSGlobalData.h

    r119865 r121058  
    3636#include "Intrinsic.h"
    3737#include "JITStubs.h"
     38#include "JSLock.h"
    3839#include "JSValue.h"
    3940#include "LLIntData.h"
     
    4748#include <wtf/Forward.h>
    4849#include <wtf/HashMap.h>
    49 #include <wtf/RefCounted.h>
    5050#include <wtf/SimpleStats.h>
     51#include <wtf/ThreadSafeRefCounted.h>
    5152#include <wtf/ThreadSpecific.h>
    5253#include <wtf/WTFThreadData.h>
     
    153154#endif
    154155
    155     class JSGlobalData : public RefCounted<JSGlobalData> {
     156    class JSGlobalData : public ThreadSafeRefCounted<JSGlobalData> {
    156157    public:
    157158        // WebCore has a one-to-one mapping of threads to JSGlobalDatas;
     
    181182        void makeUsableFromMultipleThreads() { heap.machineThreads().makeUsableFromMultipleThreads(); }
    182183
     184    private:
     185        JSLock m_apiLock;
     186
     187    public:
    183188        Heap heap; // The heap is our first data member to ensure that it's destructed after all the objects that reference it.
    184189
     
    410415#undef registerTypedArrayFunction
    411416
     417        JSLock& apiLock() { return m_apiLock; }
     418
    412419    private:
    413420        friend class LLIntOffsetsExtractor;
  • trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp

    r120886 r121058  
    115115JSGlobalObject::~JSGlobalObject()
    116116{
    117     ASSERT(JSLock::currentThreadIsHoldingLock());
    118 
    119117    if (m_debugger)
    120118        m_debugger->detach(this);
     
    131129void JSGlobalObject::init(JSObject* thisValue)
    132130{
    133     ASSERT(JSLock::currentThreadIsHoldingLock());
     131    ASSERT(globalData().apiLock().currentThreadIsHoldingLock());
    134132   
    135133    m_globalScopeChain.set(globalData(), this, ScopeChainNode::create(0, this, &globalData(), this, thisValue));
  • trunk/Source/JavaScriptCore/runtime/JSLock.cpp

    r100080 r121058  
    2424#include "Heap.h"
    2525#include "CallFrame.h"
     26#include "JSGlobalObject.h"
    2627#include "JSObject.h"
    2728#include "ScopeChain.h"
     
    3940
    4041// Acquire this mutex before accessing lock-related data.
    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);
     42static pthread_mutex_t giantGlobalJSLock = PTHREAD_MUTEX_INITIALIZER;
     43
     44GlobalJSLock::GlobalJSLock()
     45{
     46    pthread_mutex_lock(&giantGlobalJSLock);
     47}
     48
     49GlobalJSLock::~GlobalJSLock()
     50{
     51    pthread_mutex_unlock(&giantGlobalJSLock);
     52}
     53
     54JSLockHolder::JSLockHolder(ExecState* exec)
     55    : m_globalData(&exec->globalData())
     56{
     57    m_globalData->apiLock().lock();
     58}
     59
     60JSLockHolder::JSLockHolder(JSGlobalData* globalData)
     61    : m_globalData(globalData)
     62{
     63    m_globalData->apiLock().lock();
     64}
     65
     66JSLockHolder::JSLockHolder(JSGlobalData& globalData)
     67    : m_globalData(&globalData)
     68{
     69    m_globalData->apiLock().lock();
     70}
     71
     72JSLockHolder::~JSLockHolder()
     73{
     74    m_globalData->apiLock().unlock();
     75}
     76
     77JSLock::JSLock()
     78    : m_lockCount(0)
     79{
     80    m_spinLock.Init();
     81}
     82
     83JSLock::~JSLock()
     84{
     85}
     86
     87void 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        }
    9396    }
    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     }
     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
     106void JSLock::unlock()
     107{
     108    ASSERT(currentThreadIsHoldingLock());
     109
     110    SpinLockHolder holder(&m_spinLock);
     111    m_lockCount--;
     112
     113    if (!m_lockCount)
     114        m_lock.unlock();
    113115}
    114116
    115117void JSLock::lock(ExecState* exec)
    116118{
    117     lock(exec->globalData().isSharedInstance() ? LockForReal : SilenceAssertionsOnly);
     119    exec->globalData().apiLock().lock();
    118120}
    119121
    120122void JSLock::unlock(ExecState* exec)
    121123{
    122     unlock(exec->globalData().isSharedInstance() ? LockForReal : SilenceAssertionsOnly);
     124    exec->globalData().apiLock().unlock();
    123125}
    124126
    125127bool JSLock::currentThreadIsHoldingLock()
    126128{
    127     pthread_once(&createJSLockCountOnce, createJSLockCount);
    128     return !!pthread_getspecific(JSLockCount);
     129    return m_lockCount && m_ownerThread == WTF::currentThread();
    129130}
    130131
     
    150151// write over the second thread's call frames.
    151152//
    152 // In avoid JS stack corruption we enforce a policy of only ever allowing two
     153// To avoid JS stack corruption we enforce a policy of only ever allowing two
    153154// threads to use a JS context concurrently, and only allowing the second of
    154155// these threads to execute until it has completed and fully returned from its
     
    159160// again through a callback, then the locks will not be dropped when DropAllLocks
    160161// is called (since lockDropDepth is non-zero).  Since this thread is still holding
    161 // the locks, only it will re able to re-enter JSC (either be returning from the
     162// the locks, only it will be able to re-enter JSC (either be returning from the
    162163// callback, or by re-entering through another call to evaulate script or call
    163164// function).
     
    169170// would likely increase complexity and overhead.
    170171//
    171 static unsigned lockDropDepth = 0;
     172
     173// This function returns the number of locks that were dropped.
     174unsigned JSLock::dropAllLocks()
     175{
     176    if (m_lockDropDepth++)
     177        return 0;
     178
     179    return dropAllLocksUnconditionally();
     180}
     181
     182unsigned JSLock::dropAllLocksUnconditionally()
     183{
     184    unsigned lockCount = m_lockCount;
     185    for (unsigned i = 0; i < lockCount; i++)
     186        unlock();
     187
     188    return lockCount;
     189}
     190
     191void JSLock::grabAllLocks(unsigned lockCount)
     192{
     193    for (unsigned i = 0; i < lockCount; i++)
     194        lock();
     195
     196    m_lockDropDepth--;
     197}
    172198
    173199JSLock::DropAllLocks::DropAllLocks(ExecState* exec)
    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);
     200    : m_lockCount(0)
     201    , m_globalData(&exec->globalData())
     202{
     203    m_lockCount = m_globalData->apiLock().dropAllLocks();
     204}
     205
     206JSLock::DropAllLocks::DropAllLocks(JSGlobalData* globalData)
     207    : m_lockCount(0)
     208    , m_globalData(globalData)
     209{
     210    m_lockCount = m_globalData->apiLock().dropAllLocks();
    204211}
    205212
    206213JSLock::DropAllLocks::~DropAllLocks()
    207214{
    208     for (intptr_t i = 0; i < m_lockCount; i++)
    209         JSLock::lock(m_lockBehavior);
    210 
    211     --lockDropDepth;
     215    m_globalData->apiLock().grabAllLocks(m_lockCount);
    212216}
    213217
    214218#else // (OS(DARWIN) || USE(PTHREADS))
    215219
    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;
     220GlobalJSLock::GlobalJSLock()
     221{
     222}
     223
     224GlobalJSLock::~GlobalJSLock()
     225{
     226}
     227
     228JSLockHolder::JSLockHolder(JSGlobalData*)
     229{
     230}
     231
     232JSLockHolder::JSLockHolder(JSGlobalData&)
     233{
     234}
     235
     236JSLockHolder::JSLockHolder(ExecState*)
     237{
     238}
     239
     240JSLockHolder::~JSLockHolder()
     241{
     242}
     243
     244JSLock::JSLock()
     245{
     246}
     247
     248JSLock::~JSLock()
     249{
    226250}
    227251
     
    231255}
    232256
    233 void JSLock::lock(JSLockBehavior)
    234 {
    235 }
    236 
    237 void JSLock::unlock(JSLockBehavior)
     257void JSLock::lock()
     258{
     259}
     260
     261void JSLock::unlock()
    238262{
    239263}
     
    247271}
    248272
     273void JSLock::lock(JSGlobalData&)
     274{
     275}
     276
     277void JSLock::unlock(JSGlobalData&)
     278{
     279}
     280
     281unsigned JSLock::dropAllLocks()
     282{
     283    return 0;
     284}
     285
     286unsigned JSLock::dropAllLocksUnconditionally()
     287{
     288    return 0;
     289}
     290
     291void JSLock::grabAllLocks(unsigned)
     292{
     293}
     294
    249295JSLock::DropAllLocks::DropAllLocks(ExecState*)
    250296{
    251297}
    252298
    253 JSLock::DropAllLocks::DropAllLocks(JSLockBehavior)
     299JSLock::DropAllLocks::DropAllLocks(JSGlobalData*)
    254300{
    255301}
  • trunk/Source/JavaScriptCore/runtime/JSLock.h

    r104900 r121058  
    2424#include <wtf/Assertions.h>
    2525#include <wtf/Noncopyable.h>
     26#include <wtf/RefPtr.h>
     27#include <wtf/TCSpinLock.h>
     28#include <wtf/Threading.h>
    2629
    2730namespace JSC {
     
    3134    // JavaScript data structure or that interacts with shared state
    3235    // such as the protect count hash table. The simplest way to lock
    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
     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
    3539    // object also acts as a convenience short-hand for running important
    3640    // initialization routines.
     
    4549    // thread acquired it to begin with.
    4650
    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 
    5151    class ExecState;
    5252    class JSGlobalData;
    5353
    54     enum JSLockBehavior { SilenceAssertionsOnly, LockForReal };
     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    };
    5573
    5674    class JSLock {
    5775        WTF_MAKE_NONCOPYABLE(JSLock);
    5876    public:
    59         JS_EXPORT_PRIVATE JSLock(ExecState*);
    60         JSLock(JSGlobalData*);
     77        JSLock();
     78        JS_EXPORT_PRIVATE ~JSLock();
    6179
    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         }
     80        JS_EXPORT_PRIVATE void lock();
     81        JS_EXPORT_PRIVATE void unlock();
    7282
    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);
    8583        static void lock(ExecState*);
    8684        static void unlock(ExecState*);
     85        static void lock(JSGlobalData&);
     86        static void unlock(JSGlobalData&);
    8787
    88         JS_EXPORT_PRIVATE static intptr_t lockCount();
    89         JS_EXPORT_PRIVATE static bool currentThreadIsHoldingLock();
     88        JS_EXPORT_PRIVATE bool currentThreadIsHoldingLock();
    9089
    91         JSLockBehavior m_lockBehavior;
     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;
    9299
    93100        class DropAllLocks {
     
    95102        public:
    96103            JS_EXPORT_PRIVATE DropAllLocks(ExecState* exec);
    97             JS_EXPORT_PRIVATE DropAllLocks(JSLockBehavior);
     104            JS_EXPORT_PRIVATE DropAllLocks(JSGlobalData*);
    98105            JS_EXPORT_PRIVATE ~DropAllLocks();
    99106           
    100107        private:
    101108            intptr_t m_lockCount;
    102             JSLockBehavior m_lockBehavior;
     109            RefPtr<JSGlobalData> m_globalData;
    103110        };
    104111    };
  • trunk/Source/JavaScriptCore/runtime/WeakGCMap.h

    r118856 r121058  
    7676    }
    7777
    78     void set(JSGlobalData&, const KeyType& key, ExternalType value)
     78    void set(JSGlobalData& globalData, const KeyType& key, ExternalType value)
    7979    {
     80        ASSERT_UNUSED(globalData, globalData.apiLock().currentThreadIsHoldingLock());
    8081        typename MapType::AddResult result = m_map.add(key, 0);
    8182        if (!result.isNewEntry)
  • trunk/Source/JavaScriptCore/testRegExp.cpp

    r115579 r121058  
    496496int realMain(int argc, char** argv)
    497497{
    498     JSLock lock(SilenceAssertionsOnly);
    499 
    500498    RefPtr<JSGlobalData> globalData = JSGlobalData::create(ThreadStackTypeLarge, LargeHeap);
     499    JSLockHolder lock(globalData.get());
    501500
    502501    CommandLine options;
Note: See TracChangeset for help on using the changeset viewer.