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

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

Issue 1316673006: dart2js cps: Use TypeMaskSystem when inserting refinement nodes. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Remove unused ClassElement variable && rebase Created 5 years, 3 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/type_mask_system.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) 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 cps_ir.optimization.insert_refinements; 5 library cps_ir.optimization.insert_refinements;
6 6
7 import 'optimizers.dart' show Pass; 7 import 'optimizers.dart' show Pass;
8 import 'shrinking_reductions.dart' show ParentVisitor; 8 import 'shrinking_reductions.dart' show ParentVisitor;
9 import 'cps_ir_nodes.dart'; 9 import 'cps_ir_nodes.dart';
10 import '../types/types.dart';
11 import '../types/constants.dart'; 10 import '../types/constants.dart';
12 import '../constants/values.dart'; 11 import '../constants/values.dart';
13 import '../world.dart';
14 import '../common/names.dart'; 12 import '../common/names.dart';
15 import '../universe/universe.dart'; 13 import '../universe/universe.dart';
16 import '../elements/elements.dart'; 14 import '../elements/elements.dart';
15 import '../types/types.dart' show TypeMask;
16 import 'type_mask_system.dart';
17 17
18 /// Inserts [Refinement] nodes in the IR to allow for sparse path-sensitive 18 /// Inserts [Refinement] nodes in the IR to allow for sparse path-sensitive
19 /// type analysis in the [TypePropagator] pass. 19 /// type analysis in the [TypePropagator] pass.
20 /// 20 ///
21 /// Refinement nodes are inserted at the arms of a [Branch] node with a 21 /// Refinement nodes are inserted at the arms of a [Branch] node with a
22 /// condition of form `x is T` or `x == null`. 22 /// condition of form `x is T` or `x == null`.
23 /// 23 ///
24 /// Refinement nodes are inserted after a method invocation to refine the 24 /// Refinement nodes are inserted after a method invocation to refine the
25 /// receiver to the types that can respond to the given selector. 25 /// receiver to the types that can respond to the given selector.
26 class InsertRefinements extends RecursiveVisitor implements Pass { 26 class InsertRefinements extends RecursiveVisitor implements Pass {
27 String get passName => 'Insert refinement nodes'; 27 String get passName => 'Insert refinement nodes';
28 28
29 final TypesTask types; 29 final TypeMaskSystem types;
30 final World world;
31 final TypeMask nonNullType;
32 final TypeMask nullType;
33 30
34 /// Maps unrefined primitives to its refinement currently in scope (if any). 31 /// Maps unrefined primitives to its refinement currently in scope (if any).
35 final Map<Primitive, Refinement> refinementFor = <Primitive, Refinement>{}; 32 final Map<Primitive, Refinement> refinementFor = <Primitive, Refinement>{};
36 33
37 InsertRefinements(this.types, World world) 34 InsertRefinements(this.types);
38 : this.world = world,
39 nonNullType = new TypeMask.nonNullSubtype(world.objectClass, world),
40 nullType = new TypeMask.empty();
41 35
42 void rewrite(FunctionDefinition node) { 36 void rewrite(FunctionDefinition node) {
43 new ParentVisitor().visit(node); 37 new ParentVisitor().visit(node);
44 visit(node.body); 38 visit(node.body);
45 } 39 }
46 40
47 /// Updates references to refer to the refinement currently in scope. 41 /// Updates references to refer to the refinement currently in scope.
48 void processReference(Reference node) { 42 void processReference(Reference node) {
49 Refinement refined = refinementFor[node.definition]; 43 Refinement refined = refinementFor[node.definition];
50 if (refined != null) { 44 if (refined != null) {
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
127 // Sink the continuation to the call to ensure everything in scope 121 // Sink the continuation to the call to ensure everything in scope
128 // here is also in scope inside the continuations. 122 // here is also in scope inside the continuations.
129 sinkContinuationToUse(cont, node); 123 sinkContinuationToUse(cont, node);
130 124
131 if (node.selector.isClosureCall) { 125 if (node.selector.isClosureCall) {
132 // Do not try to refine the receiver of closure calls; the class world 126 // Do not try to refine the receiver of closure calls; the class world
133 // does not know about closure classes. 127 // does not know about closure classes.
134 push(cont); 128 push(cont);
135 } else { 129 } else {
136 // Filter away receivers that throw on this selector. 130 // Filter away receivers that throw on this selector.
137 TypeMask type = world.allFunctions.receiverType(node.selector, node.mask); 131 TypeMask type = types.receiverTypeFor(node.selector, node.mask);
138 pushRefinement(cont, new Refinement(receiver, type)); 132 pushRefinement(cont, new Refinement(receiver, type));
139 } 133 }
140 } 134 }
141 135
142 CallExpression getCallWithResult(Primitive prim) { 136 CallExpression getCallWithResult(Primitive prim) {
143 if (prim is Parameter && prim.parent is Continuation) { 137 if (prim is Parameter && prim.parent is Continuation) {
144 Continuation cont = prim.parent; 138 Continuation cont = prim.parent;
145 if (cont.hasExactlyOneUse && cont.firstRef.parent is CallExpression) { 139 if (cont.hasExactlyOneUse && cont.firstRef.parent is CallExpression) {
146 return cont.firstRef.parent; 140 return cont.firstRef.parent;
147 } 141 }
148 } 142 }
149 return null; 143 return null;
150 } 144 }
151 145
152 bool isTrue(Primitive prim) { 146 bool isTrue(Primitive prim) {
153 return prim is Constant && prim.value.isTrue; 147 return prim is Constant && prim.value.isTrue;
154 } 148 }
155 149
156 TypeMask getTypeOf(ConstantValue constant) {
157 return computeTypeMask(types.compiler, constant);
158 }
159
160 void visitBranch(Branch node) { 150 void visitBranch(Branch node) {
161 processReference(node.condition); 151 processReference(node.condition);
162 Primitive condition = node.condition.definition; 152 Primitive condition = node.condition.definition;
163 CallExpression call = getCallWithResult(condition); 153 CallExpression call = getCallWithResult(condition);
164 154
165 Continuation trueCont = node.trueContinuation.definition; 155 Continuation trueCont = node.trueContinuation.definition;
166 Continuation falseCont = node.falseContinuation.definition; 156 Continuation falseCont = node.falseContinuation.definition;
167 157
168 // Sink both continuations to the Branch to ensure everything in scope 158 // Sink both continuations to the Branch to ensure everything in scope
169 // here is also in scope inside the continuations. 159 // here is also in scope inside the continuations.
170 sinkContinuationToUse(trueCont, node); 160 sinkContinuationToUse(trueCont, node);
171 sinkContinuationToUse(falseCont, node); 161 sinkContinuationToUse(falseCont, node);
172 162
173 // If the condition is an 'is' check, promote the checked value. 163 // If the condition is an 'is' check, promote the checked value.
174 if (condition is TypeTest && condition.type.element is ClassElement) { 164 if (condition is TypeTest) {
175 Primitive value = condition.value.definition; 165 Primitive value = condition.value.definition;
176 ClassElement classElement = condition.type.element; 166 TypeMask type = types.subtypesOf(condition.type);
177 TypeMask type = new TypeMask.nonNullSubtype(classElement, world);
178 Primitive refinedValue = new Refinement(value, type); 167 Primitive refinedValue = new Refinement(value, type);
179 pushRefinement(trueCont, refinedValue); 168 pushRefinement(trueCont, refinedValue);
180 push(falseCont); 169 push(falseCont);
181 return; 170 return;
182 } 171 }
183 172
184 // If the condition is comparison with a constant, promote the other value. 173 // If the condition is comparison with a constant, promote the other value.
185 // This can happen either for calls to `==` or `identical` calls, such 174 // This can happen either for calls to `==` or `identical` calls, such
186 // as the ones inserted by the unsugaring pass. 175 // as the ones inserted by the unsugaring pass.
187 176
188 void refineEquality(Primitive first, 177 void refineEquality(Primitive first,
189 Primitive second, 178 Primitive second,
190 Continuation trueCont, 179 Continuation trueCont,
191 Continuation falseCont) { 180 Continuation falseCont) {
192 if (second is Constant && second.value.isNull) { 181 if (second is Constant && second.value.isNull) {
193 Refinement refinedTrue = new Refinement(first, nullType); 182 Refinement refinedTrue = new Refinement(first, types.nullType);
194 Refinement refinedFalse = new Refinement(first, nonNullType); 183 Refinement refinedFalse = new Refinement(first, types.nonNullType);
195 pushRefinement(trueCont, refinedTrue); 184 pushRefinement(trueCont, refinedTrue);
196 pushRefinement(falseCont, refinedFalse); 185 pushRefinement(falseCont, refinedFalse);
197 } else if (first is Constant && first.value.isNull) { 186 } else if (first is Constant && first.value.isNull) {
198 Refinement refinedTrue = new Refinement(second, nullType); 187 Refinement refinedTrue = new Refinement(second, types.nullType);
199 Refinement refinedFalse = new Refinement(second, nonNullType); 188 Refinement refinedFalse = new Refinement(second, types.nonNullType);
200 pushRefinement(trueCont, refinedTrue); 189 pushRefinement(trueCont, refinedTrue);
201 pushRefinement(falseCont, refinedFalse); 190 pushRefinement(falseCont, refinedFalse);
202 } else { 191 } else {
203 push(trueCont); 192 push(trueCont);
204 push(falseCont); 193 push(falseCont);
205 } 194 }
206 } 195 }
207 196
208 if (call is InvokeMethod && call.selector == Selectors.equals) { 197 if (call is InvokeMethod && call.selector == Selectors.equals) {
209 refineEquality(call.arguments[0].definition, 198 refineEquality(call.arguments[0].definition,
(...skipping 24 matching lines...) Expand all
234 cont.firstRef.parent is Branch)) { 223 cont.firstRef.parent is Branch)) {
235 // Do not push the continuation here. 224 // Do not push the continuation here.
236 // visitInvokeMethod and visitBranch will do that. 225 // visitInvokeMethod and visitBranch will do that.
237 } else { 226 } else {
238 push(cont); 227 push(cont);
239 } 228 }
240 } 229 }
241 return node.body; 230 return node.body;
242 } 231 }
243 } 232 }
OLDNEW
« no previous file with comments | « no previous file | pkg/compiler/lib/src/cps_ir/type_mask_system.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698