Bug 781700: Don't hold strong references to databases from the synchronization queue, so that GCing a database will unblock waiting operations. r=bent

--HG--
extra : rebase_source : 2f1b2405ffc91831d33eb91e4b2d61c2b1ac872b
This commit is contained in:
Kyle Huey 2012-08-10 09:15:02 -07:00
parent 997965d339
commit 018dc47367
11 changed files with 79 additions and 10 deletions

View File

@ -1181,7 +1181,7 @@ IndexedDatabaseManager::RunSynchronizedOp(IDBDatabase* aDatabase,
FileService* service = FileService::Get();
TransactionThreadPool* pool = TransactionThreadPool::Get();
nsTArray<nsRefPtr<IDBDatabase> > databases;
nsTArray<IDBDatabase*> databases;
if (aDatabase) {
if (service || pool) {
databases.AppendElement(aDatabase);

View File

@ -379,7 +379,7 @@ private:
nsRefPtr<AsyncConnectionHelper> mHelper;
nsCOMPtr<nsIRunnable> mRunnable;
nsTArray<nsCOMPtr<nsIRunnable> > mDelayedRunnables;
nsTArray<nsRefPtr<IDBDatabase> > mDatabases;
nsTArray<IDBDatabase*> mDatabases;
};
// A callback runnable used by the TransactionPool when it's safe to proceed

View File

@ -450,8 +450,8 @@ TransactionThreadPool::Dispatch(IDBTransaction* aTransaction,
bool
TransactionThreadPool::WaitForAllDatabasesToComplete(
nsTArray<nsRefPtr<IDBDatabase> >& aDatabases,
nsIRunnable* aCallback)
nsTArray<IDBDatabase*>& aDatabases,
nsIRunnable* aCallback)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
NS_ASSERTION(!aDatabases.IsEmpty(), "No databases to wait on!");

View File

@ -46,9 +46,8 @@ public:
bool aFinish,
nsIRunnable* aFinishRunnable);
bool WaitForAllDatabasesToComplete(
nsTArray<nsRefPtr<IDBDatabase> >& aDatabases,
nsIRunnable* aCallback);
bool WaitForAllDatabasesToComplete(nsTArray<IDBDatabase*>& aDatabases,
nsIRunnable* aCallback);
// Abort all transactions, unless they are already in the process of being
// committed, for aDatabase.
@ -107,7 +106,7 @@ protected:
struct DatabasesCompleteCallback
{
nsTArray<nsRefPtr<IDBDatabase> > mDatabases;
nsTArray<IDBDatabase*> mDatabases;
nsCOMPtr<nsIRunnable> mCallback;
};

View File

@ -202,3 +202,9 @@ function resetUnlimitedQuota(url)
{
removePermission("indexedDB-unlimited", url);
}
function gc()
{
SpecialPowers.forceGC();
SpecialPowers.forceCC();
}

View File

@ -172,6 +172,12 @@ function disallowUnlimitedQuota(url)
throw "disallowUnlimitedQuota";
}
function gc()
{
Components.utils.forceGC();
Components.utils.forceCC();
}
var SpecialPowers = {
isMainProcess: function() {
return Components.classes["@mozilla.org/xre/app-info;1"]

View File

@ -113,12 +113,29 @@ function testSteps()
is(event.oldVersion, 2, "Correct event oldVersion");
is(event.newVersion, 3, "Correct event newVersion");
versionChangeEventCount++;
// Test one closed explicitly, and one closed by GC.
db2.close();
db3.close();
db3 = null;
gc();
request.onupgradeneeded = grabEventAndContinueHandler;
request.onsuccess = grabEventAndContinueHandler;
executeSoon(function() { testGenerator.next(); });
yield;
gc();
if (!this.window) {
// In xpcshell, we need to spin the event loop to ensure that GCd things
// are finalized (since XPConnect does deferred finalization).
let thread = Components.classes["@mozilla.org/thread-manager;1"]
.getService(Components.interfaces.nsIThreadManager)
.currentThread;
while (thread.hasPendingEvents()) {
thread.processNextEvent(false);
}
}
event = yield;
event = yield;

View File

@ -118,7 +118,7 @@ interface ScheduledGCCallback : nsISupports
/**
* interface of Components.utils
*/
[scriptable, uuid(2df24c04-f1ef-481c-8605-433082a34e95)]
[scriptable, uuid(cc7ef3b0-339d-4317-927b-fdc8f0664927)]
interface nsIXPCComponents_Utils : nsISupports
{
@ -228,6 +228,13 @@ interface nsIXPCComponents_Utils : nsISupports
* Force an immediate garbage collection cycle.
*/
void forceGC();
/*
* To be called from JS only.
*
* Force an immediate cycle collection cycle.
*/
void forceCC();
/*
* To be called from JS only.

View File

@ -32,6 +32,7 @@
#include "nsPrincipal.h"
#include "mozilla/Attributes.h"
#include "nsIScriptContext.h"
#include "nsJSEnvironment.h"
using namespace mozilla;
using namespace js;
@ -4048,6 +4049,14 @@ nsXPCComponents_Utils::ForceGC()
return NS_OK;
}
/* void forceCC (); */
NS_IMETHODIMP
nsXPCComponents_Utils::ForceCC()
{
nsJSContext::CycleCollectNow(nullptr, 0);
return NS_OK;
}
/* void forceShrinkingGC (); */
NS_IMETHODIMP
nsXPCComponents_Utils::ForceShrinkingGC()

View File

@ -38,6 +38,7 @@
#include "nsWrapperCacheInlines.h"
#include "nsDOMMutationObserver.h"
#include "nsICycleCollectorListener.h"
using namespace mozilla::dom;
using namespace xpc;
@ -2970,5 +2971,25 @@ JS_EXPORT_API(void) DumpJSValue(JS::Value val)
printf("No idea what this value is.\n");
}
}
JS_EXPORT_API(void) DumpCompleteHeap()
{
nsCOMPtr<nsICycleCollectorListener> listener =
do_CreateInstance("@mozilla.org/cycle-collector-logger;1");
if (!listener) {
NS_WARNING("Failed to create CC logger");
return;
}
nsCOMPtr<nsICycleCollectorListener> alltracesListener;
listener->AllTraces(getter_AddRefs(alltracesListener));
if (!alltracesListener) {
NS_WARNING("Failed to get all traces logger");
return;
}
nsJSContext::CycleCollectNow(alltracesListener);
}
JS_END_EXTERN_C

View File

@ -834,6 +834,10 @@ SpecialPowersAPI.prototype = {
Components.utils.forceGC();
},
forceCC: function() {
Components.utils.forceCC();
},
exactGC: function(win, callback) {
var self = this;
let count = 0;