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

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

Reviewed by Gavin Barraclough.

Source/JavaScriptCore:

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

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

  • API/JSContextRef.cpp:

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

  • heap/CopiedSpace.cpp:

(JSC::CopiedSpace::tryAllocateSlowCase):

  • heap/Heap.cpp:

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

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

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

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

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

  • heap/HeapTimer.h:

(HeapTimer):

  • heap/IncrementalSweeper.cpp:

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

  • heap/IncrementalSweeper.h:

(IncrementalSweeper):

  • heap/MarkedAllocator.cpp:

(JSC::MarkedAllocator::allocateSlowCase):

  • heap/WeakBlock.cpp:

(JSC::WeakBlock::reap):

  • jsc.cpp:

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

  • runtime/Completion.cpp:

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

  • runtime/GCActivityCallback.h:

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

  • runtime/JSGlobalData.cpp:

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

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

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

  • runtime/JSGlobalObject.cpp:

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

  • runtime/JSLock.cpp:

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

  • runtime/JSLock.h:

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

  • runtime/WeakGCMap.h:

(JSC::WeakGCMap::set):

  • testRegExp.cpp:

(realMain):

Source/WebCore:

No new tests. Current regression tests are sufficient.

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

  • bindings/js/GCController.cpp:

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

  • bindings/js/JSCustomSQLStatementErrorCallback.cpp:

(WebCore::JSSQLStatementErrorCallback::handleEvent):

  • bindings/js/JSCustomVoidCallback.cpp:

(WebCore::JSCustomVoidCallback::handleEvent):

  • bindings/js/JSCustomXPathNSResolver.cpp:

(WebCore::JSCustomXPathNSResolver::lookupNamespaceURI):

  • bindings/js/JSErrorHandler.cpp:

(WebCore::JSErrorHandler::handleEvent):

  • bindings/js/JSEventCustom.cpp:

(WebCore::toJS):

  • bindings/js/JSEventListener.cpp:

(WebCore::JSEventListener::handleEvent):

  • bindings/js/JSInjectedScriptHostCustom.cpp:

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

  • bindings/js/JSInjectedScriptManager.cpp:

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

  • bindings/js/JSLazyEventListener.cpp:

(WebCore::JSLazyEventListener::initializeJSFunction):

  • bindings/js/JSMainThreadExecState.h:

(WebCore::JSMainThreadExecState::evaluate):

  • bindings/js/JSMutationCallbackCustom.cpp:

(WebCore::JSMutationCallback::handleEvent):

  • bindings/js/JSNodeFilterCondition.cpp:

(WebCore::JSNodeFilterCondition::acceptNode):

  • bindings/js/JSRequestAnimationFrameCallbackCustom.cpp:

(WebCore::JSRequestAnimationFrameCallback::handleEvent):

  • bindings/js/JavaScriptCallFrame.cpp:

(WebCore::JavaScriptCallFrame::evaluate):

  • bindings/js/PageScriptDebugServer.cpp:

(WebCore::PageScriptDebugServer::recompileAllJSFunctions):

  • bindings/js/ScheduledAction.cpp:

(WebCore::ScheduledAction::executeFunctionInContext):

  • bindings/js/ScriptCachedFrameData.cpp:

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

  • bindings/js/ScriptController.cpp:

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

  • bindings/js/ScriptControllerMac.mm:

(WebCore::ScriptController::windowScriptObject):

  • bindings/js/ScriptDebugServer.cpp:

(WebCore::ScriptDebugServer::dispatchDidPause):

  • bindings/js/ScriptEventListener.cpp:

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

  • bindings/js/ScriptFunctionCall.cpp:

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

  • bindings/js/ScriptObject.cpp:

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

  • bindings/js/ScriptValue.cpp:

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

  • bindings/js/WorkerScriptController.cpp:

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

  • bindings/objc/WebScriptObject.mm:

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

  • bindings/scripts/CodeGeneratorJS.pm:

(GenerateCallbackImplementation):

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

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

  • bridge/NP_jsobject.cpp:

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

  • bridge/c/c_class.cpp:

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

  • bridge/c/c_instance.cpp:

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

  • bridge/c/c_runtime.cpp:

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

  • bridge/c/c_utility.cpp:

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

  • bridge/jni/jni_jsobject.mm:

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

  • bridge/jni/jni_objc.mm:

