commit b31de09df6f4f2cdfbd8a5113f7a0c97e80d1c5a
parent 4a128f5d807df9ec662e00b98d5554410703b0cd
Author: Jan de Mooij <jdemooij@mozilla.com>
Date: Fri, 28 Nov 2025 07:46:54 +0000
Bug 2002447 - Fix overzealous assertion for GuardMultipleShapes. r=iain
This includes the Major-GC number in the `ICScript` hash to handle the case where
a new shape is added later but then removed again by the GC (the list has weak pointers).
Differential Revision: https://phabricator.services.mozilla.com/D274311
Diffstat:
4 files changed, 26 insertions(+), 4 deletions(-)
diff --git a/js/src/jit-test/tests/warp/bug2002447.js b/js/src/jit-test/tests/warp/bug2002447.js
@@ -0,0 +1,16 @@
+// |jit-test| --fast-warmup
+gczeal(2, 54);
+var bin = new Uint8Array(2);
+function f(i) {
+ bin[1] = i;
+ Object.defineProperty(bin, [], {get: function() {}, [bin]: f});
+ WebAssembly(x);
+}
+function test() {
+ for (let i = 1; i < 120; i++) {
+ try {
+ f(i);
+ } catch {}
+ }
+}
+test();
diff --git a/js/src/jit/JitScript.cpp b/js/src/jit/JitScript.cpp
@@ -982,7 +982,7 @@ JitScript* ICScript::outerJitScript() {
// 5. The hash will change if the set of shapes stored in ShapeListSnapshot
// is changed by stub folding or GC (the shapes in ShapeListObject are weak
// pointers).
-HashNumber ICScript::hash() {
+HashNumber ICScript::hash(JSContext* cx) {
HashNumber h = 0;
for (size_t i = 0; i < numICEntries(); i++) {
ICStub* stub = icEntry(i).firstStub();
@@ -1010,6 +1010,11 @@ HashNumber ICScript::hash() {
Shape* shape = shapesObject->getUnbarriered(i);
h = mozilla::AddToHash(h, shape);
}
+ // Also include the GC number to handle the case where we bail
+ // out, add an additional shape, remove this new shape during GC,
+ // and then recompile with the current set of shapes.
+ // See bug 2002447.
+ h = mozilla::AddToHash(h, cx->runtime()->gc.majorGCCount());
}
break;
}
diff --git a/js/src/jit/JitScript.h b/js/src/jit/JitScript.h
@@ -214,7 +214,7 @@ class alignas(uintptr_t) ICScript final : public TrailingArray<ICScript> {
bool traceWeak(JSTracer* trc);
#ifdef DEBUG
- mozilla::HashNumber hash();
+ mozilla::HashNumber hash(JSContext* cx);
#endif
private:
diff --git a/js/src/jit/WarpOracle.cpp b/js/src/jit/WarpOracle.cpp
@@ -134,7 +134,8 @@ void WarpOracle::addScriptSnapshot(WarpScriptSnapshot* scriptSnapshot,
scriptSnapshots_.insertBack(scriptSnapshot);
accumulatedBytecodeSize_ += bytecodeLength;
#ifdef DEBUG
- runningScriptHash_ = mozilla::AddToHash(runningScriptHash_, icScript->hash());
+ runningScriptHash_ =
+ mozilla::AddToHash(runningScriptHash_, icScript->hash(cx_));
#endif
}
@@ -207,7 +208,7 @@ AbortReasonOr<WarpSnapshot*> WarpOracle::createSnapshot() {
// Failing this assertion is not a correctness/security problem.
// We therefore ignore cases involving resource exhaustion (OOM,
// stack overflow, etc), or stubs purged by GC.
- HashNumber hash = mozilla::AddToHash(icScript->hash(), runningScriptHash_);
+ HashNumber hash = mozilla::AddToHash(icScript->hash(cx_), runningScriptHash_);
if (outerScript_->jitScript()->hasFailedICHash()) {
HashNumber oldHash = outerScript_->jitScript()->getFailedICHash();
MOZ_ASSERT_IF(hash == oldHash && !js::SupportDifferentialTesting(),