05207b098a
Removes the --ignition flag which is now on by default. Adds a --stress-fullcodegen flag which enables running all functions supported by fullcodegen to be compiled by fullcodegen. This will enable moving parser internalization later when we are not stressing fullcodegen or compiling asm.js functions. BUG=v8:5203, v8:6409, v8:6589 Change-Id: I7fa68016d4e734755434ec0b4e749ef65ffa7f4e Reviewed-on: https://chromium-review.googlesource.com/565569 Commit-Queue: Ross McIlroy <rmcilroy@chromium.org> Reviewed-by: Michael Achenbach <machenbach@chromium.org> Reviewed-by: Michael Starzinger <mstarzinger@chromium.org> Cr-Commit-Position: refs/heads/master@{#46635}
307 lines
7.1 KiB
JavaScript
307 lines
7.1 KiB
JavaScript
// Copyright 2015 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: --harmony-do-expressions --allow-natives-syntax --no-always-opt
|
|
// Flags: --opt --no-stress-fullcodegen
|
|
|
|
function returnValue(v) { return v; }
|
|
function MyError() {}
|
|
var global = this;
|
|
|
|
function TestBasic() {
|
|
// Looping and lexical declarations
|
|
assertEquals(512, returnValue(do {
|
|
let n = 2;
|
|
for (let i = 0; i < 4; i++) n <<= 2;
|
|
}));
|
|
|
|
// Strings do the right thing
|
|
assertEquals("spooky halloween", returnValue(do {
|
|
"happy halloween".replace('happy', 'spooky');
|
|
}));
|
|
|
|
// Do expressions with no completion produce an undefined value
|
|
assertEquals(undefined, returnValue(do {}));
|
|
assertEquals(undefined, returnValue(do { var x = 99; }));
|
|
assertEquals(undefined, returnValue(do { function f() {}; }));
|
|
assertEquals(undefined, returnValue(do { let z = 33; }));
|
|
|
|
// Propagation of exception
|
|
assertThrows(function() {
|
|
(do {
|
|
throw new MyError();
|
|
"potatoes";
|
|
});
|
|
}, MyError);
|
|
|
|
assertThrows(function() {
|
|
return do {
|
|
throw new MyError();
|
|
"potatoes";
|
|
};
|
|
}, MyError);
|
|
|
|
// Return value within do-block overrides `return |do-expression|`
|
|
assertEquals("inner-return", (function() {
|
|
return "outer-return" + do {
|
|
return "inner-return";
|
|
"";
|
|
};
|
|
})());
|
|
|
|
var count = 0, n = 1;
|
|
// Breaking out |do-expression|
|
|
assertEquals(3, (function() {
|
|
for (var i = 0; i < 10; ++i) (count += 2 * do { if (i === 3) break; ++n });
|
|
return i;
|
|
})());
|
|
// (2 * 2) + (2 * 3) + (2 * 4)
|
|
assertEquals(18, count);
|
|
|
|
// Continue in |do-expression|
|
|
count = 0, n = 1;
|
|
assertEquals([1, 3, 5, 7, 9], (function() {
|
|
var values = [];
|
|
for (var i = 0; i < 10; ++i) {
|
|
count += 2 * (do {
|
|
if ((i & 1) === 0) continue;
|
|
values.push(i);
|
|
++n;
|
|
}) + 1;
|
|
}
|
|
// (2*2) + 1 + (2*3) + 1 + (2*4) + 1 + (2*5) + 1 + (2*6) + 1
|
|
return values;
|
|
})());
|
|
assertEquals(count, 45);
|
|
|
|
assertThrows("(do { break; });", SyntaxError);
|
|
assertThrows("(do { continue; });", SyntaxError);
|
|
|
|
// Real-world use case for desugaring
|
|
var array = [1, 2, 3, 4, 5], iterable = [6, 7, 8,9];
|
|
assertEquals([1, 2, 3, 4, 5, 6, 7, 8, 9], do {
|
|
for (var element of iterable) array.push(element);
|
|
array;
|
|
});
|
|
|
|
// Nested do-expressions
|
|
assertEquals(125, do { (do { (do { 5 * 5 * 5 }) }) });
|
|
|
|
// Directives are not honoured
|
|
(do {
|
|
"use strict";
|
|
foo = 80;
|
|
assertEquals(foo, 80);
|
|
});
|
|
|
|
// Non-empty operand stack testing
|
|
var O = {
|
|
method1() {
|
|
let x = 256;
|
|
return x + do {
|
|
for (var i = 0; i < 4; ++i) x += i;
|
|
} + 17;
|
|
},
|
|
method2() {
|
|
let x = 256;
|
|
this.reset();
|
|
return x + do {
|
|
for (var i = 0; i < this.length(); ++i) x += this.index() * 2;
|
|
};
|
|
},
|
|
_index: 0,
|
|
index() {
|
|
return ++this._index;
|
|
},
|
|
_length: 4,
|
|
length() { return this._length; },
|
|
reset() { this._index = 0; }
|
|
};
|
|
assertEquals(535, O["method" + do { 1 } + ""]());
|
|
assertEquals(532, O["method" + do { ({ valueOf() { return "2"; } }); }]());
|
|
assertEquals(532, O[
|
|
do { let s = ""; for (let c of "method") s += c; } + "2"]());
|
|
}
|
|
TestBasic();
|
|
|
|
|
|
function TestDeoptimization1() {
|
|
function f(v) {
|
|
return 88 + do {
|
|
v.a * v.b + v.c;
|
|
};
|
|
}
|
|
|
|
var o1 = {};
|
|
o1.a = 10;
|
|
o1.b = 5;
|
|
o1.c = 50;
|
|
|
|
var o2 = {};
|
|
o2.c = 100;
|
|
o2.a = 10;
|
|
o2.b = 10;
|
|
|
|
assertEquals(188, f(o1));
|
|
assertEquals(188, f(o1));
|
|
%OptimizeFunctionOnNextCall(f);
|
|
assertEquals(188, f(o1));
|
|
assertOptimized(f);
|
|
assertEquals(288, f(o2));
|
|
assertUnoptimized(f);
|
|
assertEquals(288, f(o2));
|
|
}
|
|
TestDeoptimization1();
|
|
|
|
|
|
function TestInParameterInitializers() {
|
|
var first_name = "George";
|
|
var last_name = "Jetson";
|
|
function fn1(name = do { first_name + " " + last_name }) {
|
|
return name;
|
|
}
|
|
assertEquals("George Jetson", fn1());
|
|
|
|
var _items = [1, 2, 3, NaN, 4, 5];
|
|
function fn2(items = do {
|
|
let items = [];
|
|
for (var el of _items) {
|
|
if (el !== el) {
|
|
items;
|
|
break;
|
|
}
|
|
items.push(el), items;
|
|
}
|
|
}) {
|
|
return items;
|
|
}
|
|
assertEquals([1, 2, 3], fn2());
|
|
|
|
function thrower() { throw new MyError(); }
|
|
function fn3(exception = do { try { thrower(); } catch (e) { e } }) {
|
|
return exception;
|
|
}
|
|
assertDoesNotThrow(fn3);
|
|
assertInstanceof(fn3(), MyError);
|
|
|
|
function fn4(exception = do { throw new MyError() }) {}
|
|
function catcher(fn) {
|
|
try {
|
|
fn();
|
|
assertUnreachable("fn() initializer should throw");
|
|
} catch (e) {
|
|
assertInstanceof(e, MyError);
|
|
}
|
|
}
|
|
catcher(fn4);
|
|
}
|
|
TestInParameterInitializers();
|
|
|
|
|
|
function TestWithEval() {
|
|
(function sloppy1() {
|
|
assertEquals(do { eval("var x = 5"), x }, 5);
|
|
assertEquals(x, 5);
|
|
})();
|
|
|
|
assertThrows(function strict1() {
|
|
"use strict";
|
|
(do { eval("var x = 5"), x }, 5);
|
|
}, ReferenceError);
|
|
|
|
assertThrows(function strict2() {
|
|
(do { eval("'use strict'; var x = 5"), x }, 5);
|
|
}, ReferenceError);
|
|
}
|
|
TestWithEval();
|
|
|
|
|
|
function TestHoisting() {
|
|
(do { var a = 1; });
|
|
assertEquals(a, 1);
|
|
assertEquals(global.a, undefined);
|
|
|
|
(do {
|
|
for (let it of [1, 2, 3, 4, 5]) {
|
|
var b = it;
|
|
}
|
|
});
|
|
assertEquals(b, 5);
|
|
assertEquals(global.b, undefined);
|
|
|
|
{
|
|
let x = 1
|
|
|
|
// TODO(caitp): ensure VariableStatements in |do-expressions| in parameter
|
|
// initializers, are evaluated in the same VariableEnvironment as they would
|
|
// be for eval().
|
|
// function f1(a = do { var x = 2 }, b = x) { return b }
|
|
// assertEquals(1, f1())
|
|
|
|
// function f2(a = x, b = do { var x = 2 }) { return a }
|
|
// assertEquals(1, f2())
|
|
|
|
function f3({a = do { var x = 2 }, b = x}) { return b }
|
|
assertEquals(2, f3({}))
|
|
|
|
function f4({a = x, b = do { var x = 2 }}) { return b }
|
|
assertEquals(undefined, f4({}))
|
|
|
|
function f5(a = do { var y = 0 }) {}
|
|
assertThrows(() => y, ReferenceError)
|
|
}
|
|
|
|
// TODO(caitp): Always block-scope function declarations in |do| expressions
|
|
//(do {
|
|
// assertEquals(true, inner_func());
|
|
// function inner_func() { return true; }
|
|
//});
|
|
//assertThrows(function() { return innerFunc(); }, ReferenceError);
|
|
}
|
|
TestHoisting();
|
|
|
|
|
|
// v8:4661
|
|
|
|
function tryFinallySimple() { (do { try {} finally {} }); }
|
|
tryFinallySimple();
|
|
tryFinallySimple();
|
|
tryFinallySimple();
|
|
tryFinallySimple();
|
|
|
|
var finallyRanCount = 0;
|
|
function tryFinallyDoExpr() {
|
|
return (do {
|
|
try {
|
|
throw "BOO";
|
|
} catch (e) {
|
|
"Caught: " + e + " (" + finallyRanCount + ")"
|
|
} finally {
|
|
++finallyRanCount;
|
|
}
|
|
});
|
|
}
|
|
assertEquals("Caught: BOO (0)", tryFinallyDoExpr());
|
|
assertEquals(1, finallyRanCount);
|
|
assertEquals("Caught: BOO (1)", tryFinallyDoExpr());
|
|
assertEquals(2, finallyRanCount);
|
|
assertEquals("Caught: BOO (2)", tryFinallyDoExpr());
|
|
assertEquals(3, finallyRanCount);
|
|
assertEquals("Caught: BOO (3)", tryFinallyDoExpr());
|
|
assertEquals(4, finallyRanCount);
|
|
|
|
|
|
function TestOSR() {
|
|
var numbers = do {
|
|
let nums = [];
|
|
for (let i = 0; i < 1000; ++i) {
|
|
let value = (Math.random() * 100) | 0;
|
|
nums.push(value === 0 ? 1 : value), nums;
|
|
}
|
|
};
|
|
assertEquals(numbers.length, 1000);
|
|
}
|
|
|
|
for (var i = 0; i < 64; ++i) TestOSR();
|