mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-07 16:28:38 +09:00
Fix a rare crash with asm.js caching.
This commit is contained in:
parent
2029eff3f1
commit
03fe589f41
2 changed files with 316 additions and 116 deletions
|
|
@ -69,6 +69,8 @@ namespace asmjscache {
|
|||
|
||||
namespace {
|
||||
|
||||
class ParentRunnable;
|
||||
|
||||
// Anything smaller should compile fast enough that caching will just add
|
||||
// overhead.
|
||||
static const size_t sMinCachedModuleLength = 10000;
|
||||
|
|
@ -76,6 +78,10 @@ static const size_t sMinCachedModuleLength = 10000;
|
|||
// The number of characters to hash into the Metadata::Entry::mFastHash.
|
||||
static const unsigned sNumFastHashChars = 4096;
|
||||
|
||||
// Track all live parent actors.
|
||||
typedef nsTArray<const ParentRunnable*> ParentActorArray;
|
||||
StaticAutoPtr<ParentActorArray> sLiveParentActors;
|
||||
|
||||
nsresult
|
||||
WriteMetadataFile(nsIFile* aMetadataFile, const Metadata& aMetadata)
|
||||
{
|
||||
|
|
@ -236,6 +242,94 @@ EvictEntries(nsIFile* aDirectory, const nsACString& aGroup,
|
|||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Client
|
||||
******************************************************************************/
|
||||
|
||||
class Client
|
||||
: public quota::Client
|
||||
{
|
||||
static Client* sInstance;
|
||||
|
||||
bool mShutdownRequested;
|
||||
|
||||
public:
|
||||
Client();
|
||||
|
||||
static bool
|
||||
IsShuttingDownOnBackgroundThread()
|
||||
{
|
||||
AssertIsOnBackgroundThread();
|
||||
|
||||
if (sInstance) {
|
||||
return sInstance->IsShuttingDown();
|
||||
}
|
||||
|
||||
return QuotaManager::IsShuttingDown();
|
||||
}
|
||||
|
||||
static bool
|
||||
IsShuttingDownOnNonBackgroundThread()
|
||||
{
|
||||
MOZ_ASSERT(!IsOnBackgroundThread());
|
||||
|
||||
return QuotaManager::IsShuttingDown();
|
||||
}
|
||||
|
||||
bool
|
||||
IsShuttingDown() const
|
||||
{
|
||||
AssertIsOnBackgroundThread();
|
||||
|
||||
return mShutdownRequested;
|
||||
}
|
||||
|
||||
NS_INLINE_DECL_REFCOUNTING(Client, override)
|
||||
|
||||
virtual Type
|
||||
GetType() override;
|
||||
|
||||
virtual nsresult
|
||||
InitOrigin(PersistenceType aPersistenceType,
|
||||
const nsACString& aGroup,
|
||||
const nsACString& aOrigin,
|
||||
const AtomicBool& aCanceled,
|
||||
UsageInfo* aUsageInfo) override;
|
||||
|
||||
virtual nsresult
|
||||
GetUsageForOrigin(PersistenceType aPersistenceType,
|
||||
const nsACString& aGroup,
|
||||
const nsACString& aOrigin,
|
||||
const AtomicBool& aCanceled,
|
||||
UsageInfo* aUsageInfo) override;
|
||||
|
||||
virtual void
|
||||
OnOriginClearCompleted(PersistenceType aPersistenceType,
|
||||
const nsACString& aOrigin)
|
||||
override;
|
||||
|
||||
virtual void
|
||||
ReleaseIOThreadObjects() override;
|
||||
|
||||
virtual void
|
||||
AbortOperations(const nsACString& aOrigin) override;
|
||||
|
||||
virtual void
|
||||
AbortOperationsForProcess(ContentParentId aContentParentId) override;
|
||||
|
||||
virtual void
|
||||
StartIdleMaintenance() override;
|
||||
|
||||
virtual void
|
||||
StopIdleMaintenance() override;
|
||||
|
||||
virtual void
|
||||
ShutdownWorkThreads() override;
|
||||
|
||||
private:
|
||||
~Client();
|
||||
};
|
||||
|
||||
// FileDescriptorHolder owns a file descriptor and its memory mapping.
|
||||
// FileDescriptorHolder is derived by two runnable classes (that is,
|
||||
// (Parent|Child)Runnable.
|
||||
|
|
@ -897,6 +991,13 @@ ParentRunnable::FinishOnOwningThread()
|
|||
FileDescriptorHolder::Finish();
|
||||
|
||||
mDirectoryLock = nullptr;
|
||||
|
||||
MOZ_ASSERT(sLiveParentActors);
|
||||
sLiveParentActors->RemoveElement(this);
|
||||
|
||||
if (sLiveParentActors->IsEmpty()) {
|
||||
sLiveParentActors = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
|
@ -1140,6 +1241,10 @@ AllocEntryParent(OpenMode aOpenMode,
|
|||
{
|
||||
AssertIsOnBackgroundThread();
|
||||
|
||||
if (NS_WARN_IF(Client::IsShuttingDownOnBackgroundThread())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(aPrincipalInfo.type() == PrincipalInfo::TNullPrincipalInfo)) {
|
||||
MOZ_ASSERT(false);
|
||||
return nullptr;
|
||||
|
|
@ -1148,6 +1253,12 @@ AllocEntryParent(OpenMode aOpenMode,
|
|||
RefPtr<ParentRunnable> runnable =
|
||||
new ParentRunnable(aPrincipalInfo, aOpenMode, aWriteParams);
|
||||
|
||||
if (!sLiveParentActors) {
|
||||
sLiveParentActors = new ParentActorArray();
|
||||
}
|
||||
|
||||
sLiveParentActors->AppendElement(runnable);
|
||||
|
||||
nsresult rv = NS_DispatchToMainThread(runnable);
|
||||
NS_ENSURE_SUCCESS(rv, nullptr);
|
||||
|
||||
|
|
@ -1712,128 +1823,163 @@ CloseEntryForWrite(size_t aSize,
|
|||
}
|
||||
}
|
||||
|
||||
class Client : public quota::Client
|
||||
/*******************************************************************************
|
||||
* Client
|
||||
******************************************************************************/
|
||||
|
||||
Client* Client::sInstance = nullptr;
|
||||
|
||||
Client::Client()
|
||||
: mShutdownRequested(false)
|
||||
{
|
||||
~Client() {}
|
||||
AssertIsOnBackgroundThread();
|
||||
MOZ_ASSERT(!sInstance, "We expect this to be a singleton!");
|
||||
|
||||
public:
|
||||
NS_IMETHOD_(MozExternalRefCountType)
|
||||
AddRef() override;
|
||||
sInstance = this;
|
||||
}
|
||||
|
||||
NS_IMETHOD_(MozExternalRefCountType)
|
||||
Release() override;
|
||||
Client::~Client()
|
||||
{
|
||||
AssertIsOnBackgroundThread();
|
||||
MOZ_ASSERT(sInstance == this, "We expect this to be a singleton!");
|
||||
|
||||
virtual Type
|
||||
GetType() override
|
||||
{
|
||||
return ASMJS;
|
||||
}
|
||||
sInstance = nullptr;
|
||||
}
|
||||
|
||||
virtual nsresult
|
||||
InitOrigin(PersistenceType aPersistenceType,
|
||||
const nsACString& aGroup,
|
||||
const nsACString& aOrigin,
|
||||
const AtomicBool& aCanceled,
|
||||
UsageInfo* aUsageInfo) override
|
||||
{
|
||||
if (!aUsageInfo) {
|
||||
return NS_OK;
|
||||
}
|
||||
return GetUsageForOrigin(aPersistenceType,
|
||||
aGroup,
|
||||
aOrigin,
|
||||
aCanceled,
|
||||
aUsageInfo);
|
||||
}
|
||||
|
||||
virtual nsresult
|
||||
GetUsageForOrigin(PersistenceType aPersistenceType,
|
||||
const nsACString& aGroup,
|
||||
const nsACString& aOrigin,
|
||||
const AtomicBool& aCanceled,
|
||||
UsageInfo* aUsageInfo) override
|
||||
{
|
||||
QuotaManager* qm = QuotaManager::Get();
|
||||
MOZ_ASSERT(qm, "We were being called by the QuotaManager");
|
||||
|
||||
nsCOMPtr<nsIFile> directory;
|
||||
nsresult rv = qm->GetDirectoryForOrigin(aPersistenceType, aOrigin,
|
||||
getter_AddRefs(directory));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
MOZ_ASSERT(directory, "We're here because the origin directory exists");
|
||||
|
||||
rv = directory->Append(NS_LITERAL_STRING(ASMJSCACHE_DIRECTORY_NAME));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
DebugOnly<bool> exists;
|
||||
MOZ_ASSERT(NS_SUCCEEDED(directory->Exists(&exists)) && exists);
|
||||
|
||||
nsCOMPtr<nsISimpleEnumerator> entries;
|
||||
rv = directory->GetDirectoryEntries(getter_AddRefs(entries));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
bool hasMore;
|
||||
while (NS_SUCCEEDED((rv = entries->HasMoreElements(&hasMore))) &&
|
||||
hasMore && !aCanceled) {
|
||||
nsCOMPtr<nsISupports> entry;
|
||||
rv = entries->GetNext(getter_AddRefs(entry));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIFile> file = do_QueryInterface(entry);
|
||||
NS_ENSURE_TRUE(file, NS_NOINTERFACE);
|
||||
|
||||
int64_t fileSize;
|
||||
rv = file->GetFileSize(&fileSize);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
MOZ_ASSERT(fileSize >= 0, "Negative size?!");
|
||||
|
||||
// Since the client is not explicitly storing files, append to database
|
||||
// usage which represents implicit storage allocation.
|
||||
aUsageInfo->AppendToDatabaseUsage(uint64_t(fileSize));
|
||||
}
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
Client::Type
|
||||
Client::GetType()
|
||||
{
|
||||
return ASMJS;
|
||||
}
|
||||
|
||||
nsresult
|
||||
Client::InitOrigin(PersistenceType aPersistenceType,
|
||||
const nsACString& aGroup,
|
||||
const nsACString& aOrigin,
|
||||
const AtomicBool& aCanceled,
|
||||
UsageInfo* aUsageInfo)
|
||||
{
|
||||
if (!aUsageInfo) {
|
||||
return NS_OK;
|
||||
}
|
||||
return GetUsageForOrigin(aPersistenceType,
|
||||
aGroup,
|
||||
aOrigin,
|
||||
aCanceled,
|
||||
aUsageInfo);
|
||||
}
|
||||
|
||||
virtual void
|
||||
OnOriginClearCompleted(PersistenceType aPersistenceType,
|
||||
const nsACString& aOrigin)
|
||||
override
|
||||
{ }
|
||||
nsresult
|
||||
Client::GetUsageForOrigin(PersistenceType aPersistenceType,
|
||||
const nsACString& aGroup,
|
||||
const nsACString& aOrigin,
|
||||
const AtomicBool& aCanceled,
|
||||
UsageInfo* aUsageInfo)
|
||||
{
|
||||
QuotaManager* qm = QuotaManager::Get();
|
||||
MOZ_ASSERT(qm, "We were being called by the QuotaManager");
|
||||
|
||||
virtual void
|
||||
ReleaseIOThreadObjects() override
|
||||
{ }
|
||||
nsCOMPtr<nsIFile> directory;
|
||||
nsresult rv = qm->GetDirectoryForOrigin(aPersistenceType, aOrigin,
|
||||
getter_AddRefs(directory));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
virtual void
|
||||
AbortOperations(const nsACString& aOrigin) override
|
||||
{ }
|
||||
MOZ_ASSERT(directory, "We're here because the origin directory exists");
|
||||
|
||||
virtual void
|
||||
AbortOperationsForProcess(ContentParentId aContentParentId) override
|
||||
{ }
|
||||
rv = directory->Append(NS_LITERAL_STRING(ASMJSCACHE_DIRECTORY_NAME));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
virtual void
|
||||
StartIdleMaintenance() override
|
||||
{ }
|
||||
DebugOnly<bool> exists;
|
||||
MOZ_ASSERT(NS_SUCCEEDED(directory->Exists(&exists)) && exists);
|
||||
|
||||
virtual void
|
||||
StopIdleMaintenance() override
|
||||
{ }
|
||||
nsCOMPtr<nsISimpleEnumerator> entries;
|
||||
rv = directory->GetDirectoryEntries(getter_AddRefs(entries));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
virtual void
|
||||
ShutdownWorkThreads() override
|
||||
{ }
|
||||
bool hasMore;
|
||||
while (NS_SUCCEEDED((rv = entries->HasMoreElements(&hasMore))) &&
|
||||
hasMore && !aCanceled) {
|
||||
nsCOMPtr<nsISupports> entry;
|
||||
rv = entries->GetNext(getter_AddRefs(entry));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
private:
|
||||
nsAutoRefCnt mRefCnt;
|
||||
NS_DECL_OWNINGTHREAD
|
||||
};
|
||||
nsCOMPtr<nsIFile> file = do_QueryInterface(entry);
|
||||
if (NS_WARN_IF(!file)) {
|
||||
return NS_NOINTERFACE;
|
||||
}
|
||||
|
||||
NS_IMPL_ADDREF(asmjscache::Client)
|
||||
NS_IMPL_RELEASE(asmjscache::Client)
|
||||
int64_t fileSize;
|
||||
rv = file->GetFileSize(&fileSize);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(fileSize >= 0, "Negative size?!");
|
||||
|
||||
// Since the client is not explicitly storing files, append to database
|
||||
// usage which represents implicit storage allocation.
|
||||
aUsageInfo->AppendToDatabaseUsage(uint64_t(fileSize));
|
||||
}
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
Client::OnOriginClearCompleted(PersistenceType aPersistenceType,
|
||||
const nsACString& aOrigin)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
Client::ReleaseIOThreadObjects()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
Client::AbortOperations(const nsACString& aOrigin)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
Client::AbortOperationsForProcess(ContentParentId aContentParentId)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
Client::StartIdleMaintenance()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
Client::StopIdleMaintenance()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
Client::ShutdownWorkThreads()
|
||||
{
|
||||
AssertIsOnBackgroundThread();
|
||||
|
||||
if (sLiveParentActors) {
|
||||
nsIThread* currentThread = NS_GetCurrentThread();
|
||||
MOZ_ASSERT(currentThread);
|
||||
|
||||
do {
|
||||
MOZ_ALWAYS_TRUE(NS_ProcessNextEvent(currentThread));
|
||||
} while (!sLiveParentActors);
|
||||
}
|
||||
}
|
||||
|
||||
quota::Client*
|
||||
CreateClient()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue