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

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

Issue 1525163002: dart2js cps: Use oneshot interceptors and 'instanceof' expressions. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Merge Created 5 years 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
OLDNEW
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.optimize_interceptors; 5 library dart2js.cps_ir.optimize_interceptors;
6 6
7 import 'optimizers.dart'; 7 import 'optimizers.dart';
8 import 'cps_ir_nodes.dart'; 8 import 'cps_ir_nodes.dart';
9 import 'loop_hierarchy.dart'; 9 import 'loop_hierarchy.dart';
10 import 'cps_fragment.dart'; 10 import 'cps_fragment.dart';
11 import '../constants/values.dart'; 11 import '../constants/values.dart';
12 import '../elements/elements.dart'; 12 import '../elements/elements.dart';
13 import '../js_backend/backend_helpers.dart' show BackendHelpers; 13 import '../js_backend/backend_helpers.dart' show BackendHelpers;
14 import '../js_backend/js_backend.dart' show JavaScriptBackend; 14 import '../js_backend/js_backend.dart' show JavaScriptBackend;
15 import '../types/types.dart' show TypeMask; 15 import '../types/types.dart' show TypeMask;
16 import '../io/source_information.dart' show SourceInformation; 16 import '../io/source_information.dart' show SourceInformation;
17 import '../universe/selector.dart';
17 18
18 /// Replaces `getInterceptor` calls with interceptor constants when possible, 19 /// Replaces `getInterceptor` calls with interceptor constants when possible,
19 /// or with "almost constant" expressions like "x && CONST" when the input 20 /// or with "almost constant" expressions like "x && CONST" when the input
20 /// is either null or has a known interceptor. 21 /// is either null or has a known interceptor.
21 // 22 //
22 // TODO(asgerf): Compute intercepted classes in this pass. 23 // TODO(asgerf): Compute intercepted classes in this pass.
23 class OptimizeInterceptors extends TrampolineRecursiveVisitor implements Pass { 24 class OptimizeInterceptors extends TrampolineRecursiveVisitor implements Pass {
24 String get passName => 'Optimize interceptors'; 25 String get passName => 'Optimize interceptors';
25 26
26 JavaScriptBackend backend; 27 JavaScriptBackend backend;
27 LoopHierarchy loopHierarchy; 28 LoopHierarchy loopHierarchy;
28 Continuation currentLoopHeader; 29 Continuation currentLoopHeader;
29 30
30 OptimizeInterceptors(this.backend); 31 OptimizeInterceptors(this.backend);
31 32
32 BackendHelpers get helpers => backend.helpers; 33 BackendHelpers get helpers => backend.helpers;
33 34
35 Map<Interceptor, Continuation> loopHeaderFor = <Interceptor, Continuation>{};
36
34 void rewrite(FunctionDefinition node) { 37 void rewrite(FunctionDefinition node) {
35 // TODO(asgerf): Computing the LoopHierarchy here may be overkill when all 38 // TODO(asgerf): Computing the LoopHierarchy here may be overkill when all
36 // we want is to hoist constants out of loops. 39 // we want is to hoist constants out of loops.
37 loopHierarchy = new LoopHierarchy(node); 40 loopHierarchy = new LoopHierarchy(node);
38 visit(node.body); 41 visit(node.body);
39 new ShareConstants().visit(node); 42 new ShareConstants().visit(node);
40 } 43 }
41 44
42 @override 45 @override
43 Expression traverseContinuation(Continuation cont) { 46 Expression traverseContinuation(Continuation cont) {
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
94 Continuation loop = getCurrentOuterLoop(); 97 Continuation loop = getCurrentOuterLoop();
95 if (loop != null) { 98 if (loop != null) {
96 LetCont loopBinding = loop.parent; 99 LetCont loopBinding = loop.parent;
97 letPrim.insertAbove(loopBinding); 100 letPrim.insertAbove(loopBinding);
98 } else { 101 } else {
99 letPrim.insertAbove(useSite); 102 letPrim.insertAbove(useSite);
100 } 103 }
101 return prim; 104 return prim;
102 } 105 }
103 106
104 void constifyInterceptor(Interceptor interceptor) { 107 bool constifyInterceptor(Interceptor interceptor) {
105 LetPrim let = interceptor.parent; 108 LetPrim let = interceptor.parent;
106 InterceptorConstantValue constant = getInterceptorConstant(interceptor); 109 InterceptorConstantValue constant = getInterceptorConstant(interceptor);
107 110
108 if (constant == null) return; 111 if (constant == null) return false;
109 112
110 if (interceptor.isAlwaysIntercepted) { 113 if (interceptor.isAlwaysIntercepted) {
111 Primitive constantPrim = makeConstantFor(constant, 114 Primitive constantPrim = makeConstantFor(constant,
112 useSite: let, 115 useSite: let,
113 type: interceptor.type, 116 type: interceptor.type,
114 sourceInformation: interceptor.sourceInformation); 117 sourceInformation: interceptor.sourceInformation);
115 constantPrim.useElementAsHint(interceptor.hint); 118 constantPrim.useElementAsHint(interceptor.hint);
116 interceptor..replaceUsesWith(constantPrim)..destroy(); 119 interceptor..replaceUsesWith(constantPrim)..destroy();
117 let.remove(); 120 let.remove();
118 } else if (interceptor.isAlwaysNullOrIntercepted) { 121 } else if (interceptor.isAlwaysNullOrIntercepted) {
(...skipping 15 matching lines...) Expand all
134 BuiltinOperator.LooseEq, 137 BuiltinOperator.LooseEq,
135 [input, cps.makeNull()]); 138 [input, cps.makeNull()]);
136 cps.ifTruthy(condition).invokeContinuation(cont, [input]); 139 cps.ifTruthy(condition).invokeContinuation(cont, [input]);
137 } 140 }
138 cps.invokeContinuation(cont, [constantPrim]); 141 cps.invokeContinuation(cont, [constantPrim]);
139 cps.context = cont; 142 cps.context = cont;
140 cps.insertAbove(let); 143 cps.insertAbove(let);
141 interceptor..replaceUsesWith(param)..destroy(); 144 interceptor..replaceUsesWith(param)..destroy();
142 let.remove(); 145 let.remove();
143 } 146 }
147 return true;
144 } 148 }
145 149
146 @override 150 @override
147 Expression traverseLetPrim(LetPrim node) { 151 Expression traverseLetPrim(LetPrim node) {
148 Expression next = node.body; 152 Expression next = node.body;
149 if (node.primitive is Interceptor) { 153 visit(node.primitive);
150 constifyInterceptor(node.primitive); 154 return next;
155 }
156
157 @override
158 void visitInterceptor(Interceptor node) {
159 if (constifyInterceptor(node)) return;
160 if (node.hasExactlyOneUse) {
161 // Set the loop header on single-use interceptors so [visitInvokeMethod]
162 // can determine if it should become a one-shot interceptor.
163 loopHeaderFor[node] = currentLoopHeader;
151 } 164 }
152 return next; 165 }
166
167 @override
168 void visitInvokeMethod(InvokeMethod node) {
169 if (node.callingConvention != CallingConvention.Intercepted) return;
170 Primitive interceptor = node.receiver.definition;
171 if (interceptor is! Interceptor ||
172 interceptor.hasMultipleUses ||
173 loopHeaderFor[interceptor] != currentLoopHeader) {
174 return;
175 }
176 // TODO(asgerf): Consider heuristics for when to use one-shot interceptors.
177 // E.g. using only one-shot interceptors with a fast path.
178 node.callingConvention = CallingConvention.OneShotIntercepted;
179 node..receiver.unlink()..receiver = node.arguments.removeAt(0);
180 }
181
182 @override
183 void visitTypeTestViaFlag(TypeTestViaFlag node) {
184 Primitive interceptor = node.interceptor.definition;
185 if (interceptor is! Interceptor ||
186 interceptor.hasMultipleUses ||
187 loopHeaderFor[interceptor] != currentLoopHeader ||
188 !backend.mayGenerateInstanceofCheck(node.dartType)) {
189 return;
190 }
191 Interceptor inter = interceptor;
192 Primitive value = inter.input.definition;
193 node.replaceWith(new TypeTest(value, node.dartType, [])..type = node.type);
153 } 194 }
154 } 195 }
155 196
156 /// Shares interceptor constants when one is in scope of another. 197 /// Shares interceptor constants when one is in scope of another.
157 /// 198 ///
158 /// Interceptor optimization runs after GVN, hence this clean-up step is needed. 199 /// Interceptor optimization runs after GVN, hence this clean-up step is needed.
159 /// 200 ///
160 /// TODO(asgerf): Handle in separate constant optimization pass? With some other 201 /// TODO(asgerf): Handle in separate constant optimization pass? With some other
161 /// constant-related optimizations, like cloning small constants at use-site. 202 /// constant-related optimizations, like cloning small constants at use-site.
162 class ShareConstants extends TrampolineRecursiveVisitor { 203 class ShareConstants extends TrampolineRecursiveVisitor {
(...skipping 16 matching lines...) Expand all
179 sharedConstantFor.remove(prim.value); 220 sharedConstantFor.remove(prim.value);
180 }); 221 });
181 } 222 }
182 return next; 223 return next;
183 } 224 }
184 225
185 bool shouldShareConstant(Constant constant) { 226 bool shouldShareConstant(Constant constant) {
186 return constant.value.isInterceptor; 227 return constant.value.isInterceptor;
187 } 228 }
188 } 229 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart ('k') | pkg/compiler/lib/src/js_backend/codegen/codegen.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698