OLD | NEW |
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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 | 4 |
5 library dart2js.cps_ir.share_interceptors; | 5 library dart2js.cps_ir.share_interceptors; |
6 | 6 |
7 import 'cps_ir_nodes.dart'; | 7 import 'cps_ir_nodes.dart'; |
8 import 'optimizers.dart'; | 8 import 'optimizers.dart'; |
| 9 import '../constants/values.dart'; |
9 | 10 |
10 /// Merges calls to `getInterceptor` when one call dominates the other. | 11 /// Merges calls to `getInterceptor` when one call dominates the other. |
11 /// | 12 /// |
12 /// Should run after [LoopInvariantCodeMotion] so interceptors lifted out from | 13 /// Should run after [LoopInvariantCodeMotion] so interceptors lifted out from |
13 /// loops can be merged. | 14 /// loops can be merged. |
14 class ShareInterceptors extends RecursiveVisitor implements Pass { | 15 class ShareInterceptors extends RecursiveVisitor implements Pass { |
15 String get passName => 'Share interceptors'; | 16 String get passName => 'Share interceptors'; |
16 | 17 |
17 final Map<Primitive, Interceptor> interceptorFor = | 18 final Map<Primitive, Primitive> interceptorFor = |
18 <Primitive, Interceptor>{}; | 19 <Primitive, Primitive>{}; |
| 20 |
| 21 final Map<ConstantValue, Primitive> sharedConstantFor = |
| 22 <ConstantValue, Primitive>{}; |
19 | 23 |
20 void rewrite(FunctionDefinition node) { | 24 void rewrite(FunctionDefinition node) { |
21 visit(node.body); | 25 visit(node.body); |
22 } | 26 } |
23 | 27 |
24 @override | 28 @override |
25 Expression traverseLetPrim(LetPrim node) { | 29 Expression traverseLetPrim(LetPrim node) { |
26 if (node.primitive is Interceptor) { | 30 if (node.primitive is Interceptor) { |
27 Interceptor interceptor = node.primitive; | 31 Interceptor interceptor = node.primitive; |
28 Primitive input = interceptor.input.definition; | 32 Primitive input = interceptor.input.definition; |
29 Interceptor existing = interceptorFor[input]; | 33 Interceptor existing = interceptorFor[input]; |
30 if (existing != null) { | 34 if (existing != null) { |
31 existing.interceptedClasses.addAll(interceptor.interceptedClasses); | 35 if (existing is Interceptor) { |
| 36 existing.interceptedClasses.addAll(interceptor.interceptedClasses); |
| 37 } |
32 existing.substituteFor(interceptor); | 38 existing.substituteFor(interceptor); |
| 39 } else if (interceptor.constantValue != null) { |
| 40 InterceptorConstantValue value = interceptor.constantValue; |
| 41 // There is no interceptor obtained from this particular input, but |
| 42 // there might one obtained from another input that is known to |
| 43 // have the same result, so try to reuse that. |
| 44 Primitive shared = sharedConstantFor[value]; |
| 45 if (shared != null) { |
| 46 shared.substituteFor(interceptor); |
| 47 } else { |
| 48 Constant constant = new Constant(value); |
| 49 constant.hint = interceptor.hint; |
| 50 node.primitive = constant; |
| 51 constant.parent = node; |
| 52 interceptor.input.unlink(); |
| 53 constant.substituteFor(interceptor); |
| 54 interceptorFor[input] = constant; |
| 55 sharedConstantFor[value] = constant; |
| 56 pushAction(() { |
| 57 interceptorFor.remove(input); |
| 58 sharedConstantFor.remove(value); |
| 59 |
| 60 if (constant.hasExactlyOneUse) { |
| 61 // As a heuristic, always sink single-use interceptor constants |
| 62 // to their use, even if it is inside a loop. |
| 63 Expression use = getEnclosingExpression(constant.firstRef.parent); |
| 64 InteriorNode parent = node.parent; |
| 65 parent.body = node.body; |
| 66 node.body.parent = parent; |
| 67 |
| 68 InteriorNode useParent = use.parent; |
| 69 useParent.body = node; |
| 70 node.body = use; |
| 71 use.parent = node; |
| 72 node.parent = useParent; |
| 73 } |
| 74 }); |
| 75 } |
33 } else { | 76 } else { |
34 interceptorFor[input] = interceptor; | 77 interceptorFor[input] = interceptor; |
35 pushAction(() { | 78 pushAction(() { |
36 interceptorFor.remove(input); | 79 interceptorFor.remove(input); |
37 }); | 80 }); |
38 } | 81 } |
39 } | 82 } |
40 return node.body; | 83 return node.body; |
41 } | 84 } |
| 85 |
| 86 Expression getEnclosingExpression(Node node) { |
| 87 while (node is! Expression) { |
| 88 node = node.parent; |
| 89 } |
| 90 return node; |
| 91 } |
42 } | 92 } |
OLD | NEW |