-
Notifications
You must be signed in to change notification settings - Fork 55
Upgrade to upstream WebKit d81bcc3d833c #263
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
ad3c1ab
144aa0d
b690833
c3ca56b
3ccfb3e
d8576e6
82a21e0
3c46119
bdf08cf
e1084c3
8c0e20b
bb98ffd
bd5f1e5
0d6fe16
16b1bde
8d4c709
543f99d
20d1bae
e2b88c2
aad3188
e147963
d9783c3
7a9d149
4691d48
2620d0d
ff4c717
ebcf150
5dd6865
9d4788b
ef2bac7
5c93ade
a828526
b590f91
9b4ffe1
5044a54
6ea1f0a
a93904b
736ce62
d3cffdd
8e5b854
ce030f7
8bdea30
0012e61
3ab3db0
0f85710
0053494
e23afe6
e081edf
8d85f54
140ce5b
7deaf9d
a18c0a8
6aa96bc
2020284
6c94926
f9eddca
4b7a49a
508bfb2
88e4fef
ae0d90b
2f91fd7
4454093
9bb8fdf
d7eb859
d6fb60c
bf0c7c6
ba3be26
b12f122
a2de66f
54b8e49
336c35e
e540a45
c5fabb4
b48b4d4
d75a9fd
a0291f1
019c43f
95a70d5
c312747
cfced00
7a5ee54
428365d
600eab6
d81bcc3
f652829
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| //@ skip if $model == "Apple Watch Series 3" # added by mark-jsc-stress-test.py | ||
| // Hole/miss-dominated reads of a large sparse array (ArrayStorage mode with a sparse map). Every read | ||
| // hits an in-bounds hole that is absent from the sparse map, so the int-indexed GetByVal slow path | ||
| // (operationGetByValArrayStorageInt) must resolve it to undefined via the (sane) prototype chain. | ||
| function get(array, i) | ||
| { | ||
| return array[i]; | ||
| } | ||
| noInline(get); | ||
|
|
||
| var maxIndex = 200000; | ||
| var step = 16; | ||
|
|
||
| var array = []; | ||
| for (var i = maxIndex - step; i >= 0; i -= step) | ||
| array[i] = i + 1; | ||
|
|
||
| var expectedPass = 0; | ||
| for (var i = 1; i < maxIndex; i += step) // i = 1, 17, 33, ... are all holes (never written). | ||
| ++expectedPass; | ||
|
|
||
| var iterations = 400; | ||
| var holes = 0; | ||
| for (var iter = 0; iter < iterations; ++iter) { | ||
| for (var i = 1; i < maxIndex; i += step) { | ||
| if (get(array, i) === void 0) | ||
| ++holes; | ||
| } | ||
| } | ||
|
|
||
| if (holes !== expectedPass * iterations) | ||
| throw "Error: bad hole count: " + holes; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| //@ skip if $model == "Apple Watch Series 3" # added by mark-jsc-stress-test.py | ||
| // Hit-dominated reads of a large sparse array (ArrayStorage mode with a sparse map). Every read | ||
| // resolves through the int-indexed GetByVal slow path (operationGetByValArrayStorageInt) and finds | ||
| // its value in the sparse map. | ||
| function get(array, i) | ||
| { | ||
| return array[i]; | ||
| } | ||
| noInline(get); | ||
|
|
||
| var maxIndex = 200000; | ||
| var step = 16; // 1/16 density (< 1/8) keeps the array in ArrayStorage with a sparse map. | ||
|
|
||
| var array = []; | ||
| // Descending writes: the first one is far beyond length, forcing ArrayStorage + sparse map. | ||
| for (var i = maxIndex - step; i >= 0; i -= step) | ||
| array[i] = i + 1; | ||
|
|
||
| var expectedPass = 0; | ||
| for (var i = 0; i < maxIndex; i += step) | ||
| expectedPass += i + 1; | ||
|
|
||
| var iterations = 800; | ||
| var sum = 0; | ||
| for (var iter = 0; iter < iterations; ++iter) { | ||
| for (var i = 0; i < maxIndex; i += step) | ||
| sum += get(array, i); | ||
| } | ||
|
|
||
| if (sum !== expectedPass * iterations) | ||
| throw "Error: bad sum: " + sum; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| //@ skip if $buildType == "debug" | ||
| //@ runDefault("--useConcurrentJIT=false", "--jitPolicyScale=0", "--maximumFunctionForCallInlineCandidateBytecodeCostForFTL=500") | ||
|
|
||
| let g = 0; | ||
| function restY(c, ...r) { g = c ? 1 : 2; return r; } | ||
| function h(c, ...r) { return r; } | ||
| function h2(...r) { return r; } | ||
| function sink() { | ||
| let out = []; | ||
| for (let i = 0; i < arguments.length; i++) out.push(arguments[i]); | ||
| return out; | ||
| } | ||
| noInline(sink); | ||
|
|
||
| function restX(c, ...rx) { | ||
| let arr = [...rx, ...restY(c, ...rx)]; | ||
| let dummy = [0, 0, 0, 0, 0, 0, 0, h(50, 9.9, 8.8)]; | ||
| return [sink.apply(null, arr), dummy]; | ||
| } | ||
| for (let i = 0; i < 1000000; i++) restX(i & 1, 0.1, 0.2); | ||
|
|
||
| function makeSrc(k) { | ||
| return ` | ||
| (function() { | ||
| function victim${k}(c1) { | ||
| let q = restX(c1, 0.1, 0.2); | ||
| let z = h2(7.7, 6.6); | ||
| return [q, z]; | ||
| } | ||
| noInline(victim${k}); | ||
| for (let i = 0; i < 1000000; i++) { | ||
| victim${k}(i & 1); | ||
| } | ||
| })() | ||
| `; | ||
| } | ||
|
|
||
| for (let k = 0; k < 30; k++) eval(makeSrc(k)); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| //@ runDefault("--useFTLJIT=1", "--jitPolicyScale=0.1", "--useConcurrentJIT=0", "--useConcurrentGC=0", "--sweepSynchronously=1", "--collectContinuously=1") | ||
|
|
||
| function opt(s, needle) { | ||
| return [s + "A", s + "B", s + "C", s + "D", s + "E", s + "F", s + "G", s + "H"].indexOf(needle); | ||
| } | ||
| noInline(opt); | ||
|
|
||
| let big = "Q".repeat(1024 * 1024); | ||
| let needleStr = "Z".repeat(big.length + 1); | ||
|
|
||
| for (let i = 0; i < 2000; i++) | ||
| opt(big, (i & 1) ? needleStr : 1234); | ||
|
|
||
| for (let i = 0; i < 10000; i++) | ||
| opt(big, needleStr); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,87 @@ | ||
| function createObject1() { | ||
| const tmp = { | ||
| toJSON: 1, | ||
| a: 1, | ||
| }; | ||
|
|
||
| Object.create(tmp); | ||
|
|
||
| return tmp; | ||
| } | ||
|
|
||
| function createObject2() { | ||
| const tmp = { | ||
| b: 1, | ||
| toJSON: {} | ||
| }; | ||
|
|
||
| Object.create(tmp); | ||
|
|
||
| return tmp; | ||
| } | ||
|
|
||
| function opt(container1, object2, array, thenable, flags) { | ||
| const promise = new Promise(() => {}); | ||
|
|
||
| container1.x; | ||
| thenable.x; | ||
|
|
||
| const object1 = Object.getPrototypeOf(container1); | ||
|
|
||
| let tmp = object1; | ||
| object1.a; | ||
|
|
||
| if (flags & 1) { | ||
| tmp = object2; | ||
| tmp.b; | ||
|
|
||
| 0[0]; | ||
| } | ||
|
|
||
| +tmp.toJSON; | ||
| +tmp.toJSON; | ||
|
|
||
| array[0]; | ||
| Promise.resolve(+tmp.toJSON === 1 ? thenable : promise); | ||
|
|
||
| array[0] = 2.3023e-320; | ||
| } | ||
|
|
||
| function main() { | ||
| noDFG(main); | ||
|
|
||
| const object1 = createObject1(); | ||
| const object2 = createObject2(); | ||
|
|
||
| createObject1().z = 1; | ||
|
|
||
| const container1 = Object.create(object1); | ||
|
|
||
| const thenable = { | ||
| x: 1 | ||
| }; | ||
|
|
||
| for (let i = 0; i < 100; i++) { | ||
| thenable['a' + i] = 1; | ||
| } | ||
|
|
||
| const array = { | ||
| 0: 1.1 | ||
| }; | ||
|
|
||
| JSON.stringify(container1); | ||
|
|
||
| for (let i = 0; i < 200; i++) { | ||
| opt(container1, object2, array, thenable, i); | ||
| } | ||
|
|
||
| thenable.__defineGetter__('then', () => { | ||
| array[0] = {}; | ||
| }); | ||
|
|
||
| opt(container1, object2, array, thenable, 0); | ||
|
|
||
| array[0].x; | ||
| } | ||
|
|
||
| main(); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| //@ runDefault("--useConcurrentJIT=false", "--jitPolicyScale=0.1", "--useConcurrentGC=false", "--verifyGC=true", "--gcMaxHeapSize=500000") | ||
|
|
||
| var g_value = {}; | ||
|
|
||
| function makeObj() { return {}; } | ||
|
|
||
| function foo(cond) { | ||
| let a = makeObj(); | ||
| a.p1 = 1; | ||
| a.p2 = 1; | ||
| a.p3 = 1; | ||
| a.p4 = 1; | ||
| a.p5 = 1; | ||
| if (cond) | ||
| a.y = 1; | ||
| else | ||
| a.z = 1; | ||
| a.x = g_value; | ||
| return a; | ||
| } | ||
| noInline(foo); | ||
|
|
||
| for (let i = 0; i < testLoopCount; ++i) { | ||
| g_value = {}; | ||
| foo(i & 1); | ||
| } | ||
|
|
||
| var holder = new Array(100000).fill(null); | ||
| fullGC(); | ||
|
|
||
| for (let i = 0; i < testLoopCount * 10; ++i) | ||
| holder[i % 100000] = foo(i & 1); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| // Test that regular expressions with many sequential non-greedy quantified | ||
| // parenthesized groups produce correct results at various sizes. | ||
|
|
||
| function testLargeNonGreedyParens(n) { | ||
| let s = '(?:a){0,2}?'.repeat(n); | ||
|
|
||
| let r = new RegExp(s); | ||
|
|
||
| let result = 'aaa'.match(r); | ||
| if (result === null) | ||
| throw new Error("Expected match for n=" + n); | ||
| if (result.index !== 0) | ||
| throw new Error("Expected index 0 for n=" + n + ", got " + result.index); | ||
|
|
||
| let replaced = 'a'.replace(r, 'x'); | ||
| if (typeof replaced !== 'string') | ||
| throw new Error("replace failed for n=" + n); | ||
| } | ||
|
|
||
| testLargeNonGreedyParens(10); | ||
| testLargeNonGreedyParens(100); | ||
| testLargeNonGreedyParens(1000); | ||
| testLargeNonGreedyParens(2000); | ||
| testLargeNonGreedyParens(4000); | ||
| testLargeNonGreedyParens(8193); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| const icCount = 100; | ||
| const structCount = 16; | ||
|
|
||
| let body = "var x = 0;\n"; | ||
| for (let i = 0; i < icCount; i++) | ||
| body += "x += o.p;\n"; | ||
| body += "return x;\n"; | ||
|
|
||
| let objs = []; | ||
| for (let i = 0; i < structCount; i++) { | ||
| let o = {}; | ||
| o["k" + i] = i; | ||
| o.p = 1; | ||
| objs.push(o); | ||
| } | ||
|
|
||
| let f = new Function("o", body); | ||
|
|
||
| for (let j = 0; j < 130; j++) | ||
| f(objs[j % structCount]); | ||
|
|
||
| for (let j = 0; j < 100000; j++) | ||
| f(objs[j % structCount]); | ||
|
|
||
| f(42); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| Object.defineProperty(Object.prototype, 0, { get() {}, configurable: true }); | ||
| delete Object.prototype[0]; | ||
| let target = [1, 2, 3]; | ||
| Object.defineProperty(target, "length", { writable: false }); | ||
|
|
||
| let proxyGet = new Proxy(target, { | ||
| get: (t, k) => k === "length" ? 999 : t[k] | ||
| }); | ||
|
|
||
| try { | ||
| let lengthLie = proxyGet.length; | ||
| if (lengthLie === 999) { | ||
| throw "\"get\" trap successfully returned a lying value (999) for a non-configurable, non-writable property!"; | ||
| } | ||
| } catch (e) { | ||
| if (!(e instanceof TypeError)) { | ||
| throw "Expected TypeError for \"get\" trap invariant violation, got: " + e; | ||
| } | ||
| } | ||
|
|
||
| let proxySet = new Proxy(target, { | ||
| set: (t, k, v) => true | ||
| }); | ||
|
|
||
| try { | ||
| let setSuccess = Reflect.set(proxySet, "length", 999); | ||
| if (setSuccess === true && target.length !== 999) { | ||
| throw "Reflect.set returned true claiming success on a non-configurable, non-writable property!"; | ||
| } | ||
| } catch (e) { | ||
| if (!(e instanceof TypeError)) { | ||
| throw "Expected TypeError for \"set\" trap invariant violation, got: " + e; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| //@ runDefault("--forceEagerCompilation=1", "--validateAbstractInterpreterState=1") | ||
|
|
||
| const array = [""]; | ||
|
|
||
| for (let index = 0; index < testLoopCount; index++) | ||
| (() => {})(...array); |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,47 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| function testResize(ctor, bytesPerElement, initialBytes, shrinkBytes, resizeAt) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const newCount = shrinkBytes / bytesPerElement; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const resizableArrayBuffer = new ArrayBuffer(initialBytes, { maxByteLength: initialBytes * 4 }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const source = new ctor(resizableArrayBuffer); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| source[Symbol.iterator] = null; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let callbacks = 0; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ctor.from(source, (val, index) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (index === resizeAt) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| resizableArrayBuffer.resize(shrinkBytes); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| callbacks++; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return val; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const expected = Math.max(resizeAt + 1, newCount); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (callbacks > expected) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| throw new Error(ctor.name + ": " + callbacks + " callbacks (expected <= " + expected + ")"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| function testDetach(detachAt) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const arrayBuffer = new ArrayBuffer(256); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const source = new Int32Array(arrayBuffer); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| source[Symbol.iterator] = null; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let callbacks = 0; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Int32Array.from(source, (val, index) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (index === detachAt) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| arrayBuffer.transfer(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| callbacks++; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return val; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } catch (e) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+26
to
+35
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win Don't swallow unexpected exceptions in the detach regression. This Suggested fix let callbacks = 0;
+ let didDetach = false;
try {
Int32Array.from(source, (val, index) => {
- if (index === detachAt)
+ if (index === detachAt) {
arrayBuffer.transfer();
+ didDetach = true;
+ }
callbacks++;
return val;
});
} catch (e) {
- return;
+ if (didDetach)
+ return;
+ throw e;
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (callbacks > detachAt + 1) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| throw new Error("detach: " + callbacks + " callbacks (expected <= " + (detachAt + 1) + ")"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| testResize(Int32Array, 4, 4096, 16, 4); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| testResize(Int32Array, 4, 4096, 8, 8); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| testResize(Float64Array, 8, 8192, 32, 8); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| testResize(Uint8Array, 1, 1024, 4, 8); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| testResize(Int32Array, 4, 4096, 8, 0); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| testDetach(4); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| testDetach(0); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Fail when the invariant check does not throw.
Both blocks currently pass if the engine skips the proxy trap path and returns the ordinary target result instead of throwing. That makes this regression test too weak for the stale-structure bug it is trying to pin down.
Suggested fix
try { - let lengthLie = proxyGet.length; - if (lengthLie === 999) { - throw "\"get\" trap successfully returned a lying value (999) for a non-configurable, non-writable property!"; - } + proxyGet.length; + throw "Expected TypeError for \"get\" trap invariant violation, but no exception was thrown"; } catch (e) { if (!(e instanceof TypeError)) { throw "Expected TypeError for \"get\" trap invariant violation, got: " + e; } } @@ try { - let setSuccess = Reflect.set(proxySet, "length", 999); - if (setSuccess === true && target.length !== 999) { - throw "Reflect.set returned true claiming success on a non-configurable, non-writable property!"; - } + Reflect.set(proxySet, "length", 999); + throw "Expected TypeError for \"set\" trap invariant violation, but no exception was thrown"; } catch (e) { if (!(e instanceof TypeError)) { throw "Expected TypeError for \"set\" trap invariant violation, got: " + e; } }Also applies to: 25-33
🤖 Prompt for AI Agents