aboutsummaryrefslogtreecommitdiff
path: root/deps/v8/test/mjsunit/optimized-array-some.js
diff options
context:
space:
mode:
authorMichaël Zasso <targos@protonmail.com>2018-03-07 08:54:53 +0100
committerMichaël Zasso <targos@protonmail.com>2018-03-07 16:48:52 +0100
commit88786fecff336342a56e6f2e7ff3b286be716e47 (patch)
tree92e6ba5b8ac8dae1a058988d20c9d27bfa654390 /deps/v8/test/mjsunit/optimized-array-some.js
parent4e86f9b5ab83cbabf43839385bf383e6a7ef7d19 (diff)
downloadandroid-node-v8-88786fecff336342a56e6f2e7ff3b286be716e47.tar.gz
android-node-v8-88786fecff336342a56e6f2e7ff3b286be716e47.tar.bz2
android-node-v8-88786fecff336342a56e6f2e7ff3b286be716e47.zip
deps: update V8 to 6.5.254.31
PR-URL: https://github.com/nodejs/node/pull/18453 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Yang Guo <yangguo@chromium.org> Reviewed-By: Ali Ijaz Sheikh <ofrobots@google.com> Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com>
Diffstat (limited to 'deps/v8/test/mjsunit/optimized-array-some.js')
-rw-r--r--deps/v8/test/mjsunit/optimized-array-some.js502
1 files changed, 502 insertions, 0 deletions
diff --git a/deps/v8/test/mjsunit/optimized-array-some.js b/deps/v8/test/mjsunit/optimized-array-some.js
new file mode 100644
index 0000000000..8d0114aa64
--- /dev/null
+++ b/deps/v8/test/mjsunit/optimized-array-some.js
@@ -0,0 +1,502 @@
+// Copyright 2017 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax --turbo-inline-array-builtins --opt
+// Flags: --no-always-opt
+
+// Early exit from some functions properly.
+(() => {
+ const a = [1, 2, 3, 4, 5];
+ let result = 0;
+ function earlyExit() {
+ return a.some(v => {
+ result += v;
+ return v > 2;
+ });
+ }
+ assertTrue(earlyExit());
+ earlyExit();
+ %OptimizeFunctionOnNextCall(earlyExit);
+ assertTrue(earlyExit());
+ assertEquals(18, result);
+})();
+
+// Soft-deopt plus early exit.
+(() => {
+ const a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
+ let result = 0;
+ function softyPlusEarlyExit(deopt) {
+ return a.some(v => {
+ result += v;
+ if (v === 4 && deopt) {
+ a.abc = 25;
+ }
+ return v > 7;
+ });
+ }
+ assertTrue(softyPlusEarlyExit(false));
+ softyPlusEarlyExit(false);
+ %OptimizeFunctionOnNextCall(softyPlusEarlyExit);
+ assertTrue(softyPlusEarlyExit(true));
+ assertEquals(36*3, result);
+})();
+
+// Soft-deopt synced with early exit, which forces the lazy deoptimization
+// continuation handler to exit.
+(() => {
+ const a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
+ let called_values = [];
+ function softyPlusEarlyExit(deopt) {
+ called_values = [];
+ return a.some(v => {
+ called_values.push(v);
+ if (v === 4 && deopt) {
+ a.abc = 25;
+ return true;
+ }
+ return v > 7;
+ });
+ }
+ assertTrue(softyPlusEarlyExit(false));
+ assertArrayEquals([1, 2, 3, 4, 5, 6, 7, 8], called_values);
+ softyPlusEarlyExit(false);
+ %OptimizeFunctionOnNextCall(softyPlusEarlyExit);
+ assertTrue(softyPlusEarlyExit(true));
+ assertArrayEquals([1, 2, 3, 4], called_values);
+})();
+
+// Unknown field access leads to soft-deopt unrelated to some, should still
+// lead to correct result.
+(() => {
+ const a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 23, 24, 25];
+ let result = 0;
+ function eagerDeoptInCalled(deopt) {
+ return a.some((v, i) => {
+ if (i === 13 && deopt) {
+ a.abc = 25;
+ }
+ result += v;
+ return false;
+ });
+ }
+ eagerDeoptInCalled();
+ eagerDeoptInCalled();
+ %OptimizeFunctionOnNextCall(eagerDeoptInCalled);
+ eagerDeoptInCalled();
+ assertFalse(eagerDeoptInCalled(true));
+ eagerDeoptInCalled();
+ assertEquals(1625, result);
+})();
+
+// Length change detected during loop, must cause properly handled eager deopt.
+(() => {
+ let called_values;
+ function eagerDeoptInCalled(deopt) {
+ const a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
+ called_values = [];
+ return a.some((v,i) => {
+ called_values.push(v);
+ a.length = (i === 5 && deopt) ? 8 : 10;
+ return false;
+ });
+ }
+ assertFalse(eagerDeoptInCalled());
+ assertArrayEquals([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], called_values);
+ eagerDeoptInCalled();
+ %OptimizeFunctionOnNextCall(eagerDeoptInCalled);
+ assertFalse(eagerDeoptInCalled());
+ assertFalse(eagerDeoptInCalled(true));
+ assertArrayEquals([1, 2, 3, 4, 5, 6, 7, 8], called_values);
+ eagerDeoptInCalled();
+})();
+
+// Lazy deopt from a callback that changes the input array. Deopt in a callback
+// execution that returns true.
+(() => {
+ const a = [1, 2, 3, 4, 5];
+ function lazyChanger(deopt) {
+ return a.some((v, i) => {
+ if (i === 3 && deopt) {
+ a[3] = 100;
+ %DeoptimizeNow();
+ }
+ return false;
+ });
+ }
+ assertFalse(lazyChanger());
+ lazyChanger();
+ %OptimizeFunctionOnNextCall(lazyChanger);
+ assertFalse(lazyChanger(true));
+ assertFalse(lazyChanger());
+})();
+
+// Lazy deopt from a callback that will always return false and no element is
+// found. Verifies the lazy-after-callback continuation builtin.
+(() => {
+ const a = [1, 2, 3, 4, 5];
+ function lazyChanger(deopt) {
+ return a.some((v, i) => {
+ if (i === 3 && deopt) {
+ %DeoptimizeNow();
+ }
+ return false;
+ });
+ }
+ assertFalse(lazyChanger());
+ lazyChanger();
+ %OptimizeFunctionOnNextCall(lazyChanger);
+ assertFalse(lazyChanger(true));
+ assertFalse(lazyChanger());
+})();
+
+// Lazy deopt from a callback that changes the input array. Deopt in a callback
+// execution that returns false.
+(() => {
+ const a = [1, 2, 3, 4, 5];
+ function lazyChanger(deopt) {
+ return a.every((v, i) => {
+ if (i === 2 && deopt) {
+ a[3] = 100;
+ %DeoptimizeNow();
+ }
+ return false;
+ });
+ }
+ assertFalse(lazyChanger());
+ lazyChanger();
+ %OptimizeFunctionOnNextCall(lazyChanger);
+ assertFalse(lazyChanger(true));
+ assertFalse(lazyChanger());
+})();
+
+// Escape analyzed array
+(() => {
+ let result = 0;
+ function eagerDeoptInCalled(deopt) {
+ const a_noescape = [0, 1, 2, 3, 4, 5];
+ a_noescape.some((v, i) => {
+ result += v | 0;
+ if (i === 13 && deopt) {
+ a_noescape.length = 25;
+ }
+ return false;
+ });
+ }
+ eagerDeoptInCalled();
+ eagerDeoptInCalled();
+ %OptimizeFunctionOnNextCall(eagerDeoptInCalled);
+ eagerDeoptInCalled();
+ eagerDeoptInCalled(true);
+ eagerDeoptInCalled();
+ assertEquals(75, result);
+})();
+
+// Lazy deopt from runtime call from inlined callback function.
+(() => {
+ const a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 23, 24, 25];
+ let result = 0;
+ function lazyDeopt(deopt) {
+ a.some((v, i) => {
+ result += i;
+ if (i === 13 && deopt) {
+ %DeoptimizeNow();
+ }
+ return false;
+ });
+ }
+ lazyDeopt();
+ lazyDeopt();
+ %OptimizeFunctionOnNextCall(lazyDeopt);
+ lazyDeopt();
+ lazyDeopt(true);
+ lazyDeopt();
+ assertEquals(1500, result);
+})();
+
+// Lazy deopt from runtime call from non-inline callback function.
+(() => {
+ const a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 23, 24, 25];
+ let result = 0;
+ function lazyDeopt(deopt) {
+ function callback(v, i) {
+ result += i;
+ if (i === 13 && deopt) {
+ %DeoptimizeNow();
+ }
+ return false;
+ }
+ %NeverOptimizeFunction(callback);
+ a.some(callback);
+ }
+ lazyDeopt();
+ lazyDeopt();
+ %OptimizeFunctionOnNextCall(lazyDeopt);
+ lazyDeopt();
+ lazyDeopt(true);
+ lazyDeopt();
+ assertEquals(1500, result);
+})();
+
+// Call to a.some is done inside a try-catch block and the callback function
+// being called actually throws.
+(() => {
+ const a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 23, 24, 25];
+ let caught = false;
+ function lazyDeopt(deopt) {
+ try {
+ a.some((v, i) => {
+ if (i === 1 && deopt) {
+ throw("a");
+ }
+ return false;
+ });
+ } catch (e) {
+ caught = true;
+ }
+ }
+ lazyDeopt();
+ lazyDeopt();
+ %OptimizeFunctionOnNextCall(lazyDeopt);
+ lazyDeopt();
+ assertDoesNotThrow(() => lazyDeopt(true));
+ assertTrue(caught);
+ lazyDeopt();
+})();
+
+// Call to a.some is done inside a try-catch block and the callback function
+// being called actually throws, but the callback is not inlined.
+(() => {
+ let a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
+ let caught = false;
+ function lazyDeopt(deopt) {
+ function callback(v, i) {
+ if (i === 1 && deopt) {
+ throw("a");
+ }
+ return false;
+ }
+ %NeverOptimizeFunction(callback);
+ try {
+ a.some(callback);
+ } catch (e) {
+ caught = true;
+ }
+ }
+ lazyDeopt();
+ lazyDeopt();
+ %OptimizeFunctionOnNextCall(lazyDeopt);
+ lazyDeopt();
+ assertDoesNotThrow(() => lazyDeopt(true));
+ assertTrue(caught);
+ lazyDeopt();
+})();
+
+// Call to a.some is done inside a try-catch block and the callback function
+// being called throws into a deoptimized caller function.
+(function TestThrowIntoDeoptimizedOuter() {
+ const a = [1, 2, 3, 4];
+ function lazyDeopt(deopt) {
+ function callback(v, i) {
+ if (i === 1 && deopt) {
+ %DeoptimizeFunction(lazyDeopt);
+ throw "some exception";
+ }
+ return false;
+ }
+ %NeverOptimizeFunction(callback);
+ let result = 0;
+ try {
+ result = a.some(callback);
+ } catch (e) {
+ assertEquals("some exception", e);
+ result = "nope";
+ }
+ return result;
+ }
+ assertEquals(false, lazyDeopt(false));
+ assertEquals(false, lazyDeopt(false));
+ assertEquals("nope", lazyDeopt(true));
+ assertEquals("nope", lazyDeopt(true));
+ %OptimizeFunctionOnNextCall(lazyDeopt);
+ assertEquals(false, lazyDeopt(false));
+ assertEquals("nope", lazyDeopt(true));
+})();
+
+// An error generated inside the callback includes some in it's
+// stack trace.
+(() => {
+ const re = /Array\.some/;
+ function lazyDeopt(deopt) {
+ const b = [1, 2, 3];
+ let result = 0;
+ b.some((v, i) => {
+ result += v;
+ if (i === 1) {
+ const e = new Error();
+ assertTrue(re.exec(e.stack) !== null);
+ }
+ return false;
+ });
+ }
+ lazyDeopt();
+ lazyDeopt();
+ %OptimizeFunctionOnNextCall(lazyDeopt);
+ lazyDeopt();
+})();
+
+// An error generated inside a non-inlined callback function also
+// includes some in it's stack trace.
+(() => {
+ const re = /Array\.some/;
+ function lazyDeopt(deopt) {
+ const b = [1, 2, 3];
+ let did_assert_error = false;
+ let result = 0;
+ function callback(v, i) {
+ result += v;
+ if (i === 1) {
+ const e = new Error();
+ assertTrue(re.exec(e.stack) !== null);
+ did_assert_error = true;
+ }
+ return false;
+ }
+ %NeverOptimizeFunction(callback);
+ b.some(callback);
+ return did_assert_error;
+ }
+ lazyDeopt();
+ lazyDeopt();
+ %OptimizeFunctionOnNextCall(lazyDeopt);
+ assertTrue(lazyDeopt());
+})();
+
+// An error generated inside a recently deoptimized callback function
+// includes some in it's stack trace.
+(() => {
+ const re = /Array\.some/;
+ function lazyDeopt(deopt) {
+ const b = [1, 2, 3];
+ let did_assert_error = false;
+ let result = 0;
+ b.some((v, i) => {
+ result += v;
+ if (i === 1) {
+ %DeoptimizeNow();
+ } else if (i === 2) {
+ const e = new Error();
+ assertTrue(re.exec(e.stack) !== null);
+ did_assert_error = true;
+ }
+ return false;
+ });
+ return did_assert_error;
+ }
+ lazyDeopt();
+ lazyDeopt();
+ %OptimizeFunctionOnNextCall(lazyDeopt);
+ assertTrue(lazyDeopt());
+})();
+
+// Verify that various exception edges are handled appropriately.
+// The thrown Error object should always indicate it was created from
+// a some call stack.
+(() => {
+ const re = /Array\.some/;
+ const a = [1, 2, 3];
+ let result = 0;
+ function lazyDeopt() {
+ a.some((v, i) => {
+ result += i;
+ if (i === 1) {
+ %DeoptimizeFunction(lazyDeopt);
+ throw new Error();
+ }
+ return false;
+ });
+ }
+ assertThrows(() => lazyDeopt());
+ assertThrows(() => lazyDeopt());
+ try {
+ lazyDeopt();
+ } catch (e) {
+ assertTrue(re.exec(e.stack) !== null);
+ }
+ %OptimizeFunctionOnNextCall(lazyDeopt);
+ try {
+ lazyDeopt();
+ } catch (e) {
+ assertTrue(re.exec(e.stack) !== null);
+ }
+})();
+
+// Messing with the Array prototype causes deoptimization.
+(() => {
+ const a = [1, 2, 3];
+ let result = 0;
+ function prototypeChanged() {
+ a.some((v, i) => {
+ result += v;
+ return false;
+ });
+ }
+ prototypeChanged();
+ prototypeChanged();
+ %OptimizeFunctionOnNextCall(prototypeChanged);
+ prototypeChanged();
+ a.constructor = {};
+ prototypeChanged();
+ assertUnoptimized(prototypeChanged);
+ assertEquals(24, result);
+})();
+
+// Verify holes are skipped.
+(() => {
+ const a = [1, 2, , 3, 4];
+ function withHoles() {
+ const callback_values = [];
+ a.some(v => {
+ callback_values.push(v);
+ return false;
+ });
+ return callback_values;
+ }
+ withHoles();
+ withHoles();
+ %OptimizeFunctionOnNextCall(withHoles);
+ assertArrayEquals([1, 2, 3, 4], withHoles());
+})();
+
+(() => {
+ const a = [1.5, 2.5, , 3.5, 4.5];
+ function withHoles() {
+ const callback_values = [];
+ a.some(v => {
+ callback_values.push(v);
+ return false;
+ });
+ return callback_values;
+ }
+ withHoles();
+ withHoles();
+ %OptimizeFunctionOnNextCall(withHoles);
+ assertArrayEquals([1.5, 2.5, 3.5, 4.5], withHoles());
+})();
+
+// Handle callback is not callable.
+(() => {
+ const a = [1, 2, 3, 4, 5];
+ function notCallable() {
+ return a.some(undefined);
+ }
+
+ assertThrows(notCallable, TypeError);
+ try { notCallable(); } catch(e) { }
+ %OptimizeFunctionOnNextCall(notCallable);
+ assertThrows(notCallable, TypeError);
+})();