Changeset 121381 in webkit for trunk/Source/JavaScriptCore


Ignore:
Timestamp:
Jun 27, 2012, 4:08:26 PM (13 years ago)
Author:
[email protected]
Message:

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

Reviewed by Geoffrey Garen.

Source/JavaScriptCore:

  • 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):
(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):

  • JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def:
  • 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 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):

  • bridge/runtime_root.cpp:

(JSC::Bindings::RootObject::gcProtect):
(JSC::Bindings::RootObject::gcUnprotect):

  • 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. Also added a couple JSLocks to places that didn't already
have it that needed it.

  • 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. Also added a couple JSLocks to places that didn't already
have it that needed it.

  • 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. Also added a couple JSLocks to places that didn't already
have it that needed it.

  • 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. Also added a couple JSLocks to places that didn't already
have it that needed it.

  • 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. Also added a couple JSLocks to places that didn't already
have it that needed it.

  • 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. Also added a couple JSLocks to places that didn't already
have it that needed it.

  • 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. Also added a couple JSLocks to places that didn't already
have it that needed it.

  • 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

    r121098 r121381  
    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

    r121098 r121381  
    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

    r121374 r121381  
     12012-06-25  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 Geoffrey Garen.
     7
     8        * API/APIShims.h:
     9        (APIEntryShimWithoutLock):
     10        (JSC::APIEntryShimWithoutLock::APIEntryShimWithoutLock): Added an extra parameter to the constructor to
     11        determine whether we should ref the JSGlobalData or not. We want to ref all the time except for in the
     12        HeapTimer class because timerDidFire could run after somebody has started to tear down that particular
     13        JSGlobalData, so we wouldn't want to resurrect the ref count of that JSGlobalData from 0 back to 1 after
     14        its destruction has begun.
     15        (JSC::APIEntryShimWithoutLock::~APIEntryShimWithoutLock):
     16        (JSC::APIEntryShim::APIEntryShim):
     17        (APIEntryShim):
     18        (JSC::APIEntryShim::~APIEntryShim):
     19        (JSC::APIEntryShim::init): Factored out common initialization code for the various APIEntryShim constructors.
     20        Also moved the timeoutChecker stop and start here because we need to start after we've grabbed the API lock
     21        and before we've released it, which can only done in APIEntryShim.
     22        (JSC::APICallbackShim::~APICallbackShim): We no longer need to synchronize here.
     23        * API/JSContextRef.cpp:
     24        (JSGlobalContextCreate):
     25        (JSGlobalContextCreateInGroup):
     26        (JSGlobalContextRelease):
     27        (JSContextCreateBacktrace):
     28        * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def:
     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-27  Filip Pizlo  <[email protected]>
    2121
  • trunk/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def

    r121215 r121381  
    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
    1213    ??0JSGlobalObject@JSC@@IAE@AAVJSGlobalData@1@PAVStructure@1@PBUGlobalObjectMethodTable@1@@Z
    13     ??0JSLock@JSC@@QAE@PAVExecState@1@@Z
     14    ??0JSLockHolder@JSC@@QAE@AAVJSGlobalData@1@@Z
     15    ??0JSLockHolder@JSC@@QAE@PAVExecState@1@@Z
     16    ??0JSLockHolder@JSC@@QAE@PAVJSGlobalData@1@@Z
    1417    ??0MD5@WTF@@QAE@XZ
    1518    ??0Mutex@WTF@@QAE@XZ
     
    3437    ??1JSGlobalData@JSC@@QAE@XZ
    3538    ??1JSGlobalObject@JSC@@QAE@XZ
     39    ??1JSLockHolder@JSC@@QAE@XZ
    3640    ??1Mutex@WTF@@QAE@XZ
    3741    ??1RefCountedLeakCounter@WTF@@QAE@XZ
     
    125129    ?cryptographicallyRandomValues@WTF@@YAXPAXI@Z
    126130    ?currentThread@WTF@@YAIXZ
    127     ?currentThreadIsHoldingLock@JSLock@JSC@@SA_NXZ
    128131    ?currentTime@WTF@@YANXZ
    129132    ?data@CString@WTF@@QBEPBDXZ
     
    237240    ?jsString@JSC@@YAPAVJSString@1@PAVJSGlobalData@1@ABVUString@1@@Z
    238241    ?length@CString@WTF@@QBEIXZ
    239     ?lock@JSLock@JSC@@SAXW4JSLockBehavior@2@@Z
     242    ?lock@JSLock@JSC@@QAEXXZ
    240243    ?lock@Mutex@WTF@@QAEXXZ
    241244    ?lockAtomicallyInitializedStaticMutex@WTF@@YAXXZ
    242     ?lockCount@JSLock@JSC@@SAHXZ
    243245    ?match@RegExp@JSC@@QAEHAAVJSGlobalData@2@ABVUString@2@IAAV?$Vector@H$0CA@@WTF@@@Z
    244246    ?materializePropertyMap@Structure@JSC@@AAEXAAVJSGlobalData@2@@Z
     
    325327    ?substringSharingImpl@UString@JSC@@QBE?AV12@II@Z
    326328    ?suggestedNewPropertyStorageSize@Structure@JSC@@QAEIXZ
     329    ?sweeper@Heap@JSC@@QAEPAVIncrementalSweeper@2@XZ
    327330    ?synthesizePrototype@JSValue@JSC@@QBEPAVJSObject@2@PAVExecState@2@@Z
    328331    ?thisObject@DebuggerCallFrame@JSC@@QBEPAVJSObject@2@XZ
     
    354357    ?tryLock@Mutex@WTF@@QAE_NXZ
    355358    ?type@DebuggerCallFrame@JSC@@QBE?AW4Type@12@XZ
    356     ?unlock@JSLock@JSC@@SAXW4JSLockBehavior@2@@Z
     359    ?unlock@JSLock@JSC@@QAEXXZ
    357360    ?unlock@Mutex@WTF@@QAEXXZ
    358361    ?unlockAtomicallyInitializedStaticMutex@WTF@@YAXXZ
  • trunk/Source/JavaScriptCore/heap/CopiedSpace.cpp

    r121098 r121381  
    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

    r121098 r121381  
    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

    r121098 r121381  
    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

    r121098 r121381  
    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

    r121098 r121381  
    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

    r121316 r121381  
    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
     
    111110}
    112111
    113 PassOwnPtr<IncrementalSweeper> IncrementalSweeper::create(Heap* heap)
     112IncrementalSweeper* IncrementalSweeper::create(Heap* heap)
    114113{
    115     return adoptPtr(new IncrementalSweeper(heap->globalData()));
     114    return new IncrementalSweeper(heap->globalData());
    116115}
    117116
  • trunk/Source/JavaScriptCore/heap/IncrementalSweeper.h

    r121098 r121381  
    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

    r121098 r121381  
    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

    r121098 r121381  
    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

    r121098 r121381  
    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

    r121098 r121381  
    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

    r121098 r121381  
    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

    r121098 r121381  
    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

    r121098 r121381  
    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

    r121215 r121381  
    124124JSGlobalObject::~JSGlobalObject()
    125125{
    126     ASSERT(JSLock::currentThreadIsHoldingLock());
    127 
    128126    if (m_debugger)
    129127        m_debugger->detach(this);
     
    140138void JSGlobalObject::init(JSObject* thisValue)
    141139{
    142     ASSERT(JSLock::currentThreadIsHoldingLock());
     140    ASSERT(globalData().apiLock().currentThreadIsHoldingLock());
    143141   
    144142    m_globalScopeChain.set(globalData(), this, ScopeChainNode::create(0, this, &globalData(), this, thisValue));
  • trunk/Source/JavaScriptCore/runtime/JSLock.cpp

    r121098 r121381  
    2424#include "Heap.h"
    2525#include "CallFrame.h"
     26#include "JSGlobalObject.h"
    2627#include "JSObject.h"
    2728#include "ScopeChain.h"
     
    3839#if (OS(DARWIN) || USE(PTHREADS))
    3940
    40 // 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);
     41static pthread_mutex_t sharedInstanceLock = PTHREAD_MUTEX_INITIALIZER;
     42
     43GlobalJSLock::GlobalJSLock()
     44{
     45    pthread_mutex_lock(&sharedInstanceLock);
     46}
     47
     48GlobalJSLock::~GlobalJSLock()
     49{
     50    pthread_mutex_unlock(&sharedInstanceLock);
     51}
     52
     53JSLockHolder::JSLockHolder(ExecState* exec)
     54    : m_globalData(&exec->globalData())
     55{
     56    m_globalData->apiLock().lock();
     57}
     58
     59JSLockHolder::JSLockHolder(JSGlobalData* globalData)
     60    : m_globalData(globalData)
     61{
     62    m_globalData->apiLock().lock();
     63}
     64
     65JSLockHolder::JSLockHolder(JSGlobalData& globalData)
     66    : m_globalData(&globalData)
     67{
     68    m_globalData->apiLock().lock();
     69}
     70
     71JSLockHolder::~JSLockHolder()
     72{
     73    m_globalData->apiLock().unlock();
     74}
     75
     76JSLock::JSLock()
     77    : m_lockCount(0)
     78{
     79    m_spinLock.Init();
     80}
     81
     82JSLock::~JSLock()
     83{
     84}
     85
     86void JSLock::lock()
     87{
     88    ThreadIdentifier currentThread = WTF::currentThread();
     89    {
     90        SpinLockHolder holder(&m_spinLock);
     91        if (m_ownerThread == currentThread && m_lockCount) {
     92            m_lockCount++;
     93            return;
     94        }
    9395    }
    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);
     96
     97    m_lock.lock();
     98
     99    {
     100        SpinLockHolder holder(&m_spinLock);
     101        m_ownerThread = currentThread;
     102        ASSERT(!m_lockCount);
     103        m_lockCount = 1;
    112104    }
    113105}
    114106
     107void JSLock::unlock()
     108{
     109    ASSERT(currentThreadIsHoldingLock());
     110
     111    SpinLockHolder holder(&m_spinLock);
     112    m_lockCount--;
     113
     114    if (!m_lockCount)
     115        m_lock.unlock();
     116}
     117
    115118void JSLock::lock(ExecState* exec)
    116119{
    117     lock(exec->globalData().isSharedInstance() ? LockForReal : SilenceAssertionsOnly);
     120    exec->globalData().apiLock().lock();
    118121}
    119122
    120123void JSLock::unlock(ExecState* exec)
    121124{
    122     unlock(exec->globalData().isSharedInstance() ? LockForReal : SilenceAssertionsOnly);
     125    exec->globalData().apiLock().unlock();
    123126}
    124127
    125128bool JSLock::currentThreadIsHoldingLock()
    126129{
    127     pthread_once(&createJSLockCountOnce, createJSLockCount);
    128     return !!pthread_getspecific(JSLockCount);
     130    return m_lockCount && m_ownerThread == WTF::currentThread();
    129131}
    130132
     
    150152// write over the second thread's call frames.
    151153//
    152 // In avoid JS stack corruption we enforce a policy of only ever allowing two
     154// To avoid JS stack corruption we enforce a policy of only ever allowing two
    153155// threads to use a JS context concurrently, and only allowing the second of
    154156// these threads to execute until it has completed and fully returned from its
     
    159161// again through a callback, then the locks will not be dropped when DropAllLocks
    160162// 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
     163// the locks, only it will be able to re-enter JSC (either be returning from the
    162164// callback, or by re-entering through another call to evaulate script or call
    163165// function).
     
    169171// would likely increase complexity and overhead.
    170172//
    171 static unsigned lockDropDepth = 0;
     173
     174// This function returns the number of locks that were dropped.
     175unsigned JSLock::dropAllLocks()
     176{
     177    if (m_lockDropDepth++)
     178        return 0;
     179
     180    return dropAllLocksUnconditionally();
     181}
     182
     183unsigned JSLock::dropAllLocksUnconditionally()
     184{
     185    unsigned lockCount = m_lockCount;
     186    for (unsigned i = 0; i < lockCount; i++)
     187        unlock();
     188
     189    return lockCount;
     190}
     191
     192void JSLock::grabAllLocks(unsigned lockCount)
     193{
     194    for (unsigned i = 0; i < lockCount; i++)
     195        lock();
     196
     197    m_lockDropDepth--;
     198}
    172199
    173200JSLock::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);
     201    : m_lockCount(0)
     202    , m_globalData(&exec->globalData())
     203{
     204    m_lockCount = m_globalData->apiLock().dropAllLocks();
     205}
     206
     207JSLock::DropAllLocks::DropAllLocks(JSGlobalData* globalData)
     208    : m_lockCount(0)
     209    , m_globalData(globalData)
     210{
     211    m_lockCount = m_globalData->apiLock().dropAllLocks();
    204212}
    205213
    206214JSLock::DropAllLocks::~DropAllLocks()
    207215{
    208     for (intptr_t i = 0; i < m_lockCount; i++)
    209         JSLock::lock(m_lockBehavior);
    210 
    211     --lockDropDepth;
     216    m_globalData->apiLock().grabAllLocks(m_lockCount);
    212217}
    213218
    214219#else // (OS(DARWIN) || USE(PTHREADS))
    215220
    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;
     221GlobalJSLock::GlobalJSLock()
     222{
     223}
     224
     225GlobalJSLock::~GlobalJSLock()
     226{
     227}
     228
     229JSLockHolder::JSLockHolder(JSGlobalData*)
     230{
     231}
     232
     233JSLockHolder::JSLockHolder(JSGlobalData&)
     234{
     235}
     236
     237JSLockHolder::JSLockHolder(ExecState*)
     238{
     239}
     240
     241JSLockHolder::~JSLockHolder()
     242{
     243}
     244
     245JSLock::JSLock()
     246{
     247}
     248
     249JSLock::~JSLock()
     250{
    226251}
    227252
     
    231256}
    232257
    233 void JSLock::lock(JSLockBehavior)
    234 {
    235 }
    236 
    237 void JSLock::unlock(JSLockBehavior)
     258void JSLock::lock()
     259{
     260}
     261
     262void JSLock::unlock()
    238263{
    239264}
     
    247272}
    248273
     274void JSLock::lock(JSGlobalData&)
     275{
     276}
     277
     278void JSLock::unlock(JSGlobalData&)
     279{
     280}
     281
     282unsigned JSLock::dropAllLocks()
     283{
     284    return 0;
     285}
     286
     287unsigned JSLock::dropAllLocksUnconditionally()
     288{
     289    return 0;
     290}
     291
     292void JSLock::grabAllLocks(unsigned)
     293{
     294}
     295
    249296JSLock::DropAllLocks::DropAllLocks(ExecState*)
    250297{
    251298}
    252299
    253 JSLock::DropAllLocks::DropAllLocks(JSLockBehavior)
     300JSLock::DropAllLocks::DropAllLocks(JSGlobalData*)
    254301{
    255302}
  • trunk/Source/JavaScriptCore/runtime/JSLock.h

    r121098 r121381  
    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

    r121098 r121381  
    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

    r121098 r121381  
    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.