diff --git a/dom/asmjscache/AsmJSCache.cpp b/dom/asmjscache/AsmJSCache.cpp index cd79b2eee92..a080e300753 100644 --- a/dom/asmjscache/AsmJSCache.cpp +++ b/dom/asmjscache/AsmJSCache.cpp @@ -375,7 +375,7 @@ public: } }; - bool + JS::AsmJSCacheResult BlockUntilOpen(AutoClose* aCloser) { MOZ_ASSERT(!mWaiting, "Can only call BlockUntilOpen once"); @@ -384,7 +384,9 @@ public: mWaiting = true; nsresult rv = NS_DispatchToMainThread(this); - NS_ENSURE_SUCCESS(rv, false); + if (NS_WARN_IF(NS_FAILED(rv))) { + return JS::AsmJSCache_InternalError; + } { MutexAutoLock lock(mMutex); @@ -394,7 +396,7 @@ public: } if (!mOpened) { - return false; + return mResult; } // Now that we're open, we're guarnateed a Close() call. However, we are @@ -402,7 +404,7 @@ public: // is closed, so we do that ourselves and Release() in OnClose(). aCloser->Init(this); AddRef(); - return true; + return JS::AsmJSCache_Success; } // This method must be called if BlockUntilOpen returns 'true'. AutoClose @@ -416,7 +418,8 @@ protected: : mMutex("File::mMutex"), mCondVar(mMutex, "File::mCondVar"), mWaiting(false), - mOpened(false) + mOpened(false), + mResult(JS::AsmJSCache_InternalError) { } ~File() @@ -428,15 +431,16 @@ protected: void OnOpen() { - Notify(true); + Notify(JS::AsmJSCache_Success); } void - OnFailure() + OnFailure(JS::AsmJSCacheResult aResult) { - FileDescriptorHolder::Finish(); + MOZ_ASSERT(aResult != JS::AsmJSCache_Success); - Notify(false); + FileDescriptorHolder::Finish(); + Notify(aResult); } void @@ -455,7 +459,7 @@ protected: private: void - Notify(bool aSuccess) + Notify(JS::AsmJSCacheResult aResult) { MOZ_ASSERT(NS_IsMainThread()); @@ -463,7 +467,8 @@ private: MOZ_ASSERT(mWaiting); mWaiting = false; - mOpened = aSuccess; + mOpened = aResult == JS::AsmJSCache_Success; + mResult = aResult; mCondVar.Notify(); } @@ -471,6 +476,7 @@ private: CondVar mCondVar; bool mWaiting; bool mOpened; + JS::AsmJSCacheResult mResult; }; // MainProcessRunnable is a base class shared by (Single|Parent)ProcessRunnable @@ -493,6 +499,7 @@ public: mNeedAllowNextSynchronizedOp(false), mPersistence(quota::PERSISTENCE_TYPE_INVALID), mState(eInitial), + mResult(JS::AsmJSCache_InternalError), mIsApp(false), mHasUnlimStoragePerm(false), mEnforcingQuota(true) @@ -582,7 +589,7 @@ protected: // This method may be overridden, but it must be called from the overrider. // Called by MainProcessRunnable on the main thread after a call to Fail(): virtual void - OnFailure() + OnFailure(JS::AsmJSCacheResult aResult) { FinishOnMainThread(); } @@ -665,6 +672,7 @@ private: eFinished, // Terminal state }; State mState; + JS::AsmJSCacheResult mResult; bool mIsApp; bool mHasUnlimStoragePerm; @@ -850,6 +858,7 @@ MainProcessRunnable::OpenCacheFileForWrite() // enough space. EvictEntries(mDirectory, mGroup, mOrigin, mWriteParams.mSize, mMetadata); if (!mQuotaObject->MaybeAllocateMoreSpace(0, mWriteParams.mSize)) { + mResult = JS::AsmJSCache_QuotaExceeded; return NS_ERROR_FAILURE; } } @@ -1048,7 +1057,7 @@ MainProcessRunnable::Run() MOZ_ASSERT(NS_IsMainThread()); mState = eFinished; - OnFailure(); + OnFailure(mResult); return NS_OK; } @@ -1168,10 +1177,10 @@ private: } void - OnFailure() MOZ_OVERRIDE + OnFailure(JS::AsmJSCacheResult aResult) MOZ_OVERRIDE { - MainProcessRunnable::OnFailure(); - File::OnFailure(); + MainProcessRunnable::OnFailure(aResult); + File::OnFailure(aResult); } void @@ -1225,7 +1234,7 @@ private: } bool - Recv__delete__() MOZ_OVERRIDE + Recv__delete__(const JS::AsmJSCacheResult& aResult) MOZ_OVERRIDE { MOZ_ASSERT(!mFinished); mFinished = true; @@ -1267,7 +1276,7 @@ private: MOZ_ASSERT(NS_IsMainThread()); if (!SendOnOpenMetadataForRead(aMetadata)) { - unused << Send__delete__(this); + unused << Send__delete__(this, JS::AsmJSCache_InternalError); } } @@ -1296,7 +1305,7 @@ private: FileDescriptor::PlatformHandleType handle = FileDescriptor::PlatformHandleType(PR_FileDesc2NativeHandle(mFileDesc)); if (!SendOnOpenCacheFile(mFileSize, FileDescriptor(handle))) { - unused << Send__delete__(this); + unused << Send__delete__(this, JS::AsmJSCache_InternalError); } } @@ -1316,17 +1325,17 @@ private: } void - OnFailure() MOZ_OVERRIDE + OnFailure(JS::AsmJSCacheResult aResult) MOZ_OVERRIDE { MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(!mOpened); mFinished = true; - MainProcessRunnable::OnFailure(); + MainProcessRunnable::OnFailure(aResult); if (!mActorDestroyed) { - unused << Send__delete__(this); + unused << Send__delete__(this, aResult); } mPrincipalHolder = nullptr; @@ -1435,12 +1444,12 @@ private: } bool - Recv__delete__() MOZ_OVERRIDE + Recv__delete__(const JS::AsmJSCacheResult& aResult) MOZ_OVERRIDE { MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(mState == eOpening); - Fail(); + Fail(aResult); return true; } @@ -1462,13 +1471,13 @@ private: private: void - Fail() + Fail(JS::AsmJSCacheResult aResult) { MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(mState == eInitial || mState == eOpening); mState = eFinished; - File::OnFailure(); + File::OnFailure(aResult); } nsIPrincipal* const mPrincipal; @@ -1507,7 +1516,7 @@ ChildProcessRunnable::Run() // 'this' alive until returning to the event loop. Release(); - Fail(); + Fail(JS::AsmJSCache_InternalError); return NS_OK; } @@ -1524,7 +1533,7 @@ ChildProcessRunnable::Run() File::OnClose(); if (!mActorDestroyed) { - unused << Send__delete__(this); + unused << Send__delete__(this, JS::AsmJSCache_Success); } mState = eFinished; @@ -1553,7 +1562,7 @@ DeallocEntryChild(PAsmJSCacheEntryChild* aActor) namespace { -bool +JS::AsmJSCacheResult OpenFile(nsIPrincipal* aPrincipal, OpenMode aOpenMode, WriteParams aWriteParams, @@ -1576,7 +1585,7 @@ OpenFile(nsIPrincipal* aPrincipal, // in the middle of running JS (eval()) and nested event loops can be // semantically observable. if (NS_IsMainThread()) { - return false; + return JS::AsmJSCache_SynchronousScript; } // If we are in a child process, we need to synchronously call into the @@ -1591,11 +1600,16 @@ OpenFile(nsIPrincipal* aPrincipal, aReadParams); } - if (!file->BlockUntilOpen(aFile)) { - return false; + JS::AsmJSCacheResult openResult = file->BlockUntilOpen(aFile); + if (openResult != JS::AsmJSCache_Success) { + return openResult; } - return file->MapMemory(aOpenMode); + if (!file->MapMemory(aOpenMode)) { + return JS::AsmJSCache_InternalError; + } + + return JS::AsmJSCache_Success; } } // anonymous namespace @@ -1621,7 +1635,9 @@ OpenEntryForRead(nsIPrincipal* aPrincipal, File::AutoClose file; WriteParams notAWrite; - if (!OpenFile(aPrincipal, eOpenForRead, notAWrite, readParams, &file)) { + JS::AsmJSCacheResult openResult = + OpenFile(aPrincipal, eOpenForRead, notAWrite, readParams, &file); + if (openResult != JS::AsmJSCache_Success) { return false; } @@ -1661,7 +1677,7 @@ CloseEntryForRead(size_t aSize, MOZ_ASSERT(aMemory - sizeof(AsmJSCookieType) == file->MappedMemory()); } -bool +JS::AsmJSCacheResult OpenEntryForWrite(nsIPrincipal* aPrincipal, bool aInstalled, const char16_t* aBegin, @@ -1671,7 +1687,7 @@ OpenEntryForWrite(nsIPrincipal* aPrincipal, intptr_t* aFile) { if (size_t(aEnd - aBegin) < sMinCachedModuleLength) { - return false; + return JS::AsmJSCache_ModuleTooSmall; } // Add extra space for the AsmJSCookieType (see OpenEntryForRead). @@ -1688,8 +1704,10 @@ OpenEntryForWrite(nsIPrincipal* aPrincipal, File::AutoClose file; ReadParams notARead; - if (!OpenFile(aPrincipal, eOpenForWrite, writeParams, notARead, &file)) { - return false; + JS::AsmJSCacheResult openResult = + OpenFile(aPrincipal, eOpenForWrite, writeParams, notARead, &file); + if (openResult != JS::AsmJSCache_Success) { + return openResult; } // Strip off the AsmJSCookieType from the buffer returned to the caller, @@ -1700,7 +1718,7 @@ OpenEntryForWrite(nsIPrincipal* aPrincipal, // The caller guarnatees a call to CloseEntryForWrite (on success or // failure) at which point the file will be closed file.Forget(reinterpret_cast(aFile)); - return true; + return JS::AsmJSCache_Success; } void diff --git a/dom/asmjscache/AsmJSCache.h b/dom/asmjscache/AsmJSCache.h index 9ddf61de63a..dd8fdc50993 100644 --- a/dom/asmjscache/AsmJSCache.h +++ b/dom/asmjscache/AsmJSCache.h @@ -112,7 +112,7 @@ void CloseEntryForRead(size_t aSize, const uint8_t* aMemory, intptr_t aHandle); -bool +JS::AsmJSCacheResult OpenEntryForWrite(nsIPrincipal* aPrincipal, bool aInstalled, const char16_t* aBegin, @@ -178,6 +178,13 @@ struct ParamTraits static void Log(const paramType& aParam, std::wstring* aLog); }; +template <> +struct ParamTraits : + public ContiguousEnumSerializer +{ }; + } // namespace IPC #endif // mozilla_dom_asmjscache_asmjscache_h diff --git a/dom/asmjscache/PAsmJSCacheEntry.ipdl b/dom/asmjscache/PAsmJSCacheEntry.ipdl index 9a9f83c05e3..47747cfbe82 100644 --- a/dom/asmjscache/PAsmJSCacheEntry.ipdl +++ b/dom/asmjscache/PAsmJSCacheEntry.ipdl @@ -5,6 +5,7 @@ include protocol PContent; using mozilla::dom::asmjscache::Metadata from "mozilla/dom/asmjscache/AsmJSCache.h"; +using JS::AsmJSCacheResult from "mozilla/dom/asmjscache/AsmJSCache.h"; namespace mozilla { namespace dom { @@ -29,7 +30,7 @@ child: OnOpenCacheFile(int64_t fileSize, FileDescriptor fileDesc); both: - __delete__(); + __delete__(AsmJSCacheResult result); }; } // namespace asmjscache diff --git a/dom/base/nsJSEnvironment.cpp b/dom/base/nsJSEnvironment.cpp index c8ee786b2c9..93240f5491d 100644 --- a/dom/base/nsJSEnvironment.cpp +++ b/dom/base/nsJSEnvironment.cpp @@ -2703,7 +2703,7 @@ AsmJSCacheOpenEntryForRead(JS::Handle aGlobal, aHandle); } -static bool +static JS::AsmJSCacheResult AsmJSCacheOpenEntryForWrite(JS::Handle aGlobal, bool aInstalled, const char16_t* aBegin, diff --git a/dom/workers/RuntimeService.cpp b/dom/workers/RuntimeService.cpp index 849feeb5e67..9cee65802cb 100644 --- a/dom/workers/RuntimeService.cpp +++ b/dom/workers/RuntimeService.cpp @@ -734,7 +734,7 @@ AsmJSCacheOpenEntryForRead(JS::Handle aGlobal, aHandle); } -static bool +static JS::AsmJSCacheResult AsmJSCacheOpenEntryForWrite(JS::Handle aGlobal, bool aInstalled, const char16_t* aBegin, @@ -745,7 +745,7 @@ AsmJSCacheOpenEntryForWrite(JS::Handle aGlobal, { nsIPrincipal* principal = GetPrincipalForAsmJSCacheOp(); if (!principal) { - return false; + return JS::AsmJSCache_InternalError; } return asmjscache::OpenEntryForWrite(principal, aInstalled, aBegin, aEnd, diff --git a/js/src/asmjs/AsmJSModule.cpp b/js/src/asmjs/AsmJSModule.cpp index ae86f8fb05c..eaee85435be 100644 --- a/js/src/asmjs/AsmJSModule.cpp +++ b/js/src/asmjs/AsmJSModule.cpp @@ -2134,7 +2134,7 @@ struct ScopedCacheEntryOpenedForWrite } }; -bool +JS::AsmJSCacheResult js::StoreAsmJSModuleInCache(AsmJSParser &parser, const AsmJSModule &module, ExclusiveContext *cx) @@ -2144,15 +2144,15 @@ js::StoreAsmJSModuleInCache(AsmJSParser &parser, // that can't be serialized. (This is separate from normal profiling and // requires an addon to activate). if (module.numFunctionCounts()) - return false; + return JS::AsmJSCache_Disabled_JitInspector; MachineId machineId; if (!machineId.extractCurrentState(cx)) - return false; + return JS::AsmJSCache_InternalError; ModuleCharsForStore moduleChars; if (!moduleChars.init(parser)) - return false; + return JS::AsmJSCache_InternalError; size_t serializedSize = machineId.serializedSize() + moduleChars.serializedSize() + @@ -2160,17 +2160,17 @@ js::StoreAsmJSModuleInCache(AsmJSParser &parser, JS::OpenAsmJSCacheEntryForWriteOp open = cx->asmJSCacheOps().openEntryForWrite; if (!open) - return false; + return JS::AsmJSCache_Disabled_Internal; const char16_t *begin = parser.tokenStream.rawBase() + ModuleChars::beginOffset(parser); const char16_t *end = parser.tokenStream.rawBase() + ModuleChars::endOffset(parser); bool installed = parser.options().installedFile; ScopedCacheEntryOpenedForWrite entry(cx, serializedSize); - if (!open(cx->global(), installed, begin, end, entry.serializedSize, - &entry.memory, &entry.handle)) { - return false; - } + JS::AsmJSCacheResult openResult = + open(cx->global(), installed, begin, end, serializedSize, &entry.memory, &entry.handle); + if (openResult != JS::AsmJSCache_Success) + return openResult; uint8_t *cursor = entry.memory; cursor = machineId.serialize(cursor); @@ -2178,7 +2178,7 @@ js::StoreAsmJSModuleInCache(AsmJSParser &parser, cursor = module.serialize(cursor); MOZ_ASSERT(cursor == entry.memory + serializedSize); - return true; + return JS::AsmJSCache_Success; } struct ScopedCacheEntryOpenedForRead diff --git a/js/src/asmjs/AsmJSModule.h b/js/src/asmjs/AsmJSModule.h index 129e1b3c5db..3443cd8da93 100644 --- a/js/src/asmjs/AsmJSModule.h +++ b/js/src/asmjs/AsmJSModule.h @@ -1538,7 +1538,7 @@ class AsmJSModule }; // Store the just-parsed module in the cache using AsmJSCacheOps. -extern bool +extern JS::AsmJSCacheResult StoreAsmJSModuleInCache(AsmJSParser &parser, const AsmJSModule &module, ExclusiveContext *cx); diff --git a/js/src/asmjs/AsmJSValidate.cpp b/js/src/asmjs/AsmJSValidate.cpp index 0d1f13cefe9..c51798ae35a 100644 --- a/js/src/asmjs/AsmJSValidate.cpp +++ b/js/src/asmjs/AsmJSValidate.cpp @@ -1874,7 +1874,7 @@ class MOZ_STACK_CLASS ModuleCompiler return module_->addBuiltinThunkCodeRange(builtin, begin->offset(), pret->offset(), end); } - void buildCompilationTimeReport(bool storedInCache, ScopedJSFreePtr *out) { + void buildCompilationTimeReport(JS::AsmJSCacheResult cacheResult, ScopedJSFreePtr *out) { ScopedJSFreePtr slowFuns; #ifndef JS_MORE_DETERMINISTIC int64_t usecAfter = PRMJ_Now(); @@ -1895,10 +1895,39 @@ class MOZ_STACK_CLASS ModuleCompiler return; } } + const char *cacheString = ""; + switch (cacheResult) { + case JS::AsmJSCache_Success: + cacheString = "stored in cache"; + break; + case JS::AsmJSCache_ModuleTooSmall: + cacheString = "not stored in cache (too small to benefit)"; + break; + case JS::AsmJSCache_SynchronousScript: + cacheString = "unable to cache asm.js in synchronous scripts; try loading " + "asm.js via