Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(213)

Side by Side Diff: pkg/compiler/lib/src/cps_ir/duplicate_branch.dart

Issue 1655183002: dart2js cps: Remove interceptors in cases where type propagation fails. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | pkg/compiler/lib/src/cps_ir/optimizers.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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.duplicate_branch; 4 library dart2js.cps_ir.duplicate_branch; // FIXME: Rename file.
asgerf 2016/02/02 15:30:59 Will rename before committing.
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';
10 import '../constants/values.dart';
11 import '../elements/elements.dart';
12 import '../universe/selector.dart';
13 import '../types/types.dart';
14 import 'type_mask_system.dart';
9 15
16 /// Optimizations based on intraprocedural forward dataflow analysis, taking
17 /// into account path information that is not expressed by [Refinement] nodes.
18 ///
19 /// ---
20 ///
10 /// Removes branches that branch on the same value as a previously seen branch. 21 /// Removes branches that branch on the same value as a previously seen branch.
11 /// For example: 22 /// For example:
12 /// 23 ///
13 /// if (x == y) { 24 /// if (x == y) {
14 /// if (x == y) TRUE else FALSE 25 /// if (x == y) TRUE else FALSE
15 /// } 26 /// }
16 /// 27 ///
17 /// ==> ([GVN] pass merges identical expressions) 28 /// ==> ([GVN] pass merges identical expressions)
18 /// 29 ///
19 /// var b = (x == y) 30 /// var b = (x == y)
20 /// if (b) { 31 /// if (b) {
21 /// if (b) TRUE else FALSE 32 /// if (b) TRUE else FALSE
22 /// } 33 /// }
23 /// 34 ///
24 /// ==> (this pass removes the duplicate branch) 35 /// ==> (this pass removes the duplicate branch)
25 /// 36 ///
26 /// var b = (x == y) 37 /// var b = (x == y)
27 /// if (b) { 38 /// if (b) {
28 /// TRUE 39 /// TRUE
29 /// } 40 /// }
41 ///
42 /// ---
43 ///
44 /// Removes interceptors for method calls whose receiver is known to be a
45 /// self-interceptor. For example:
46 ///
47 /// x.foo$1();
48 /// getInterceptor(x).$eq(x, y);
49 ///
50 /// ==> (`x` is a self-interceptor, remove the `getInterceptor` call)
51 ///
52 /// x.foo$1();
53 /// x.$eq(0, y);
54 ///
55 /// Although there is a [Refinement] node after the call to `x.foo$1()`, the
56 /// refined type cannot always be represented exactly, and type propagation
57 /// may therefore not see that `x` is a self-interceptor.
30 // 58 //
31 // TODO(asgerf): A kind of redundant join can arise where a branching condition 59 // TODO(asgerf): A kind of redundant join can arise where a branching condition
32 // is known to be true/false on all but one predecessor for a branch. We could 60 // is known to be true/false on all but one predecessor for a branch. We could
33 // try to reduce those. 61 // try to reduce those.
34 // 62 //
35 // TODO(asgerf): Could be more precise if GVN shared expressions that are not 63 // TODO(asgerf): Could be more precise if GVN shared expressions that are not
36 // in direct scope of one another, e.g. by using phis pass the shared value. 64 // in direct scope of one another, e.g. by using phis pass the shared value.
37 // 65 //
38 class DuplicateBranchEliminator extends TrampolineRecursiveVisitor 66 class PathBasedOptimizer extends TrampolineRecursiveVisitor
39 implements Pass { 67 implements Pass {
40 String get passName => 'Duplicate branch elimination'; 68 String get passName => 'Path-based optimizations';
41 69
70 // Classification of all values.
42 static const int TRUE = 1 << 0; 71 static const int TRUE = 1 << 0;
43 static const int OTHER_TRUTHY = 1 << 1; 72 static const int SELF_INTERCEPTOR = 1 << 1;
44 static const int FALSE = 1 << 2; 73 static const int INTERCEPTED_TRUTHY = 1 << 2;
45 static const int OTHER_FALSY = 1 << 3; 74 static const int FALSE = 1 << 3;
75 static const int OTHER_FALSY = 1 << 4;
46 76
47 static const int TRUTHY = TRUE | OTHER_TRUTHY; 77 static const int TRUTHY = TRUE | SELF_INTERCEPTOR | INTERCEPTED_TRUTHY;
48 static const int FALSY = FALSE | OTHER_FALSY; 78 static const int FALSY = FALSE | OTHER_FALSY;
49 static const int ANY = TRUTHY | FALSY; 79 static const int ANY = TRUTHY | FALSY;
50 80
81 final JavaScriptBackend backend;
82 final TypeMaskSystem typeSystem;
83
84 PathBasedOptimizer(this.backend, this.typeSystem);
85
51 /// The possible values of the given primitive (or ANY if absent) at the 86 /// The possible values of the given primitive (or ANY if absent) at the
52 /// current traversal position. 87 /// current traversal position.
53 Map<Primitive, int> valueOf = <Primitive, int>{}; 88 Map<Primitive, int> valueOf = <Primitive, int>{};
54 89
55 /// The possible values of each primitive at the entry to a continuation. 90 /// The possible values of each primitive at the entry to a continuation.
56 /// 91 ///
57 /// Unreachable continuations are absent from the map. 92 /// Unreachable continuations are absent from the map.
58 final Map<Continuation, Map<Primitive, int>> valuesAt = 93 final Map<Continuation, Map<Primitive, int>> valuesAt =
59 <Continuation, Map<Primitive, int>>{}; 94 <Continuation, Map<Primitive, int>>{};
60 95
(...skipping 13 matching lines...) Expand all
74 109
75 Expression traverseContinuation(Continuation cont) { 110 Expression traverseContinuation(Continuation cont) {
76 valueOf = valuesAt[cont]; 111 valueOf = valuesAt[cont];
77 if (valueOf == null) { 112 if (valueOf == null) {
78 // Do not go into unreachable code. 113 // Do not go into unreachable code.
79 destroyAndReplace(cont.body, new Unreachable()); 114 destroyAndReplace(cont.body, new Unreachable());
80 } 115 }
81 return cont.body; 116 return cont.body;
82 } 117 }
83 118
119 /// Returns the possible targets of [selector] when invoked on a receiver
120 /// of type [receiverType].
121 Iterable<Element> getAllTargets(TypeMask receiverType, Selector selector) {
122 return backend.compiler.world.allFunctions.filter(selector, receiverType);
123 }
124
84 void visitInvokeContinuation(InvokeContinuation node) { 125 void visitInvokeContinuation(InvokeContinuation node) {
85 Continuation cont = node.continuation.definition; 126 Continuation cont = node.continuation.definition;
86 if (cont.isReturnContinuation) return; 127 if (cont.isReturnContinuation) return;
87 if (node.isRecursive) return; 128 if (node.isRecursive) return;
88 Map<Primitive, int> target = valuesAt[cont]; 129 Map<Primitive, int> target = valuesAt[cont];
89 if (target == null) { 130 if (target == null) {
90 valuesAt[cont] = valueOf; 131 valuesAt[cont] = valueOf;
91 } else { 132 } else {
92 for (Primitive prim in target.keys) { 133 for (Primitive prim in target.keys) {
93 target[prim] |= valueOf[prim] ?? ANY; 134 target[prim] |= valueOf[prim] ?? ANY;
(...skipping 19 matching lines...) Expand all
113 destroyAndReplace(node, new InvokeContinuation(falseCont, [])); 154 destroyAndReplace(node, new InvokeContinuation(falseCont, []));
114 valuesAt[falseCont] = valueOf; 155 valuesAt[falseCont] = valueOf;
115 } else if (values & negativeValues == 0) { 156 } else if (values & negativeValues == 0) {
116 destroyAndReplace(node, new InvokeContinuation(trueCont, [])); 157 destroyAndReplace(node, new InvokeContinuation(trueCont, []));
117 valuesAt[trueCont] = valueOf; 158 valuesAt[trueCont] = valueOf;
118 } else { 159 } else {
119 valuesAt[trueCont] = copy(valueOf)..[condition] = values & positiveValues; 160 valuesAt[trueCont] = copy(valueOf)..[condition] = values & positiveValues;
120 valuesAt[falseCont] = valueOf..[condition] = values & negativeValues; 161 valuesAt[falseCont] = valueOf..[condition] = values & negativeValues;
121 } 162 }
122 } 163 }
164
165 void visitInvokeMethod(InvokeMethod node) {
166 int receiverValue = valueOf[node.dartReceiver] ?? ANY;
167 if (!backend.isInterceptedSelector(node.selector)) {
168 // Only self-interceptors can respond to a non-intercepted selector.
169 valueOf[node.dartReceiver] = receiverValue & SELF_INTERCEPTOR;
170 } else if (receiverValue & ~SELF_INTERCEPTOR == 0 &&
171 node.callingConvention == CallingConvention.Intercepted) {
172 // This is an intercepted call whose receiver is definitely a
173 // self-interceptor.
174 // TODO(25646): If TypeMasks could represent "any self-interceptor" this
175 // optimization should be subsumed by type propagation.
176 node.receiver.changeTo(node.dartReceiver);
177
178 // Replace the extra receiver argument with a dummy value if the
179 // target definitely does not use it.
180 if (typeSystem.targetIgnoresReceiverArgument(node.dartReceiver.type,
181 node.selector)) {
182 Constant dummy = new Constant(new IntConstantValue(0))
183 ..type = typeSystem.intType;
184 new LetPrim(dummy).insertAbove(node.parent);
185 node.arguments[0].changeTo(dummy);
186 node.callingConvention = CallingConvention.DummyIntercepted;
187 }
188 }
189 }
123 } 190 }
OLDNEW
« no previous file with comments | « no previous file | pkg/compiler/lib/src/cps_ir/optimizers.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698