Bug 1359653: Part 9 - Observe "startupcache-invalidate" and flush the cache when received. r=erahm
Flushing the cache at startup is already handled automatically by the AppStartup code, which removes the entire startupCache directory when necessary. The add-on manager requires being able to flush the cache at runtime, though, for the sake of updating bootstrapped add-ons. MozReview-Commit-ID: LIdiNHrXYXu
This commit is contained in:
@@ -29,6 +29,7 @@
|
||||
#define DELAYED_STARTUP_TOPIC "browser-delayed-startup-finished"
|
||||
#define CLEANUP_TOPIC "xpcom-shutdown"
|
||||
#define SHUTDOWN_TOPIC "quit-application-granted"
|
||||
#define CACHE_FLUSH_TOPIC "startupcache-invalidate"
|
||||
|
||||
namespace mozilla {
|
||||
namespace {
|
||||
@@ -124,6 +125,7 @@ ScriptPreloader::ScriptPreloader()
|
||||
obs->AddObserver(this, DELAYED_STARTUP_TOPIC, false);
|
||||
obs->AddObserver(this, SHUTDOWN_TOPIC, false);
|
||||
obs->AddObserver(this, CLEANUP_TOPIC, false);
|
||||
obs->AddObserver(this, CACHE_FLUSH_TOPIC, false);
|
||||
|
||||
AutoSafeJSAPI jsapi;
|
||||
JS_AddExtraGCRootsTracer(jsapi.cx(), TraceOp, this);
|
||||
@@ -161,6 +163,44 @@ ScriptPreloader::Cleanup()
|
||||
UnregisterWeakMemoryReporter(this);
|
||||
}
|
||||
|
||||
void
|
||||
ScriptPreloader::FlushScripts(LinkedList<CachedScript>& scripts)
|
||||
{
|
||||
for (auto next = scripts.getFirst(); next; ) {
|
||||
auto script = next;
|
||||
next = script->getNext();
|
||||
|
||||
// We can only purge finished scripts here. Async scripts that are
|
||||
// still being parsed off-thread have a non-refcounted reference to
|
||||
// this script, which needs to stay alive until they finish parsing.
|
||||
if (script->mReadyToExecute) {
|
||||
script->Cancel();
|
||||
script->remove();
|
||||
delete script;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ScriptPreloader::FlushCache()
|
||||
{
|
||||
MonitorAutoLock mal(mMonitor);
|
||||
|
||||
FlushScripts(mSavedScripts);
|
||||
FlushScripts(mRestoredScripts);
|
||||
|
||||
// If we've already finished saving the cache at this point, start a new
|
||||
// delayed save operation. This will write out an empty cache file in place
|
||||
// of any cache file we've already written out this session, which will
|
||||
// prevent us from falling back to the current session's cache file on the
|
||||
// next startup.
|
||||
if (mSaveComplete) {
|
||||
mSaveComplete = false;
|
||||
|
||||
Unused << NS_NewNamedThread("SaveScripts",
|
||||
getter_AddRefs(mSaveThread), this);
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
ScriptPreloader::Observe(nsISupports* subject, const char* topic, const char16_t* data)
|
||||
@@ -179,6 +219,8 @@ ScriptPreloader::Observe(nsISupports* subject, const char* topic, const char16_t
|
||||
ForceWriteCacheFile();
|
||||
} else if (!strcmp(topic, CLEANUP_TOPIC)) {
|
||||
Cleanup();
|
||||
} else if (!strcmp(topic, CACHE_FLUSH_TOPIC)) {
|
||||
FlushCache();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
@@ -609,6 +651,7 @@ ScriptPreloader::OffThreadDecodeCallback(void* token, void* context)
|
||||
mal.NotifyAll();
|
||||
}
|
||||
|
||||
inline
|
||||
ScriptPreloader::CachedScript::CachedScript(InputBuffer& buf)
|
||||
{
|
||||
Code(buf);
|
||||
@@ -631,6 +674,20 @@ ScriptPreloader::CachedScript::XDREncode(JSContext* cx)
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
ScriptPreloader::CachedScript::Cancel()
|
||||
{
|
||||
if (mToken) {
|
||||
GetSingleton().mMonitor.AssertCurrentThreadOwns();
|
||||
|
||||
AutoSafeJSAPI jsapi;
|
||||
JS::CancelOffThreadScriptDecoder(jsapi.cx(), mToken);
|
||||
|
||||
mReadyToExecute = true;
|
||||
mToken = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
JSScript*
|
||||
ScriptPreloader::CachedScript::GetJSScript(JSContext* cx)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user