| 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 |