(JSC::Bindings::dispatchJNICall):

  • bridge/jni/jsc/JNIUtilityPrivate.cpp:

(JSC::Bindings::convertValueToJValue):

  • bridge/jni/jsc/JavaClassJSC.cpp:

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

  • bridge/jni/jsc/JavaInstanceJSC.cpp:

(JavaInstance::stringValue):

  • bridge/jni/jsc/JavaMethodJSC.cpp:

(appendClassName):
(JavaMethod::signature):

  • bridge/jni/jsc/JavaStringJSC.h:

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

  • bridge/jsc/BridgeJSC.cpp:

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

  • bridge/objc/objc_instance.mm:

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

  • bridge/objc/objc_runtime.mm:

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

  • bridge/objc/objc_utility.mm:

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

  • bridge/qt/qt_instance.cpp:

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

  • bridge/qt/qt_pixmapruntime.cpp:

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

  • bridge/qt/qt_runtime.cpp:

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

  • bridge/qt/qt_runtime_qt4.cpp:

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

  • html/HTMLCanvasElement.cpp:

(WebCore::HTMLCanvasElement::createImageBuffer):

  • html/HTMLImageLoader.cpp:

(WebCore::HTMLImageLoader::notifyFinished):

  • plugins/PluginView.cpp:

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

  • plugins/blackberry/PluginViewBlackBerry.cpp:

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

  • plugins/efl/PluginViewEfl.cpp:

(WebCore::PluginView::dispatchNPEvent):

  • plugins/gtk/PluginViewGtk.cpp:

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

  • plugins/mac/PluginViewMac.mm:

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

  • plugins/qt/PluginViewQt.cpp:

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

  • plugins/win/PluginViewWin.cpp:

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

  • testing/js/WebCoreTestSupport.cpp:

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

  • xml/XMLHttpRequest.cpp:

(WebCore::XMLHttpRequest::dropProtection):

Source/WebKit/blackberry:

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

  • Api/BlackBerryGlobal.cpp:

(BlackBerry::WebKit::clearMemoryCaches):

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

(WebCore::PagePopupBlackBerry::installDomFunction):

  • WebKitSupport/DumpRenderTreeSupport.cpp:

(DumpRenderTreeSupport::computedStyleIncludingVisitedInfo):

Source/WebKit/efl:

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

  • ewk/ewk_frame.cpp:

(ewk_frame_script_execute):

  • ewk/ewk_view.cpp:

(ewk_view_js_object_add):

Source/WebKit/gtk:

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

  • WebCoreSupport/DumpRenderTreeSupportGtk.cpp:

(DumpRenderTreeSupportGtk::gcCountJavascriptObjects):

Source/WebKit/mac:

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

  • DOM/WebDOMOperations.mm:

(JSC):

  • Misc/WebCoreStatistics.mm:

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

  • Plugins/Hosted/NetscapePluginInstanceProxy.mm:

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

  • Plugins/WebNetscapePluginStream.mm:

(WebNetscapePluginStream::wantsAllStreams):

  • Plugins/WebNetscapePluginView.mm:

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

  • Plugins/WebPluginController.mm:

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

  • WebView/WebFrame.mm:

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

  • WebView/WebScriptDebugDelegate.mm:

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

  • WebView/WebView.mm:

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

Source/WebKit/qt:

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

  • Api/qwebframe.cpp:

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

  • WebCoreSupport/DumpRenderTreeSupportQt.cpp:

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

Source/WebKit/win:

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

  • WebCoreStatistics.cpp:

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

  • WebFrame.cpp:

(WebFrame::stringByEvaluatingJavaScriptInScriptWorld):

  • WebJavaScriptCollector.cpp:

(WebJavaScriptCollector::objectCount):

  • WebView.cpp:

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

Source/WebKit2:

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

  • Shared/mac/WebMemorySampler.mac.mm:

