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