| OLD | NEW |
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 library dart2js.cps_ir.path_based_optimizer; | 4 library dart2js.cps_ir.path_based_optimizer; |
| 5 | 5 |
| 6 import 'cps_ir_nodes.dart'; | 6 import 'cps_ir_nodes.dart'; |
| 7 import 'optimizers.dart'; | 7 import 'optimizers.dart'; |
| 8 import 'cps_fragment.dart'; | 8 import 'cps_fragment.dart'; |
| 9 import '../js_backend/js_backend.dart'; | 9 import '../js_backend/js_backend.dart'; |
| 10 import 'type_mask_system.dart'; | 10 import 'type_mask_system.dart'; |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 52 /// refined type cannot always be represented exactly, and type propagation | 52 /// refined type cannot always be represented exactly, and type propagation |
| 53 /// may therefore not see that `x` is a self-interceptor. | 53 /// may therefore not see that `x` is a self-interceptor. |
| 54 // | 54 // |
| 55 // TODO(asgerf): A kind of redundant join can arise where a branching condition | 55 // TODO(asgerf): A kind of redundant join can arise where a branching condition |
| 56 // is known to be true/false on all but one predecessor for a branch. We could | 56 // is known to be true/false on all but one predecessor for a branch. We could |
| 57 // try to reduce those. | 57 // try to reduce those. |
| 58 // | 58 // |
| 59 // TODO(asgerf): Could be more precise if GVN shared expressions that are not | 59 // TODO(asgerf): Could be more precise if GVN shared expressions that are not |
| 60 // in direct scope of one another, e.g. by using phis pass the shared value. | 60 // in direct scope of one another, e.g. by using phis pass the shared value. |
| 61 // | 61 // |
| 62 class PathBasedOptimizer extends TrampolineRecursiveVisitor | 62 class PathBasedOptimizer extends TrampolineRecursiveVisitor implements Pass { |
| 63 implements Pass { | |
| 64 String get passName => 'Path-based optimizations'; | 63 String get passName => 'Path-based optimizations'; |
| 65 | 64 |
| 66 // Classification of all values. | 65 // Classification of all values. |
| 67 static const int TRUE = 1 << 0; | 66 static const int TRUE = 1 << 0; |
| 68 static const int SELF_INTERCEPTOR = 1 << 1; | 67 static const int SELF_INTERCEPTOR = 1 << 1; |
| 69 static const int INTERCEPTED_TRUTHY = 1 << 2; | 68 static const int INTERCEPTED_TRUTHY = 1 << 2; |
| 70 static const int FALSE = 1 << 3; | 69 static const int FALSE = 1 << 3; |
| 71 static const int OTHER_FALSY = 1 << 4; | 70 static const int OTHER_FALSY = 1 << 4; |
| 72 | 71 |
| 73 static const int TRUTHY = TRUE | SELF_INTERCEPTOR | INTERCEPTED_TRUTHY; | 72 static const int TRUTHY = TRUE | SELF_INTERCEPTOR | INTERCEPTED_TRUTHY; |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 151 valuesAt[falseCont] = valueOf..[condition] = values & negativeValues; | 150 valuesAt[falseCont] = valueOf..[condition] = values & negativeValues; |
| 152 } | 151 } |
| 153 } | 152 } |
| 154 | 153 |
| 155 void visitInvokeMethod(InvokeMethod node) { | 154 void visitInvokeMethod(InvokeMethod node) { |
| 156 int receiverValue = valueOf[node.receiver] ?? ANY; | 155 int receiverValue = valueOf[node.receiver] ?? ANY; |
| 157 if (!backend.isInterceptedSelector(node.selector)) { | 156 if (!backend.isInterceptedSelector(node.selector)) { |
| 158 // Only self-interceptors can respond to a non-intercepted selector. | 157 // Only self-interceptors can respond to a non-intercepted selector. |
| 159 valueOf[node.receiver] = receiverValue & SELF_INTERCEPTOR; | 158 valueOf[node.receiver] = receiverValue & SELF_INTERCEPTOR; |
| 160 } else if (receiverValue & ~SELF_INTERCEPTOR == 0 && | 159 } else if (receiverValue & ~SELF_INTERCEPTOR == 0 && |
| 161 node.callingConvention == CallingConvention.Intercepted) { | 160 node.callingConvention == CallingConvention.Intercepted) { |
| 162 // This is an intercepted call whose receiver is definitely a | 161 // This is an intercepted call whose receiver is definitely a |
| 163 // self-interceptor. | 162 // self-interceptor. |
| 164 // TODO(25646): If TypeMasks could represent "any self-interceptor" this | 163 // TODO(25646): If TypeMasks could represent "any self-interceptor" this |
| 165 // optimization should be subsumed by type propagation. | 164 // optimization should be subsumed by type propagation. |
| 166 node.interceptorRef.changeTo(node.receiver); | 165 node.interceptorRef.changeTo(node.receiver); |
| 167 | 166 |
| 168 // Replace the extra receiver argument with a dummy value if the | 167 // Replace the extra receiver argument with a dummy value if the |
| 169 // target definitely does not use it. | 168 // target definitely does not use it. |
| 170 if (typeSystem.targetIgnoresReceiverArgument(node.receiver.type, | 169 if (typeSystem.targetIgnoresReceiverArgument( |
| 171 node.selector)) { | 170 node.receiver.type, node.selector)) { |
| 172 node.makeDummyIntercepted(); | 171 node.makeDummyIntercepted(); |
| 173 } | 172 } |
| 174 } | 173 } |
| 175 } | 174 } |
| 176 } | 175 } |
| OLD | NEW |