Commit 6d9f86d9 authored by mhahnenberg@apple.com's avatar mhahnenberg@apple.com

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


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@121058 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent b7a84459
......@@ -28,31 +28,40 @@
#include "CallFrame.h"
#include "GCActivityCallback.h"
#include "IncrementalSweeper.h"
#include "JSLock.h"
#include <wtf/WTFThreadData.h>
namespace JSC {
class APIEntryShimWithoutLock {
public:
enum RefGlobalDataTag { DontRefGlobalData = 0, RefGlobalData };
protected:
APIEntryShimWithoutLock(JSGlobalData* globalData, bool registerThread)
: m_globalData(globalData)
APIEntryShimWithoutLock(JSGlobalData* globalData, bool registerThread, RefGlobalDataTag shouldRefGlobalData)
: m_shouldRefGlobalData(shouldRefGlobalData)
, m_globalData(globalData)
, m_entryIdentifierTable(wtfThreadData().setCurrentIdentifierTable(globalData->identifierTable))
{
if (shouldRefGlobalData)
m_globalData->ref();
UNUSED_PARAM(registerThread);
if (registerThread)
globalData->heap.machineThreads().addCurrentThread();
m_globalData->heap.activityCallback()->synchronize();
m_globalData->timeoutChecker.start();
m_globalData->heap.sweeper()->synchronize();
}
~APIEntryShimWithoutLock()
{
m_globalData->timeoutChecker.stop();
wtfThreadData().setCurrentIdentifierTable(m_entryIdentifierTable);
if (m_shouldRefGlobalData)
m_globalData->deref();
}
private:
protected:
RefGlobalDataTag m_shouldRefGlobalData;
JSGlobalData* m_globalData;
IdentifierTable* m_entryIdentifierTable;
};
......@@ -61,20 +70,38 @@ class APIEntryShim : public APIEntryShimWithoutLock {
public:
// Normal API entry
APIEntryShim(ExecState* exec, bool registerThread = true)
: APIEntryShimWithoutLock(&exec->globalData(), registerThread)
, m_lock(exec)
: APIEntryShimWithoutLock(&exec->globalData(), registerThread, RefGlobalData)
{
init();
}
// This constructor is necessary for HeapTimer to prevent it from accidentally resurrecting
// the ref count of a "dead" JSGlobalData.
APIEntryShim(JSGlobalData* globalData, RefGlobalDataTag refGlobalData, bool registerThread = true)
: APIEntryShimWithoutLock(globalData, registerThread, refGlobalData)
{
init();
}
// JSPropertyNameAccumulator only has a globalData.
APIEntryShim(JSGlobalData* globalData, bool registerThread = true)
: APIEntryShimWithoutLock(globalData, registerThread)
, m_lock(globalData->isSharedInstance() ? LockForReal : SilenceAssertionsOnly)
: APIEntryShimWithoutLock(globalData, registerThread, RefGlobalData)
{
init();
}
~APIEntryShim()
{
m_globalData->timeoutChecker.stop();
m_globalData->apiLock().unlock();
}
private:
JSLock m_lock;
void init()
{
m_globalData->apiLock().lock();
m_globalData->timeoutChecker.start();
}
};
class APICallbackShim {
......@@ -88,7 +115,6 @@ public:
~APICallbackShim()
{
m_globalData->heap.activityCallback()->synchronize();
wtfThreadData().setCurrentIdentifierTable(m_globalData->identifierTable);
}
......
......@@ -78,7 +78,6 @@ JSGlobalContextRef JSGlobalContextCreate(JSClassRef globalObjectClass)
// If the application was linked before JSGlobalContextCreate was changed to use a unique JSGlobalData,
// we use a shared one for backwards compatibility.
if (NSVersionOfLinkTimeLibrary("JavaScriptCore") <= webkitFirstVersionWithConcurrentGlobalContexts) {
JSLock lock(LockForReal);
return JSGlobalContextCreateInGroup(toRef(&JSGlobalData::sharedInstance()), globalObjectClass);
}
#endif // OS(DARWIN)
......@@ -90,11 +89,9 @@ JSGlobalContextRef JSGlobalContextCreateInGroup(JSContextGroupRef group, JSClass
{
initializeThreading();
JSLock lock(LockForReal);
RefPtr<JSGlobalData> globalData = group ? PassRefPtr<JSGlobalData>(toJS(group)) : JSGlobalData::createContextGroup(ThreadStackTypeSmall);
APIEntryShim entryShim(globalData.get(), false);
globalData->makeUsableFromMultipleThreads();
if (!globalObjectClass) {
......@@ -124,18 +121,19 @@ JSGlobalContextRef JSGlobalContextRetain(JSGlobalContextRef ctx)
void JSGlobalContextRelease(JSGlobalContextRef ctx)
{
IdentifierTable* savedIdentifierTable;
ExecState* exec = toJS(ctx);
JSLock lock(exec);
{
JSLockHolder lock(exec);
JSGlobalData& globalData = exec->globalData();
IdentifierTable* savedIdentifierTable = wtfThreadData().setCurrentIdentifierTable(globalData.identifierTable);
JSGlobalData& globalData = exec->globalData();
savedIdentifierTable = wtfThreadData().setCurrentIdentifierTable(globalData.identifierTable);
bool protectCountIsZero = Heap::heap(exec->dynamicGlobalObject())->unprotect(exec->dynamicGlobalObject());
if (protectCountIsZero) {
globalData.heap.activityCallback()->synchronize();
globalData.heap.reportAbandonedObjectGraph();
bool protectCountIsZero = Heap::heap(exec->dynamicGlobalObject())->unprotect(exec->dynamicGlobalObject());
if (protectCountIsZero)
globalData.heap.reportAbandonedObjectGraph();
globalData.deref();
}
globalData.deref();
wtfThreadData().setCurrentIdentifierTable(savedIdentifierTable);
}
......@@ -166,7 +164,7 @@ JSGlobalContextRef JSContextGetGlobalContext(JSContextRef ctx)
JSStringRef JSContextCreateBacktrace(JSContextRef ctx, unsigned maxStackSize)
{
ExecState* exec = toJS(ctx);
JSLock lock(exec);
JSLockHolder lock(exec);
unsigned count = 0;
UStringBuilder builder;
......
2012-06-20 Mark Hahnenberg <mhahnenberg@apple.com>
JSLock should be per-JSGlobalData
https://bugs.webkit.org/show_bug.cgi?id=89123
Reviewed by Gavin Barraclough.
* 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):
2012-06-22 Peter Beverloo <peter@chromium.org>
[Chromium] Disable c++0x compatibility warnings in JavaScriptCore.gyp when building for Android
......
......@@ -6,10 +6,13 @@ EXPORTS
??0Collator@WTF@@QAE@PBD@Z
??0DateInstance@JSC@@IAE@PAVExecState@1@PAVStructure@1@@Z
??0DefaultGCActivityCallback@JSC@@QAE@PAVHeap@1@@Z
??0DropAllLocks@JSLock@JSC@@QAE@W4JSLockBehavior@2@@Z
??0DropAllLocks@JSLock@JSC@@QAE@PAVExecState@2@@Z
??0DropAllLocks@JSLock@JSC@@QAE@PAVJSGlobalData@2@@Z
??0DynamicGlobalObjectScope@JSC@@QAE@AAVJSGlobalData@1@PAVJSGlobalObject@1@@Z
??0InternalFunction@JSC@@IAE@PAVJSGlobalObject@1@PAVStructure@1@@Z
??0JSLock@JSC@@QAE@PAVExecState@1@@Z
??0JSLockHolder@JSC@@QAE@AAVJSGlobalData@1@@Z
??0JSLockHolder@JSC@@QAE@PAVExecState@1@@Z
??0JSLockHolder@JSC@@QAE@PAVJSGlobalData@1@@Z
??0MD5@WTF@@QAE@XZ
??0Mutex@WTF@@QAE@XZ
??0ParallelEnvironment@WTF@@QAE@P6AXPAX@ZIH@Z
......@@ -32,6 +35,7 @@ EXPORTS
??1DropAllLocks@JSLock@JSC@@QAE@XZ
??1JSGlobalData@JSC@@QAE@XZ
??1JSGlobalObject@JSC@@QAE@XZ
??1JSLockHolder@JSC@@QAE@XZ
??1Mutex@WTF@@QAE@XZ
??1RefCountedLeakCounter@WTF@@QAE@XZ
??1SourceProviderCache@JSC@@QAE@XZ
......@@ -123,7 +127,6 @@ EXPORTS
?cryptographicallyRandomNumber@WTF@@YAIXZ
?cryptographicallyRandomValues@WTF@@YAXPAXI@Z
?currentThread@WTF@@YAIXZ
?currentThreadIsHoldingLock@JSLock@JSC@@SA_NXZ
?currentTime@WTF@@YANXZ
?data@CString@WTF@@QBEPBDXZ
?dataLog@WTF@@YAXPBDZZ
......@@ -235,10 +238,9 @@ EXPORTS
?jsOwnedString@JSC@@YAPAVJSString@1@PAVJSGlobalData@1@ABVUString@1@@Z
?jsString@JSC@@YAPAVJSString@1@PAVJSGlobalData@1@ABVUString@1@@Z
?length@CString@WTF@@QBEIXZ
?lock@JSLock@JSC@@SAXW4JSLockBehavior@2@@Z
?lock@JSLock@JSC@@QAEXXZ
?lock@Mutex@WTF@@QAEXXZ
?lockAtomicallyInitializedStaticMutex@WTF@@YAXXZ
?lockCount@JSLock@JSC@@SAHXZ
?match@RegExp@JSC@@QAEHAAVJSGlobalData@2@ABVUString@2@IAAV?$Vector@H$0CA@@WTF@@@Z
?materializePropertyMap@Structure@JSC@@AAEXAAVJSGlobalData@2@@Z
?monotonicallyIncreasingTime@WTF@@YANXZ
......@@ -323,6 +325,7 @@ EXPORTS
?stopSampling@JSGlobalData@JSC@@QAEXXZ
?substringSharingImpl@UString@JSC@@QBE?AV12@II@Z
?suggestedNewPropertyStorageSize@Structure@JSC@@QAEIXZ
?sweeper@Heap@JSC@@QAEPAVIncrementalSweeper@2@XZ
?synthesizePrototype@JSValue@JSC@@QBEPAVJSObject@2@PAVExecState@2@@Z
?thisObject@DebuggerCallFrame@JSC@@QBEPAVJSObject@2@XZ
?throwError@JSC@@YA?AVJSValue@1@PAVExecState@1@V21@@Z
......@@ -352,7 +355,7 @@ EXPORTS
?tryFinishCreationUninitialized@JSArray@JSC@@IAEPAV12@AAVJSGlobalData@2@I@Z
?tryLock@Mutex@WTF@@QAE_NXZ
?type@DebuggerCallFrame@JSC@@QBE?AW4Type@12@XZ
?unlock@JSLock@JSC@@SAXW4JSLockBehavior@2@@Z
?unlock@JSLock@JSC@@QAEXXZ
?unlock@Mutex@WTF@@QAEXXZ
?unlockAtomicallyInitializedStaticMutex@WTF@@YAXXZ
?unprotect@Heap@JSC@@QAE_NVJSValue@2@@Z
......
......@@ -66,6 +66,7 @@ CheckedBoolean CopiedSpace::tryAllocateSlowCase(size_t bytes, void** outPtr)
if (isOversize(bytes))
return tryAllocateOversize(bytes, outPtr);
ASSERT(m_heap->globalData()->apiLock().currentThreadIsHoldingLock());
m_heap->didAllocate(m_allocator.currentCapacity());
allocateBlock();
......
......@@ -160,15 +160,9 @@ static inline size_t proportionalHeapSize(size_t heapSize, size_t ramSize)
return 1.25 * heapSize;
}
static inline bool isValidSharedInstanceThreadState()
static inline bool isValidSharedInstanceThreadState(JSGlobalData* globalData)
{
if (!JSLock::lockCount())
return false;
if (!JSLock::currentThreadIsHoldingLock())
return false;
return true;
return globalData->apiLock().currentThreadIsHoldingLock();
}
static inline bool isValidThreadState(JSGlobalData* globalData)
......@@ -176,7 +170,7 @@ static inline bool isValidThreadState(JSGlobalData* globalData)
if (globalData->identifierTable != wtfThreadData().currentIdentifierTable())
return false;
if (globalData->isSharedInstance() && !isValidSharedInstanceThreadState())
if (globalData->isSharedInstance() && !isValidSharedInstanceThreadState(globalData))
return false;
return true;
......@@ -327,7 +321,7 @@ void Heap::didAbandon(size_t bytes)
void Heap::protect(JSValue k)
{
ASSERT(k);
ASSERT(JSLock::currentThreadIsHoldingLock() || !m_globalData->isSharedInstance());
ASSERT(m_globalData->apiLock().currentThreadIsHoldingLock());
if (!k.isCell())
return;
......@@ -338,7 +332,7 @@ void Heap::protect(JSValue k)
bool Heap::unprotect(JSValue k)
{
ASSERT(k);
ASSERT(JSLock::currentThreadIsHoldingLock() || !m_globalData->isSharedInstance());
ASSERT(m_globalData->apiLock().currentThreadIsHoldingLock());
if (!k.isCell())
return false;
......@@ -692,6 +686,7 @@ void Heap::collect(SweepToggle sweepToggle)
SamplingRegion samplingRegion("Garbage Collection");
GCPHASE(Collect);
ASSERT(globalData()->apiLock().currentThreadIsHoldingLock());
ASSERT(globalData()->identifierTable == wtfThreadData().currentIdentifierTable());
ASSERT(m_isSafeToCollect);
JAVASCRIPTCORE_GC_BEGIN();
......@@ -777,19 +772,19 @@ void Heap::collect(SweepToggle sweepToggle)
JAVASCRIPTCORE_GC_END();
}
void Heap::setActivityCallback(PassOwnPtr<GCActivityCallback> activityCallback)
void Heap::setActivityCallback(GCActivityCallback* activityCallback)
{
m_activityCallback = activityCallback;
}
GCActivityCallback* Heap::activityCallback()
{
return m_activityCallback.get();
return m_activityCallback;
}
IncrementalSweeper* Heap::sweeper()
{
return m_sweeper.get();
return m_sweeper;
}
void Heap::setGarbageCollectionTimerEnabled(bool enable)
......
......@@ -99,10 +99,10 @@ namespace JSC {
MachineThreads& machineThreads() { return m_machineThreads; }
JS_EXPORT_PRIVATE GCActivityCallback* activityCallback();
JS_EXPORT_PRIVATE void setActivityCallback(PassOwnPtr<GCActivityCallback>);
JS_EXPORT_PRIVATE void setActivityCallback(GCActivityCallback*);
JS_EXPORT_PRIVATE void setGarbageCollectionTimerEnabled(bool);
IncrementalSweeper* sweeper();
JS_EXPORT_PRIVATE IncrementalSweeper* sweeper();
// true if an allocation or collection is in progress
inline bool isBusy();
......@@ -237,10 +237,10 @@ namespace JSC {
double m_lastGCLength;
double m_lastCodeDiscardTime;
OwnPtr<GCActivityCallback> m_activityCallback;
OwnPtr<IncrementalSweeper> m_sweeper;
DoublyLinkedList<ExecutableBase> m_compiledCode;
GCActivityCallback* m_activityCallback;
IncrementalSweeper* m_sweeper;
};
inline bool Heap::shouldCollect()
......
......@@ -26,6 +26,10 @@
#include "config.h"
#include "HeapTimer.h"
#include "APIShims.h"
#include "JSObject.h"
#include "JSString.h"
#include "ScopeChain.h"
#include <wtf/Threading.h>
namespace JSC {
......@@ -46,7 +50,8 @@ HeapTimer::HeapTimer(JSGlobalData* globalData, CFRunLoopRef runLoop)
HeapTimer::~HeapTimer()
{
invalidate();
CFRunLoopRemoveTimer(m_runLoop.get(), m_timer.get(), kCFRunLoopCommonModes);
CFRunLoopTimerInvalidate(m_timer.get());
}
void HeapTimer::synchronize()
......@@ -60,14 +65,37 @@ void HeapTimer::synchronize()
void HeapTimer::invalidate()
{
CFRunLoopRemoveTimer(m_runLoop.get(), m_timer.get(), kCFRunLoopCommonModes);
CFRunLoopTimerInvalidate(m_timer.get());
m_globalData = 0;
CFRunLoopTimerSetNextFireDate(m_timer.get(), CFAbsoluteTimeGetCurrent() - s_decade);
}
void HeapTimer::didStartVMShutdown()
{
if (CFRunLoopGetCurrent() == m_runLoop.get()) {
invalidate();
delete this;
return;
}
ASSERT(!m_globalData->apiLock().currentThreadIsHoldingLock());
MutexLocker locker(m_shutdownMutex);
invalidate();
}
void HeapTimer::timerDidFire(CFRunLoopTimerRef, void* info)
{
HeapTimer* agent = static_cast<HeapTimer*>(info);
agent->doWork();
agent->m_shutdownMutex.lock();
if (!agent->m_globalData) {
agent->m_shutdownMutex.unlock();
delete agent;
return;
}
{
// We don't ref here to prevent us from resurrecting the ref count of a "dead" JSGlobalData.
APIEntryShim shim(agent->m_globalData, APIEntryShimWithoutLock::DontRefGlobalData);
agent->doWork();
}
agent->m_shutdownMutex.unlock();
}
#else
......@@ -81,6 +109,11 @@ HeapTimer::~HeapTimer()
{
}
void HeapTimer::didStartVMShutdown()
{
delete this;
}
void HeapTimer::synchronize()
{
}
......@@ -89,7 +122,6 @@ void HeapTimer::invalidate()
{
}
#endif
......
......@@ -27,6 +27,7 @@
#define HeapTimer_h
#include <wtf/RetainPtr.h>
#include <wtf/Threading.h>
#if USE(CF)
#include <CoreFoundation/CoreFoundation.h>
......@@ -46,7 +47,8 @@ public:
#endif
virtual ~HeapTimer();
void didStartVMShutdown();
virtual void synchronize();
virtual void doWork() = 0;
......@@ -59,6 +61,8 @@ protected:
RetainPtr<CFRunLoopTimerRef> m_timer;
RetainPtr<CFRunLoopRef> m_runLoop;
CFRunLoopTimerContext m_context;
Mutex m_shutdownMutex;
#endif
private:
......
......@@ -45,7 +45,6 @@ static const CFTimeInterval sweepTimeMultiplier = 1.0 / sweepTimeTotal;
void IncrementalSweeper::doWork()
{
APIEntryShim shim(m_globalData);
doSweep(WTF::monotonicallyIncreasingTime());
}
......@@ -55,9 +54,9 @@ IncrementalSweeper::IncrementalSweeper(Heap* heap, CFRunLoopRef runLoop)
{
}
PassOwnPtr<IncrementalSweeper> IncrementalSweeper::create(Heap* heap)
IncrementalSweeper* IncrementalSweeper::create(Heap* heap)
{
return adoptPtr(new IncrementalSweeper(heap, CFRunLoopGetCurrent()));
return new IncrementalSweeper(heap, CFRunLoopGetCurrent());
}
void IncrementalSweeper::scheduleTimer()
......@@ -109,9 +108,9 @@ void IncrementalSweeper::doWork()
{
}
PassOwnPtr<IncrementalSweeper> IncrementalSweeper::create(Heap* heap)
IncrementalSweeper* IncrementalSweeper::create(Heap* heap)
{
return adoptPtr(new IncrementalSweeper(heap->