8ad125f607
This is a first step towards fully optimizing try-catch-finally.
At a catch entry, all local variables and parameters are
expected at a fixed stack location. There is a list of
initial definitions at the catch entry block, similar to
the initial definitions at graph entry.
Inside every try-block there is a special prologue code before each
call (instruction that may throw) inside the try-block. This prologue
is similar to a parallel move instruction: It moves all locals+parameters
to the locations expected by the catch-entry block. The stack frame
is extended with the corresponding number of fixed slots right below
the normal spill slots.
Every function containing try-catch has additional compiler-
generated local variables to pass the context, the exception and
the stack trace.
Variable liveness analysis is adapted to treat locals inside try{} blocks
specially: Every call has an implicit LoadLocal of every local variable.
This CL uses a safe approximiation of liveness which can be optimized further.
Current restrictions which are planned for future CLs:
* No inlining inside try-blocks.
* No inlining of functions containing try-catch.
* No try-finally yet.
R=kmillikin@google.com
Review URL: https://codereview.chromium.org//14682020
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@22615 260f80e4-7a28-3924-810f-c04153c831b5
300 lines
5.1 KiB
Dart
300 lines
5.1 KiB
Dart
// Copyright (c) 2013, 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.
|
|
|
|
import "package:expect/expect.dart";
|
|
|
|
maythrow(x) {
|
|
if (x == null) throw 42;
|
|
return 99;
|
|
}
|
|
|
|
|
|
f1(x) {
|
|
var result = 123;
|
|
try {
|
|
result = maythrow(x);
|
|
if (result > 100) throw 42;
|
|
} catch(e) {
|
|
Expect.equals(result, 123);
|
|
Expect.equals(42, e);
|
|
result = 0;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
|
|
class A {
|
|
maythrow(x) {
|
|
if (x == null) throw 42;
|
|
return 99;
|
|
}
|
|
}
|
|
|
|
|
|
f2(x) {
|
|
var result = 123;
|
|
var a = new A();
|
|
try {
|
|
result++;
|
|
result = a.maythrow(x);
|
|
} catch(e) {
|
|
Expect.equals(124, result);
|
|
result = x;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
|
|
f3(x, y) {
|
|
var result = 123;
|
|
var a = new A();
|
|
try {
|
|
result++;
|
|
result = a.maythrow(x);
|
|
} catch(e) {
|
|
result = y + 1; // Deopt on overflow
|
|
}
|
|
return result;
|
|
}
|
|
|
|
|
|
f4(x) {
|
|
try {
|
|
maythrow(x);
|
|
} catch(e) {
|
|
check_f4(e, "abc");
|
|
}
|
|
}
|
|
|
|
check_f4(e, s) {
|
|
if (e != 42) throw "ERROR";
|
|
if (s != "abc") throw "ERROR";
|
|
}
|
|
|
|
|
|
f5(x) {
|
|
try {
|
|
maythrow(x);
|
|
} catch(e) {
|
|
check_f5(e, "abc");
|
|
}
|
|
|
|
try {
|
|
maythrow(x);
|
|
} catch(e) {
|
|
check_f5(e, "abc");
|
|
}
|
|
}
|
|
|
|
check_f5(e, s) {
|
|
if (e != 42) throw "ERROR";
|
|
if (s != "abc") throw "ERROR";
|
|
}
|
|
|
|
|
|
f6(x, y) {
|
|
var a = x;
|
|
var b = y;
|
|
var c = 123;
|
|
check_f6(42, null, 1, 123, null, 1);
|
|
try {
|
|
maythrow(x);
|
|
} catch(e) {
|
|
check_f6(e, a, b, c, x, y);
|
|
}
|
|
}
|
|
|
|
check_f6(e, a, b, c, x, y) {
|
|
if (e != 42) throw "ERROR";
|
|
if (a != null) throw "ERROR";
|
|
if (b != 1) throw "ERROR";
|
|
if (c != 123) throw "ERROR";
|
|
if (x != null) throw "ERROR";
|
|
if (y != 1) throw "ERROR";
|
|
}
|
|
|
|
|
|
bool f7(String str) {
|
|
double d = double.parse(str);
|
|
var t = d;
|
|
try {
|
|
var a = d.toInt();
|
|
return false;
|
|
} on UnsupportedError catch (e) {
|
|
Expect.equals(true, identical(t, d));
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
f8(x, [a = 3, b = 4]) {
|
|
var c = 123;
|
|
var y = a;
|
|
try {
|
|
maythrow(x);
|
|
} catch(e, s) {
|
|
check_f8(e, s, a, b, c, x, y);
|
|
}
|
|
}
|
|
|
|
check_f8(e, s, a, b, c, x, y) {
|
|
if (e != 42) throw "ERROR";
|
|
if (s is! StackTrace) throw "ERROR";
|
|
if (a != 3) { print(a); throw "ERROR"; }
|
|
if (b != 4) throw "ERROR";
|
|
if (c != 123) throw "ERROR";
|
|
if (x != null) throw "ERROR";
|
|
if (y != a) throw "ERROR";
|
|
}
|
|
|
|
|
|
f9(x, [a = 3, b = 4]) {
|
|
var c = 123;
|
|
var y = a;
|
|
try {
|
|
if (x < a) maythrow(null);
|
|
maythrow(x);
|
|
} catch(e, s) {
|
|
check_f9(e, s, a, b, c, x, y);
|
|
}
|
|
}
|
|
|
|
|
|
check_f9(e, s, a, b, c, x, y) {
|
|
if (e != 42) throw "ERROR";
|
|
if (s is! StackTrace) throw "ERROR";
|
|
if (a != 3) { print(a); throw "ERROR"; }
|
|
if (b != 4) throw "ERROR";
|
|
if (c != 123) throw "ERROR";
|
|
if (x != null) throw "ERROR";
|
|
if (y != a) throw "ERROR";
|
|
}
|
|
|
|
|
|
f10(x, y) {
|
|
var result = 123;
|
|
try {
|
|
result = maythrow(x);
|
|
} catch(e) {
|
|
Expect.equals(123, result);
|
|
Expect.equals(0.5, y / 2.0);
|
|
result = 0;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
|
|
f11(x) {
|
|
var result = 123;
|
|
var tmp = x;
|
|
try {
|
|
result = maythrow(x);
|
|
if (result > 100) throw 42;
|
|
} catch(e, s) {
|
|
Expect.equals(123, result);
|
|
Expect.equals(true, identical(tmp, x));
|
|
Expect.equals(true, s is StackTrace);
|
|
result = 0;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
|
|
f12([x = null]) {
|
|
try {
|
|
maythrow(x);
|
|
} catch(e) {
|
|
check_f12(e, x);
|
|
}
|
|
}
|
|
|
|
check_f12(e, x) {
|
|
if (e != 42) throw "ERROR";
|
|
if (x != null) throw "ERROR";
|
|
}
|
|
|
|
|
|
f13(x) {
|
|
var result = 123;
|
|
try {
|
|
try {
|
|
result = maythrow(x);
|
|
if (result > 100) throw 42;
|
|
} catch(e) {
|
|
Expect.equals(123, result);
|
|
result = 0;
|
|
}
|
|
maythrow(x);
|
|
} catch(e) {
|
|
result++;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
|
|
main() {
|
|
for (var i=0; i<10000; i++) f1("abc");
|
|
Expect.equals(99, f1("abc"));
|
|
Expect.equals(0, f1(null));
|
|
|
|
for (var i=0; i<10000; i++) f2("abc");
|
|
Expect.equals(99, f2("abc"));
|
|
Expect.equals(null, f2(null));
|
|
|
|
f3("123", 0);
|
|
for (var i=0; i<10000; i++) f3(null, 0);
|
|
Expect.equals(99, f3("123", 0));
|
|
Expect.equals(0x40000000, f3(null, 0x3fffffff));
|
|
|
|
f4(null);
|
|
for (var i=0; i<10000; i++) f4(123);
|
|
f4(null);
|
|
|
|
f5(null);
|
|
for (var i=0; i<10000; i++) f5(123);
|
|
f5(null);
|
|
|
|
f6(null, 1);
|
|
for (var i=0; i<10000; i++) f6(123, 1);
|
|
f6(null, 1);
|
|
|
|
f7("1.2");
|
|
f7("Infinity");
|
|
f7("-Infinity");
|
|
for (var i=0; i<10000; i++) f7("1.2");
|
|
Expect.equals(false, f7("1.2"));
|
|
Expect.equals(true, f7("Infinity"));
|
|
Expect.equals(true, f7("-Infinity"));
|
|
Expect.equals(false, f7("123456789012345")); // Deopt.
|
|
for (var i=0; i<10000; i++) f7("123456789012345");
|
|
Expect.equals(true, f7("Infinity"));
|
|
Expect.equals(true, f7("-Infinity"));
|
|
|
|
for (var i=0; i<10000; i++) f8(null);
|
|
f8(null);
|
|
|
|
f9(5);
|
|
f9(5.0);
|
|
for (var i=0; i<10000; i++) f9(3);
|
|
f9(3);
|
|
|
|
var y = 1.0;
|
|
Expect.equals(0, f10(null, y));
|
|
for (var i = 0; i < 10000; i++) f10("abc", y);
|
|
Expect.equals(99, f10("abc", y));
|
|
Expect.equals(0, f10(null, y));
|
|
|
|
for (var i=0; i<10000; i++) f11("abc");
|
|
Expect.equals(99, f11("abc"));
|
|
Expect.equals(0, f11(null));
|
|
|
|
for (var i=0; i<10000; i++) f12(null);
|
|
f12(null);
|
|
|
|
f13(null);
|
|
for (var i=0; i<10000; i++) f13("abc");
|
|
Expect.equals(99, f13("abc"));
|
|
Expect.equals(1, f13(null));
|
|
}
|