blob: b60f7893c590da61d4d65e578575058cdec41a78 [file] [log] [blame] [edit]
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// Test deoptimization.
import "package:expect/expect.dart";
class SmiCompares {
// Test deoptimization when one argument is known to be Smi.
static bool smiCompareLessThan2(a) {
return a < 2;
}
// Test deoptimization when one argument is known to be Smi.
static bool smiCompareGreaterThan2(a) {
return 2 < a;
}
// Test deoptimization when both arguments unknown.
static bool smiCompareLessThan(a, b) {
return a < b;
}
// Test deoptimization when both arguments unknown.
static bool smiCompareGreaterThan(a, b) {
return a > b;
}
static smiComparesTest() {
for (int i = 0; i < 2000; i++) {
Expect.equals(true, smiCompareLessThan2(1));
Expect.equals(false, smiCompareLessThan2(3));
Expect.equals(false, smiCompareGreaterThan2(1));
Expect.equals(true, smiCompareGreaterThan2(3));
Expect.equals(true, smiCompareLessThan(1, 2));
Expect.equals(false, smiCompareGreaterThan(1, 2));
}
// Deoptimize by passing a double instead of Smi
Expect.equals(true, smiCompareLessThan2(1.0));
Expect.equals(false, smiCompareGreaterThan2(1.0));
Expect.equals(true, smiCompareLessThan(1.0, 2));
Expect.equals(false, smiCompareGreaterThan(1, 2.0));
}
}
class SmiBinop {
static subWithLiteral(a) {
return a - 1;
}
static void smiBinopTest() {
for (int i = 0; i < 2000; i++) {
Expect.equals(2, subWithLiteral(3));
}
// Deoptimize.
Expect.equals(2.0, subWithLiteral(3.0));
}
static mul(x) {
return x * 1024;
}
static void smiBinopOverflowTest() {
final int big = 536870912;
for (int i = 0; i < 2000; i++) {
Expect.equals(1024, mul(1));
}
// Deoptimize by overflow.
Expect.equals(1024 * big, mul(big));
}
}
class ObjectsEquality {
static bool compareEqual(a, b) {
return a == b;
}
static bool compareNotEqual(a, b) {
return a != b;
}
// Use only Object.==.
static void objectsEqualityTest() {
var a = new ObjectsEquality();
var b = new ObjectsEquality();
for (int i = 0; i < 1000; i++) {
Expect.equals(true, compareEqual(a, a));
Expect.equals(true, compareEqual(null, null));
Expect.equals(false, compareEqual(null, a));
Expect.equals(false, compareEqual(a, null));
Expect.equals(true, compareEqual(b, b));
Expect.equals(false, compareEqual(a, b));
Expect.equals(false, compareNotEqual(a, a));
Expect.equals(false, compareNotEqual(null, null));
Expect.equals(true, compareNotEqual(null, a));
Expect.equals(true, compareNotEqual(a, null));
Expect.equals(false, compareNotEqual(b, b));
Expect.equals(true, compareNotEqual(a, b));
}
var c = new SmiBinop();
// Deoptimize.
Expect.equals(true, compareEqual(c, c));
Expect.equals(false, compareEqual(c, null));
Expect.equals(false, compareNotEqual(c, c));
Expect.equals(true, compareNotEqual(c, null));
}
}
class DeoptimizationTest {
static foo(a, b) {
return a - b;
}
static test1() {
for (int i = 0; i < 2000; i++) {
Expect.equals(2, foo(3, 1)); // <-- Optimizes 'foo',
}
Expect.equals(2.2, foo(1.2, -1.0)); // <-- Deoptimizes 'foo'.
for (int i = 0; i < 10000; i++) {
Expect.equals(2, foo(3, 1)); // <-- Optimizes 'foo'.
}
Expect.equals(2.2, foo(1.2, -1)); // <-- Deoptimizes 'foo'.
}
static moo(n) {
return ++n;
}
static test2() {
for (int i = 0; i < 2000; i++) {
Expect.equals(4, moo(3)); // <-- Optimizes 'moo',
}
Expect.equals(2.2, moo(1.2)); // <-- Deoptimizes 'moo'.
for (int i = 0; i < 10000; i++) {
Expect.equals(4, moo(3)); // <-- Optimizes 'moo'.
}
Expect.equals(2.2, moo(1.2)); // <-- Deoptimizes 'moo'.
}
static test3() {
for (int i = 0; i < 2000; i++) {
Expect.equals(2.0, foo(3.0, 1.0)); // <-- Optimizes 'foo',
}
Expect.equals(2, foo(1, -1)); // <-- Deoptimizes 'foo'.
for (int i = 0; i < 2000; i++) {
Expect.equals(2.0, foo(3.0, 1.0)); // <-- Optimizes 'foo',
}
Expect.equals(2.2, moo(1.2)); // <-- Deoptimizes 'moo'.
}
static bool compareInt(a, b) {
return a < b;
}
static bool compareDouble(a, b) {
return a < b;
}
static test4() {
for (int i = 0; i < 2000; i++) {
Expect.equals(true, compareInt(1, 2));
Expect.equals(true, compareDouble(1.0, 2.0));
}
// Trigger deoptimization in compareInt and compareDouble.
Expect.equals(true, compareInt(1, 2.0));
Expect.equals(true, compareDouble(1.0, 2));
}
static smiRightShift() {
int ShiftRight(int a, int b) {
return a >> b;
}
for (int i = 0; i < 2000; i++) {
var r = ShiftRight(10, 2);
Expect.equals(2, r);
}
// ShiftRight is optimized.
Expect.equals(0, ShiftRight(10, 64));
// Deoptimize ShiftRight because 'a' is a Mint.
var mint = 1 << 63;
Expect.equals(-1 << 3, ShiftRight(mint, 60));
}
static doubleUnary() {
num unary(num a) {
return -a;
}
for (int i = 0; i < 2000; i++) {
var r = unary(2.0);
Expect.equals(-2.0, r);
}
var r = unary(5);
Expect.equals(-5, r);
}
static void testMain() {
test1();
test2();
test3();
test4();
SmiCompares.smiComparesTest();
SmiBinop.smiBinopTest();
SmiBinop.smiBinopOverflowTest();
ObjectsEquality.objectsEqualityTest();
smiRightShift();
doubleUnary();
}
}
main() {
DeoptimizationTest.testMain();
}