Skip to content

Commit 1566615

Browse files
committed
[JSC] EnumeratorNextUpdateIndexAndMode should require the original array structure before using InBoundsSaneChain
https://bugs.webkit.org/show_bug.cgi?id=320620 Reviewed by Yusuke Suzuki and Keith Miller. The sane-chain speculation for the indexed enumerator mode was guarded only by benefitsFromOriginalArray(), which checks the indexing type but not the array class. As a result an array with a custom prototype got InBoundsSaneChain and DFG/FTL skipped hole checks against the prototype, diverging from LLInt/baseline. Check isJSArrayWithOriginalStructure() first, like every other sane-chain site in fixup does. Test: JSTests/stress/for-in-enumerator-hole-with-inherited-index-custom-prototype.js * JSTests/stress/for-in-enumerator-hole-with-inherited-index-custom-prototype.js: Added. (shouldBe): (mutate): (test): (makeArray): * Source/JavaScriptCore/dfg/DFGFixupPhase.cpp: (JSC::DFG::FixupPhase::fixupNode): Canonical link: https://commits.webkit.org/318293@main
1 parent 90b2ecf commit 1566615

2 files changed

Lines changed: 38 additions & 1 deletion

File tree

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
function shouldBe(actual, expected) {
2+
if (actual !== expected)
3+
throw new Error("bad value: " + actual + " expected: " + expected);
4+
}
5+
6+
function mutate(array, proto, key, doMutate) {
7+
if (doMutate && key === "1") {
8+
delete array[3];
9+
proto[3] = "inherited";
10+
}
11+
}
12+
noInline(mutate);
13+
14+
function test(array, proto, doMutate) {
15+
var keys = [];
16+
for (var key in array) {
17+
keys.push(key);
18+
mutate(array, proto, key, doMutate);
19+
}
20+
return keys.join(",");
21+
}
22+
noInline(test);
23+
24+
function makeArray() {
25+
var proto = {};
26+
var array = [1, 2, 3, 4, 5];
27+
Object.setPrototypeOf(array, proto);
28+
return [array, proto];
29+
}
30+
31+
for (var i = 0; i < testLoopCount; i++) {
32+
var [array, proto] = makeArray();
33+
shouldBe(test(array, proto, false), "0,1,2,3,4");
34+
}
35+
36+
var [array, proto] = makeArray();
37+
shouldBe(test(array, proto, true), "0,1,2,3,4");

Source/JavaScriptCore/dfg/DFGFixupPhase.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3058,7 +3058,7 @@ class FixupPhase : public Phase {
30583058
blessArrayOperation(base, index, storageEdge);
30593059

30603060
ArrayMode arrayMode = node->arrayMode();
3061-
if (arrayMode.benefitsFromOriginalArray())
3061+
if (arrayMode.isJSArrayWithOriginalStructure() && arrayMode.benefitsFromOriginalArray())
30623062
setSaneChainIfPossible(node, arrayMode.speculation() == Array::InBounds ? Array::InBoundsSaneChain : Array::OutOfBoundsSaneChain);
30633063
}
30643064

0 commit comments

Comments
 (0)