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

File:
1 edited

Legend:

Unmodified
Added
Removed
  • 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}
Note: See TracChangeset for help on using the changeset viewer.