mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Test-landing (again) Bug 373462, bug 385322, Better scheduling of cycle collection/gc, r+sr=sicking,jst
This commit is contained in:
parent
33e3d4f7e7
commit
cad8f0b8c4
@ -56,6 +56,7 @@
|
|||||||
#include "prprf.h"
|
#include "prprf.h"
|
||||||
#include "nsIDOMEventListener.h"
|
#include "nsIDOMEventListener.h"
|
||||||
#include "nsIJSContextStack.h"
|
#include "nsIJSContextStack.h"
|
||||||
|
#include "nsJSEnvironment.h"
|
||||||
#include "nsIScriptSecurityManager.h"
|
#include "nsIScriptSecurityManager.h"
|
||||||
#include "nsWeakPtr.h"
|
#include "nsWeakPtr.h"
|
||||||
#include "nsICharsetAlias.h"
|
#include "nsICharsetAlias.h"
|
||||||
@ -1778,6 +1779,7 @@ nsXMLHttpRequest::RequestCompleted()
|
|||||||
ChangeState(XML_HTTP_REQUEST_OPENED);
|
ChangeState(XML_HTTP_REQUEST_OPENED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsJSContext::MaybeCC(PR_FALSE);
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2320,6 +2322,7 @@ nsXMLHttpRequest::Error(nsIDOMEvent* aEvent)
|
|||||||
NotifyEventListeners(errorEventListeners, event);
|
NotifyEventListeners(errorEventListeners, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsJSContext::MaybeCC(PR_FALSE);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,6 +136,9 @@
|
|||||||
#include "nsEventDispatcher.h"
|
#include "nsEventDispatcher.h"
|
||||||
#include "nsPresShellIterator.h"
|
#include "nsPresShellIterator.h"
|
||||||
|
|
||||||
|
#include "nsServiceManagerUtils.h"
|
||||||
|
#include "nsITimer.h"
|
||||||
|
|
||||||
#ifdef XP_MACOSX
|
#ifdef XP_MACOSX
|
||||||
#include <Events.h>
|
#include <Events.h>
|
||||||
#endif
|
#endif
|
||||||
@ -144,6 +147,8 @@
|
|||||||
//#define DEBUG_DOCSHELL_FOCUS
|
//#define DEBUG_DOCSHELL_FOCUS
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define NS_USER_INTERACTION_INTERVAL 5000 // ms
|
||||||
|
|
||||||
static NS_DEFINE_CID(kFrameTraversalCID, NS_FRAMETRAVERSAL_CID);
|
static NS_DEFINE_CID(kFrameTraversalCID, NS_FRAMETRAVERSAL_CID);
|
||||||
|
|
||||||
|
|
||||||
@ -171,6 +176,41 @@ static PRUint32 sESMInstanceCount = 0;
|
|||||||
static PRInt32 sChromeAccessModifier = 0, sContentAccessModifier = 0;
|
static PRInt32 sChromeAccessModifier = 0, sContentAccessModifier = 0;
|
||||||
PRInt32 nsEventStateManager::sUserInputEventDepth = 0;
|
PRInt32 nsEventStateManager::sUserInputEventDepth = 0;
|
||||||
|
|
||||||
|
static PRUint32 gMouseOrKeyboardEventCounter = 0;
|
||||||
|
static nsITimer* gUserInteractionTimer = nsnull;
|
||||||
|
static nsITimerCallback* gUserInteractionTimerCallback = nsnull;
|
||||||
|
|
||||||
|
class nsUITimerCallback : public nsITimerCallback
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
nsUITimerCallback() : mPreviousCount(0) {}
|
||||||
|
NS_DECL_ISUPPORTS
|
||||||
|
NS_DECL_NSITIMERCALLBACK
|
||||||
|
private:
|
||||||
|
PRUint32 mPreviousCount;
|
||||||
|
};
|
||||||
|
|
||||||
|
NS_IMPL_ISUPPORTS1(nsUITimerCallback, nsITimerCallback)
|
||||||
|
|
||||||
|
// If aTimer is nsnull, this method always sends "user-interaction-inactive"
|
||||||
|
// notification.
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsUITimerCallback::Notify(nsITimer* aTimer)
|
||||||
|
{
|
||||||
|
nsresult rv;
|
||||||
|
nsCOMPtr<nsIObserverService> obs =
|
||||||
|
do_GetService("@mozilla.org/observer-service;1", &rv);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
if ((gMouseOrKeyboardEventCounter == mPreviousCount) || !aTimer) {
|
||||||
|
gMouseOrKeyboardEventCounter = 0;
|
||||||
|
obs->NotifyObservers(nsnull, "user-interaction-inactive", nsnull);
|
||||||
|
} else {
|
||||||
|
obs->NotifyObservers(nsnull, "user-interaction-active", nsnull);
|
||||||
|
}
|
||||||
|
mPreviousCount = gMouseOrKeyboardEventCounter;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
MOUSE_SCROLL_N_LINES,
|
MOUSE_SCROLL_N_LINES,
|
||||||
MOUSE_SCROLL_PAGE,
|
MOUSE_SCROLL_PAGE,
|
||||||
@ -431,6 +471,18 @@ nsEventStateManager::nsEventStateManager()
|
|||||||
mTabbedThroughDocument(PR_FALSE),
|
mTabbedThroughDocument(PR_FALSE),
|
||||||
mAccessKeys(nsnull)
|
mAccessKeys(nsnull)
|
||||||
{
|
{
|
||||||
|
if (sESMInstanceCount == 0) {
|
||||||
|
gUserInteractionTimerCallback = new nsUITimerCallback();
|
||||||
|
if (gUserInteractionTimerCallback) {
|
||||||
|
NS_ADDREF(gUserInteractionTimerCallback);
|
||||||
|
CallCreateInstance("@mozilla.org/timer;1", &gUserInteractionTimer);
|
||||||
|
if (gUserInteractionTimer) {
|
||||||
|
gUserInteractionTimer->InitWithCallback(gUserInteractionTimerCallback,
|
||||||
|
NS_USER_INTERACTION_INTERVAL,
|
||||||
|
nsITimer::TYPE_REPEATING_SLACK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
++sESMInstanceCount;
|
++sESMInstanceCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -509,6 +561,14 @@ nsEventStateManager::~nsEventStateManager()
|
|||||||
if(sESMInstanceCount == 0) {
|
if(sESMInstanceCount == 0) {
|
||||||
NS_IF_RELEASE(gLastFocusedContent);
|
NS_IF_RELEASE(gLastFocusedContent);
|
||||||
NS_IF_RELEASE(gLastFocusedDocument);
|
NS_IF_RELEASE(gLastFocusedDocument);
|
||||||
|
if (gUserInteractionTimerCallback) {
|
||||||
|
gUserInteractionTimerCallback->Notify(nsnull);
|
||||||
|
NS_RELEASE(gUserInteractionTimerCallback);
|
||||||
|
}
|
||||||
|
if (gUserInteractionTimer) {
|
||||||
|
gUserInteractionTimer->Cancel();
|
||||||
|
NS_RELEASE(gUserInteractionTimer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
delete mAccessKeys;
|
delete mAccessKeys;
|
||||||
@ -724,6 +784,21 @@ nsEventStateManager::PreHandleEvent(nsPresContext* aPresContext,
|
|||||||
if (!mCurrentTarget) return NS_ERROR_NULL_POINTER;
|
if (!mCurrentTarget) return NS_ERROR_NULL_POINTER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (NS_IS_TRUSTED_EVENT(aEvent) &&
|
||||||
|
((aEvent->eventStructType == NS_MOUSE_EVENT &&
|
||||||
|
static_cast<nsMouseEvent*>(aEvent)->reason == nsMouseEvent::eReal) ||
|
||||||
|
aEvent->eventStructType == NS_MOUSE_SCROLL_EVENT ||
|
||||||
|
aEvent->eventStructType == NS_KEY_EVENT)) {
|
||||||
|
if (gMouseOrKeyboardEventCounter == 0) {
|
||||||
|
nsCOMPtr<nsIObserverService> obs =
|
||||||
|
do_GetService("@mozilla.org/observer-service;1");
|
||||||
|
if (obs) {
|
||||||
|
obs->NotifyObservers(nsnull, "user-interaction-active", nsnull);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
++gMouseOrKeyboardEventCounter;
|
||||||
|
}
|
||||||
|
|
||||||
*aStatus = nsEventStatus_eIgnore;
|
*aStatus = nsEventStatus_eIgnore;
|
||||||
|
|
||||||
nsMouseWheelTransaction::OnEvent(aEvent);
|
nsMouseWheelTransaction::OnEvent(aEvent);
|
||||||
|
@ -149,8 +149,26 @@ static PRLogModuleInfo* gJSDiagnostics;
|
|||||||
|
|
||||||
#define JAVASCRIPT nsIProgrammingLanguage::JAVASCRIPT
|
#define JAVASCRIPT nsIProgrammingLanguage::JAVASCRIPT
|
||||||
|
|
||||||
|
// The max number of delayed cycle collects..
|
||||||
|
#define NS_MAX_DELAYED_CCOLLECT 45
|
||||||
|
// The max number of user interaction notifications in inactive state before
|
||||||
|
// we try to call cycle collector more aggressively.
|
||||||
|
#define NS_CC_SOFT_LIMIT_INACTIVE 6
|
||||||
|
// The max number of user interaction notifications in active state before
|
||||||
|
// we try to call cycle collector more aggressively.
|
||||||
|
#define NS_CC_SOFT_LIMIT_ACTIVE 12
|
||||||
|
// When higher probability MaybeCC is used, the number of sDelayedCCollectCount
|
||||||
|
// is multiplied with this number.
|
||||||
|
#define NS_PROBABILITY_MULTIPLIER 3
|
||||||
|
// Cycle collector should never run more often than this value
|
||||||
|
#define NS_MIN_CC_INTERVAL 10000 // ms
|
||||||
|
|
||||||
// if you add statics here, add them to the list in nsJSRuntime::Startup
|
// if you add statics here, add them to the list in nsJSRuntime::Startup
|
||||||
|
|
||||||
|
static PRUint32 sDelayedCCollectCount;
|
||||||
|
static PRUint32 sCCollectCount;
|
||||||
|
static PRTime sPreviousCCTime;
|
||||||
|
static PRBool sPreviousCCDidCollect;
|
||||||
static nsITimer *sGCTimer;
|
static nsITimer *sGCTimer;
|
||||||
static PRBool sReadyForGC;
|
static PRBool sReadyForGC;
|
||||||
|
|
||||||
@ -194,6 +212,75 @@ static nsICollation *gCollation;
|
|||||||
|
|
||||||
static nsIUnicodeDecoder *gDecoder;
|
static nsIUnicodeDecoder *gDecoder;
|
||||||
|
|
||||||
|
// nsUserActivityObserver observes user-interaction-active and
|
||||||
|
// user-interaction-inactive notifications. It counts the number of
|
||||||
|
// notifications and if the number is bigger than NS_CC_SOFT_LIMIT_ACTIVE
|
||||||
|
// (in case the current notification is user-interaction-active) or
|
||||||
|
// NS_CC_SOFT_LIMIT_INACTIVE (current notification is user-interaction-inactive)
|
||||||
|
// MaybeCC is called with aHigherParameter set to PR_TRUE, otherwise PR_FALSE.
|
||||||
|
//
|
||||||
|
// When moving from active state to inactive, nsJSContext::CC() is called
|
||||||
|
// unless the timer related to page load is active.
|
||||||
|
|
||||||
|
class nsUserActivityObserver : public nsIObserver
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
nsUserActivityObserver()
|
||||||
|
: mUserActivityCounter(0), mOldCCollectCount(0), mUserIsActive(PR_FALSE) {}
|
||||||
|
NS_DECL_ISUPPORTS
|
||||||
|
NS_DECL_NSIOBSERVER
|
||||||
|
private:
|
||||||
|
PRUint32 mUserActivityCounter;
|
||||||
|
PRUint32 mOldCCollectCount;
|
||||||
|
PRBool mUserIsActive;
|
||||||
|
};
|
||||||
|
|
||||||
|
NS_IMPL_ISUPPORTS1(nsUserActivityObserver, nsIObserver)
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsUserActivityObserver::Observe(nsISupports* aSubject, const char* aTopic,
|
||||||
|
const PRUnichar* aData)
|
||||||
|
{
|
||||||
|
if (mOldCCollectCount != sCCollectCount) {
|
||||||
|
mOldCCollectCount = sCCollectCount;
|
||||||
|
// Cycle collector was called between user interaction notifications, so
|
||||||
|
// we can reset the counter.
|
||||||
|
mUserActivityCounter = 0;
|
||||||
|
}
|
||||||
|
PRBool higherProbability = PR_FALSE;
|
||||||
|
++mUserActivityCounter;
|
||||||
|
if (!strcmp(aTopic, "user-interaction-inactive")) {
|
||||||
|
#ifdef DEBUG_smaug
|
||||||
|
printf("user-interaction-inactive\n");
|
||||||
|
#endif
|
||||||
|
if (mUserIsActive) {
|
||||||
|
mUserIsActive = PR_FALSE;
|
||||||
|
if (!sGCTimer) {
|
||||||
|
nsJSContext::CC();
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
higherProbability = (mUserActivityCounter > NS_CC_SOFT_LIMIT_INACTIVE);
|
||||||
|
} else if (!strcmp(aTopic, "user-interaction-active")) {
|
||||||
|
#ifdef DEBUG_smaug
|
||||||
|
printf("user-interaction-active\n");
|
||||||
|
#endif
|
||||||
|
mUserIsActive = PR_TRUE;
|
||||||
|
higherProbability = (mUserActivityCounter > NS_CC_SOFT_LIMIT_ACTIVE);
|
||||||
|
} else if (!strcmp(aTopic, "xpcom-shutdown")) {
|
||||||
|
nsCOMPtr<nsIObserverService> obs =
|
||||||
|
do_GetService("@mozilla.org/observer-service;1");
|
||||||
|
if (obs) {
|
||||||
|
obs->RemoveObserver(this, "user-interaction-active");
|
||||||
|
obs->RemoveObserver(this, "user-interaction-inactive");
|
||||||
|
obs->RemoveObserver(this, "xpcom-shutdown");
|
||||||
|
}
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
nsJSContext::MaybeCC(higherProbability);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************
|
/****************************************************************
|
||||||
************************** AutoFree ****************************
|
************************** AutoFree ****************************
|
||||||
****************************************************************/
|
****************************************************************/
|
||||||
@ -3171,6 +3258,80 @@ nsJSContext::PreserveWrapper(nsIXPConnectWrappedNative *aWrapper)
|
|||||||
return nsDOMClassInfo::PreserveNodeWrapper(aWrapper);
|
return nsDOMClassInfo::PreserveNodeWrapper(aWrapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//static
|
||||||
|
void
|
||||||
|
nsJSContext::MaybeCCOrGC(nsIScriptContext* aContext)
|
||||||
|
{
|
||||||
|
if (!nsJSContext::MaybeCC(PR_TRUE)) {
|
||||||
|
nsCOMPtr<nsIScriptContext> context = aContext;
|
||||||
|
if (context) {
|
||||||
|
JSContext* cx = static_cast<JSContext*>(context->GetNativeContext());
|
||||||
|
if (cx) {
|
||||||
|
#ifdef DEBUG_smaug
|
||||||
|
printf("Will call JS_GC\n");
|
||||||
|
#endif
|
||||||
|
::JS_GC(cx);
|
||||||
|
#ifdef DEBUG_smaug
|
||||||
|
printf("Did call JS_GC\n");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//static
|
||||||
|
void
|
||||||
|
nsJSContext::CC()
|
||||||
|
{
|
||||||
|
sPreviousCCTime = PR_Now();
|
||||||
|
sDelayedCCollectCount = 0;
|
||||||
|
++sCCollectCount;
|
||||||
|
#ifdef DEBUG_smaug
|
||||||
|
printf("Will run cycle collector (%i)\n", sCCollectCount);
|
||||||
|
#endif
|
||||||
|
// nsCycleCollector_collect() will run a ::JS_GC() indirectly, so
|
||||||
|
// we do not explicitly call ::JS_GC() here.
|
||||||
|
PRBool firstRun = nsCycleCollector_collect();
|
||||||
|
#ifdef DEBUG_smaug
|
||||||
|
printf("(1) %s\n", firstRun ?
|
||||||
|
"Cycle collector did collect nodes" :
|
||||||
|
"Cycle collector did not collect nodes");
|
||||||
|
#endif
|
||||||
|
PRBool secondRun = nsCycleCollector_collect();
|
||||||
|
#ifdef DEBUG_smaug
|
||||||
|
printf("(2) %s\n", secondRun ?
|
||||||
|
"Cycle collector did collect nodes" :
|
||||||
|
"Cycle collector did not collect nodes");
|
||||||
|
#endif
|
||||||
|
sPreviousCCDidCollect = firstRun || secondRun;
|
||||||
|
}
|
||||||
|
|
||||||
|
//static
|
||||||
|
PRBool
|
||||||
|
nsJSContext::MaybeCC(PRBool aHigherProbability)
|
||||||
|
{
|
||||||
|
++sDelayedCCollectCount;
|
||||||
|
// Increase the probability also if the previous call to cycle collector
|
||||||
|
// collected something.
|
||||||
|
if (aHigherProbability || sPreviousCCDidCollect) {
|
||||||
|
sDelayedCCollectCount *= NS_PROBABILITY_MULTIPLIER;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sGCTimer && (sDelayedCCollectCount > NS_MAX_DELAYED_CCOLLECT)) {
|
||||||
|
if ((PR_Now() - sPreviousCCTime) >=
|
||||||
|
PRTime(NS_MIN_CC_INTERVAL * PR_USEC_PER_MSEC)) {
|
||||||
|
nsJSContext::CC();
|
||||||
|
return PR_TRUE;
|
||||||
|
}
|
||||||
|
#ifdef DEBUG_smaug
|
||||||
|
else {
|
||||||
|
printf("Running cycle collector was delayed: NS_MIN_CC_INTERVAL\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return PR_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsJSContext::Notify(nsITimer *timer)
|
nsJSContext::Notify(nsITimer *timer)
|
||||||
{
|
{
|
||||||
@ -3189,9 +3350,7 @@ nsJSContext::Notify(nsITimer *timer)
|
|||||||
// loading and move on as if they weren't.
|
// loading and move on as if they weren't.
|
||||||
sPendingLoadCount = 0;
|
sPendingLoadCount = 0;
|
||||||
|
|
||||||
// nsCycleCollector_collect() will run a ::JS_GC() indirectly,
|
MaybeCCOrGC(this);
|
||||||
// so we do not explicitly call ::JS_GC() here.
|
|
||||||
nsCycleCollector_collect();
|
|
||||||
} else {
|
} else {
|
||||||
FireGCTimer(PR_TRUE);
|
FireGCTimer(PR_TRUE);
|
||||||
}
|
}
|
||||||
@ -3210,7 +3369,7 @@ nsJSContext::LoadStart()
|
|||||||
|
|
||||||
// static
|
// static
|
||||||
void
|
void
|
||||||
nsJSContext::LoadEnd()
|
nsJSContext::LoadEnd(nsIScriptGlobalObject* aGlobalObject)
|
||||||
{
|
{
|
||||||
// sPendingLoadCount is not a well managed load counter (and doesn't
|
// sPendingLoadCount is not a well managed load counter (and doesn't
|
||||||
// need to be), so make sure we don't make it wrap backwards here.
|
// need to be), so make sure we don't make it wrap backwards here.
|
||||||
@ -3220,13 +3379,10 @@ nsJSContext::LoadEnd()
|
|||||||
|
|
||||||
if (!sPendingLoadCount && sLoadInProgressGCTimer) {
|
if (!sPendingLoadCount && sLoadInProgressGCTimer) {
|
||||||
sGCTimer->Cancel();
|
sGCTimer->Cancel();
|
||||||
|
|
||||||
NS_RELEASE(sGCTimer);
|
NS_RELEASE(sGCTimer);
|
||||||
sLoadInProgressGCTimer = PR_FALSE;
|
sLoadInProgressGCTimer = PR_FALSE;
|
||||||
|
|
||||||
// nsCycleCollector_collect() will run a ::JS_GC() indirectly, so
|
MaybeCCOrGC(aGlobalObject ? aGlobalObject->GetContext() : nsnull);
|
||||||
// we do not explicitly call ::JS_GC() here.
|
|
||||||
nsCycleCollector_collect();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3253,10 +3409,7 @@ nsJSContext::FireGCTimer(PRBool aLoadInProgress)
|
|||||||
// timer.
|
// timer.
|
||||||
sLoadInProgressGCTimer = PR_FALSE;
|
sLoadInProgressGCTimer = PR_FALSE;
|
||||||
|
|
||||||
// nsCycleCollector_collect() will run a ::JS_GC() indirectly, so
|
MaybeCCOrGC(this);
|
||||||
// we do not explicitly call ::JS_GC() here.
|
|
||||||
nsCycleCollector_collect();
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3364,6 +3517,10 @@ void
|
|||||||
nsJSRuntime::Startup()
|
nsJSRuntime::Startup()
|
||||||
{
|
{
|
||||||
// initialize all our statics, so that we can restart XPCOM
|
// initialize all our statics, so that we can restart XPCOM
|
||||||
|
sDelayedCCollectCount = 0;
|
||||||
|
sCCollectCount = 0;
|
||||||
|
sPreviousCCTime = 0;
|
||||||
|
sPreviousCCDidCollect = PR_FALSE;
|
||||||
sGCTimer = nsnull;
|
sGCTimer = nsnull;
|
||||||
sReadyForGC = PR_FALSE;
|
sReadyForGC = PR_FALSE;
|
||||||
sLoadInProgressGCTimer = PR_FALSE;
|
sLoadInProgressGCTimer = PR_FALSE;
|
||||||
@ -3482,6 +3639,15 @@ nsJSRuntime::Init()
|
|||||||
MaxScriptRunTimePrefChangedCallback("dom.max_chrome_script_run_time",
|
MaxScriptRunTimePrefChangedCallback("dom.max_chrome_script_run_time",
|
||||||
nsnull);
|
nsnull);
|
||||||
|
|
||||||
|
nsCOMPtr<nsIObserverService> obs =
|
||||||
|
do_GetService("@mozilla.org/observer-service;1", &rv);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
nsIObserver* activityObserver = new nsUserActivityObserver();
|
||||||
|
NS_ENSURE_TRUE(activityObserver, NS_ERROR_OUT_OF_MEMORY);
|
||||||
|
obs->AddObserver(activityObserver, "user-interaction-inactive", PR_FALSE);
|
||||||
|
obs->AddObserver(activityObserver, "user-interaction-active", PR_FALSE);
|
||||||
|
obs->AddObserver(activityObserver, "xpcom-shutdown", PR_FALSE);
|
||||||
|
|
||||||
rv = CallGetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &sSecurityManager);
|
rv = CallGetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &sSecurityManager);
|
||||||
|
|
||||||
sIsInitialized = NS_SUCCEEDED(rv);
|
sIsInitialized = NS_SUCCEEDED(rv);
|
||||||
|
@ -168,7 +168,26 @@ public:
|
|||||||
NS_DECL_NSITIMERCALLBACK
|
NS_DECL_NSITIMERCALLBACK
|
||||||
|
|
||||||
static void LoadStart();
|
static void LoadStart();
|
||||||
static void LoadEnd();
|
static void LoadEnd(nsIScriptGlobalObject* aGlobalObject);
|
||||||
|
|
||||||
|
// CC does always call cycle collector and it also updates the counters
|
||||||
|
// that MaybeCC uses.
|
||||||
|
static void CC();
|
||||||
|
|
||||||
|
// MaybeCC calls cycle collector if certain conditions are fulfilled.
|
||||||
|
// The conditions are:
|
||||||
|
// - The timer related to page load (sGCTimer) must not be active.
|
||||||
|
// - At least NS_MIN_CC_INTERVAL milliseconds must have elapsed since the
|
||||||
|
// previous cycle collector call.
|
||||||
|
// - Certain number of MaybeCC calls have occurred.
|
||||||
|
// The number of needed MaybeCC calls depends on the aHigherProbability
|
||||||
|
// parameter. If the parameter is true, probability for calling cycle
|
||||||
|
// collector rises increasingly. If the parameter is all the time false,
|
||||||
|
// at least NS_MAX_DELAYED_CCOLLECT MaybeCC calls are needed.
|
||||||
|
// If the previous call to cycle collector did collect something,
|
||||||
|
// MaybeCC works effectively as if aHigherProbability was true.
|
||||||
|
// @return PR_TRUE if cycle collector was called.
|
||||||
|
static PRBool MaybeCC(PRBool aHigherProbability);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
nsresult InitializeExternalClasses();
|
nsresult InitializeExternalClasses();
|
||||||
@ -190,6 +209,8 @@ protected:
|
|||||||
nsresult JSObjectFromInterface(nsISupports *aSup, void *aScript,
|
nsresult JSObjectFromInterface(nsISupports *aSup, void *aScript,
|
||||||
JSObject **aRet);
|
JSObject **aRet);
|
||||||
|
|
||||||
|
static void MaybeCCOrGC(nsIScriptContext* aContext);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
JSContext *mContext;
|
JSContext *mContext;
|
||||||
PRUint32 mNumEvaluations;
|
PRUint32 mNumEvaluations;
|
||||||
|
@ -993,7 +993,7 @@ DocumentViewerImpl::LoadComplete(nsresult aStatus)
|
|||||||
mPresShell->UnsuppressPainting();
|
mPresShell->UnsuppressPainting();
|
||||||
}
|
}
|
||||||
|
|
||||||
nsJSContext::LoadEnd();
|
nsJSContext::LoadEnd(mDocument ? mDocument->GetScriptGlobalObject() : nsnull);
|
||||||
|
|
||||||
#ifdef NS_PRINTING
|
#ifdef NS_PRINTING
|
||||||
// Check to see if someone tried to print during the load
|
// Check to see if someone tried to print during the load
|
||||||
|
@ -869,7 +869,7 @@ struct nsCycleCollector
|
|||||||
PRBool Forget(nsISupports *n);
|
PRBool Forget(nsISupports *n);
|
||||||
void Allocated(void *n, size_t sz);
|
void Allocated(void *n, size_t sz);
|
||||||
void Freed(void *n);
|
void Freed(void *n);
|
||||||
void Collect(PRUint32 aTryCollections = 1);
|
PRBool Collect(PRUint32 aTryCollections = 1);
|
||||||
void Shutdown();
|
void Shutdown();
|
||||||
|
|
||||||
#ifdef DEBUG_CC
|
#ifdef DEBUG_CC
|
||||||
@ -2021,9 +2021,10 @@ nsCycleCollector::Freed(void *n)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void
|
PRBool
|
||||||
nsCycleCollector::Collect(PRUint32 aTryCollections)
|
nsCycleCollector::Collect(PRUint32 aTryCollections)
|
||||||
{
|
{
|
||||||
|
PRBool didCollect = PR_FALSE;
|
||||||
#if defined(DEBUG_CC) && !defined(__MINGW32__)
|
#if defined(DEBUG_CC) && !defined(__MINGW32__)
|
||||||
if (!mParams.mDoNothing && mParams.mHookMalloc)
|
if (!mParams.mDoNothing && mParams.mHookMalloc)
|
||||||
InitMemHook();
|
InitMemHook();
|
||||||
@ -2031,7 +2032,7 @@ nsCycleCollector::Collect(PRUint32 aTryCollections)
|
|||||||
|
|
||||||
// This can legitimately happen in a few cases. See bug 383651.
|
// This can legitimately happen in a few cases. See bug 383651.
|
||||||
if (mCollectionInProgress)
|
if (mCollectionInProgress)
|
||||||
return;
|
return didCollect;
|
||||||
|
|
||||||
#ifdef COLLECT_TIME_DEBUG
|
#ifdef COLLECT_TIME_DEBUG
|
||||||
printf("cc: Starting nsCycleCollector::Collect(%d)\n", aTryCollections);
|
printf("cc: Starting nsCycleCollector::Collect(%d)\n", aTryCollections);
|
||||||
@ -2168,8 +2169,11 @@ nsCycleCollector::Collect(PRUint32 aTryCollections)
|
|||||||
// mBuf.GetSize() == 0 check above), we should stop
|
// mBuf.GetSize() == 0 check above), we should stop
|
||||||
// repeating collections if we didn't collect anything
|
// repeating collections if we didn't collect anything
|
||||||
// this time.
|
// this time.
|
||||||
if (!collected)
|
if (!collected) {
|
||||||
aTryCollections = 0;
|
aTryCollections = 0;
|
||||||
|
} else {
|
||||||
|
didCollect = PR_TRUE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG_CC
|
#ifdef DEBUG_CC
|
||||||
@ -2194,6 +2198,7 @@ nsCycleCollector::Collect(PRUint32 aTryCollections)
|
|||||||
#ifdef DEBUG_CC
|
#ifdef DEBUG_CC
|
||||||
ExplainLiveExpectedGarbage();
|
ExplainLiveExpectedGarbage();
|
||||||
#endif
|
#endif
|
||||||
|
return didCollect;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -2594,11 +2599,10 @@ NS_CycleCollectorForget(nsISupports *n)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
PRBool
|
||||||
nsCycleCollector_collect()
|
nsCycleCollector_collect()
|
||||||
{
|
{
|
||||||
if (sCollector)
|
return sCollector ? sCollector->Collect() : PR_FALSE;
|
||||||
sCollector->Collect();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
|
@ -66,7 +66,8 @@ struct nsCycleCollectionLanguageRuntime
|
|||||||
NS_COM void nsCycleCollector_suspectCurrent(nsISupports *n);
|
NS_COM void nsCycleCollector_suspectCurrent(nsISupports *n);
|
||||||
// NS_COM PRBool nsCycleCollector_forget(nsISupports *n);
|
// NS_COM PRBool nsCycleCollector_forget(nsISupports *n);
|
||||||
nsresult nsCycleCollector_startup();
|
nsresult nsCycleCollector_startup();
|
||||||
NS_COM void nsCycleCollector_collect();
|
// Returns PR_TRUE if some nodes were collected.
|
||||||
|
NS_COM PRBool nsCycleCollector_collect();
|
||||||
void nsCycleCollector_shutdown();
|
void nsCycleCollector_shutdown();
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
Loading…
Reference in New Issue
Block a user