From 81663e45566ac63df91ae223028ad4e2e5afad8e Mon Sep 17 00:00:00 2001 From: test262-automation Date: Wed, 7 Nov 2018 18:56:01 +0000 Subject: [PATCH] [javascriptcore-test262-automation] Changes from https://github.com/webkit/webkit.git at sha 24719c7634 on Wed Nov 07 2018 18:52:42 GMT+0000 (Coordinated Universal Time) --- ...activation-sink-default-value-tdz-error.js | 46 + .../stress/activation-sink-default-value.js | 33 + ...on-sink-osrexit-default-value-tdz-error.js | 48 + .../activation-sink-osrexit-default-value.js | 39 + .../stress/activation-sink-osrexit.js | 27 + .../javascriptcore/stress/activation-sink.js | 26 + .../allow-math-ic-b3-code-duplication.js | 3 +- .../stress/array-push-multiple-int32.js | 26 + ...on-sink-osrexit-default-value-tdz-error.js | 48 + ...on-lexical-this-activation-sink-osrexit.js | 36 + ...owfunction-lexical-this-activation-sink.js | 40 + ...-on-stack-overflow-when-parsing-builtin.js | 13 + ...erflow-when-parsing-default-constructor.js | 17 + .../stress/elide-new-object-dag-then-exit.js | 45 + .../stress/materialize-regexp-cyclic.js | 41 + .../javascriptcore/stress/new-regex-inline.js | 84 ++ .../javascriptcore/stress/op_add.js | 2 +- .../javascriptcore/stress/op_bitand.js | 2 +- .../javascriptcore/stress/op_bitor.js | 2 +- .../javascriptcore/stress/op_bitxor.js | 2 +- .../javascriptcore/stress/op_div-ConstVar.js | 20 + .../javascriptcore/stress/op_div-VarConst.js | 20 + .../javascriptcore/stress/op_div-VarVar.js | 20 + .../stress/op_lshift-ConstVar.js | 2 +- .../stress/op_lshift-VarConst.js | 2 +- .../javascriptcore/stress/op_lshift-VarVar.js | 2 +- .../javascriptcore/stress/op_mod-ConstVar.js | 2 +- .../javascriptcore/stress/op_mod-VarConst.js | 2 +- .../javascriptcore/stress/op_mod-VarVar.js | 2 +- .../javascriptcore/stress/op_mul-ConstVar.js | 2 +- .../javascriptcore/stress/op_mul-VarConst.js | 2 +- .../javascriptcore/stress/op_mul-VarVar.js | 2 +- .../stress/op_rshift-ConstVar.js | 2 +- .../stress/op_rshift-VarConst.js | 2 +- .../javascriptcore/stress/op_rshift-VarVar.js | 2 +- .../javascriptcore/stress/op_sub-ConstVar.js | 2 +- .../javascriptcore/stress/op_sub-VarConst.js | 2 +- .../javascriptcore/stress/op_sub-VarVar.js | 2 +- .../stress/op_urshift-ConstVar.js | 2 +- .../stress/op_urshift-VarConst.js | 2 +- .../stress/op_urshift-VarVar.js | 2 +- .../stress/proxy-get-set-correct-receiver.js | 117 +++ .../stress/regexp-compile-oom.js | 72 +- .../javascriptcore/stress/regress-179562.js | 33 + .../stress/rest-parameter-many-arguments.js | 52 + .../stress/sampling-profiler-richards.js | 1 + .../stress/splay-flash-access-1ms.js | 904 ++++++++++++++++++ .../stress/tailCallForwardArguments.js | 165 ++++ .../typed-array-get-by-val-profiling.js | 93 ++ 49 files changed, 2071 insertions(+), 42 deletions(-) create mode 100644 implementation-contributed/javascriptcore/stress/activation-sink-default-value-tdz-error.js create mode 100644 implementation-contributed/javascriptcore/stress/activation-sink-default-value.js create mode 100644 implementation-contributed/javascriptcore/stress/activation-sink-osrexit-default-value-tdz-error.js create mode 100644 implementation-contributed/javascriptcore/stress/activation-sink-osrexit-default-value.js create mode 100644 implementation-contributed/javascriptcore/stress/activation-sink-osrexit.js create mode 100644 implementation-contributed/javascriptcore/stress/activation-sink.js create mode 100644 implementation-contributed/javascriptcore/stress/array-push-multiple-int32.js create mode 100644 implementation-contributed/javascriptcore/stress/arrowfunction-activation-sink-osrexit-default-value-tdz-error.js create mode 100644 implementation-contributed/javascriptcore/stress/arrowfunction-lexical-this-activation-sink-osrexit.js create mode 100644 implementation-contributed/javascriptcore/stress/arrowfunction-lexical-this-activation-sink.js create mode 100644 implementation-contributed/javascriptcore/stress/dont-crash-on-stack-overflow-when-parsing-builtin.js create mode 100644 implementation-contributed/javascriptcore/stress/dont-crash-on-stack-overflow-when-parsing-default-constructor.js create mode 100644 implementation-contributed/javascriptcore/stress/elide-new-object-dag-then-exit.js create mode 100644 implementation-contributed/javascriptcore/stress/materialize-regexp-cyclic.js create mode 100644 implementation-contributed/javascriptcore/stress/new-regex-inline.js create mode 100644 implementation-contributed/javascriptcore/stress/op_div-ConstVar.js create mode 100644 implementation-contributed/javascriptcore/stress/op_div-VarConst.js create mode 100644 implementation-contributed/javascriptcore/stress/op_div-VarVar.js create mode 100644 implementation-contributed/javascriptcore/stress/proxy-get-set-correct-receiver.js create mode 100644 implementation-contributed/javascriptcore/stress/regress-179562.js create mode 100644 implementation-contributed/javascriptcore/stress/rest-parameter-many-arguments.js create mode 100644 implementation-contributed/javascriptcore/stress/splay-flash-access-1ms.js create mode 100644 implementation-contributed/javascriptcore/stress/tailCallForwardArguments.js create mode 100644 implementation-contributed/javascriptcore/stress/typed-array-get-by-val-profiling.js diff --git a/implementation-contributed/javascriptcore/stress/activation-sink-default-value-tdz-error.js b/implementation-contributed/javascriptcore/stress/activation-sink-default-value-tdz-error.js new file mode 100644 index 0000000000..c780b38732 --- /dev/null +++ b/implementation-contributed/javascriptcore/stress/activation-sink-default-value-tdz-error.js @@ -0,0 +1,46 @@ +//@ skip if $buildType == "debug" or $architecture == "x86" + +"use strict"; + +var n = 10000000; + +function shouldThrowTDZ(func) { + var hasThrown = false; + try { + func(); + } catch(e) { + if (e.name.indexOf("ReferenceError") !== -1) + hasThrown = true; + } + if (!hasThrown) + throw new Error("Did not throw TDZ error"); +} +noInline(shouldThrowTDZ); + +function bar(f) { f(10); } + +function foo(b) { + let result = 0; + var set = function (x) { result = x; } + var cap = function() { return tdzPerpetrator; } + if (b) { + bar(set); + return tdzPerpetrator; + } + let tdzPerpetrator; + return result; +} + +noInline(bar); +noInline(foo); + +for (var i = 0; i < n; i++) { + var bool = !(i % 100); + if (bool) + shouldThrowTDZ(function() { foo(bool); }); + else { + var result = foo(bool); + if (result != 0) + throw "Error: bad result: " + result; + } +} diff --git a/implementation-contributed/javascriptcore/stress/activation-sink-default-value.js b/implementation-contributed/javascriptcore/stress/activation-sink-default-value.js new file mode 100644 index 0000000000..4bb5277f98 --- /dev/null +++ b/implementation-contributed/javascriptcore/stress/activation-sink-default-value.js @@ -0,0 +1,33 @@ +//@ skip if $architecture == "x86" + +var n = 10000000; + +function bar(f) { f(10); } + +function foo(b) { + var result = 0; + var imUndefined; + var baz; + var set = function (x) { result = x; return (imUndefined, baz); } + baz = 40; + if (b) { + bar(set); + if (result != 10) + throw "Error: bad: " + result; + if (baz !== 40) + throw "Error: bad: " + baz; + if (imUndefined !== void 0) + throw "Error: bad value: " + imUndefined; + return 0; + } + return result; +} + +noInline(bar); +noInline(foo); + +for (var i = 0; i < n; i++) { + var result = foo(!(i % 100)); + if (result != 0) + throw "Error: bad result: " + result; +} diff --git a/implementation-contributed/javascriptcore/stress/activation-sink-osrexit-default-value-tdz-error.js b/implementation-contributed/javascriptcore/stress/activation-sink-osrexit-default-value-tdz-error.js new file mode 100644 index 0000000000..4ca18e3d16 --- /dev/null +++ b/implementation-contributed/javascriptcore/stress/activation-sink-osrexit-default-value-tdz-error.js @@ -0,0 +1,48 @@ +//@ skip if $architecture == "x86" + +"use strict"; + +var n = 10000000; + +function shouldThrowTDZ(func) { + var hasThrown = false; + try { + func(); + } catch(e) { + if (e.name.indexOf("ReferenceError") !== -1) + hasThrown = true; + } + if (!hasThrown) + throw new Error("Did not throw TDZ error"); +} + +function bar(f) { } + +function foo(b) { + let result = 0; + var set = function (x) { result = x; return tdzPerpetrator; } + if (b) { + OSRExit(); + if (b) { + bar(set); + return tdzPerpetrator; + } + } + let tdzPerpetrator; + return result; +} + +noInline(bar); +noInline(foo); +noInline(shouldThrowTDZ); + +for (var i = 0; i < n; i++) { + var bool = !(i % 100); + if (bool) + shouldThrowTDZ(function() { foo(bool); }); + else { + var result = foo(bool); + if (result != 0) + throw "Error: bad result: " + result; + } +} diff --git a/implementation-contributed/javascriptcore/stress/activation-sink-osrexit-default-value.js b/implementation-contributed/javascriptcore/stress/activation-sink-osrexit-default-value.js new file mode 100644 index 0000000000..60623ad1a7 --- /dev/null +++ b/implementation-contributed/javascriptcore/stress/activation-sink-osrexit-default-value.js @@ -0,0 +1,39 @@ +//@ skip if $architecture == "x86" + +var n = 10000000; + +function bar(set) { + var result = set(0); + if (result !== void 0) + throw "Error: bad value: " + result; +} + +function foo(b) { + var result = 0; + var imUndefined; + var baz; + var set = function (x) { + result = x; + if (baz !== 50) + throw "Error: bad value: " + baz; + return imUndefined; + } + baz = 50; + if (b) { + OSRExit(); + if (b) { + bar(set); + } + return 0; + } + return result; +} + +noInline(bar); +noInline(foo); + +for (var i = 0; i < n; i++) { + var result = foo(!(i % 100)); + if (result != 0) + throw "Error: bad result: " + result; +} diff --git a/implementation-contributed/javascriptcore/stress/activation-sink-osrexit.js b/implementation-contributed/javascriptcore/stress/activation-sink-osrexit.js new file mode 100644 index 0000000000..bd5a2af47e --- /dev/null +++ b/implementation-contributed/javascriptcore/stress/activation-sink-osrexit.js @@ -0,0 +1,27 @@ +//@ skip if $architecture == "x86" + +var n = 10000000; + +function bar() { } + +function foo(b) { + var result = 0; + var set = function (x) { result = x; } + if (b) { + OSRExit(); + if (b) { + bar(set); + } + return 0; + } + return result; +} + +noInline(bar); +noInline(foo); + +for (var i = 0; i < n; i++) { + var result = foo(!(i % 100)); + if (result != 0) + throw "Error: bad result: " + result; +} diff --git a/implementation-contributed/javascriptcore/stress/activation-sink.js b/implementation-contributed/javascriptcore/stress/activation-sink.js new file mode 100644 index 0000000000..ccde211447 --- /dev/null +++ b/implementation-contributed/javascriptcore/stress/activation-sink.js @@ -0,0 +1,26 @@ +//@ skip if $architecture == "x86" + +var n = 10000000; + +function bar(f) { f(10); } + +function foo(b) { + var result = 0; + var set = function (x) { result = x; } + if (b) { + bar(set); + if (result != 10) + throw "Error: bad: " + result; + return 0; + } + return result; +} + +noInline(bar); +noInline(foo); + +for (var i = 0; i < n; i++) { + var result = foo(!(i % 100)); + if (result != 0) + throw "Error: bad result: " + result; +} diff --git a/implementation-contributed/javascriptcore/stress/allow-math-ic-b3-code-duplication.js b/implementation-contributed/javascriptcore/stress/allow-math-ic-b3-code-duplication.js index 92213ac348..0dc18276cf 100644 --- a/implementation-contributed/javascriptcore/stress/allow-math-ic-b3-code-duplication.js +++ b/implementation-contributed/javascriptcore/stress/allow-math-ic-b3-code-duplication.js @@ -1,4 +1,5 @@ -// Reviewed +//@ skip if $architecture == "x86" + function test1() { var o1; for (let i = 0; i < 1000000; ++i) { diff --git a/implementation-contributed/javascriptcore/stress/array-push-multiple-int32.js b/implementation-contributed/javascriptcore/stress/array-push-multiple-int32.js new file mode 100644 index 0000000000..f4164d8989 --- /dev/null +++ b/implementation-contributed/javascriptcore/stress/array-push-multiple-int32.js @@ -0,0 +1,26 @@ +//@ skip if $architecture == "x86" + +function shouldBe(actual, expected) +{ + if (actual !== expected) + throw new Error('bad value: ' + actual); +} + +function test(array, val1, val2, val3) +{ + return array.push(val1, val2, val3); +} +noInline(test); + +for (var i = 0; i < 1e7; ++i) { + var array = []; + shouldBe(test(array, 1, 2, 3), 3); + shouldBe(array[0], 1); + shouldBe(array[1], 2); + shouldBe(array[2], 3); +} +var array = []; +shouldBe(test(array, 1, 2, 3.3), 3); +shouldBe(array[0], 1); +shouldBe(array[1], 2); +shouldBe(array[2], 3.3); diff --git a/implementation-contributed/javascriptcore/stress/arrowfunction-activation-sink-osrexit-default-value-tdz-error.js b/implementation-contributed/javascriptcore/stress/arrowfunction-activation-sink-osrexit-default-value-tdz-error.js new file mode 100644 index 0000000000..905073e998 --- /dev/null +++ b/implementation-contributed/javascriptcore/stress/arrowfunction-activation-sink-osrexit-default-value-tdz-error.js @@ -0,0 +1,48 @@ +//@ skip if $architecture == "x86" + +"use strict"; + +var n = 1000000; + +function shouldThrowTDZ(func) { + var hasThrown = false; + try { + func(); + } catch(e) { + if (e.name.indexOf("ReferenceError") !== -1) + hasThrown = true; + } + if (!hasThrown) + throw new Error("Did not throw TDZ error"); +} + +function bar(f) { } + +function foo(b) { + let result = 0; + var set = (x) => { result = x; return tdzPerpetrator; } + if (b) { + OSRExit(); + if (b) { + bar(set); + return tdzPerpetrator; + } + } + let tdzPerpetrator; + return result; +} + +noInline(bar); +noInline(foo); +noInline(shouldThrowTDZ); + +for (var i = 0; i < n; i++) { + var bool = !(i % 100); + if (bool) + shouldThrowTDZ(()=> { foo(bool); }); + else { + var result = foo(bool); + if (result != 0) + throw "Error: bad result: " + result; + } +} diff --git a/implementation-contributed/javascriptcore/stress/arrowfunction-lexical-this-activation-sink-osrexit.js b/implementation-contributed/javascriptcore/stress/arrowfunction-lexical-this-activation-sink-osrexit.js new file mode 100644 index 0000000000..d7a322e4bf --- /dev/null +++ b/implementation-contributed/javascriptcore/stress/arrowfunction-lexical-this-activation-sink-osrexit.js @@ -0,0 +1,36 @@ +//@ skip if $architecture == "x86" + +var n = 10000000; + +var newContext = { + id : 'new-context' +}; + +function bar() { } + +function foo(b) { + var result = 0; + var set = (x) => { + // Check if arrow function store context + if (this != newContext || this.id != newContext.id) + throw 'Wrong context of arrow function'; + result = x; + } + if (b) { + OSRExit(); + if (b) { + bar(set); + } + return result; + } + return result; +} + +noInline(bar); +noInline(foo); + +for (var i = 0; i < n; i++) { + var result = foo.call(newContext, !(i % 100)); + if (result != 0) + throw "Error: bad result: " + result; +} diff --git a/implementation-contributed/javascriptcore/stress/arrowfunction-lexical-this-activation-sink.js b/implementation-contributed/javascriptcore/stress/arrowfunction-lexical-this-activation-sink.js new file mode 100644 index 0000000000..92655f4faf --- /dev/null +++ b/implementation-contributed/javascriptcore/stress/arrowfunction-lexical-this-activation-sink.js @@ -0,0 +1,40 @@ +//@ skip if $architecture == "x86" + +var n = 10000000; + +var newContext = { + id : 'new-context' +}; + +function bar(f) { + if (this == newContext) + throw 'Wrong context of nesting function'; + f(10); +} + +function foo(b) { + var result = 0; + var set = (x) => { + result = x; + // Check if arrow function store context + if (this != newContext || this.id != newContext.id) + throw 'Wrong context of arrow function'; + }; + + if (b) { + bar(set); + if (result != 10) + throw "Error: bad: " + result; + return 0; + } + return result; +} + +noInline(bar); +noInline(foo); + +for (var i = 0; i < n; i++) { + var result = foo.call(newContext, !(i % 100)); + if (result != 0) + throw "Error: bad result: " + result; +} diff --git a/implementation-contributed/javascriptcore/stress/dont-crash-on-stack-overflow-when-parsing-builtin.js b/implementation-contributed/javascriptcore/stress/dont-crash-on-stack-overflow-when-parsing-builtin.js new file mode 100644 index 0000000000..4254ec8686 --- /dev/null +++ b/implementation-contributed/javascriptcore/stress/dont-crash-on-stack-overflow-when-parsing-builtin.js @@ -0,0 +1,13 @@ +//@ runDefault("--softReservedZoneSize=16384", "--reservedZoneSize=0", "--useJIT=0", "--validateBytecode=1", "--maxPerThreadStackUsage=499712") + +function f() { + try { + f(); + } catch (e) { + try { + Map.prototype.forEach.call('', {}); + } catch (e) {} + } +} + +f() diff --git a/implementation-contributed/javascriptcore/stress/dont-crash-on-stack-overflow-when-parsing-default-constructor.js b/implementation-contributed/javascriptcore/stress/dont-crash-on-stack-overflow-when-parsing-default-constructor.js new file mode 100644 index 0000000000..55454418a3 --- /dev/null +++ b/implementation-contributed/javascriptcore/stress/dont-crash-on-stack-overflow-when-parsing-default-constructor.js @@ -0,0 +1,17 @@ +//@ runDefault("--softReservedZoneSize=16384", "--reservedZoneSize=0", "--useJIT=0", "--validateBytecode=1", "--maxPerThreadStackUsage=499712") + +function runNearStackLimit(f) { + function t() { + try { + return t(); + } catch (e) { + new class extends (class {}) {}(); + return f(); + } + } + return t(); +} +function foo() { + new class extends (class {}) {}(); +} +runNearStackLimit(() => { return foo(); }); diff --git a/implementation-contributed/javascriptcore/stress/elide-new-object-dag-then-exit.js b/implementation-contributed/javascriptcore/stress/elide-new-object-dag-then-exit.js new file mode 100644 index 0000000000..a2ed594082 --- /dev/null +++ b/implementation-contributed/javascriptcore/stress/elide-new-object-dag-then-exit.js @@ -0,0 +1,45 @@ +//@ skip if $architecture == "x86" + +function sumOfArithSeries(limit) { + return limit * (limit + 1) / 2; +} + +var n = 10000000; + +function bar() { } + +function verify(q, i) { + if (q.f == q.g) + throw "Error: q.f == q.g"; + if (q.f.f != q.g.f) + throw "Error: q.f.f != q.g.f"; + if (q.f.f.f != i) + throw "Error: q.f.f.f != i"; +} + +function foo() { + var result = 0; + for (var i = 0; i < n; ++i) { + var leaf = {f:i}; + var o = {f:leaf}; + var p = {f:leaf}; + var q = {f:o, g:p}; + result += q.f.f.f; + if (i >= n - 100) { + // We want the materialization to happen in the exit. So, before calling the thing that + // causes the materialization, we call bar(). We've never profiled this call at the time + // of FTL compilation, so this should be an exit. + bar(); + verify(q, i); + } + } + return result; +} + +noInline(foo); +noInline(verify); +noInline(bar); + +var result = foo(); +if (result != sumOfArithSeries(n - 1)) + throw "Error: bad result: " + result; diff --git a/implementation-contributed/javascriptcore/stress/materialize-regexp-cyclic.js b/implementation-contributed/javascriptcore/stress/materialize-regexp-cyclic.js new file mode 100644 index 0000000000..1787639a11 --- /dev/null +++ b/implementation-contributed/javascriptcore/stress/materialize-regexp-cyclic.js @@ -0,0 +1,41 @@ +//@ slow! + +function shouldBe(actual, expected) +{ + if (actual !== expected) + throw new Error('bad value: ' + actual); +} + +function test(num) +{ + var regexp = /hello world/; + regexp.lastIndex = { ok: regexp, value: 42 }; + if (num === 0) + return regexp; + if (num === 1) + return regexp.lastIndex; + return regexp.lastIndex.value; +} +noInline(test); + +for (var i = 0; i < 1e6; ++i) { + var num = i % 3; + switch (num) { + case 0: + var regexp = test(num); + shouldBe(regexp instanceof RegExp, true); + shouldBe(typeof regexp.lastIndex, "object"); + shouldBe(regexp.lastIndex.ok, regexp); + break; + case 1: + var object = test(num); + shouldBe(object.value, 42); + shouldBe(object.ok instanceof RegExp, true); + shouldBe(object.ok.lastIndex, object); + break; + case 2: + var value = test(num); + shouldBe(value, 42); + break; + } +} diff --git a/implementation-contributed/javascriptcore/stress/new-regex-inline.js b/implementation-contributed/javascriptcore/stress/new-regex-inline.js new file mode 100644 index 0000000000..53d80477b4 --- /dev/null +++ b/implementation-contributed/javascriptcore/stress/new-regex-inline.js @@ -0,0 +1,84 @@ +//@ skip if $architecture == "x86" + +function assert(a) { + if (!a) + throw Error("bad assertion"); +} + +function testRegexpInline(functor) { + for (let i = 0; i < 100000; i++) { + functor(); + } + + gc(); + + // Create objects to force collected objects be reused + for (let i = 0; i < 10000000; i++) { + let a = {value: i}; + } + + // Checking if RegExp were collected + for (let i = 0; i < 100; i++) { + functor(); + } +} + +function toInlineGlobal() { + var re = /cc+/; + + assert(re.test("ccc")); + assert(!re.test("abc")); + return 0; +} + +function withRegexp() { + toInlineGlobal(); + var re = /(ab)+/; + assert(re.test("ab")); + assert(!re.test("ba")); + return 0; +} + +noInline(withRegexp); + +testRegexpInline(withRegexp); + +function inlineRegexpNotGlobal() { + let toInline = () => { + let re = /a+/; + + assert(re.test("aaaaaa")); + assert(!re.test("bc")); + } + + toInline(); +} + +noInline(inlineRegexpNotGlobal); + +testRegexpInline(inlineRegexpNotGlobal); + +function toInlineRecursive(depth) { + if (depth == 5) { + return; + } + + var re = /(ef)+/; + + assert(re.test("efef")); + assert(!re.test("abc")); + + toInlineRecursive(depth + 1); +} + +function regexpContainsRecursive() { + var re = /r+/; + toInlineRecursive(0); + + assert(re.test("r")); + assert(!re.test("ab")); +} +noInline(regexpContainsRecursive); + +testRegexpInline(regexpContainsRecursive); + diff --git a/implementation-contributed/javascriptcore/stress/op_add.js b/implementation-contributed/javascriptcore/stress/op_add.js index 65679b43ae..c6290406cc 100644 --- a/implementation-contributed/javascriptcore/stress/op_add.js +++ b/implementation-contributed/javascriptcore/stress/op_add.js @@ -1,6 +1,6 @@ // FIXME: unskip when this is solved // https://bugs.webkit.org/show_bug.cgi?id=191163 -//@ skip if $architecture == "arm" +//@ skip if $architecture == "arm" or $architecture == "x86" //@ runFTLNoCJIT // If all goes well, this test module will terminate silently. If not, it will print diff --git a/implementation-contributed/javascriptcore/stress/op_bitand.js b/implementation-contributed/javascriptcore/stress/op_bitand.js index 1bc61a00eb..a4586034d3 100644 --- a/implementation-contributed/javascriptcore/stress/op_bitand.js +++ b/implementation-contributed/javascriptcore/stress/op_bitand.js @@ -1,6 +1,6 @@ // FIXME: unskip when this is solved // https://bugs.webkit.org/show_bug.cgi?id=191163 -//@ skip if $architecture == "arm" +//@ skip if $architecture == "arm" or $architecture == "x86" //@ runFTLNoCJIT // If all goes well, this test module will terminate silently. If not, it will print diff --git a/implementation-contributed/javascriptcore/stress/op_bitor.js b/implementation-contributed/javascriptcore/stress/op_bitor.js index 685e236241..2668a99997 100644 --- a/implementation-contributed/javascriptcore/stress/op_bitor.js +++ b/implementation-contributed/javascriptcore/stress/op_bitor.js @@ -1,6 +1,6 @@ // FIXME: unskip when this is solved // https://bugs.webkit.org/show_bug.cgi?id=191163 -//@ skip if $architecture == "arm" +//@ skip if $architecture == "arm" or $architecture == "x86" //@ runFTLNoCJIT // If all goes well, this test module will terminate silently. If not, it will print diff --git a/implementation-contributed/javascriptcore/stress/op_bitxor.js b/implementation-contributed/javascriptcore/stress/op_bitxor.js index e05fa5d78a..769c5520ec 100644 --- a/implementation-contributed/javascriptcore/stress/op_bitxor.js +++ b/implementation-contributed/javascriptcore/stress/op_bitxor.js @@ -1,6 +1,6 @@ // FIXME: unskip when this is solved // https://bugs.webkit.org/show_bug.cgi?id=191163 -//@ skip if $architecture == "arm" +//@ skip if $architecture == "arm" or $architecture == "x86" //@ runFTLNoCJIT // If all goes well, this test module will terminate silently. If not, it will print diff --git a/implementation-contributed/javascriptcore/stress/op_div-ConstVar.js b/implementation-contributed/javascriptcore/stress/op_div-ConstVar.js new file mode 100644 index 0000000000..45086543ad --- /dev/null +++ b/implementation-contributed/javascriptcore/stress/op_div-ConstVar.js @@ -0,0 +1,20 @@ +//@ skip if $architecture == "x86" +//@ runFTLNoCJIT("--timeoutMultiplier=2.0") + +// If all goes well, this test module will terminate silently. If not, it will print +// errors. See binary-op-test.js for debugging options if needed. + +load("./resources/binary-op-test.js"); + +//============================================================================ +// Test configuration data: + +var opName = "div"; +var op = "/"; + +load("./resources/binary-op-values.js"); + +tests = []; +generateBinaryTests(tests, opName, op, "ConstVar", values, values); + +run(); diff --git a/implementation-contributed/javascriptcore/stress/op_div-VarConst.js b/implementation-contributed/javascriptcore/stress/op_div-VarConst.js new file mode 100644 index 0000000000..91ff2f14ad --- /dev/null +++ b/implementation-contributed/javascriptcore/stress/op_div-VarConst.js @@ -0,0 +1,20 @@ +//@ skip if $architecture == "x86" +//@ runFTLNoCJIT("--timeoutMultiplier=2.0") + +// If all goes well, this test module will terminate silently. If not, it will print +// errors. See binary-op-test.js for debugging options if needed. + +load("./resources/binary-op-test.js"); + +//============================================================================ +// Test configuration data: + +var opName = "div"; +var op = "/"; + +load("./resources/binary-op-values.js"); + +tests = []; +generateBinaryTests(tests, opName, op, "VarConst", values, values); + +run(); diff --git a/implementation-contributed/javascriptcore/stress/op_div-VarVar.js b/implementation-contributed/javascriptcore/stress/op_div-VarVar.js new file mode 100644 index 0000000000..828a203045 --- /dev/null +++ b/implementation-contributed/javascriptcore/stress/op_div-VarVar.js @@ -0,0 +1,20 @@ +//@ skip if $architecture == "x86" +//@ runFTLNoCJIT("--timeoutMultiplier=2.0") + +// If all goes well, this test module will terminate silently. If not, it will print +// errors. See binary-op-test.js for debugging options if needed. + +load("./resources/binary-op-test.js"); + +//============================================================================ +// Test configuration data: + +var opName = "div"; +var op = "/"; + +load("./resources/binary-op-values.js"); + +tests = []; +generateBinaryTests(tests, opName, op, "VarVar", values, values); + +run(); diff --git a/implementation-contributed/javascriptcore/stress/op_lshift-ConstVar.js b/implementation-contributed/javascriptcore/stress/op_lshift-ConstVar.js index 0feac842b0..79b46c11d4 100644 --- a/implementation-contributed/javascriptcore/stress/op_lshift-ConstVar.js +++ b/implementation-contributed/javascriptcore/stress/op_lshift-ConstVar.js @@ -1,6 +1,6 @@ // FIXME: unskip when this is solved // https://bugs.webkit.org/show_bug.cgi?id=191163 -//@ skip if $architecture == "arm" +//@ skip if $architecture == "arm" or $architecture == "x86" //@ runFTLNoCJIT // If all goes well, this test module will terminate silently. If not, it will print diff --git a/implementation-contributed/javascriptcore/stress/op_lshift-VarConst.js b/implementation-contributed/javascriptcore/stress/op_lshift-VarConst.js index 3345eee26b..da7e06f10e 100644 --- a/implementation-contributed/javascriptcore/stress/op_lshift-VarConst.js +++ b/implementation-contributed/javascriptcore/stress/op_lshift-VarConst.js @@ -1,6 +1,6 @@ // FIXME: unskip when this is solved // https://bugs.webkit.org/show_bug.cgi?id=191163 -//@ skip if $architecture == "arm" +//@ skip if $architecture == "arm" or $architecture == "x86" //@ runFTLNoCJIT // If all goes well, this test module will terminate silently. If not, it will print diff --git a/implementation-contributed/javascriptcore/stress/op_lshift-VarVar.js b/implementation-contributed/javascriptcore/stress/op_lshift-VarVar.js index 5c20cc3b79..26b8688d1a 100644 --- a/implementation-contributed/javascriptcore/stress/op_lshift-VarVar.js +++ b/implementation-contributed/javascriptcore/stress/op_lshift-VarVar.js @@ -1,6 +1,6 @@ // FIXME: unskip when this is solved // https://bugs.webkit.org/show_bug.cgi?id=191163 -//@ skip if $architecture == "arm" +//@ skip if $architecture == "arm" or $architecture == "x86" //@ runFTLNoCJIT // If all goes well, this test module will terminate silently. If not, it will print diff --git a/implementation-contributed/javascriptcore/stress/op_mod-ConstVar.js b/implementation-contributed/javascriptcore/stress/op_mod-ConstVar.js index f7d439f82a..6052bb2a76 100644 --- a/implementation-contributed/javascriptcore/stress/op_mod-ConstVar.js +++ b/implementation-contributed/javascriptcore/stress/op_mod-ConstVar.js @@ -1,6 +1,6 @@ // FIXME: unskip when this is solved // https://bugs.webkit.org/show_bug.cgi?id=191163 -//@ skip if $architecture == "arm" +//@ skip if $architecture == "arm" or $architecture == "x86" //@ runFTLNoCJIT("--timeoutMultiplier=1.5") // If all goes well, this test module will terminate silently. If not, it will print diff --git a/implementation-contributed/javascriptcore/stress/op_mod-VarConst.js b/implementation-contributed/javascriptcore/stress/op_mod-VarConst.js index 97bdcf26fa..3ecc67dc70 100644 --- a/implementation-contributed/javascriptcore/stress/op_mod-VarConst.js +++ b/implementation-contributed/javascriptcore/stress/op_mod-VarConst.js @@ -1,6 +1,6 @@ // FIXME: unskip when this is solved // https://bugs.webkit.org/show_bug.cgi?id=191163 -//@ skip if $architecture == "arm" +//@ skip if $architecture == "arm" or $architecture == "x86" //@ runFTLNoCJIT("--timeoutMultiplier=1.5") // If all goes well, this test module will terminate silently. If not, it will print diff --git a/implementation-contributed/javascriptcore/stress/op_mod-VarVar.js b/implementation-contributed/javascriptcore/stress/op_mod-VarVar.js index 4d321700f8..1f09be897c 100644 --- a/implementation-contributed/javascriptcore/stress/op_mod-VarVar.js +++ b/implementation-contributed/javascriptcore/stress/op_mod-VarVar.js @@ -1,6 +1,6 @@ // FIXME: unskip when this is solved // https://bugs.webkit.org/show_bug.cgi?id=191163 -//@ skip if $architecture == "arm" +//@ skip if $architecture == "arm" or $architecture == "x86" //@ runFTLNoCJIT("--timeoutMultiplier=1.5") // If all goes well, this test module will terminate silently. If not, it will print diff --git a/implementation-contributed/javascriptcore/stress/op_mul-ConstVar.js b/implementation-contributed/javascriptcore/stress/op_mul-ConstVar.js index 934926afb9..f1ca9b55e7 100644 --- a/implementation-contributed/javascriptcore/stress/op_mul-ConstVar.js +++ b/implementation-contributed/javascriptcore/stress/op_mul-ConstVar.js @@ -1,6 +1,6 @@ // FIXME: unskip when this is solved // https://bugs.webkit.org/show_bug.cgi?id=191163 -//@ skip if $architecture == "arm" +//@ skip if $architecture == "arm" or $architecture == "x86" //@ runFTLNoCJIT // If all goes well, this test module will terminate silently. If not, it will print diff --git a/implementation-contributed/javascriptcore/stress/op_mul-VarConst.js b/implementation-contributed/javascriptcore/stress/op_mul-VarConst.js index e7c617bfd1..1de41fed68 100644 --- a/implementation-contributed/javascriptcore/stress/op_mul-VarConst.js +++ b/implementation-contributed/javascriptcore/stress/op_mul-VarConst.js @@ -1,6 +1,6 @@ // FIXME: unskip when this is solved // https://bugs.webkit.org/show_bug.cgi?id=191163 -//@ skip if $architecture == "arm" +//@ skip if $architecture == "arm" or $architecture == "x86" //@ runFTLNoCJIT // If all goes well, this test module will terminate silently. If not, it will print diff --git a/implementation-contributed/javascriptcore/stress/op_mul-VarVar.js b/implementation-contributed/javascriptcore/stress/op_mul-VarVar.js index ec1225bca2..fd9f1d0eeb 100644 --- a/implementation-contributed/javascriptcore/stress/op_mul-VarVar.js +++ b/implementation-contributed/javascriptcore/stress/op_mul-VarVar.js @@ -1,6 +1,6 @@ // FIXME: unskip when this is solved // https://bugs.webkit.org/show_bug.cgi?id=191163 -//@ skip if $architecture == "arm" +//@ skip if $architecture == "arm" or $architecture == "x86" //@ runFTLNoCJIT // If all goes well, this test module will terminate silently. If not, it will print diff --git a/implementation-contributed/javascriptcore/stress/op_rshift-ConstVar.js b/implementation-contributed/javascriptcore/stress/op_rshift-ConstVar.js index b6d65bccd7..721856c242 100644 --- a/implementation-contributed/javascriptcore/stress/op_rshift-ConstVar.js +++ b/implementation-contributed/javascriptcore/stress/op_rshift-ConstVar.js @@ -1,6 +1,6 @@ // FIXME: unskip when this is solved // https://bugs.webkit.org/show_bug.cgi?id=191163 -//@ skip if $architecture == "arm" +//@ skip if $architecture == "arm" or $architecture == "x86" //@ runFTLNoCJIT // If all goes well, this test module will terminate silently. If not, it will print diff --git a/implementation-contributed/javascriptcore/stress/op_rshift-VarConst.js b/implementation-contributed/javascriptcore/stress/op_rshift-VarConst.js index ab46fcdb34..b2bf2da248 100644 --- a/implementation-contributed/javascriptcore/stress/op_rshift-VarConst.js +++ b/implementation-contributed/javascriptcore/stress/op_rshift-VarConst.js @@ -1,6 +1,6 @@ // FIXME: unskip when this is solved // https://bugs.webkit.org/show_bug.cgi?id=191163 -//@ skip if $architecture == "arm" +//@ skip if $architecture == "arm" or $architecture == "x86" //@ runFTLNoCJIT // If all goes well, this test module will terminate silently. If not, it will print diff --git a/implementation-contributed/javascriptcore/stress/op_rshift-VarVar.js b/implementation-contributed/javascriptcore/stress/op_rshift-VarVar.js index 02c5b4112b..a6a1bfc87a 100644 --- a/implementation-contributed/javascriptcore/stress/op_rshift-VarVar.js +++ b/implementation-contributed/javascriptcore/stress/op_rshift-VarVar.js @@ -1,6 +1,6 @@ // FIXME: unskip when this is solved // https://bugs.webkit.org/show_bug.cgi?id=191163 -//@ skip if $architecture == "arm" +//@ skip if $architecture == "arm" or $architecture == "x86" //@ runFTLNoCJIT // If all goes well, this test module will terminate silently. If not, it will print diff --git a/implementation-contributed/javascriptcore/stress/op_sub-ConstVar.js b/implementation-contributed/javascriptcore/stress/op_sub-ConstVar.js index 9e94c2b0ce..f651df2e65 100644 --- a/implementation-contributed/javascriptcore/stress/op_sub-ConstVar.js +++ b/implementation-contributed/javascriptcore/stress/op_sub-ConstVar.js @@ -1,6 +1,6 @@ // FIXME: unskip when this is solved // https://bugs.webkit.org/show_bug.cgi?id=191163 -//@ skip if $architecture == "arm" +//@ skip if $architecture == "arm" or $architecture == "x86" //@ runFTLNoCJIT // If all goes well, this test module will terminate silently. If not, it will print diff --git a/implementation-contributed/javascriptcore/stress/op_sub-VarConst.js b/implementation-contributed/javascriptcore/stress/op_sub-VarConst.js index 5223846d68..f590d0ed8e 100644 --- a/implementation-contributed/javascriptcore/stress/op_sub-VarConst.js +++ b/implementation-contributed/javascriptcore/stress/op_sub-VarConst.js @@ -1,6 +1,6 @@ // FIXME: unskip when this is solved // https://bugs.webkit.org/show_bug.cgi?id=191163 -//@ skip if $architecture == "arm" +//@ skip if $architecture == "arm" or $architecture == "x86" //@ runFTLNoCJIT // If all goes well, this test module will terminate silently. If not, it will print diff --git a/implementation-contributed/javascriptcore/stress/op_sub-VarVar.js b/implementation-contributed/javascriptcore/stress/op_sub-VarVar.js index e8bbc15400..f194861e6b 100644 --- a/implementation-contributed/javascriptcore/stress/op_sub-VarVar.js +++ b/implementation-contributed/javascriptcore/stress/op_sub-VarVar.js @@ -1,6 +1,6 @@ // FIXME: unskip when this is solved // https://bugs.webkit.org/show_bug.cgi?id=191163 -//@ skip if $architecture == "arm" +//@ skip if $architecture == "arm" or $architecture == "x86" //@ runFTLNoCJIT // If all goes well, this test module will terminate silently. If not, it will print diff --git a/implementation-contributed/javascriptcore/stress/op_urshift-ConstVar.js b/implementation-contributed/javascriptcore/stress/op_urshift-ConstVar.js index 82312fe5c8..d427c1f294 100644 --- a/implementation-contributed/javascriptcore/stress/op_urshift-ConstVar.js +++ b/implementation-contributed/javascriptcore/stress/op_urshift-ConstVar.js @@ -1,6 +1,6 @@ // FIXME: unskip when this is solved // https://bugs.webkit.org/show_bug.cgi?id=191163 -//@ skip if $architecture == "arm" +//@ skip if $architecture == "arm" or $architecture == "x86" //@ runFTLNoCJIT // If all goes well, this test module will terminate silently. If not, it will print diff --git a/implementation-contributed/javascriptcore/stress/op_urshift-VarConst.js b/implementation-contributed/javascriptcore/stress/op_urshift-VarConst.js index 491153b43a..1bf063c545 100644 --- a/implementation-contributed/javascriptcore/stress/op_urshift-VarConst.js +++ b/implementation-contributed/javascriptcore/stress/op_urshift-VarConst.js @@ -1,6 +1,6 @@ // FIXME: unskip when this is solved // https://bugs.webkit.org/show_bug.cgi?id=191163 -//@ skip if $architecture == "arm" +//@ skip if $architecture == "arm" or $architecture == "x86" //@ runFTLNoCJIT // If all goes well, this test module will terminate silently. If not, it will print diff --git a/implementation-contributed/javascriptcore/stress/op_urshift-VarVar.js b/implementation-contributed/javascriptcore/stress/op_urshift-VarVar.js index 5b6f5cb739..bc22b997e6 100644 --- a/implementation-contributed/javascriptcore/stress/op_urshift-VarVar.js +++ b/implementation-contributed/javascriptcore/stress/op_urshift-VarVar.js @@ -1,6 +1,6 @@ // FIXME: unskip when this is solved // https://bugs.webkit.org/show_bug.cgi?id=191163 -//@ skip if $architecture == "arm" +//@ skip if $architecture == "arm" or $architecture == "x86" //@ runFTLNoCJIT // If all goes well, this test module will terminate silently. If not, it will print diff --git a/implementation-contributed/javascriptcore/stress/proxy-get-set-correct-receiver.js b/implementation-contributed/javascriptcore/stress/proxy-get-set-correct-receiver.js new file mode 100644 index 0000000000..6708ab185d --- /dev/null +++ b/implementation-contributed/javascriptcore/stress/proxy-get-set-correct-receiver.js @@ -0,0 +1,117 @@ +"use strict"; + +function assert(b) { + if (!b) + throw new Error("Bad") +} + +function test(f, count = 1000) { + noInline(f); + for (let i = 0; i < count; ++i) + f(); +} + +test(function() { + let called = false; + let target = { + set prop(x) + { + assert(x === 20); + called = true; + assert(this === proxy) + } + } + + let proxy = new Proxy(target, {}) + proxy.prop = 20; + assert(called); +}); + +test(function() { + let called = false; + let target = { + get prop() + { + called = true; + assert(this === proxy) + } + } + + let proxy = new Proxy(target, {}) + proxy.prop + assert(called); +}); + +test(function() { + let target = { + get prop() + { + called = true; + assert(this === proxy) + } + } + let p1 = new Proxy(target, {}); + + let called = false; + let proxy = new Proxy(p1, {}); + proxy.prop + assert(called); +}); + +test(function() { + let t = {}; + let p1 = new Proxy(t, { + get(target, prop, receiver) { + called = true; + assert(target === t); + assert(receiver === proxy); + assert(prop === "prop"); + } + }); + + let called = false; + let proxy = new Proxy(p1, {}); + proxy.prop + assert(called); +}); + +test(function() { + let t = {}; + let callCount = 0; + let handler = { + get(target, prop, receiver) { + if (callCount === 100) + assert(target === t); + ++callCount; + assert(receiver === proxy); + assert(prop === "prop"); + return Reflect.get(target, prop, receiver); + } + }; + let proxy = new Proxy(t, handler); + for (let i = 0; i < 100; ++i) + proxy = new Proxy(proxy, handler); + proxy.prop + assert(callCount === 101); +}, 10); + +test(function() { + let t = {}; + let callCount = 0; + let handler = { + set(target, prop, value, receiver) { + if (callCount === 100) + assert(target === t); + ++callCount; + assert(receiver === proxy); + assert(prop === "prop"); + assert(value === 20); + return Reflect.set(target, prop, value, receiver); + } + }; + let proxy = new Proxy(t, handler); + for (let i = 0; i < 100; ++i) + proxy = new Proxy(proxy, handler); + proxy.prop = 20; + assert(callCount === 101); +}, 10); diff --git a/implementation-contributed/javascriptcore/stress/regexp-compile-oom.js b/implementation-contributed/javascriptcore/stress/regexp-compile-oom.js index 45c63d9e77..b1c62e9065 100644 --- a/implementation-contributed/javascriptcore/stress/regexp-compile-oom.js +++ b/implementation-contributed/javascriptcore/stress/regexp-compile-oom.js @@ -1,18 +1,38 @@ //@ skip if $hostOS != "darwin" // Test that throw an OOM exception when compiling a pathological, but valid nested RegExp. -function recurseAndTest(depth, f, expectedException) +var failures = []; + +class TestAndExpectedException +{ + constructor(func, exception) + { + this.func = func; + this.exception = exception; + } + + runTest() + { + try { + this.func(); + failures.push("Running " + this.func + ", expected OOM exception, but didn't get one"); + } catch (e) { + let errStr = e.toString(); + if (errStr != this.exception) + failures.push("Running " + this.func + ", expected: \"" + this.exception + "\" but got \"" + errStr + "\""); + } + } +} + +function recurseAndTest(depth, testList) { // Probe stack depth try { - let result = recurseAndTest(depth + 1, f, expectedException); + let result = recurseAndTest(depth + 1, testList); if (result == 0) { - try { - // Call the test function with a nearly full stack. - f(); - } catch (e) { - return e.toString(); - } + // Call the test functions with a nearly full stack. + for (const test of testList) + test.runTest(); return 1; } else if (result < 0) @@ -20,26 +40,40 @@ function recurseAndTest(depth, f, expectedException) else return result; } catch (e) { - // Go up a several frames and then call the test function - return -10; + // Go up a several frames and then call the test functions + return -24; } return 1; } -let deepRE = /((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((x))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))/; -let matchLen = 381; // The number of parens plus 1 for the whole match. +let deepRE = new RegExp("((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((x))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))"); +let deepGlobalRE = new RegExp(deepRE, "g"); + +let matchLen = 401; // The number of parens plus 1 for the whole match. let regExpOOMError = "Error: Out of memory: Invalid regular expression: too many nested disjunctions"; -// Test that both exec (captured compilation) and test (match only compilation) handles OOM. -let result = recurseAndTest(1, () => { deepRE.exec(); }); -if (result != regExpOOMError) - throw "Expected: \"" + regExpOOMError + "\" but got \"" + result + "\""; +testList = []; -result = recurseAndTest(1, () => { deepRE.test(); }); -if (result != regExpOOMError) - throw "Expected: \"" + regExpOOMError + "\" but got \"" + result + "\""; +// Test that all RegExp related APIs that compile RE's properly handle OOM. +testList.push(new TestAndExpectedException(() => { deepRE.exec("x"); }, regExpOOMError)); +testList.push(new TestAndExpectedException(() => { deepRE.test("x"); }, regExpOOMError)); +testList.push(new TestAndExpectedException(() => { "x".match(deepRE); }, regExpOOMError)); +testList.push(new TestAndExpectedException(() => { "x".match(deepGlobalRE); }, regExpOOMError)); +testList.push(new TestAndExpectedException(() => { "x".replace(deepGlobalRE, ""); }, regExpOOMError)); +testList.push(new TestAndExpectedException(() => { "x".replace(deepGlobalRE, "X"); }, regExpOOMError)); +testList.push(new TestAndExpectedException(() => { "x".replace(deepGlobalRE, () => { return "X" }); }, regExpOOMError)); +testList.push(new TestAndExpectedException(() => { "x".search(deepRE); }, regExpOOMError)); + +recurseAndTest(1, testList); + +if (failures.length) { + print("Got the following failures:"); + for (const failure of failures) + print(failure); + throw "Got failures"; +} // Test that the RegExp works correctly with RegExp.exec() and RegExp.test() when there is sufficient stack space to compile it. let m = deepRE.exec("x"); diff --git a/implementation-contributed/javascriptcore/stress/regress-179562.js b/implementation-contributed/javascriptcore/stress/regress-179562.js new file mode 100644 index 0000000000..488bf9b3ae --- /dev/null +++ b/implementation-contributed/javascriptcore/stress/regress-179562.js @@ -0,0 +1,33 @@ +//@ runFTLNoCJIT("--maxPerThreadStackUsage=400000") if $jitTests + +function runNearStackLimit(f) { + function t() { + try { + return t(); + } catch (e) { + return f(); + } + } + return t() +} + +function foo(a, b) { + return [{ + name: b + "" + a + }]; +} + +var exception; +try { + __v_25012 = [].concat( + foo(1, []), + runNearStackLimit(() => { + return foo("bla", Symbol.search); + }) + ); +} catch (e) { + exception = e; +} + +if (exception != "TypeError: Cannot convert a symbol to a string") + throw "FAILED"; diff --git a/implementation-contributed/javascriptcore/stress/rest-parameter-many-arguments.js b/implementation-contributed/javascriptcore/stress/rest-parameter-many-arguments.js new file mode 100644 index 0000000000..16a1f28831 --- /dev/null +++ b/implementation-contributed/javascriptcore/stress/rest-parameter-many-arguments.js @@ -0,0 +1,52 @@ +//@ skip if $architecture == "x86" +//@ if $architecture == "x86" then defaultSpotCheckNoMaximalFlush else defaultRun end + +function assert(b) { + if (!b) + throw new Error("Bad!") +} +noInline(assert); + +let calledGet = false; +let definedAccessor = false; +function test() { + function foo(...rest) { + return rest; + } + noInline(foo); + + for (let i = 0; i < 10000; i++) { + const size = 800; + let arr = new Array(size); + for (let i = 0; i < size; i++) + arr[i] = i; + let result = foo(...arr); + + assert(result.length === arr.length); + assert(result.length === size); + for (let i = 0; i < arr.length; i++) { + assert(arr[i] === result[i]); + assert(result[i] === i); + } + if (definedAccessor) { + calledGet = false; + result[0]; + assert(!calledGet); + arr[0]; + assert(calledGet); + + let testArr = [...arr]; + calledGet = false; + testArr[0]; + assert(!calledGet); + } + } +} +test(); + +definedAccessor = true; +Reflect.defineProperty(Array.prototype, "0", { + get() { calledGet = true; return 0; }, + set(x) { } +}); +test(); diff --git a/implementation-contributed/javascriptcore/stress/sampling-profiler-richards.js b/implementation-contributed/javascriptcore/stress/sampling-profiler-richards.js index 40af90290a..475063b37b 100644 --- a/implementation-contributed/javascriptcore/stress/sampling-profiler-richards.js +++ b/implementation-contributed/javascriptcore/stress/sampling-profiler-richards.js @@ -1,6 +1,7 @@ // [JSC] [Armv7] stress/sampling-profiler-richards.js crashes // https://bugs.webkit.org/show_bug.cgi?id=190426 //@ skip if $architecture == "arm" and $hostOS == "linux" +//@ skip if $architecture == "x86" //@ runDefault("--collectContinuously=1", "--useSamplingProfiler=1", "--collectSamplingProfilerDataForJSCShell=1") "use strict"; diff --git a/implementation-contributed/javascriptcore/stress/splay-flash-access-1ms.js b/implementation-contributed/javascriptcore/stress/splay-flash-access-1ms.js new file mode 100644 index 0000000000..aa676ee7c0 --- /dev/null +++ b/implementation-contributed/javascriptcore/stress/splay-flash-access-1ms.js @@ -0,0 +1,904 @@ +//@ skip if $memoryLimited +//@ skip if $architecture == "x86" +//@ runNoisyTestDefault +//@ runNoisyTestNoCJIT + +// Copyright 2013 the V8 project authors. All rights reserved. +// Copyright (C) 2015 Apple Inc. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +// Performance.now is used in latency benchmarks, the fallback is Date.now. +var performance = performance || {}; +performance.now = (function() { + return performance.now || + performance.mozNow || + performance.msNow || + performance.oNow || + performance.webkitNow || + Date.now; +})(); + +// Simple framework for running the benchmark suites and +// computing a score based on the timing measurements. + + +// A benchmark has a name (string) and a function that will be run to +// do the performance measurement. The optional setup and tearDown +// arguments are functions that will be invoked before and after +// running the benchmark, but the running time of these functions will +// not be accounted for in the benchmark score. +function Benchmark(name, doWarmup, doDeterministic, run, setup, tearDown, latencyResult, minIterations) { + this.name = name; + this.doWarmup = doWarmup; + this.doDeterministic = doDeterministic; + this.run = run; + this.Setup = setup ? setup : function() { }; + this.TearDown = tearDown ? tearDown : function() { }; + this.latencyResult = latencyResult ? latencyResult : null; + this.minIterations = minIterations ? minIterations : 32; +} + + +// Benchmark results hold the benchmark and the measured time used to +// run the benchmark. The benchmark score is computed later once a +// full benchmark suite has run to completion. If latency is set to 0 +// then there is no latency score for this benchmark. +function BenchmarkResult(benchmark, time, latency) { + this.benchmark = benchmark; + this.time = time; + this.latency = latency; +} + + +// Automatically convert results to numbers. Used by the geometric +// mean computation. +BenchmarkResult.prototype.valueOf = function() { + return this.time; +} + + +// Suites of benchmarks consist of a name and the set of benchmarks in +// addition to the reference timing that the final score will be based +// on. This way, all scores are relative to a reference run and higher +// scores implies better performance. +function BenchmarkSuite(name, reference, benchmarks) { + this.name = name; + this.reference = reference; + this.benchmarks = benchmarks; + BenchmarkSuite.suites.push(this); +} + + +// Keep track of all declared benchmark suites. +BenchmarkSuite.suites = []; + +// Scores are not comparable across versions. Bump the version if +// you're making changes that will affect that scores, e.g. if you add +// a new benchmark or change an existing one. +BenchmarkSuite.version = '9'; + +// Override the alert function to throw an exception instead. +alert = function(s) { + throw "Alert called with argument: " + s; +}; + + +// To make the benchmark results predictable, we replace Math.random +// with a 100% deterministic alternative. +BenchmarkSuite.ResetRNG = function() { + Math.random = (function() { + var seed = 49734321; + return function() { + // Robert Jenkins' 32 bit integer hash function. + seed = ((seed + 0x7ed55d16) + (seed << 12)) & 0xffffffff; + seed = ((seed ^ 0xc761c23c) ^ (seed >>> 19)) & 0xffffffff; + seed = ((seed + 0x165667b1) + (seed << 5)) & 0xffffffff; + seed = ((seed + 0xd3a2646c) ^ (seed << 9)) & 0xffffffff; + seed = ((seed + 0xfd7046c5) + (seed << 3)) & 0xffffffff; + seed = ((seed ^ 0xb55a4f09) ^ (seed >>> 16)) & 0xffffffff; + return (seed & 0xfffffff) / 0x10000000; + }; + })(); +} + + +// Runs all registered benchmark suites and optionally yields between +// each individual benchmark to avoid running for too long in the +// context of browsers. Once done, the final score is reported to the +// runner. +BenchmarkSuite.RunSuites = function(runner) { + var continuation = null; + var suites = BenchmarkSuite.suites; + var length = suites.length; + BenchmarkSuite.scores = []; + var index = 0; + function RunStep() { + while (continuation || index < length) { + if (continuation) { + continuation = continuation(); + } else { + var suite = suites[index++]; + if (runner.NotifyStart) runner.NotifyStart(suite.name); + continuation = suite.RunStep(runner); + } + if (continuation && typeof window != 'undefined' && window.setTimeout) { + window.setTimeout(RunStep, 25); + return; + } + } + + // show final result + if (runner.NotifyScore) { + var score = BenchmarkSuite.GeometricMean(BenchmarkSuite.scores); + var formatted = BenchmarkSuite.FormatScore(100 * score); + runner.NotifyScore(formatted); + } + } + RunStep(); +} + + +// Counts the total number of registered benchmarks. Useful for +// showing progress as a percentage. +BenchmarkSuite.CountBenchmarks = function() { + var result = 0; + var suites = BenchmarkSuite.suites; + for (var i = 0; i < suites.length; i++) { + result += suites[i].benchmarks.length; + } + return result; +} + + +// Computes the geometric mean of a set of numbers. +BenchmarkSuite.GeometricMean = function(numbers) { + var log = 0; + for (var i = 0; i < numbers.length; i++) { + log += Math.log(numbers[i]); + } + return Math.pow(Math.E, log / numbers.length); +} + + +// Computes the geometric mean of a set of throughput time measurements. +BenchmarkSuite.GeometricMeanTime = function(measurements) { + var log = 0; + for (var i = 0; i < measurements.length; i++) { + log += Math.log(measurements[i].time); + } + return Math.pow(Math.E, log / measurements.length); +} + + +// Computes the average of the worst samples. For example, if percentile is 99, this will report the +// average of the worst 1% of the samples. +BenchmarkSuite.AverageAbovePercentile = function(numbers, percentile) { + // Don't change the original array. + numbers = numbers.slice(); + + // Sort in ascending order. + numbers.sort(function(a, b) { return a - b; }); + + // Now the elements we want are at the end. Keep removing them until the array size shrinks too much. + // Examples assuming percentile = 99: + // + // - numbers.length starts at 100: we will remove just the worst entry and then not remove anymore, + // since then numbers.length / originalLength = 0.99. + // + // - numbers.length starts at 1000: we will remove the ten worst. + // + // - numbers.length starts at 10: we will remove just the worst. + var numbersWeWant = []; + var originalLength = numbers.length; + while (numbers.length / originalLength > percentile / 100) + numbersWeWant.push(numbers.pop()); + + var sum = 0; + for (var i = 0; i < numbersWeWant.length; ++i) + sum += numbersWeWant[i]; + + var result = sum / numbersWeWant.length; + + // Do a sanity check. + if (numbers.length && result < numbers[numbers.length - 1]) { + throw "Sanity check fail: the worst case result is " + result + + " but we didn't take into account " + numbers; + } + + return result; +} + + +// Computes the geometric mean of a set of latency measurements. +BenchmarkSuite.GeometricMeanLatency = function(measurements) { + var log = 0; + var hasLatencyResult = false; + for (var i = 0; i < measurements.length; i++) { + if (measurements[i].latency != 0) { + log += Math.log(measurements[i].latency); + hasLatencyResult = true; + } + } + if (hasLatencyResult) { + return Math.pow(Math.E, log / measurements.length); + } else { + return 0; + } +} + + +// Converts a score value to a string with at least three significant +// digits. +BenchmarkSuite.FormatScore = function(value) { + if (value > 100) { + return value.toFixed(0); + } else { + return value.toPrecision(3); + } +} + +// Notifies the runner that we're done running a single benchmark in +// the benchmark suite. This can be useful to report progress. +BenchmarkSuite.prototype.NotifyStep = function(result) { + this.results.push(result); + if (this.runner.NotifyStep) this.runner.NotifyStep(result.benchmark.name); +} + + +// Notifies the runner that we're done with running a suite and that +// we have a result which can be reported to the user if needed. +BenchmarkSuite.prototype.NotifyResult = function() { + var mean = BenchmarkSuite.GeometricMeanTime(this.results); + var score = this.reference[0] / mean; + BenchmarkSuite.scores.push(score); + if (this.runner.NotifyResult) { + var formatted = BenchmarkSuite.FormatScore(100 * score); + this.runner.NotifyResult(this.name, formatted); + } + if (this.reference.length == 2) { + var meanLatency = BenchmarkSuite.GeometricMeanLatency(this.results); + if (meanLatency != 0) { + var scoreLatency = this.reference[1] / meanLatency; + BenchmarkSuite.scores.push(scoreLatency); + if (this.runner.NotifyResult) { + var formattedLatency = BenchmarkSuite.FormatScore(100 * scoreLatency) + this.runner.NotifyResult(this.name + "Latency", formattedLatency); + } + } + } +} + + +// Notifies the runner that running a benchmark resulted in an error. +BenchmarkSuite.prototype.NotifyError = function(error) { + if (this.runner.NotifyError) { + this.runner.NotifyError(this.name, error); + } + if (this.runner.NotifyStep) { + this.runner.NotifyStep(this.name); + } +} + + +// Runs a single benchmark for at least a second and computes the +// average time it takes to run a single iteration. +BenchmarkSuite.prototype.RunSingleBenchmark = function(benchmark, data) { + function Measure(data) { + var elapsed = 0; + var start = new Date(); + + // Run either for 1 second or for the number of iterations specified + // by minIterations, depending on the config flag doDeterministic. + for (var i = 0; (benchmark.doDeterministic ? + i= keys[i + 1]) { + throw new Error("Splay tree not sorted"); + } + } +} + + +function SplayRun() { + // Replace a few nodes in the splay tree. + for (var i = 0; i < kSplayTreeModifications; i++) { + var key = InsertNewNode(); + var greatest = splayTree.findGreatestLessThan(key); + if (greatest == null) splayTree.remove(key); + else splayTree.remove(greatest.key); + } + SplayUpdateStats(performance.now()); +} + + +/** + * Constructs a Splay tree. A splay tree is a self-balancing binary + * search tree with the additional property that recently accessed + * elements are quick to access again. It performs basic operations + * such as insertion, look-up and removal in O(log(n)) amortized time. + * + * @constructor + */ +function SplayTree() { +}; + + +/** + * Pointer to the root node of the tree. + * + * @type {SplayTree.Node} + * @private + */ +SplayTree.prototype.root_ = null; + + +/** + * @return {boolean} Whether the tree is empty. + */ +SplayTree.prototype.isEmpty = function() { + return !this.root_; +}; + + +/** + * Inserts a node into the tree with the specified key and value if + * the tree does not already contain a node with the specified key. If + * the value is inserted, it becomes the root of the tree. + * + * @param {number} key Key to insert into the tree. + * @param {*} value Value to insert into the tree. + */ +SplayTree.prototype.insert = function(key, value) { + if (this.isEmpty()) { + this.root_ = new SplayTree.Node(key, value); + return; + } + // Splay on the key to move the last node on the search path for + // the key to the root of the tree. + this.splay_(key); + if (this.root_.key == key) { + return; + } + var node = new SplayTree.Node(key, value); + if (key > this.root_.key) { + node.left = this.root_; + node.right = this.root_.right; + this.root_.right = null; + } else { + node.right = this.root_; + node.left = this.root_.left; + this.root_.left = null; + } + this.root_ = node; +}; + + +/** + * Removes a node with the specified key from the tree if the tree + * contains a node with this key. The removed node is returned. If the + * key is not found, an exception is thrown. + * + * @param {number} key Key to find and remove from the tree. + * @return {SplayTree.Node} The removed node. + */ +SplayTree.prototype.remove = function(key) { + if (this.isEmpty()) { + throw Error('Key not found: ' + key); + } + this.splay_(key); + if (this.root_.key != key) { + throw Error('Key not found: ' + key); + } + var removed = this.root_; + if (!this.root_.left) { + this.root_ = this.root_.right; + } else { + var right = this.root_.right; + this.root_ = this.root_.left; + // Splay to make sure that the new root has an empty right child. + this.splay_(key); + // Insert the original right child as the right child of the new + // root. + this.root_.right = right; + } + return removed; +}; + + +/** + * Returns the node having the specified key or null if the tree doesn't contain + * a node with the specified key. + * + * @param {number} key Key to find in the tree. + * @return {SplayTree.Node} Node having the specified key. + */ +SplayTree.prototype.find = function(key) { + if (this.isEmpty()) { + return null; + } + this.splay_(key); + return this.root_.key == key ? this.root_ : null; +}; + + +/** + * @return {SplayTree.Node} Node having the maximum key value. + */ +SplayTree.prototype.findMax = function(opt_startNode) { + if (this.isEmpty()) { + return null; + } + var current = opt_startNode || this.root_; + while (current.right) { + current = current.right; + } + return current; +}; + + +/** + * @return {SplayTree.Node} Node having the maximum key value that + * is less than the specified key value. + */ +SplayTree.prototype.findGreatestLessThan = function(key) { + if (this.isEmpty()) { + return null; + } + // Splay on the key to move the node with the given key or the last + // node on the search path to the top of the tree. + this.splay_(key); + // Now the result is either the root node or the greatest node in + // the left subtree. + if (this.root_.key < key) { + return this.root_; + } else if (this.root_.left) { + return this.findMax(this.root_.left); + } else { + return null; + } +}; + + +/** + * @return {Array<*>} An array containing all the keys of tree's nodes. + */ +SplayTree.prototype.exportKeys = function() { + var result = []; + if (!this.isEmpty()) { + this.root_.traverse_(function(node) { result.push(node.key); }); + } + return result; +}; + + +/** + * Perform the splay operation for the given key. Moves the node with + * the given key to the top of the tree. If no node has the given + * key, the last node on the search path is moved to the top of the + * tree. This is the simplified top-down splaying algorithm from: + * "Self-adjusting Binary Search Trees" by Sleator and Tarjan + * + * @param {number} key Key to splay the tree on. + * @private + */ +SplayTree.prototype.splay_ = function(key) { + if (this.isEmpty()) { + return; + } + // Create a dummy node. The use of the dummy node is a bit + // counter-intuitive: The right child of the dummy node will hold + // the L tree of the algorithm. The left child of the dummy node + // will hold the R tree of the algorithm. Using a dummy node, left + // and right will always be nodes and we avoid special cases. + var dummy, left, right; + dummy = left = right = new SplayTree.Node(null, null); + var current = this.root_; + while (true) { + if (key < current.key) { + if (!current.left) { + break; + } + if (key < current.left.key) { + // Rotate right. + var tmp = current.left; + current.left = tmp.right; + tmp.right = current; + current = tmp; + if (!current.left) { + break; + } + } + // Link right. + right.left = current; + right = current; + current = current.left; + } else if (key > current.key) { + if (!current.right) { + break; + } + if (key > current.right.key) { + // Rotate left. + var tmp = current.right; + current.right = tmp.left; + tmp.left = current; + current = tmp; + if (!current.right) { + break; + } + } + // Link left. + left.right = current; + left = current; + current = current.right; + } else { + break; + } + } + // Assemble. + left.right = current.left; + right.left = current.right; + current.left = dummy.right; + current.right = dummy.left; + this.root_ = current; +}; + + +/** + * Constructs a Splay tree node. + * + * @param {number} key Key. + * @param {*} value Value. + */ +SplayTree.Node = function(key, value) { + this.key = key; + this.value = value; +}; + + +/** + * @type {SplayTree.Node} + */ +SplayTree.Node.prototype.left = null; + + +/** + * @type {SplayTree.Node} + */ +SplayTree.Node.prototype.right = null; + + +/** + * Performs an ordered traversal of the subtree starting at + * this SplayTree.Node. + * + * @param {function(SplayTree.Node)} f Visitor function. + * @private + */ +SplayTree.Node.prototype.traverse_ = function(f) { + var current = this; + while (current) { + var left = current.left; + if (left) left.traverse_(f); + f(current); + current = current.right; + } +}; +function jscSetUp() { + SplaySetup(); +} + +function jscTearDown() { + SplayTearDown(); +} + +function jscRun() { + SplayRun(); +} + +jscSetUp(); +var __before = preciseTime(); +var times = []; +for (var i = 0; i < 2000; ++i) { + var _before = preciseTime(); + jscRun(); + var _after = preciseTime(); + times.push(_after - _before); + flashHeapAccess(1); +} +var __after = preciseTime(); +jscTearDown(); + +function averageAbovePercentile(numbers, percentile) { + // Don't change the original array. + numbers = numbers.slice(); + + // Sort in ascending order. + numbers.sort(function(a, b) { return a - b; }); + + // Now the elements we want are at the end. Keep removing them until the array size shrinks too much. + // Examples assuming percentile = 99: + // + // - numbers.length starts at 100: we will remove just the worst entry and then not remove anymore, + // since then numbers.length / originalLength = 0.99. + // + // - numbers.length starts at 1000: we will remove the ten worst. + // + // - numbers.length starts at 10: we will remove just the worst. + var numbersWeWant = []; + var originalLength = numbers.length; + while (numbers.length / originalLength > percentile / 100) + numbersWeWant.push(numbers.pop()); + + var sum = 0; + for (var i = 0; i < numbersWeWant.length; ++i) + sum += numbersWeWant[i]; + + var result = sum / numbersWeWant.length; + + // Do a sanity check. + if (numbers.length && result < numbers[numbers.length - 1]) { + throw "Sanity check fail: the worst case result is " + result + + " but we didn't take into account " + numbers; + } + + return result; +} + +print("That took " + (__after - __before) * 1000 + " ms."); + +function printPercentile(percentile) +{ + print("Above " + percentile + "%: " + averageAbovePercentile(times, percentile) * 1000 + " ms."); +} + +printPercentile(99.9); +printPercentile(99.5); +printPercentile(99); +printPercentile(97.5); +printPercentile(95); +printPercentile(90); +printPercentile(75); +printPercentile(50); +printPercentile(0); + +gc(); diff --git a/implementation-contributed/javascriptcore/stress/tailCallForwardArguments.js b/implementation-contributed/javascriptcore/stress/tailCallForwardArguments.js new file mode 100644 index 0000000000..69725525d6 --- /dev/null +++ b/implementation-contributed/javascriptcore/stress/tailCallForwardArguments.js @@ -0,0 +1,165 @@ +//@ skip if $architecture == "x86" + +var createBuiltin = $vm.createBuiltin; + +// This is pretty bad but I need a private name. +var putFuncToPrivateName = createBuiltin(`(function (func) { @arrayIteratorIsDone = func })`) +putFuncToPrivateName(function (a,b) { return b; }) + +function createTailCallForwardingFuncWith(body, thisValue) { + return createBuiltin(`(function (a) { + "use strict"; + + ${body} + + return @tailCallForwardArguments(@arrayIteratorIsDone, ${thisValue}); + })`); +} + +var foo = createTailCallForwardingFuncWith("", "@undefined"); + +function baz() { + return foo.call(true, 7); +} +noInline(baz); + + + +var fooNoInline = createTailCallForwardingFuncWith("", "@undefined"); +noInline(foo); + +for (let i = 0; i < 100000; i++) { + if (baz.call() !== undefined) + throw new Error(i); + if (fooNoInline.call(undefined, 3) !== undefined) + throw new Error(i); +} + +putFuncToPrivateName(function () { "use strict"; return { thisValue: this, argumentsValue: arguments}; }); +var foo2 = createTailCallForwardingFuncWith("", "this"); +var fooNI2 = createTailCallForwardingFuncWith("", "this"); +noInline(fooNI2); + +function baz2() { + return foo2.call(true, 7); +} +noInline(baz2); + +for (let i = 0; i < 100000; i++) { + let result = foo2.call(true, 7); + if (result.thisValue !== true || result.argumentsValue.length !== 1 || result.argumentsValue[0] !== 7) + throw new Error(i); + result = baz2.call(); + if (result.thisValue !== true || result.argumentsValue.length !== 1 || result.argumentsValue[0] !== 7) + throw new Error(i); + result = fooNI2.call(true, 7); + if (result.thisValue !== true || result.argumentsValue.length !== 1 || result.argumentsValue[0] !== 7) + throw new Error(i); +} + +putFuncToPrivateName(function () { "use strict"; return this; }); +var foo3 = createTailCallForwardingFuncWith("", "{ thisValue: this, otherValue: 'hello'} "); +var fooNI3 = createTailCallForwardingFuncWith("", "{ thisValue: this, otherValue: 'hello'} "); +noInline(fooNI3); +function baz3() { + return foo3.call(true, 7); +} +noInline(baz3); + +for (let i = 0; i < 100000; i++) { + let result = foo3.call(true, 7); + if (result.thisValue !== true) + throw new Error(i); + result = baz3.call(); + if (result.thisValue !== true) + throw new Error(i); + result = fooNI3.call(true, 7); + if (result.thisValue !== true) + throw new Error(i); +} + + +putFuncToPrivateName(function () { "use strict"; return this; }); +let bodyText = ` +for (let i = 0; i < 100; i++) { + if (a + i === 100) + return a; +} +`; +var foo4 = createTailCallForwardingFuncWith(bodyText, "{ thisValue: this, otherValue: 'hello'} "); +var fooNI4 = createTailCallForwardingFuncWith(bodyText, "{ thisValue: this, otherValue: 'hello'} "); +noInline(fooNI4); +function baz4() { + return foo4.call(true, 0); +} +noInline(baz4); + +for (let i = 0; i < 100000; i++) { + let result = foo4.call(true, 0); + if (result.thisValue !== true || result.otherValue !== "hello") + throw new Error(i); + result = baz4.call(); + if (result.thisValue !== true || result.otherValue !== "hello") + throw new Error(i); + result = fooNI4.call(true, 0); + if (result.thisValue !== true || result.otherValue !== "hello") + throw new Error(i); + result = fooNI4.call(true, 1); + if (result !== 1) + throw new Error(i); + result = fooNI4.call(true, ""); + if (result.thisValue !== true || result.otherValue !== "hello") + throw new Error(i); +} + +var testFunc = function () { "use strict"; return this; } +noInline(testFunc); +putFuncToPrivateName(testFunc); + +var foo5 = createTailCallForwardingFuncWith(bodyText, "{ thisValue: this, otherValue: 'hello'} "); +var fooNI5 = createTailCallForwardingFuncWith(bodyText, "{ thisValue: this, otherValue: 'hello'} "); +noInline(fooNI5); +function baz5() { + return foo5.call(true, 0); +} +noInline(baz5); + +for (let i = 0; i < 100000; i++) { + let result = foo5.call(true, 0); + if (result.thisValue !== true || result.otherValue !== "hello") + throw new Error(i); + result = baz5.call(); + if (result.thisValue !== true || result.otherValue !== "hello") + throw new Error(i); + result = fooNI5.call(true, 0); + if (result.thisValue !== true || result.otherValue !== "hello") + throw new Error(i); + result = fooNI5.call(true, 1); + if (result !== 1) + throw new Error(i); + result = fooNI5.call(true, ""); + if (result.thisValue !== true || result.otherValue !== "hello") + throw new Error(i); +} + +putFuncToPrivateName(function() { return arguments; }); +var foo6 = createTailCallForwardingFuncWith(bodyText, "{ thisValue: this, otherValue: 'hello'} "); +function baz6() { + "use strict" + return foo6.apply(this, arguments); +} +noInline(baz6); + +function arrayEq(a, b) { + if (a.length !== b.length) + throw new Error(); + for (let i = 0; i < a.length; i++) { + if (a[i] !== b[i]) + throw new Error(); + } +} +let args = ["a", {}, [], Symbol(), 1, 1.234, undefined, null]; +for (let i = 0; i < 100000; i++) { + let result = baz6.apply(undefined, args); + arrayEq(result, args); +} diff --git a/implementation-contributed/javascriptcore/stress/typed-array-get-by-val-profiling.js b/implementation-contributed/javascriptcore/stress/typed-array-get-by-val-profiling.js new file mode 100644 index 0000000000..fe9ad101d2 --- /dev/null +++ b/implementation-contributed/javascriptcore/stress/typed-array-get-by-val-profiling.js @@ -0,0 +1,93 @@ +//@ slow! + +function testArray(arrayType) +{ + var testCode = + ` + // We make this look like a polymorphic types for incomingObject but the GetByVal are never actually + // polymorphic. The boolean isTypedArray let us differentiate the types. + function ${ arrayType }AndObjectSpeculationInBounds(incomingObject, iterationLength, isTypedArray) { + var output = 0; + output += incomingObject.length; + + if (isTypedArray) { + for (var i = 0; i < iterationLength; ++i) { + output += incomingObject[i]; + } + } else { + for (var i = 0; i < iterationLength; ++i) { + output += incomingObject[i]; + } + } + return output; + } + noInline(${ arrayType }AndObjectSpeculationInBounds); + + var typedArray = new ${ arrayType }(64); + var regularArray = new Array(64); + for (var i = 0; i < 64; ++i) { + typedArray[i] = i; + regularArray[i] = i; + } + + // Access in bounds. + for (var i = 0; i < 1e4; ++i) { + var output = ${ arrayType }AndObjectSpeculationInBounds(typedArray, 64, true); + if (output !== 32 * 65) + throw "${ arrayType }AndObjectSpeculationInBounds(typedArray, 64, true) failed, value = " + output; + + var output = ${ arrayType }AndObjectSpeculationInBounds(regularArray, 64, false); + if (output !== 32 * 65) + throw "${ arrayType }AndObjectSpeculationInBounds(regularArray, 64, false) failed, value = " + output; + } + + // One out of bounds on top of the in bounds profile. + { + var output = ${ arrayType }AndObjectSpeculationInBounds(typedArray, 128, true); + if (output === output) + throw "${ arrayType }AndObjectSpeculationInBounds(typedArray, 128, true) failed, value = " + output; + + var output = ${ arrayType }AndObjectSpeculationInBounds(regularArray, 128, false); + if (output === output) + throw "${ arrayType }AndObjectSpeculationInBounds(regularArray, 128, false) failed, value = " + output; + } + + // Same but here we make out-of-bounds a normal case. + function ${ arrayType }AndObjectSpeculationOutOfBounds(incomingObject, iterationLength, isTypedArray) { + var output = 0; + output += incomingObject.length; + + if (isTypedArray) { + for (var i = 0; i < iterationLength; ++i) { + output += incomingObject[i]|0; + } + } else { + for (var i = 0; i < iterationLength; ++i) { + output += incomingObject[i]|0; + } + } + return output; + } + noInline(${ arrayType }AndObjectSpeculationOutOfBounds); + + for (var i = 0; i < 1e4; ++i) { + var output = ${ arrayType }AndObjectSpeculationOutOfBounds(typedArray, 128, true); + if (output !== 32 * 65) + throw "${ arrayType }AndObjectSpeculationOutOfBounds(typedArray, 128, true) failed, value = " + output; + + var output = ${ arrayType }AndObjectSpeculationOutOfBounds(regularArray, 128, false); + if (output !== 32 * 65) + throw "${ arrayType }AndObjectSpeculationOutOfBounds(regularArray, 128, false) failed, value = " + output; + }` + eval(testCode); +} + +testArray("Int8Array"); +testArray("Uint8Array"); +testArray("Uint8ClampedArray"); +testArray("Int16Array"); +testArray("Uint16Array"); +testArray("Int32Array"); +testArray("Uint32Array"); +testArray("Float32Array"); +testArray("Float64Array");