(WebKit::WebMemorySampler::sampleWebKit):

  • WebProcess/InjectedBundle/InjectedBundle.cpp:

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

  • WebProcess/Plugins/Netscape/JSNPObject.cpp:

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

  • WebProcess/Plugins/Netscape/NPJSObject.cpp:

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

  • WebProcess/Plugins/Netscape/NPRuntimeObjectMap.cpp:

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

  • WebProcess/WebPage/WebFrame.cpp:

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

  • WebProcess/WebPage/WebPage.cpp:

(WebKit::WebPage::runJavaScriptInMainFrame):

  • WebProcess/WebProcess.cpp:

(WebKit::WebProcess::getWebCoreStatistics):

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/runtime/JSLock.cpp

    r100080 r121058  
    2424#include "Heap.h"
    2525#include "CallFrame.h"
     26#include "JSGlobalObject.h"
    2627#include "JSObject.h"
    2728#include "ScopeChain.h"
     
    3940
    4041// Acquire this mutex before accessing lock-related data.
    41 static pthread_mutex_t JSMutex = PTHREAD_MUTEX_INITIALIZER;
    42 
    43 // Thread-specific key that tells whether a thread holds the JSMutex, and how many times it was taken recursively.
    44 pthread_key_t JSLockCount;
    45 
    46 static void createJSLockCount()
    47 {
    48     pthread_key_create(&JSLockCount, 0);
    49 }
    50 
    51 pthread_once_t createJSLockCountOnce = PTHREAD_ONCE_INIT;
    52 
    53 // Lock nesting count.
    54 intptr_t JSLock::lockCount()
    55 {
    56     pthread_once(&createJSLockCountOnce, createJSLockCount);
    57 
    58     return reinterpret_cast<intptr_t>(pthread_getspecific(JSLockCount));
    59 }
    60 
    61 static void setLockCount(intptr_t count)
    62 {
    63     ASSERT(count >= 0);
    64     pthread_setspecific(JSLockCount, reinterpret_cast<void*>(count));
    65 }
    66 
    67 JSLock::JSLock(ExecState* exec)
    68     : m_lockBehavior(exec->globalData().isSharedInstance() ? LockForReal : SilenceAssertionsOnly)
    69 {
    70     lock(m_lockBehavior);
    71 }
    72 
    73 JSLock::JSLock(JSGlobalData* globalData)
    74     : m_lockBehavior(globalData->isSharedInstance() ? LockForReal : SilenceAssertionsOnly)
    75 {
    76     lock(m_lockBehavior);
    77 }
    78 
    79 void JSLock::lock(JSLockBehavior lockBehavior)
    80 {
    81 #ifdef NDEBUG
    82     // Locking "not for real" is a debug-only feature.
    83     if (lockBehavior == SilenceAssertionsOnly)
    84         return;
    85 #endif
    86 
    87     pthread_once(&createJSLockCountOnce, createJSLockCount);
    88 
    89     intptr_t currentLockCount = lockCount();
    90     if (!currentLockCount && lockBehavior == LockForReal) {
    91         int result = pthread_mutex_lock(&JSMutex);
    92         ASSERT_UNUSED(result, !result);
     42static pthread_mutex_t giantGlobalJSLock = PTHREAD_MUTEX_INITIALIZER;
     43
     44GlobalJSLock::GlobalJSLock()
     45{
     46    pthread_mutex_lock(&giantGlobalJSLock);
     47}
     48
     49GlobalJSLock::~GlobalJSLock()
     50{
     51    pthread_mutex_unlock(&giantGlobalJSLock);
     52}
     53
     54JSLockHolder::JSLockHolder(ExecState* exec)
     55    : m_globalData(&exec->globalData())
     56{
     57    m_globalData->apiLock().lock();
     58}
     59
     60JSLockHolder::JSLockHolder(JSGlobalData* globalData)
     61    : m_globalData(globalData)
     62{
     63    m_globalData->apiLock().lock();
     64}
     65
     66JSLockHolder::JSLockHolder(JSGlobalData& globalData)
     67    : m_globalData(&globalData)
     68{
     69    m_globalData->apiLock().lock();
     70}
     71
     72JSLockHolder::~JSLockHolder()
     73{
     74    m_globalData->apiLock().unlock();
     75}
     76
     77JSLock::JSLock()
     78    : m_lockCount(0)
     79{
     80    m_spinLock.Init();
     81}
     82
     83JSLock::~JSLock()
     84{
     85}
     86
     87void JSLock::lock()
     88{
     89    ThreadIdentifier currentThread = WTF::currentThread();
     90    {
     91        SpinLockHolder holder(&m_spinLock);
     92        if (m_ownerThread == currentThread && m_lockCount) {
     93            m_lockCount++;
     94            return;
     95        }
    9396    }
    94     setLockCount(currentLockCount + 1);
    95 }
    96 
    97 void JSLock::unlock(JSLockBehavior lockBehavior)
    98 {
    99     ASSERT(lockCount());
    100 
    101 #ifdef NDEBUG
    102     // Locking "not for real" is a debug-only feature.
    103     if (lockBehavior == SilenceAssertionsOnly)
    104         return;
    105 #endif
    106 
    107     intptr_t newLockCount = lockCount() - 1;
    108     setLockCount(newLockCount);
    109     if (!newLockCount && lockBehavior == LockForReal) {
    110         int result = pthread_mutex_unlock(&JSMutex);
    111         ASSERT_UNUSED(result, !result);
    112     }
     97
     98    m_lock.lock();
     99
     100    SpinLockHolder holder(&m_spinLock);
     101    m_ownerThread = currentThread;
     102    ASSERT(!m_lockCount);
     103    m_lockCount = 1;
     104}
     105
     106void JSLock::unlock()
     107{
     108    ASSERT(currentThreadIsHoldingLock());
     109
     110    SpinLockHolder holder(&m_spinLock);
     111    m_lockCount--;
     112
     113    if (!m_lockCount)
     114        m_lock.unlock();
    113115}
    114116
    115117void JSLock::lock(ExecState* exec)
    116118{
    117     lock(exec->globalData().isSharedInstance() ? LockForReal : SilenceAssertionsOnly);
     119    exec->globalData().apiLock().lock();
    118120}
    119121
    120122void JSLock::unlock(ExecState* exec)
    121123{
    122     unlock(exec->globalData().isSharedInstance() ? LockForReal : SilenceAssertionsOnly);
     124    exec->globalData().apiLock().unlock();
    123125}
    124126
    125127bool JSLock::currentThreadIsHoldingLock()
    126128{
    127     pthread_once(&createJSLockCountOnce, createJSLockCount);
    128     return !!pthread_getspecific(JSLockCount);
     129    return m_lockCount && m_ownerThread == WTF::currentThread();
    129130}
    130131
     
    150151// write over the second thread's call frames.
    151152//
    152 // In avoid JS stack corruption we enforce a policy of only ever allowing two
     153// To avoid JS stack corruption we enforce a policy of only ever allowing two
    153154// threads to use a JS context concurrently, and only allowing the second of
    154155// these threads to execute until it has completed and fully returned from its
     
    159160// again through a callback, then the locks will not be dropped when DropAllLocks
    160161// is called (since lockDropDepth is non-zero).  Since this thread is still holding
    161 // the locks, only it will re able to re-enter JSC (either be returning from the
     162// the locks, only it will be able to re-enter JSC (either be returning from the
    162163// callback, or by re-entering through another call to evaulate script or call
    163164// function).
     
    169170// would likely increase complexity and overhead.
    170171//
    171 static unsigned lockDropDepth = 0;
     172
     173// This function returns the number of locks that were dropped.
     174unsigned JSLock::dropAllLocks()
     175{
     176    if (m_lockDropDepth++)
     177        return 0;
     178
     179    return dropAllLocksUnconditionally();
     180}
     181
     182unsigned JSLock::dropAllLocksUnconditionally()
     183{
     184    unsigned lockCount = m_lockCount;
     185    for (unsigned i = 0; i < lockCount; i++)
     186        unlock();
     187
     188    return lockCount;
     189}
     190
     191void JSLock::grabAllLocks(unsigned lockCount)
     192{
     193    for (unsigned i = 0; i < lockCount; i++)
     194        lock();
     195
     196    m_lockDropDepth--;
     197}
    172198
    173199JSLock::DropAllLocks::DropAllLocks(ExecState* exec)
    174     : m_lockBehavior(exec->globalData().isSharedInstance() ? LockForReal : SilenceAssertionsOnly)
    175 {
    176     pthread_once(&createJSLockCountOnce, createJSLockCount);
    177 
    178     if (lockDropDepth++) {
    179         m_lockCount = 0;
    180         return;
    181     }
    182 
    183     m_lockCount = JSLock::lockCount();
    184     for (intptr_t i = 0; i < m_lockCount; i++)
    185         JSLock::unlock(m_lockBehavior);
    186 }
    187 
    188 JSLock::DropAllLocks::DropAllLocks(JSLockBehavior JSLockBehavior)
    189     : m_lockBehavior(JSLockBehavior)
    190 {
    191     pthread_once(&createJSLockCountOnce, createJSLockCount);
    192 
    193     if (lockDropDepth++) {
    194         m_lockCount = 0;
    195         return;
    196     }
    197 
    198     // It is necessary to drop even "unreal" locks, because having a non-zero lock count
    199     // will prevent a real lock from being taken.
    200 
    201     m_lockCount = JSLock::lockCount();
    202     for (intptr_t i = 0; i < m_lockCount; i++)
    203         JSLock::unlock(m_lockBehavior);
     200    : m_lockCount(0)
     201    , m_globalData(&exec->globalData())
     202{
     203    m_lockCount = m_globalData->apiLock().dropAllLocks();
     204}
     205
     206JSLock::DropAllLocks::DropAllLocks(JSGlobalData* globalData)
     207    : m_lockCount(0)
     208    , m_globalData(globalData)
     209{
     210    m_lockCount = m_globalData->apiLock().dropAllLocks();
    204211}
    205212
    206213JSLock::DropAllLocks::~DropAllLocks()
    207214{
    208     for (intptr_t i = 0; i < m_lockCount; i++)
    209         JSLock::lock(m_lockBehavior);
    210 
    211     --lockDropDepth;
     215    m_globalData->apiLock().grabAllLocks(m_lockCount);
    212216}
    213217
    214218#else // (OS(DARWIN) || USE(PTHREADS))
    215219
    216 JSLock::JSLock(ExecState*)
    217     : m_lockBehavior(SilenceAssertionsOnly)
    218 {
    219 }
    220 
    221 // If threading support is off, set the lock count to a constant value of 1 so ssertions
    222 // that the lock is held don't fail
    223 intptr_t JSLock::lockCount()
    224 {
    225     return 1;
     220GlobalJSLock::GlobalJSLock()
     221{
     222}
     223
     224GlobalJSLock::~GlobalJSLock()
     225{
     226}
     227
     228JSLockHolder::JSLockHolder(JSGlobalData*)
     229{
     230}
     231
     232JSLockHolder::JSLockHolder(JSGlobalData&)
     233{
     234}
     235
     236JSLockHolder::JSLockHolder(ExecState*)
     237{
     238}
     239
     240JSLockHolder::~JSLockHolder()
     241{
     242}
     243
     244JSLock::JSLock()
     245{
     246}
     247
     248JSLock::~JSLock()
     249{
    226250}
    227251
     
    231255}
    232256
    233 void JSLock::lock(JSLockBehavior)
    234 {
    235 }
    236 
    237 void JSLock::unlock(JSLockBehavior)
     257void JSLock::lock()
     258{
     259}
     260
     261void JSLock::unlock()
    238262{
    239263}
     
    247271}
    248272
     273void JSLock::lock(JSGlobalData&)
     274{
     275}
     276
     277void JSLock::unlock(JSGlobalData&)
     278{
     279}
     280
     281unsigned JSLock::dropAllLocks()
     282{
     283    return 0;
     284}
     285
     286unsigned JSLock::dropAllLocksUnconditionally()
     287{
     288    return 0;
     289}
     290
     291void JSLock::grabAllLocks(unsigned)
     292{
     293}
     294
    249295JSLock::DropAllLocks::DropAllLocks(ExecState*)
    250296{
    251297}
    252298
    253 JSLock::DropAllLocks::DropAllLocks(JSLockBehavior)
     299JSLock::DropAllLocks::DropAllLocks(JSGlobalData*)
    254300{
    255301}
Note: See TracChangeset for help on using the changeset viewer.