From 2dd52670989b6ea7423d6f19045f651e638d5aa9 Mon Sep 17 00:00:00 2001 From: ownedbywuigi Date: Sat, 28 Mar 2026 09:20:54 +0000 Subject: [PATCH] Increase thresholds for small function compilation and warm-up to optimize performance for jQuery-style code. --- image/imgLoader.cpp | 42 +++++++++++++--------------- js/src/jit/IonOptimizationLevels.cpp | 17 +++++++++-- js/src/jit/JitOptions.cpp | 5 ++-- 3 files changed, 37 insertions(+), 27 deletions(-) diff --git a/image/imgLoader.cpp b/image/imgLoader.cpp index 506830221a..904eaaab2d 100644 --- a/image/imgLoader.cpp +++ b/image/imgLoader.cpp @@ -1493,8 +1493,6 @@ imgLoader::PutIntoCache(const ImageCacheKey& aKey, imgCacheEntry* entry) MOZ_LOG(gImgLog, LogLevel::Debug, ("[this=%p] imgLoader::PutIntoCache -- Element already in the cache", nullptr)); - RefPtr tmpRequest = tmpCacheEntry->GetRequest(); - // If it already exists, and we're putting the same key into the cache, we // should remove the old version. MOZ_LOG(gImgLog, LogLevel::Debug, @@ -1778,30 +1776,29 @@ imgLoader::ValidateEntry(imgCacheEntry* aEntry, { LOG_SCOPE(gImgLog, "imgLoader::ValidateEntry"); - bool hasExpired; uint32_t expirationTime = aEntry->GetExpiryTime(); - if (expirationTime <= SecondsFromPRTime(PR_Now())) { - hasExpired = true; - } else { - hasExpired = false; - } + uint32_t now = SecondsFromPRTime(PR_Now()); + bool hasExpired = expirationTime <= now; nsresult rv; // Special treatment for file URLs - aEntry has expired if file has changed - nsCOMPtr fileUrl(do_QueryInterface(aURI)); - if (fileUrl) { - uint32_t lastModTime = aEntry->GetLoadTime(); + bool isFileURI = false; + if (NS_SUCCEEDED(aURI->SchemeIs("file", &isFileURI)) && isFileURI) { + nsCOMPtr fileUrl(do_QueryInterface(aURI)); + if (fileUrl) { + uint32_t lastModTime = aEntry->GetLoadTime(); - nsCOMPtr theFile; - rv = fileUrl->GetFile(getter_AddRefs(theFile)); - if (NS_SUCCEEDED(rv)) { - PRTime fileLastMod; - rv = theFile->GetLastModifiedTime(&fileLastMod); + nsCOMPtr theFile; + rv = fileUrl->GetFile(getter_AddRefs(theFile)); if (NS_SUCCEEDED(rv)) { - // nsIFile uses millisec, NSPR usec - fileLastMod *= 1000; - hasExpired = SecondsFromPRTime((PRTime)fileLastMod) > lastModTime; + PRTime fileLastMod; + rv = theFile->GetLastModifiedTime(&fileLastMod); + if (NS_SUCCEEDED(rv)) { + // nsIFile uses millisec, NSPR usec + fileLastMod *= 1000; + hasExpired = SecondsFromPRTime((PRTime)fileLastMod) > lastModTime; + } } } } @@ -1821,9 +1818,8 @@ imgLoader::ValidateEntry(imgCacheEntry* aEntry, // just return true in that case. Doing so would mean that shift-reload // doesn't reload data URI documents/images though (which is handy for // debugging during gecko development) so we make an exception in that case. - nsAutoCString scheme; - aURI->GetScheme(scheme); - if (scheme.EqualsLiteral("data") && + bool isDataURI = false; + if (NS_SUCCEEDED(aURI->SchemeIs("data", &isDataURI)) && isDataURI && !(aLoadFlags & nsIRequest::LOAD_BYPASS_CACHE)) { return true; } @@ -1870,7 +1866,7 @@ imgLoader::ValidateEntry(imgCacheEntry* aEntry, if ((appCacheContainer = do_GetInterface(request->GetRequest()))) { appCacheContainer->GetApplicationCache(getter_AddRefs(requestAppCache)); } - if ((appCacheContainer = do_QueryInterface(aLoadGroup))) { + if (aLoadGroup && (appCacheContainer = do_QueryInterface(aLoadGroup))) { appCacheContainer->GetApplicationCache(getter_AddRefs(groupAppCache)); } diff --git a/js/src/jit/IonOptimizationLevels.cpp b/js/src/jit/IonOptimizationLevels.cpp index 086969e06f..41aa0f6ed9 100644 --- a/js/src/jit/IonOptimizationLevels.cpp +++ b/js/src/jit/IonOptimizationLevels.cpp @@ -47,8 +47,11 @@ OptimizationInfo::initNormalOptimizationInfo() scalarReplacement_ = true; smallFunctionMaxInlineDepth_ = 10; compilerWarmUpThreshold_ = CompilerWarmupThreshold; - compilerSmallFunctionWarmUpThreshold_ = CompilerSmallFunctionWarmupThreshold; - inliningWarmUpThresholdFactor_ = 0.10; + // Start compiling tiny helper functions sooner. This is particularly + // useful for jQuery-style code with many frequently-called short helpers. + compilerSmallFunctionWarmUpThreshold_ = 32; + // Inline callees a bit earlier once a script becomes warm. + inliningWarmUpThresholdFactor_ = 0.08; inliningRecompileThresholdFactor_ = 4; } @@ -112,6 +115,16 @@ OptimizationInfo::compilerWarmUpThreshold(JSScript* script, jsbytecode* pc) cons warmUpThreshold *= ratio; } + // jQuery spends a lot of time in medium-small wrappers that are too large + // to be classified as "small" but still hot enough to benefit from Ion. + // Nudge these scripts toward earlier compilation without affecting large + // scripts that are expensive to optimize. + if (script->length() <= 400 && numLocalsAndArgs <= 48) { + warmUpThreshold = (warmUpThreshold * 3) / 4; + if (warmUpThreshold < 30) + warmUpThreshold = 30; + } + if (!pc || JitOptions.eagerCompilation) return warmUpThreshold; diff --git a/js/src/jit/JitOptions.cpp b/js/src/jit/JitOptions.cpp index c9b940a137..d7dacb89a0 100644 --- a/js/src/jit/JitOptions.cpp +++ b/js/src/jit/JitOptions.cpp @@ -167,8 +167,9 @@ DefaultJitOptions::DefaultJitOptions() // invalidating the script. SET_DEFAULT(osrPcMismatchesBeforeRecompile, 6000); - // The bytecode length limit for small function. - SET_DEFAULT(smallFunctionMaxBytecodeLength_, 200); + // The bytecode length limit for small function. jQuery has many helpers + // just above 200 bytecodes, so raise this to compile them sooner. + SET_DEFAULT(smallFunctionMaxBytecodeLength_, 320); // An artificial testing limit for the maximum supported offset of // pc-relative jump and call instructions.