commit 9b4615ce61d33853b7cd054f0a11463a1a54aedd
parent b90c10909db17cd4d89c5ce56016fbf07a25f2f6
Author: Hannes Verschore <hv1989@gmail.com>
Date: Thu, 11 Dec 2025 22:43:12 +0000
Bug 1999828: Part 2 - Add additional stubfolding spew information. r=iain
Add Stubfolding-details logs to have more information about the folding.
Differential Revision: https://phabricator.services.mozilla.com/D274202
Diffstat:
3 files changed, 143 insertions(+), 99 deletions(-)
diff --git a/js/src/jit/JitSpewer.cpp b/js/src/jit/JitSpewer.cpp
@@ -338,6 +338,8 @@ static void PrintHelpAndExit(int status = 0) {
" gcbarriers Redundant GC barrier elimination\n"
" loadkeys Loads used as property keys\n"
" stubfolding CacheIR stub folding\n"
+ " stubfolding-details Same as stubfolding, but with spewing of stub "
+ "content.\n"
" logs JSON visualization logging\n"
" logs-sync Same as logs, but flushes between each pass (sync. "
"compiled functions only).\n"
@@ -446,6 +448,9 @@ void jit::CheckLogging() {
EnableChannel(JitSpew_MarkLoadsUsedAsPropertyKeys);
} else if (IsFlag(found, "stubfolding")) {
EnableChannel(JitSpew_StubFolding);
+ } else if (IsFlag(found, "stubfolding-details")) {
+ EnableChannel(JitSpew_StubFolding);
+ EnableChannel(JitSpew_StubFoldingDetails);
} else if (IsFlag(found, "logs")) {
EnableIonDebugAsyncLogging();
} else if (IsFlag(found, "logs-sync")) {
diff --git a/js/src/jit/JitSpewer.h b/js/src/jit/JitSpewer.h
@@ -24,105 +24,107 @@ namespace js {
namespace jit {
// New channels may be added below.
-#define JITSPEW_CHANNEL_LIST(_) \
- /* Information during sinking */ \
- _(Prune) \
- /* Information during escape analysis */ \
- _(Escape) \
- /* Information during alias analysis */ \
- _(Alias) \
- /* Information during alias analysis */ \
- _(AliasSummaries) \
- /* Information during GVN */ \
- _(GVN) \
- /* Information during sinking */ \
- _(Sink) \
- /* Information during Range analysis */ \
- _(Range) \
- /* Information during LICM */ \
- _(LICM) \
- /* Information during Branch Hinting */ \
- _(BranchHint) \
- /* Info about fold linear constants */ \
- _(FLAC) \
- /* Effective address analysis info */ \
- _(EAA) \
- /* Wasm Bounds Check Elimination */ \
- _(WasmBCE) \
- /* Information during regalloc */ \
- _(RegAlloc) \
- /* Information during inlining */ \
- _(Inlining) \
- /* Information during codegen */ \
- _(Codegen) \
- /* Debug info about safepoints */ \
- _(Safepoints) \
- /* Debug info about Pools*/ \
- _(Pools) \
- /* Profiling-related information */ \
- _(Profiling) \
- /* Debug info about the I$ */ \
- _(CacheFlush) \
- /* Info about redundant shape guards */ \
- _(RedundantShapeGuards) \
- /* Info about redundant GC barriers */ \
- _(RedundantGCBarriers) \
- /* Info about loads used as keys */ \
- _(MarkLoadsUsedAsPropertyKeys) \
- /* Output a list of MIR expressions */ \
- _(MIRExpressions) \
- /* Summary info about loop unrolling */ \
- _(Unroll) \
- /* Detailed info about loop unrolling */ \
- _(UnrollDetails) \
- /* Information about stub folding */ \
- _(StubFolding) \
- \
- /* BASELINE COMPILER SPEW */ \
- \
- /* Aborting Script Compilation. */ \
- _(BaselineAbort) \
- /* Script Compilation. */ \
- _(BaselineScripts) \
- /* Detailed op-specific spew. */ \
- _(BaselineOp) \
- /* Inline caches. */ \
- _(BaselineIC) \
- /* Inline cache fallbacks. */ \
- _(BaselineICFallback) \
- /* OSR from Baseline => Ion. */ \
- _(BaselineOSR) \
- /* Bailouts. */ \
- _(BaselineBailouts) \
- /* Debug Mode On Stack Recompile . */ \
- _(BaselineDebugModeOSR) \
- \
- /* ION COMPILER SPEW */ \
- \
- /* Used to abort SSA construction */ \
- _(IonAbort) \
- /* Information about compiled scripts */ \
- _(IonScripts) \
- /* Info about failing to log script */ \
- _(IonSyncLogs) \
- /* Information during MIR building */ \
- _(IonMIR) \
- /* Information during bailouts */ \
- _(IonBailouts) \
- /* Information during OSI */ \
- _(IonInvalidate) \
- /* Debug info about snapshots */ \
- _(IonSnapshots) \
- /* Generated inline cache stubs */ \
- _(IonIC) \
- \
- /* WARP SPEW */ \
- \
- /* Generated WarpSnapshots */ \
- _(WarpSnapshots) \
- /* CacheIR transpiler logging */ \
- _(WarpTranspiler) \
- /* Trial inlining for Warp */ \
+#define JITSPEW_CHANNEL_LIST(_) \
+ /* Information during sinking */ \
+ _(Prune) \
+ /* Information during escape analysis */ \
+ _(Escape) \
+ /* Information during alias analysis */ \
+ _(Alias) \
+ /* Information during alias analysis */ \
+ _(AliasSummaries) \
+ /* Information during GVN */ \
+ _(GVN) \
+ /* Information during sinking */ \
+ _(Sink) \
+ /* Information during Range analysis */ \
+ _(Range) \
+ /* Information during LICM */ \
+ _(LICM) \
+ /* Information during Branch Hinting */ \
+ _(BranchHint) \
+ /* Info about fold linear constants */ \
+ _(FLAC) \
+ /* Effective address analysis info */ \
+ _(EAA) \
+ /* Wasm Bounds Check Elimination */ \
+ _(WasmBCE) \
+ /* Information during regalloc */ \
+ _(RegAlloc) \
+ /* Information during inlining */ \
+ _(Inlining) \
+ /* Information during codegen */ \
+ _(Codegen) \
+ /* Debug info about safepoints */ \
+ _(Safepoints) \
+ /* Debug info about Pools*/ \
+ _(Pools) \
+ /* Profiling-related information */ \
+ _(Profiling) \
+ /* Debug info about the I$ */ \
+ _(CacheFlush) \
+ /* Info about redundant shape guards */ \
+ _(RedundantShapeGuards) \
+ /* Info about redundant GC barriers */ \
+ _(RedundantGCBarriers) \
+ /* Info about loads used as keys */ \
+ _(MarkLoadsUsedAsPropertyKeys) \
+ /* Output a list of MIR expressions */ \
+ _(MIRExpressions) \
+ /* Summary info about loop unrolling */ \
+ _(Unroll) \
+ /* Detailed info about loop unrolling */ \
+ _(UnrollDetails) \
+ /* Information about stub folding */ \
+ _(StubFolding) \
+ /* Additional information about stub folding */ \
+ _(StubFoldingDetails) \
+ \
+ /* BASELINE COMPILER SPEW */ \
+ \
+ /* Aborting Script Compilation. */ \
+ _(BaselineAbort) \
+ /* Script Compilation. */ \
+ _(BaselineScripts) \
+ /* Detailed op-specific spew. */ \
+ _(BaselineOp) \
+ /* Inline caches. */ \
+ _(BaselineIC) \
+ /* Inline cache fallbacks. */ \
+ _(BaselineICFallback) \
+ /* OSR from Baseline => Ion. */ \
+ _(BaselineOSR) \
+ /* Bailouts. */ \
+ _(BaselineBailouts) \
+ /* Debug Mode On Stack Recompile . */ \
+ _(BaselineDebugModeOSR) \
+ \
+ /* ION COMPILER SPEW */ \
+ \
+ /* Used to abort SSA construction */ \
+ _(IonAbort) \
+ /* Information about compiled scripts */ \
+ _(IonScripts) \
+ /* Info about failing to log script */ \
+ _(IonSyncLogs) \
+ /* Information during MIR building */ \
+ _(IonMIR) \
+ /* Information during bailouts */ \
+ _(IonBailouts) \
+ /* Information during OSI */ \
+ _(IonInvalidate) \
+ /* Debug info about snapshots */ \
+ _(IonSnapshots) \
+ /* Generated inline cache stubs */ \
+ _(IonIC) \
+ \
+ /* WARP SPEW */ \
+ \
+ /* Generated WarpSnapshots */ \
+ _(WarpSnapshots) \
+ /* CacheIR transpiler logging */ \
+ _(WarpTranspiler) \
+ /* Trial inlining for Warp */ \
_(WarpTrialInlining)
enum JitSpewChannel {
diff --git a/js/src/jit/StubFolding.cpp b/js/src/jit/StubFolding.cpp
@@ -76,6 +76,25 @@ static bool TryFoldingGuardShapes(JSContext* cx, ICFallbackStub* fallback,
return true;
};
+#ifdef JS_JITSPEW
+ JitSpew(JitSpew_StubFolding, "Trying to fold stubs at offset %u @ %s:%u:%u",
+ fallback->pcOffset(), script->filename(), script->lineno(),
+ script->column().oneOriginValue());
+
+ if (JitSpewEnabled(JitSpew_StubFoldingDetails)) {
+ Fprinter& printer(JitSpewPrinter());
+ uint32_t i = 0;
+ for (ICCacheIRStub* stub = firstStub; stub; stub = stub->nextCacheIR()) {
+ printer.printf("- stub %d (enteredCount: %d)\n", i, stub->enteredCount());
+ ICCacheIRStub* cache_stub = stub->toCacheIRStub();
+
+ CacheIRReader reader(cache_stub->stubInfo());
+ SpewCacheIROps(printer, " ", cache_stub->stubInfo());
+ i++;
+ }
+ }
+#endif
+
// Find the offset of the first Shape that differs.
for (ICCacheIRStub* other = firstStub->nextCacheIR(); other;
other = other->nextCacheIR()) {
@@ -236,6 +255,12 @@ static bool TryFoldingGuardShapes(JSContext* cx, ICFallbackStub* fallback,
if (!shapeSuccess) {
// If the shape field that differed was not part of a GuardShape,
// we can't fold these stubs together.
+ JitSpew(JitSpew_StubFolding,
+ "Foldable shape field at offset %u was not a GuardShape "
+ "(icScript: %p) with %zu shapes (%s:%u:%u)",
+ fallback->pcOffset(), icScript, shapeList.length(),
+ script->filename(), script->lineno(),
+ script->column().oneOriginValue());
return true;
}
@@ -256,6 +281,18 @@ static bool TryFoldingGuardShapes(JSContext* cx, ICFallbackStub* fallback,
script->filename(), script->lineno(),
script->column().oneOriginValue());
+#ifdef JS_JITSPEW
+ if (JitSpewEnabled(JitSpew_StubFoldingDetails)) {
+ ICStub* newEntryStub = icEntry->firstStub();
+ ICCacheIRStub* newStub = newEntryStub->toCacheIRStub();
+
+ Fprinter& printer(JitSpewPrinter());
+ printer.printf("- stub 0 (enteredCount: %d)\n", newStub->enteredCount());
+ CacheIRReader reader(newStub->stubInfo());
+ SpewCacheIROps(printer, " ", newStub->stubInfo());
+ }
+#endif
+
fallback->setMayHaveFoldedStub();
return true;