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.definition)..destroy(); | 41 node..replaceUsesWith(node.object)..destroy(); |
42 return cps; | 42 return cps; |
43 } | 43 } |
44 Continuation fail = cps.letCont(); | 44 Continuation fail = cps.letCont(); |
45 Primitive index = node.index.definition; | 45 Primitive index = node.index; |
46 if (node.hasIntegerCheck) { | 46 if (node.hasIntegerCheck) { |
47 cps.ifTruthy(cps.applyBuiltin(BuiltinOperator.IsNotUnsigned32BitInteger, | 47 cps.ifTruthy(cps.applyBuiltin(BuiltinOperator.IsNotUnsigned32BitInteger, |
48 [index, index])) | 48 [index, index])) |
49 .invokeContinuation(fail); | 49 .invokeContinuation(fail); |
50 } else if (node.hasLowerBoundCheck) { | 50 } else if (node.hasLowerBoundCheck) { |
51 cps.ifTruthy(cps.applyBuiltin(BuiltinOperator.NumLt, | 51 cps.ifTruthy(cps.applyBuiltin(BuiltinOperator.NumLt, |
52 [index, cps.makeZero()])) | 52 [index, cps.makeZero()])) |
53 .invokeContinuation(fail); | 53 .invokeContinuation(fail); |
54 } | 54 } |
55 if (node.hasUpperBoundCheck) { | 55 if (node.hasUpperBoundCheck) { |
56 Primitive length = node.length.definition; | 56 Primitive length = node.length; |
57 if (length is GetLength && | 57 if (length is GetLength && |
58 length.hasExactlyOneUse && | 58 length.hasExactlyOneUse && |
59 areAdjacent(length, node)) { | 59 areAdjacent(length, node)) { |
60 // Rebind the GetLength here, so it does not get stuck outside the | 60 // Rebind the GetLength here, so it does not get stuck outside the |
61 // condition, blocked from propagating by the lower bounds check. | 61 // condition, blocked from propagating by the lower bounds check. |
62 LetPrim lengthBinding = length.parent; | 62 LetPrim lengthBinding = length.parent; |
63 lengthBinding.remove(); | 63 lengthBinding.remove(); |
64 cps.letPrim(length); | 64 cps.letPrim(length); |
65 } | 65 } |
66 cps.ifTruthy(cps.applyBuiltin(BuiltinOperator.NumGe, | 66 cps.ifTruthy(cps.applyBuiltin(BuiltinOperator.NumGe, |
67 [index, length])) | 67 [index, length])) |
68 .invokeContinuation(fail); | 68 .invokeContinuation(fail); |
69 } | 69 } |
70 if (node.hasEmptinessCheck) { | 70 if (node.hasEmptinessCheck) { |
71 cps.ifTruthy(cps.applyBuiltin(BuiltinOperator.StrictEq, | 71 cps.ifTruthy(cps.applyBuiltin(BuiltinOperator.StrictEq, |
72 [node.length.definition, cps.makeZero()])) | 72 [node.length, cps.makeZero()])) |
73 .invokeContinuation(fail); | 73 .invokeContinuation(fail); |
74 } | 74 } |
75 cps.insideContinuation(fail).invokeStaticThrower( | 75 cps.insideContinuation(fail).invokeStaticThrower( |
76 helpers.throwIndexOutOfRangeException, | 76 helpers.throwIndexOutOfRangeException, |
77 [node.object.definition, index]); | 77 [node.object, index]); |
78 node..replaceUsesWith(node.object.definition)..destroy(); | 78 node..replaceUsesWith(node.object)..destroy(); |
79 return cps; | 79 return cps; |
80 } | 80 } |
81 | 81 |
82 void visitGetStatic(GetStatic node) { | 82 void visitGetStatic(GetStatic node) { |
83 if (node.witness != null) { | 83 if (node.witnessRef != null) { |
84 node..witness.unlink()..witness = null; | 84 node..witnessRef.unlink()..witnessRef = null; |
85 } | 85 } |
86 } | 86 } |
87 | 87 |
88 void visitForeignCode(ForeignCode node) { | 88 void visitForeignCode(ForeignCode node) { |
89 if (js.isIdentityTemplate(node.codeTemplate)) { | 89 if (js.isIdentityTemplate(node.codeTemplate)) { |
90 // The CPS builder replaces identity templates with refinements, except | 90 // The CPS builder replaces identity templates with refinements, except |
91 // when the refined type is an array type. Some optimizations assume the | 91 // 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 | 92 // 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 | 93 // after allocation. After the finalize pass, this assumption is no |
94 // longer needed, so we can replace the remaining idenitity templates. | 94 // longer needed, so we can replace the remaining idenitity templates. |
95 Refinement refinement = new Refinement( | 95 Refinement refinement = new Refinement(node.argument(0), node.type) |
96 node.arguments.single.definition, | 96 ..type = node.type; |
97 node.type)..type = node.type; | |
98 node.replaceWith(refinement); | 97 node.replaceWith(refinement); |
99 } | 98 } |
100 } | 99 } |
101 } | 100 } |
OLD | NEW |