// 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(); }