// NOTE: this will not find a new entry until it has been written to disk! // Consumer should take ownership of the resulting buffer. nsresult StartupCache::GetBuffer(const char* id, char** outbuf, uint32_t* length) { NS_ASSERTION(NS_IsMainThread(), "Startup cache only available on main thread"); WaitOnWriteThread(); if (!mStartupWriteInitiated) { CacheEntry* entry; nsDependentCString idStr(id); mTable.Get(idStr, &entry); if (entry) { *outbuf = new char[entry->size]; memcpy(*outbuf, entry->data, entry->size); *length = entry->size; return NS_OK; } } nsresult rv = GetBufferFromZipArchive(mArchive, true, id, outbuf, length); if (NS_SUCCEEDED(rv)) return rv; nsRefPtr<nsZipArchive> omnijar = mozilla::Omnijar::GetReader(mozilla::Omnijar::APP); // no need to checksum omnijarred entries rv = GetBufferFromZipArchive(omnijar, false, id, outbuf, length); if (NS_SUCCEEDED(rv)) return rv; omnijar = mozilla::Omnijar::GetReader(mozilla::Omnijar::GRE); // no need to checksum omnijarred entries return GetBufferFromZipArchive(omnijar, false, id, outbuf, length); }
// Makes a copy of the buffer, client retains ownership of inbuf. nsresult StartupCache::PutBuffer(const char* id, const char* inbuf, uint32_t len) { NS_ASSERTION(NS_IsMainThread(), "Startup cache only available on main thread"); WaitOnWriteThread(); if (StartupCache::gShutdownInitiated) { return NS_ERROR_NOT_AVAILABLE; } nsAutoArrayPtr<char> data(new char[len]); memcpy(data, inbuf, len); nsDependentCString idStr(id); // Cache it for now, we'll write all together later. CacheEntry* entry; #ifdef DEBUG mTable.Get(idStr, &entry); NS_ASSERTION(entry == nullptr, "Existing entry in StartupCache."); if (mArchive) { nsZipItem* zipItem = mArchive->GetItem(id); NS_ASSERTION(zipItem == nullptr, "Existing entry in disk StartupCache."); } #endif entry = new CacheEntry(data.forget(), len); mTable.Put(idStr, entry); return ResetStartupWriteTimer(); }
// Makes a copy of the buffer, client retains ownership of inbuf. nsresult StartupCache::PutBuffer(const char* id, const char* inbuf, uint32_t len) { NS_ASSERTION(NS_IsMainThread(), "Startup cache only available on main thread"); WaitOnWriteThread(); if (StartupCache::gShutdownInitiated) { return NS_ERROR_NOT_AVAILABLE; } auto data = MakeUnique<char[]>(len); memcpy(data.get(), inbuf, len); nsCString idStr(id); // Cache it for now, we'll write all together later. CacheEntry* entry; if (mTable.Get(idStr)) { NS_ASSERTION(false, "Existing entry in StartupCache."); // Double-caching is undesirable but not an error. return NS_OK; } #ifdef DEBUG if (mArchive) { nsZipItem* zipItem = mArchive->GetItem(id); NS_ASSERTION(zipItem == nullptr, "Existing entry in disk StartupCache."); } #endif entry = new CacheEntry(Move(data), len); mTable.Put(idStr, entry); mPendingWrites.AppendElement(idStr); return ResetStartupWriteTimer(); }
// NOTE: this will not find a new entry until it has been written to disk! // Consumer should take ownership of the resulting buffer. nsresult StartupCache::GetBuffer(const char* id, UniquePtr<char[]>* outbuf, uint32_t* length) { PROFILER_LABEL_FUNC(js::ProfileEntry::Category::OTHER); NS_ASSERTION(NS_IsMainThread(), "Startup cache only available on main thread"); WaitOnWriteThread(); if (!mStartupWriteInitiated) { CacheEntry* entry; nsDependentCString idStr(id); mTable.Get(idStr, &entry); if (entry) { *outbuf = MakeUnique<char[]>(entry->size); memcpy(outbuf->get(), entry->data.get(), entry->size); *length = entry->size; return NS_OK; } } nsresult rv = GetBufferFromZipArchive(mArchive, true, id, outbuf, length); if (NS_SUCCEEDED(rv)) return rv; RefPtr<nsZipArchive> omnijar = mozilla::Omnijar::GetReader(mozilla::Omnijar::APP); // no need to checksum omnijarred entries rv = GetBufferFromZipArchive(omnijar, false, id, outbuf, length); if (NS_SUCCEEDED(rv)) return rv; omnijar = mozilla::Omnijar::GetReader(mozilla::Omnijar::GRE); // no need to checksum omnijarred entries return GetBufferFromZipArchive(omnijar, false, id, outbuf, length); }
StartupCache::~StartupCache() { if (mTimer) { mTimer->Cancel(); } // Generally, the in-memory table should be empty here, // but an early shutdown means either mTimer didn't run // or the write thread is still running. WaitOnWriteThread(); // If we shutdown quickly timer wont have fired. Instead of writing // it on the main thread and block the shutdown we simply wont update // the startup cache. Always do this if the file doesn't exist since // we use it part of the packge step. if (!mArchive) { WriteToDisk(); } gStartupCache = nullptr; (void)::NS_UnregisterMemoryReporter(mMappingMemoryReporter); (void)::NS_UnregisterMemoryReporter(mDataMemoryReporter); mMappingMemoryReporter = nullptr; mDataMemoryReporter = nullptr; }
void StartupCache::InvalidateCache() { WaitOnWriteThread(); mTable.Clear(); mArchive = NULL; mFile->Remove(false); LoadArchive(gPostFlushAgeAction); }
void StartupCache::InvalidateCache() { WaitOnWriteThread(); mTable.Clear(); mArchive = NULL; nsresult rv = mFile->Remove(false); if (NS_FAILED(rv) && rv != NS_ERROR_FILE_TARGET_DOES_NOT_EXIST && rv != NS_ERROR_FILE_NOT_FOUND) { gIgnoreDiskCache = true; return; } gIgnoreDiskCache = false; LoadArchive(gPostFlushAgeAction); }
void StartupCache::InvalidateCache() { WaitOnWriteThread(); mTable.Clear(); mArchive = nullptr; nsresult rv = mFile->Remove(false); if (NS_FAILED(rv) && rv != NS_ERROR_FILE_TARGET_DOES_NOT_EXIST && rv != NS_ERROR_FILE_NOT_FOUND) { gIgnoreDiskCache = true; mozilla::Telemetry::Accumulate(Telemetry::STARTUP_CACHE_INVALID, true); return; } gIgnoreDiskCache = false; LoadArchive(gPostFlushAgeAction); }
StartupCache::~StartupCache() { if (mTimer) { mTimer->Cancel(); } // Generally, the in-memory table should be empty here, // but an early shutdown means either mTimer didn't run // or the write thread is still running. WaitOnWriteThread(); WriteToDisk(); gStartupCache = nullptr; (void)::NS_UnregisterMemoryReporter(mMappingMemoryReporter); (void)::NS_UnregisterMemoryReporter(mDataMemoryReporter); mMappingMemoryReporter = nullptr; mDataMemoryReporter = nullptr; }
bool StartupCache::StartupWriteComplete() { WaitOnWriteThread(); return mStartupWriteInitiated && mTable.Count() == 0; }