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:
Kris Maglione
2017-05-03 12:31:51 -07:00
parent 5104fc5d25
commit 881111c21d
2 changed files with 62 additions and 0 deletions

View File

@@ -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)
{