OLD | NEW |
1 library dart2js.cps_ir.finalize; | 1 library dart2js.cps_ir.finalize; |
2 | 2 |
3 import 'cps_ir_nodes.dart'; | 3 import 'cps_ir_nodes.dart'; |
4 import 'cps_fragment.dart'; | 4 import 'cps_fragment.dart'; |
5 import 'optimizers.dart' show Pass; | 5 import 'optimizers.dart' show Pass; |
6 import '../js_backend/js_backend.dart' show JavaScriptBackend; | 6 import '../js_backend/js_backend.dart' show JavaScriptBackend; |
7 import '../js_backend/backend_helpers.dart'; | 7 import '../js_backend/backend_helpers.dart'; |
8 import '../js/js.dart' as js; | 8 import '../js/js.dart' as js; |
9 | 9 |
10 /// A transformation pass that must run immediately before the tree IR builder. | 10 /// A transformation pass that must run immediately before the tree IR builder. |
(...skipping 20 matching lines...) Expand all Loading... |
31 return next; | 31 return next; |
32 } | 32 } |
33 | 33 |
34 bool areAdjacent(Primitive first, Primitive second) { | 34 bool areAdjacent(Primitive first, Primitive second) { |
35 return first.parent == second.parent.parent; | 35 return first.parent == second.parent.parent; |
36 } | 36 } |
37 | 37 |
38 CpsFragment visitBoundsCheck(BoundsCheck node) { | 38 CpsFragment visitBoundsCheck(BoundsCheck node) { |
39 CpsFragment cps = new CpsFragment(node.sourceInformation); | 39 CpsFragment cps = new CpsFragment(node.sourceInformation); |
40 if (node.hasNoChecks) { | 40 if (node.hasNoChecks) { |
41 node..replaceUsesWith(node.object)..destroy(); | 41 node |
| 42 ..replaceUsesWith(node.object) |
| 43 ..destroy(); |
42 return cps; | 44 return cps; |
43 } | 45 } |
44 Continuation fail = cps.letCont(); | 46 Continuation fail = cps.letCont(); |
45 Primitive index = node.index; | 47 Primitive index = node.index; |
46 if (node.hasIntegerCheck) { | 48 if (node.hasIntegerCheck) { |
47 cps.ifTruthy(cps.applyBuiltin(BuiltinOperator.IsNotUnsigned32BitInteger, | 49 cps |
48 [index, index])) | 50 .ifTruthy(cps.applyBuiltin( |
| 51 BuiltinOperator.IsNotUnsigned32BitInteger, [index, index])) |
49 .invokeContinuation(fail); | 52 .invokeContinuation(fail); |
50 } else if (node.hasLowerBoundCheck) { | 53 } else if (node.hasLowerBoundCheck) { |
51 cps.ifTruthy(cps.applyBuiltin(BuiltinOperator.NumLt, | 54 cps |
52 [index, cps.makeZero()])) | 55 .ifTruthy( |
| 56 cps.applyBuiltin(BuiltinOperator.NumLt, [index, cps.makeZero()])) |
53 .invokeContinuation(fail); | 57 .invokeContinuation(fail); |
54 } | 58 } |
55 if (node.hasUpperBoundCheck) { | 59 if (node.hasUpperBoundCheck) { |
56 Primitive length = node.length; | 60 Primitive length = node.length; |
57 if (length is GetLength && | 61 if (length is GetLength && |
58 length.hasExactlyOneUse && | 62 length.hasExactlyOneUse && |
59 areAdjacent(length, node)) { | 63 areAdjacent(length, node)) { |
60 // Rebind the GetLength here, so it does not get stuck outside the | 64 // Rebind the GetLength here, so it does not get stuck outside the |
61 // condition, blocked from propagating by the lower bounds check. | 65 // condition, blocked from propagating by the lower bounds check. |
62 LetPrim lengthBinding = length.parent; | 66 LetPrim lengthBinding = length.parent; |
63 lengthBinding.remove(); | 67 lengthBinding.remove(); |
64 cps.letPrim(length); | 68 cps.letPrim(length); |
65 } | 69 } |
66 cps.ifTruthy(cps.applyBuiltin(BuiltinOperator.NumGe, | 70 cps |
67 [index, length])) | 71 .ifTruthy(cps.applyBuiltin(BuiltinOperator.NumGe, [index, length])) |
68 .invokeContinuation(fail); | 72 .invokeContinuation(fail); |
69 } | 73 } |
70 if (node.hasEmptinessCheck) { | 74 if (node.hasEmptinessCheck) { |
71 cps.ifTruthy(cps.applyBuiltin(BuiltinOperator.StrictEq, | 75 cps |
72 [node.length, cps.makeZero()])) | 76 .ifTruthy(cps.applyBuiltin( |
| 77 BuiltinOperator.StrictEq, [node.length, cps.makeZero()])) |
73 .invokeContinuation(fail); | 78 .invokeContinuation(fail); |
74 } | 79 } |
75 cps.insideContinuation(fail).invokeStaticThrower( | 80 cps.insideContinuation(fail).invokeStaticThrower( |
76 helpers.throwIndexOutOfRangeException, | 81 helpers.throwIndexOutOfRangeException, [node.object, index]); |
77 [node.object, index]); | 82 node |
78 node..replaceUsesWith(node.object)..destroy(); | 83 ..replaceUsesWith(node.object) |
| 84 ..destroy(); |
79 return cps; | 85 return cps; |
80 } | 86 } |
81 | 87 |
82 void visitGetStatic(GetStatic node) { | 88 void visitGetStatic(GetStatic node) { |
83 if (node.witnessRef != null) { | 89 if (node.witnessRef != null) { |
84 node..witnessRef.unlink()..witnessRef = null; | 90 node |
| 91 ..witnessRef.unlink() |
| 92 ..witnessRef = null; |
85 } | 93 } |
86 } | 94 } |
87 | 95 |
88 void visitForeignCode(ForeignCode node) { | 96 void visitForeignCode(ForeignCode node) { |
89 if (js.isIdentityTemplate(node.codeTemplate)) { | 97 if (js.isIdentityTemplate(node.codeTemplate)) { |
90 // The CPS builder replaces identity templates with refinements, except | 98 // The CPS builder replaces identity templates with refinements, except |
91 // when the refined type is an array type. Some optimizations assume the | 99 // when the refined type is an array type. Some optimizations assume the |
92 // type of an object is immutable, but the type of an array can change | 100 // type of an object is immutable, but the type of an array can change |
93 // after allocation. After the finalize pass, this assumption is no | 101 // after allocation. After the finalize pass, this assumption is no |
94 // longer needed, so we can replace the remaining idenitity templates. | 102 // longer needed, so we can replace the remaining idenitity templates. |
95 Refinement refinement = new Refinement(node.argument(0), node.type) | 103 Refinement refinement = new Refinement(node.argument(0), node.type) |
96 ..type = node.type; | 104 ..type = node.type; |
97 node.replaceWith(refinement); | 105 node.replaceWith(refinement); |
98 } | 106 } |
99 } | 107 } |
100 } | 108 } |
OLD | NEW |