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

Side by Side Diff: lib/compiler/implementation/ssa/optimize.dart

Issue 10827180: Move types out of the HInstructions. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Address comments. Created 8 years, 4 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 | Annotate | Revision Log
« no previous file with comments | « lib/compiler/implementation/ssa/nodes.dart ('k') | lib/compiler/implementation/ssa/tracer.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) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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 interface OptimizationPhase { 5 interface OptimizationPhase {
6 String get name(); 6 String get name();
7 void visitGraph(HGraph graph); 7 void visitGraph(HGraph graph);
8 } 8 }
9 9
10 class SsaOptimizerTask extends CompilerTask { 10 class SsaOptimizerTask extends CompilerTask {
11 final JavaScriptBackend backend; 11 final JavaScriptBackend backend;
12 SsaOptimizerTask(JavaScriptBackend backend) 12 SsaOptimizerTask(JavaScriptBackend backend)
13 : this.backend = backend, 13 : this.backend = backend,
14 super(backend.compiler); 14 super(backend.compiler);
15 String get name() => 'SSA optimizer'; 15 String get name() => 'SSA optimizer';
16 Compiler get compiler() => backend.compiler; 16 Compiler get compiler() => backend.compiler;
17 17
18 void runPhases(HGraph graph, List<OptimizationPhase> phases) { 18 void runPhases(HGraph graph, List<OptimizationPhase> phases) {
19 for (OptimizationPhase phase in phases) { 19 for (OptimizationPhase phase in phases) {
20 phase.visitGraph(graph); 20 runPhase(graph, phase);
21 compiler.tracer.traceGraph(phase.name, graph);
22 } 21 }
23 } 22 }
24 23
24 void runPhase(HGraph graph, OptimizationPhase phase) {
25 phase.visitGraph(graph);
26 compiler.tracer.traceGraph(phase.name, graph);
27 }
28
25 void optimize(WorkItem work, HGraph graph) { 29 void optimize(WorkItem work, HGraph graph) {
30 JavaScriptItemCompilationContext context = work.compilationContext;
31 HTypeMap types = context.types;
26 measure(() { 32 measure(() {
27 List<OptimizationPhase> phases = <OptimizationPhase>[ 33 List<OptimizationPhase> phases = <OptimizationPhase>[
28 // Run trivial constant folding first to optimize 34 // Run trivial constant folding first to optimize
29 // some patterns useful for type conversion. 35 // some patterns useful for type conversion.
30 new SsaConstantFolder(backend, work), 36 new SsaConstantFolder(backend, work, types),
31 new SsaTypeConversionInserter(compiler), 37 new SsaTypeConversionInserter(compiler),
32 new SsaTypePropagator(compiler), 38 new SsaTypePropagator(compiler, types),
33 new SsaCheckInserter(backend), 39 new SsaCheckInserter(backend, types),
34 new SsaConstantFolder(backend, work), 40 new SsaConstantFolder(backend, work, types),
35 new SsaRedundantPhiEliminator(), 41 new SsaRedundantPhiEliminator(),
36 new SsaDeadPhiEliminator(), 42 new SsaDeadPhiEliminator(),
37 new SsaGlobalValueNumberer(compiler), 43 new SsaGlobalValueNumberer(compiler, types),
38 new SsaCodeMotion(), 44 new SsaCodeMotion(),
39 new SsaDeadCodeEliminator(), 45 new SsaDeadCodeEliminator(types),
40 new SsaRegisterRecompilationCandidates(backend, work)]; 46 new SsaRegisterRecompilationCandidates(backend, work, types)];
41 runPhases(graph, phases); 47 runPhases(graph, phases);
42 }); 48 });
43 } 49 }
44 50
45 bool trySpeculativeOptimizations(WorkItem work, HGraph graph) { 51 bool trySpeculativeOptimizations(WorkItem work, HGraph graph) {
52 JavaScriptItemCompilationContext context = work.compilationContext;
53 HTypeMap types = context.types;
46 return measure(() { 54 return measure(() {
47 // Run the phases that will generate type guards. 55 // Run the phases that will generate type guards.
48 List<OptimizationPhase> phases = <OptimizationPhase>[ 56 List<OptimizationPhase> phases = <OptimizationPhase>[
49 new SsaRecompilationFieldTypePropagator(backend, work), 57 new SsaRecompilationFieldTypePropagator(backend, work, types),
50 new SsaSpeculativeTypePropagator(compiler), 58 new SsaSpeculativeTypePropagator(compiler, types),
51 new SsaTypeGuardInserter(compiler, work), 59 new SsaTypeGuardInserter(compiler, work, types),
52 new SsaEnvironmentBuilder(compiler), 60 new SsaEnvironmentBuilder(compiler),
53 // Change the propagated types back to what they were before we 61 // Change the propagated types back to what they were before we
54 // speculatively propagated, so that we can generate the bailout 62 // speculatively propagated, so that we can generate the bailout
55 // version. 63 // version.
56 // Note that we do this even if there were no guards inserted. If a 64 // Note that we do this even if there were no guards inserted. If a
57 // guard is not beneficial enough we don't emit one, but there might 65 // guard is not beneficial enough we don't emit one, but there might
58 // still be speculative types on the instructions. 66 // still be speculative types on the instructions.
59 new SsaTypePropagator(compiler), 67 new SsaTypePropagator(compiler, types),
60 // Then run the [SsaCheckInserter] because the type propagator also 68 // Then run the [SsaCheckInserter] because the type propagator also
61 // propagated types non-speculatively. For example, it might have 69 // propagated types non-speculatively. For example, it might have
62 // propagated the type array for a call to the List constructor. 70 // propagated the type array for a call to the List constructor.
63 new SsaCheckInserter(backend)]; 71 new SsaCheckInserter(backend, types)];
64 runPhases(graph, phases); 72 runPhases(graph, phases);
65 return !work.guards.isEmpty(); 73 return !work.guards.isEmpty();
66 }); 74 });
67 } 75 }
68 76
69 void prepareForSpeculativeOptimizations(WorkItem work, HGraph graph) { 77 void prepareForSpeculativeOptimizations(WorkItem work, HGraph graph) {
78 JavaScriptItemCompilationContext context = work.compilationContext;
79 HTypeMap types = context.types;
70 measure(() { 80 measure(() {
71 // In order to generate correct code for the bailout version, we did not 81 // In order to generate correct code for the bailout version, we did not
72 // propagate types from the instruction to the type guard. We do it 82 // propagate types from the instruction to the type guard. We do it
73 // now to be able to optimize further. 83 // now to be able to optimize further.
74 work.guards.forEach((HTypeGuard guard) { guard.isEnabled = true; }); 84 work.guards.forEach((HTypeGuard guard) { guard.isEnabled = true; });
75 // We also need to insert range and integer checks for the type 85 // We also need to insert range and integer checks for the type
76 // guards. Now that they claim to have a certain type, some 86 // guards. Now that they claim to have a certain type, some
77 // depending instructions might become builtin (like native array 87 // depending instructions might become builtin (like native array
78 // accesses) and need to be checked. 88 // accesses) and need to be checked.
79 // Also run the type propagator, to please the codegen in case 89 // Also run the type propagator, to please the codegen in case
80 // no other optimization is run. 90 // no other optimization is run.
81 runPhases(graph, 91 runPhases(graph,
82 <OptimizationPhase>[new SsaCheckInserter(backend), 92 <OptimizationPhase>[new SsaCheckInserter(backend, types),
83 new SsaTypePropagator(compiler)]); 93 new SsaTypePropagator(compiler, types)]);
84 }); 94 });
85 } 95 }
86 } 96 }
87 97
88 /** 98 /**
89 * If both inputs to known operations are available execute the operation at 99 * If both inputs to known operations are available execute the operation at
90 * compile-time. 100 * compile-time.
91 */ 101 */
92 class SsaConstantFolder extends HBaseVisitor implements OptimizationPhase { 102 class SsaConstantFolder extends HBaseVisitor implements OptimizationPhase {
93 final String name = "SsaConstantFolder"; 103 final String name = "SsaConstantFolder";
94 final JavaScriptBackend backend; 104 final JavaScriptBackend backend;
95 final WorkItem work; 105 final WorkItem work;
106 final HTypeMap types;
96 HGraph graph; 107 HGraph graph;
97 Compiler get compiler() => backend.compiler; 108 Compiler get compiler() => backend.compiler;
98 109
99 SsaConstantFolder(this.backend, this.work); 110 SsaConstantFolder(this.backend, this.work, this.types);
100 111
101 void visitGraph(HGraph visitee) { 112 void visitGraph(HGraph visitee) {
102 graph = visitee; 113 graph = visitee;
103 visitDominatorTree(visitee); 114 visitDominatorTree(visitee);
104 } 115 }
105 116
106 visitBasicBlock(HBasicBlock block) { 117 visitBasicBlock(HBasicBlock block) {
107 HInstruction instruction = block.first; 118 HInstruction instruction = block.first;
108 while (instruction !== null) { 119 while (instruction !== null) {
109 HInstruction next = instruction.next; 120 HInstruction next = instruction.next;
110 HInstruction replacement = instruction.accept(this); 121 HInstruction replacement = instruction.accept(this);
111 if (replacement !== instruction) { 122 if (replacement !== instruction) {
112 if (!replacement.isInBasicBlock()) { 123 if (!replacement.isInBasicBlock()) {
113 // The constant folding can return an instruction that is already 124 // The constant folding can return an instruction that is already
114 // part of the graph (like an input), so we only add the replacement 125 // part of the graph (like an input), so we only add the replacement
115 // if necessary. 126 // if necessary.
116 block.addAfter(instruction, replacement); 127 block.addAfter(instruction, replacement);
117 } 128 }
118 block.rewrite(instruction, replacement); 129 block.rewrite(instruction, replacement);
119 block.remove(instruction); 130 block.remove(instruction);
120 // If the replacement instruction does not know its type or 131 // If the replacement instruction does not know its type or
121 // source element yet, use the type and source element of the 132 // source element yet, use the type and source element of the
122 // instruction. 133 // instruction.
123 if (!replacement.propagatedType.isUseful()) { 134 if (!types[replacement].isUseful()) {
124 replacement.propagatedType = instruction.propagatedType; 135 types[replacement] = types[instruction];
125 } 136 }
126 if (replacement.sourceElement === null) { 137 if (replacement.sourceElement === null) {
127 replacement.sourceElement = instruction.sourceElement; 138 replacement.sourceElement = instruction.sourceElement;
128 } 139 }
129 } 140 }
130 instruction = next; 141 instruction = next;
131 } 142 }
132 } 143 }
133 144
134 HInstruction visitInstruction(HInstruction node) { 145 HInstruction visitInstruction(HInstruction node) {
135 return node; 146 return node;
136 } 147 }
137 148
138 HInstruction visitBoolify(HBoolify node) { 149 HInstruction visitBoolify(HBoolify node) {
139 List<HInstruction> inputs = node.inputs; 150 List<HInstruction> inputs = node.inputs;
140 assert(inputs.length == 1); 151 assert(inputs.length == 1);
141 HInstruction input = inputs[0]; 152 HInstruction input = inputs[0];
142 if (input.isBoolean()) return input; 153 if (input.isBoolean(types)) return input;
143 // All values !== true are boolified to false. 154 // All values !== true are boolified to false.
144 Type type = input.propagatedType.computeType(compiler); 155 Type type = types[input].computeType(compiler);
145 if (type !== null && type.element !== compiler.boolClass) { 156 if (type !== null && type.element !== compiler.boolClass) {
146 return graph.addConstantBool(false); 157 return graph.addConstantBool(false);
147 } 158 }
148 return node; 159 return node;
149 } 160 }
150 161
151 HInstruction visitNot(HNot node) { 162 HInstruction visitNot(HNot node) {
152 List<HInstruction> inputs = node.inputs; 163 List<HInstruction> inputs = node.inputs;
153 assert(inputs.length == 1); 164 assert(inputs.length == 1);
154 HInstruction input = inputs[0]; 165 HInstruction input = inputs[0];
(...skipping 29 matching lines...) Expand all
184 HConstant constantInput = input; 195 HConstant constantInput = input;
185 ListConstant constant = constantInput.constant; 196 ListConstant constant = constantInput.constant;
186 return graph.addConstantInt(constant.length); 197 return graph.addConstantInt(constant.length);
187 } else if (input.isConstantMap()) { 198 } else if (input.isConstantMap()) {
188 HConstant constantInput = input; 199 HConstant constantInput = input;
189 MapConstant constant = constantInput.constant; 200 MapConstant constant = constantInput.constant;
190 return graph.addConstantInt(constant.length); 201 return graph.addConstantInt(constant.length);
191 } 202 }
192 } 203 }
193 204
194 if (input.isString() 205 if (input.isString(types)
195 && node.name == const SourceString('toString')) { 206 && node.name == const SourceString('toString')) {
196 return node.inputs[1]; 207 return node.inputs[1];
197 } 208 }
198 209
199 if (!input.canBePrimitive() && !node.getter && !node.setter) { 210 if (!input.canBePrimitive(types) && !node.getter && !node.setter) {
200 bool transformToDynamicInvocation = true; 211 bool transformToDynamicInvocation = true;
201 if (input.canBeNull()) { 212 if (input.canBeNull(types)) {
202 // Check if the method exists on Null. If yes we must not transform 213 // Check if the method exists on Null. If yes we must not transform
203 // the static interceptor call to a dynamic invocation. 214 // the static interceptor call to a dynamic invocation.
204 // TODO(floitsch): get a list of methods that exist on 'null' and only 215 // TODO(floitsch): get a list of methods that exist on 'null' and only
205 // bail out on them. 216 // bail out on them.
206 transformToDynamicInvocation = false; 217 transformToDynamicInvocation = false;
207 } 218 }
208 if (transformToDynamicInvocation) { 219 if (transformToDynamicInvocation) {
209 return fromInterceptorToDynamicInvocation(node, node.selector); 220 return fromInterceptorToDynamicInvocation(node, node.selector);
210 } 221 }
211 } 222 }
212 223
213 return node; 224 return node;
214 } 225 }
215 226
216 HInstruction visitInvokeDynamic(HInvokeDynamic node) { 227 HInstruction visitInvokeDynamic(HInvokeDynamic node) {
217 HType receiverType = node.receiver.propagatedType; 228 HType receiverType = types[node.receiver];
218 if (receiverType.isExact()) { 229 if (receiverType.isExact()) {
219 HBoundedType type = receiverType; 230 HBoundedType type = receiverType;
220 Element element = type.lookupMember(node.name); 231 Element element = type.lookupMember(node.name);
221 // TODO(ngeoffray): Also fold if it's a getter or variable. 232 // TODO(ngeoffray): Also fold if it's a getter or variable.
222 if (element != null && element.isFunction()) { 233 if (element != null && element.isFunction()) {
223 if (node.selector.applies(element, compiler)) { 234 if (node.selector.applies(element, compiler)) {
224 FunctionElement method = element; 235 FunctionElement method = element;
225 FunctionSignature parameters = method.computeSignature(compiler); 236 FunctionSignature parameters = method.computeSignature(compiler);
226 if (parameters.optionalParameterCount == 0) { 237 if (parameters.optionalParameterCount == 0) {
227 node.element = element; 238 node.element = element;
228 } 239 }
229 // TODO(ngeoffray): If the method has optional parameters, 240 // TODO(ngeoffray): If the method has optional parameters,
230 // we should pass the default values here. 241 // we should pass the default values here.
231 } 242 }
232 } 243 }
233 } 244 }
234 return node; 245 return node;
235 } 246 }
236 247
237 HInstruction fromInterceptorToDynamicInvocation(HInvokeStatic node, 248 HInstruction fromInterceptorToDynamicInvocation(HInvokeStatic node,
238 Selector selector) { 249 Selector selector) {
239 HBoundedType type = node.inputs[1].propagatedType; 250 HBoundedType type = types[node.inputs[1]];
240 HInvokeDynamicMethod result = new HInvokeDynamicMethod( 251 HInvokeDynamicMethod result = new HInvokeDynamicMethod(
241 selector, 252 selector,
242 selector.name, 253 selector.name,
243 node.inputs.getRange(1, node.inputs.length - 1)); 254 node.inputs.getRange(1, node.inputs.length - 1));
244 if (type.isExact()) { 255 if (type.isExact()) {
245 HBoundedType concrete = type; 256 HBoundedType concrete = type;
246 result.element = concrete.lookupMember(selector.name); 257 result.element = concrete.lookupMember(selector.name);
247 } 258 }
248 return result; 259 return result;
249 } 260 }
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
281 } 292 }
282 return node; 293 return node;
283 } 294 }
284 node.staticChecks = HBoundsCheck.ALWAYS_ABOVE_ZERO; 295 node.staticChecks = HBoundsCheck.ALWAYS_ABOVE_ZERO;
285 } 296 }
286 return node; 297 return node;
287 } 298 }
288 299
289 HInstruction visitIntegerCheck(HIntegerCheck node) { 300 HInstruction visitIntegerCheck(HIntegerCheck node) {
290 HInstruction value = node.value; 301 HInstruction value = node.value;
291 if (value.isInteger()) return value; 302 if (value.isInteger(types)) return value;
292 if (value.isConstant()) { 303 if (value.isConstant()) {
293 assert((){ 304 assert((){
294 HConstant constantInstruction = value; 305 HConstant constantInstruction = value;
295 return !constantInstruction.constant.isInt(); 306 return !constantInstruction.constant.isInt();
296 }); 307 });
297 node.alwaysFalse = true; 308 node.alwaysFalse = true;
298 } 309 }
299 return node; 310 return node;
300 } 311 }
301 312
302 313
303 HInstruction visitIndex(HIndex node) { 314 HInstruction visitIndex(HIndex node) {
304 if (!node.receiver.canBePrimitive()) { 315 if (!node.receiver.canBePrimitive(types)) {
305 Selector selector = new Selector.index(); 316 Selector selector = new Selector.index();
306 return fromInterceptorToDynamicInvocation(node, selector); 317 return fromInterceptorToDynamicInvocation(node, selector);
307 } 318 }
308 return node; 319 return node;
309 } 320 }
310 321
311 HInstruction visitIndexAssign(HIndexAssign node) { 322 HInstruction visitIndexAssign(HIndexAssign node) {
312 if (!node.receiver.canBePrimitive()) { 323 if (!node.receiver.canBePrimitive(types)) {
313 Selector selector = new Selector.indexSet(); 324 Selector selector = new Selector.indexSet();
314 return fromInterceptorToDynamicInvocation(node, selector); 325 return fromInterceptorToDynamicInvocation(node, selector);
315 } 326 }
316 return node; 327 return node;
317 } 328 }
318 329
319 HInstruction visitInvokeBinary(HInvokeBinary node) { 330 HInstruction visitInvokeBinary(HInvokeBinary node) {
320 HInstruction left = node.left; 331 HInstruction left = node.left;
321 HInstruction right = node.right; 332 HInstruction right = node.right;
322 if (left is HConstant && right is HConstant) { 333 if (left is HConstant && right is HConstant) {
323 BinaryOperation operation = node.operation; 334 BinaryOperation operation = node.operation;
324 HConstant op1 = left; 335 HConstant op1 = left;
325 HConstant op2 = right; 336 HConstant op2 = right;
326 Constant folded = operation.fold(op1.constant, op2.constant); 337 Constant folded = operation.fold(op1.constant, op2.constant);
327 if (folded !== null) return graph.addConstant(folded); 338 if (folded !== null) return graph.addConstant(folded);
328 } 339 }
329 340
330 if (!left.canBePrimitive() 341 if (!left.canBePrimitive(types)
331 && node.operation.isUserDefinable() 342 && node.operation.isUserDefinable()
332 // The equals operation is being optimized in visitEquals. 343 // The equals operation is being optimized in visitEquals.
333 && node.operation !== const EqualsOperation()) { 344 && node.operation !== const EqualsOperation()) {
334 Selector selector = new Selector.binaryOperator(node.operation.name); 345 Selector selector = new Selector.binaryOperator(node.operation.name);
335 return fromInterceptorToDynamicInvocation(node, selector); 346 return fromInterceptorToDynamicInvocation(node, selector);
336 } 347 }
337 return node; 348 return node;
338 } 349 }
339 350
340 bool allUsersAreBoolifies(HInstruction instruction) { 351 bool allUsersAreBoolifies(HInstruction instruction) {
(...skipping 17 matching lines...) Expand all
358 // instructions. If it is unused it will be treated as dead code and 369 // instructions. If it is unused it will be treated as dead code and
359 // discarded. 370 // discarded.
360 oldTarget.block.addAfter(oldTarget, boolifiedTarget); 371 oldTarget.block.addAfter(oldTarget, boolifiedTarget);
361 // Remove us as user from the [oldTarget]. 372 // Remove us as user from the [oldTarget].
362 oldTarget.removeUser(node); 373 oldTarget.removeUser(node);
363 // Replace old target with boolified target. 374 // Replace old target with boolified target.
364 assert(node.target == node.inputs[0]); 375 assert(node.target == node.inputs[0]);
365 node.inputs[0] = boolifiedTarget; 376 node.inputs[0] = boolifiedTarget;
366 boolifiedTarget.usedBy.add(node); 377 boolifiedTarget.usedBy.add(node);
367 node.usesBoolifiedInterceptor = true; 378 node.usesBoolifiedInterceptor = true;
368 node.propagatedType = HType.BOOLEAN; 379 types[node] = HType.BOOLEAN;
369 } 380 }
370 // This node stays the same, but the Boolify node will go away. 381 // This node stays the same, but the Boolify node will go away.
371 } 382 }
372 // Note that we still have to call [super] to make sure that we end up 383 // Note that we still have to call [super] to make sure that we end up
373 // in the remaining optimizations. 384 // in the remaining optimizations.
374 return super.visitRelational(node); 385 return super.visitRelational(node);
375 } 386 }
376 387
377 HInstruction handleIdentityCheck(HInvokeBinary node) { 388 HInstruction handleIdentityCheck(HInvokeBinary node) {
378 HInstruction left = node.left; 389 HInstruction left = node.left;
379 HInstruction right = node.right; 390 HInstruction right = node.right;
380 HType leftType = left.propagatedType; 391 HType leftType = types[left];
381 HType rightType = right.propagatedType; 392 HType rightType = types[right];
382 assert(!leftType.isConflicting() && !rightType.isConflicting()); 393 assert(!leftType.isConflicting() && !rightType.isConflicting());
383 394
384 // We don't optimize on numbers to preserve the runtime semantics. 395 // We don't optimize on numbers to preserve the runtime semantics.
385 if (!(left.isNumber() && right.isNumber()) && 396 if (!(left.isNumber(types) && right.isNumber(types)) &&
386 leftType.intersection(rightType).isConflicting()) { 397 leftType.intersection(rightType).isConflicting()) {
387 return graph.addConstantBool(false); 398 return graph.addConstantBool(false);
388 } 399 }
389 400
390 if (left.isConstantBoolean() && right.isBoolean()) { 401 if (left.isConstantBoolean() && right.isBoolean(types)) {
391 HConstant constant = left; 402 HConstant constant = left;
392 if (constant.constant.isTrue()) { 403 if (constant.constant.isTrue()) {
393 return right; 404 return right;
394 } else { 405 } else {
395 return new HNot(right); 406 return new HNot(right);
396 } 407 }
397 } 408 }
398 409
399 if (right.isConstantBoolean() && left.isBoolean()) { 410 if (right.isConstantBoolean() && left.isBoolean(types)) {
400 HConstant constant = right; 411 HConstant constant = right;
401 if (constant.constant.isTrue()) { 412 if (constant.constant.isTrue()) {
402 return left; 413 return left;
403 } else { 414 } else {
404 return new HNot(left); 415 return new HNot(left);
405 } 416 }
406 } 417 }
407 418
408 return null; 419 return null;
409 } 420 }
(...skipping 13 matching lines...) Expand all
423 return new HIdentity(target, node.left, node.right); 434 return new HIdentity(target, node.left, node.right);
424 } else { 435 } else {
425 return newInstruction; 436 return newInstruction;
426 } 437 }
427 } 438 }
428 439
429 HInstruction visitEquals(HEquals node) { 440 HInstruction visitEquals(HEquals node) {
430 HInstruction left = node.left; 441 HInstruction left = node.left;
431 HInstruction right = node.right; 442 HInstruction right = node.right;
432 443
433 if (node.builtin) { 444 if (node.isBuiltin(types)) {
434 return foldBuiltinEqualsCheck(node); 445 return foldBuiltinEqualsCheck(node);
435 } 446 }
436 447
437 if (left.isConstant() && right.isConstant()) { 448 if (left.isConstant() && right.isConstant()) {
438 return super.visitEquals(node); 449 return super.visitEquals(node);
439 } 450 }
440 451
441 if (left.propagatedType.isExact()) { 452 HType leftType = types[left];
442 HBoundedType type = left.propagatedType; 453 if (leftType.isExact()) {
454 HBoundedType type = leftType;
443 Element element = type.lookupMember(Elements.OPERATOR_EQUALS); 455 Element element = type.lookupMember(Elements.OPERATOR_EQUALS);
444 if (element !== null) { 456 if (element !== null) {
445 // If the left-hand side is guaranteed to be a non-primitive 457 // If the left-hand side is guaranteed to be a non-primitive
446 // type and and it defines operator==, we emit a call to that 458 // type and and it defines operator==, we emit a call to that
447 // operator. 459 // operator.
448 return super.visitEquals(node); 460 return super.visitEquals(node);
449 } else if (right.isConstantNull()) { 461 } else if (right.isConstantNull()) {
450 return graph.addConstantBool(false); 462 return graph.addConstantBool(false);
451 } else { 463 } else {
452 // We can just emit an identity check because the type does 464 // We can just emit an identity check because the type does
453 // not implement operator=. 465 // not implement operator=.
454 return foldBuiltinEqualsCheck(node); 466 return foldBuiltinEqualsCheck(node);
455 } 467 }
456 } 468 }
457 469
458 if (right.isConstantNull()) { 470 if (right.isConstantNull()) {
459 if (left.propagatedType.isPrimitive()) { 471 if (leftType.isPrimitive()) {
460 return graph.addConstantBool(false); 472 return graph.addConstantBool(false);
461 } 473 }
462 } 474 }
463 475
464 // All other cases are dealt with by the [visitRelational] and 476 // All other cases are dealt with by the [visitRelational] and
465 // [visitInvokeBinary], which are visited by invoking the [super]'s 477 // [visitInvokeBinary], which are visited by invoking the [super]'s
466 // visit method. 478 // visit method.
467 return super.visitEquals(node); 479 return super.visitEquals(node);
468 } 480 }
469 481
470 HInstruction visitTypeGuard(HTypeGuard node) { 482 HInstruction visitTypeGuard(HTypeGuard node) {
471 HInstruction value = node.guarded; 483 HInstruction value = node.guarded;
472 // If the intersection of the types is still the incoming type then 484 // If the intersection of the types is still the incoming type then
473 // the incoming type was a subtype of the guarded type, and no check 485 // the incoming type was a subtype of the guarded type, and no check
474 // is required. 486 // is required.
475 HType combinedType = value.propagatedType.intersection(node.guardedType); 487 HType combinedType = types[value].intersection(node.guardedType);
476 return (combinedType == value.propagatedType) ? value : node; 488 return (combinedType == types[value]) ? value : node;
477 } 489 }
478 490
479 HInstruction visitIs(HIs node) { 491 HInstruction visitIs(HIs node) {
480 Type type = node.typeExpression; 492 Type type = node.typeExpression;
481 Element element = type.element; 493 Element element = type.element;
482 if (element.kind === ElementKind.TYPE_VARIABLE) { 494 if (element.kind === ElementKind.TYPE_VARIABLE) {
483 compiler.unimplemented("visitIs for type variables"); 495 compiler.unimplemented("visitIs for type variables");
484 } 496 }
485 497
486 HType expressionType = node.expression.propagatedType; 498 HType expressionType = types[node.expression];
487 if (element === compiler.objectClass 499 if (element === compiler.objectClass
488 || element === compiler.dynamicClass) { 500 || element === compiler.dynamicClass) {
489 return graph.addConstantBool(true); 501 return graph.addConstantBool(true);
490 } else if (expressionType.isInteger()) { 502 } else if (expressionType.isInteger()) {
491 if (element === compiler.intClass || element === compiler.numClass) { 503 if (element === compiler.intClass || element === compiler.numClass) {
492 return graph.addConstantBool(true); 504 return graph.addConstantBool(true);
493 } else if (element === compiler.doubleClass) { 505 } else if (element === compiler.doubleClass) {
494 // We let the JS semantics decide for that check. Currently 506 // We let the JS semantics decide for that check. Currently
495 // the code we emit will always return true. 507 // the code we emit will always return true.
496 return node; 508 return node;
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
539 } else if (expressionType.isExact()) { 551 } else if (expressionType.isExact()) {
540 return graph.addConstantBool(false); 552 return graph.addConstantBool(false);
541 } 553 }
542 } 554 }
543 } 555 }
544 return node; 556 return node;
545 } 557 }
546 558
547 HInstruction visitTypeConversion(HTypeConversion node) { 559 HInstruction visitTypeConversion(HTypeConversion node) {
548 HInstruction value = node.inputs[0]; 560 HInstruction value = node.inputs[0];
549 Type type = node.propagatedType.computeType(compiler); 561 Type type = types[node].computeType(compiler);
550 if (type.element === compiler.dynamicClass 562 if (type.element === compiler.dynamicClass
551 || type.element === compiler.objectClass) { 563 || type.element === compiler.objectClass) {
552 return value; 564 return value;
553 } 565 }
554 HType combinedType = value.propagatedType.intersection(node.propagatedType); 566 HType combinedType = types[value].intersection(types[node]);
555 return (combinedType == value.propagatedType) ? value : node; 567 return (combinedType == types[value]) ? value : node;
556 } 568 }
557 569
558 HInstruction visitInvokeDynamicGetter(HInvokeDynamicGetter node) { 570 HInstruction visitInvokeDynamicGetter(HInvokeDynamicGetter node) {
559 HInstruction receiver = node.inputs[0]; 571 HInstruction receiver = node.inputs[0];
560 if (!receiver.propagatedType.isUseful()) return node; 572 HType receiverType = types[receiver];
561 if (receiver.propagatedType.canBeNull()) return node; 573 if (!receiverType.isUseful()) return node;
562 Type type = receiver.propagatedType.computeType(compiler); 574 if (receiverType.canBeNull()) return node;
575 Type type = receiverType.computeType(compiler);
563 if (type === null) return node; 576 if (type === null) return node;
564 Element field = compiler.world.locateSingleField(type, node.name); 577 Element field = compiler.world.locateSingleField(type, node.name);
565 if (field === null) return node; 578 if (field === null) return node;
566 if (node.name.isPrivate() && 579 if (node.name.isPrivate() &&
567 field.getLibrary() !== work.element.getLibrary()) { 580 field.getLibrary() !== work.element.getLibrary()) {
568 return node; 581 return node;
569 } 582 }
570 Modifiers modifiers = field.modifiers; 583 Modifiers modifiers = field.modifiers;
571 bool isFinalOrConst = false; 584 bool isFinalOrConst = false;
572 if (modifiers != null) { 585 if (modifiers != null) {
(...skipping 19 matching lines...) Expand all
592 isFinalOrConst = true; 605 isFinalOrConst = true;
593 break; 606 break;
594 } 607 }
595 } 608 }
596 return new HFieldGet.withElement( 609 return new HFieldGet.withElement(
597 field, node.inputs[0], isFinalOrConst: isFinalOrConst); 610 field, node.inputs[0], isFinalOrConst: isFinalOrConst);
598 } 611 }
599 612
600 HInstruction visitInvokeDynamicSetter(HInvokeDynamicSetter node) { 613 HInstruction visitInvokeDynamicSetter(HInvokeDynamicSetter node) {
601 HInstruction receiver = node.inputs[0]; 614 HInstruction receiver = node.inputs[0];
602 if (!receiver.propagatedType.isUseful()) return node; 615 HType receiverType = types[receiver];
603 if (receiver.propagatedType.canBeNull()) return node; 616 if (!receiverType.isUseful()) return node;
604 Type type = receiver.propagatedType.computeType(compiler); 617 if (receiverType.canBeNull()) return node;
618 Type type = receiverType.computeType(compiler);
605 if (type === null) return node; 619 if (type === null) return node;
606 Element field = compiler.world.locateSingleField(type, node.name); 620 Element field = compiler.world.locateSingleField(type, node.name);
607 if (field === null) return node; 621 if (field === null) return node;
608 return new HFieldSet.withElement(field, node.inputs[0], node.inputs[1]); 622 return new HFieldSet.withElement(field, node.inputs[0], node.inputs[1]);
609 } 623 }
610 624
611 HInstruction visitStringConcat(HStringConcat node) { 625 HInstruction visitStringConcat(HStringConcat node) {
612 DartString folded = const LiteralDartString(""); 626 DartString folded = const LiteralDartString("");
613 for (int i = 0; i < node.inputs.length; i++) { 627 for (int i = 0; i < node.inputs.length; i++) {
614 HInstruction part = node.inputs[i]; 628 HInstruction part = node.inputs[i];
615 if (!part.isConstant()) return node; 629 if (!part.isConstant()) return node;
616 HConstant constant = part; 630 HConstant constant = part;
617 if (!constant.constant.isPrimitive()) return node; 631 if (!constant.constant.isPrimitive()) return node;
618 PrimitiveConstant primitive = constant.constant; 632 PrimitiveConstant primitive = constant.constant;
619 folded = new DartString.concat(folded, primitive.toDartString()); 633 folded = new DartString.concat(folded, primitive.toDartString());
620 } 634 }
621 return graph.addConstantString(folded, node.node); 635 return graph.addConstantString(folded, node.node);
622 } 636 }
623 } 637 }
624 638
625 class SsaCheckInserter extends HBaseVisitor implements OptimizationPhase { 639 class SsaCheckInserter extends HBaseVisitor implements OptimizationPhase {
640 final HTypeMap types;
626 final String name = "SsaCheckInserter"; 641 final String name = "SsaCheckInserter";
627 Element lengthInterceptor; 642 Element lengthInterceptor;
628 643
629 SsaCheckInserter(JavaScriptBackend backend) { 644 SsaCheckInserter(JavaScriptBackend backend, this.types) {
630 SourceString lengthString = const SourceString('length'); 645 SourceString lengthString = const SourceString('length');
631 lengthInterceptor = 646 lengthInterceptor =
632 backend.builder.interceptors.getStaticGetInterceptor(lengthString); 647 backend.builder.interceptors.getStaticGetInterceptor(lengthString);
633 } 648 }
634 649
635 void visitGraph(HGraph graph) { 650 void visitGraph(HGraph graph) {
636 visitDominatorTree(graph); 651 visitDominatorTree(graph);
637 } 652 }
638 653
639 void visitBasicBlock(HBasicBlock block) { 654 void visitBasicBlock(HBasicBlock block) {
(...skipping 12 matching lines...) Expand all
652 node.block.addBefore(node, interceptor); 667 node.block.addBefore(node, interceptor);
653 Selector selector = new Selector.call( 668 Selector selector = new Selector.call(
654 lengthInterceptor.name, 669 lengthInterceptor.name,
655 lengthInterceptor.getLibrary(), // TODO(kasperl): Wrong. 670 lengthInterceptor.getLibrary(), // TODO(kasperl): Wrong.
656 0); 671 0);
657 HInvokeInterceptor length = new HInvokeInterceptor( 672 HInvokeInterceptor length = new HInvokeInterceptor(
658 selector, 673 selector,
659 const SourceString("length"), 674 const SourceString("length"),
660 <HInstruction>[interceptor, receiver], 675 <HInstruction>[interceptor, receiver],
661 getter: true); 676 getter: true);
662 length.propagatedType = HType.INTEGER; 677 types[length] = HType.INTEGER;
663 node.block.addBefore(node, length); 678 node.block.addBefore(node, length);
664 679
665 HBoundsCheck check = new HBoundsCheck(index, length); 680 HBoundsCheck check = new HBoundsCheck(index, length);
666 node.block.addBefore(node, check); 681 node.block.addBefore(node, check);
667 return check; 682 return check;
668 } 683 }
669 684
670 HIntegerCheck insertIntegerCheck(HInstruction node, HInstruction value) { 685 HIntegerCheck insertIntegerCheck(HInstruction node, HInstruction value) {
671 HIntegerCheck check = new HIntegerCheck(value); 686 HIntegerCheck check = new HIntegerCheck(value);
672 node.block.addBefore(node, check); 687 node.block.addBefore(node, check);
673 Set<HInstruction> dominatedUsers = value.dominatedUsers(check); 688 Set<HInstruction> dominatedUsers = value.dominatedUsers(check);
674 for (HInstruction user in dominatedUsers) { 689 for (HInstruction user in dominatedUsers) {
675 user.changeUse(value, check); 690 user.changeUse(value, check);
676 } 691 }
677 return check; 692 return check;
678 } 693 }
679 694
680 void visitIndex(HIndex node) { 695 void visitIndex(HIndex node) {
681 if (!node.receiver.isIndexablePrimitive()) return; 696 if (!node.receiver.isIndexablePrimitive(types)) return;
682 HInstruction index = node.index; 697 HInstruction index = node.index;
683 if (index is HBoundsCheck) return; 698 if (index is HBoundsCheck) return;
684 if (!node.index.isInteger()) { 699 if (!node.index.isInteger(types)) {
685 index = insertIntegerCheck(node, index); 700 index = insertIntegerCheck(node, index);
686 } 701 }
687 index = insertBoundsCheck(node, node.receiver, index); 702 index = insertBoundsCheck(node, node.receiver, index);
688 node.changeUse(node.index, index); 703 node.changeUse(node.index, index);
689 } 704 }
690 705
691 void visitIndexAssign(HIndexAssign node) { 706 void visitIndexAssign(HIndexAssign node) {
692 if (!node.receiver.isMutableArray()) return; 707 if (!node.receiver.isMutableArray(types)) return;
693 HInstruction index = node.index; 708 HInstruction index = node.index;
694 if (index is HBoundsCheck) return; 709 if (index is HBoundsCheck) return;
695 if (!node.index.isInteger()) { 710 if (!node.index.isInteger(types)) {
696 index = insertIntegerCheck(node, index); 711 index = insertIntegerCheck(node, index);
697 } 712 }
698 index = insertBoundsCheck(node, node.receiver, index); 713 index = insertBoundsCheck(node, node.receiver, index);
699 node.changeUse(node.index, index); 714 node.changeUse(node.index, index);
700 } 715 }
701 } 716 }
702 717
703 class SsaDeadCodeEliminator extends HGraphVisitor implements OptimizationPhase { 718 class SsaDeadCodeEliminator extends HGraphVisitor implements OptimizationPhase {
719 final HTypeMap types;
704 final String name = "SsaDeadCodeEliminator"; 720 final String name = "SsaDeadCodeEliminator";
705 721
706 static bool isDeadCode(HInstruction instruction) { 722 SsaDeadCodeEliminator(this.types);
707 return !instruction.hasSideEffects() 723
724 bool isDeadCode(HInstruction instruction) {
725 return !instruction.hasSideEffects(types)
708 && instruction.usedBy.isEmpty() 726 && instruction.usedBy.isEmpty()
709 && instruction is !HCheck 727 && instruction is !HCheck
710 && instruction is !HTypeGuard 728 && instruction is !HTypeGuard
711 && !instruction.isControlFlow(); 729 && !instruction.isControlFlow();
712 } 730 }
713 731
714 void visitGraph(HGraph graph) { 732 void visitGraph(HGraph graph) {
715 visitPostDominatorTree(graph); 733 visitPostDominatorTree(graph);
716 } 734 }
717 735
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
824 } 842 }
825 phi.block.rewrite(phi, candidate); 843 phi.block.rewrite(phi, candidate);
826 phi.block.removePhi(phi); 844 phi.block.removePhi(phi);
827 } 845 }
828 } 846 }
829 } 847 }
830 848
831 class SsaGlobalValueNumberer implements OptimizationPhase { 849 class SsaGlobalValueNumberer implements OptimizationPhase {
832 final String name = "SsaGlobalValueNumberer"; 850 final String name = "SsaGlobalValueNumberer";
833 final Compiler compiler; 851 final Compiler compiler;
852 final HTypeMap types;
834 final Set<int> visited; 853 final Set<int> visited;
835 854
836 List<int> blockChangesFlags; 855 List<int> blockChangesFlags;
837 List<int> loopChangesFlags; 856 List<int> loopChangesFlags;
838 857
839 SsaGlobalValueNumberer(this.compiler) : visited = new Set<int>(); 858 SsaGlobalValueNumberer(this.compiler, this.types) : visited = new Set<int>();
840 859
841 void visitGraph(HGraph graph) { 860 void visitGraph(HGraph graph) {
842 computeChangesFlags(graph); 861 computeChangesFlags(graph);
843 moveLoopInvariantCode(graph); 862 moveLoopInvariantCode(graph);
844 visitBasicBlock(graph.entry, new ValueSet()); 863 visitBasicBlock(graph.entry, new ValueSet());
845 } 864 }
846 865
847 void moveLoopInvariantCode(HGraph graph) { 866 void moveLoopInvariantCode(HGraph graph) {
848 for (int i = graph.blocks.length - 1; i >= 0; i--) { 867 for (int i = graph.blocks.length - 1; i >= 0; i--) {
849 HBasicBlock block = graph.blocks[i]; 868 HBasicBlock block = graph.blocks[i];
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
955 // Run through all the basic blocks in the graph and fill in the 974 // Run through all the basic blocks in the graph and fill in the
956 // changes flags lists. 975 // changes flags lists.
957 for (int i = length - 1; i >= 0; i--) { 976 for (int i = length - 1; i >= 0; i--) {
958 final HBasicBlock block = graph.blocks[i]; 977 final HBasicBlock block = graph.blocks[i];
959 final int id = block.id; 978 final int id = block.id;
960 979
961 // Compute block changes flags for the block. 980 // Compute block changes flags for the block.
962 int changesFlags = 0; 981 int changesFlags = 0;
963 HInstruction instruction = block.first; 982 HInstruction instruction = block.first;
964 while (instruction !== null) { 983 while (instruction !== null) {
965 instruction.prepareGvn(); 984 instruction.prepareGvn(types);
966 changesFlags |= instruction.getChangesFlags(); 985 changesFlags |= instruction.getChangesFlags();
967 instruction = instruction.next; 986 instruction = instruction.next;
968 } 987 }
969 assert(blockChangesFlags[id] === null); 988 assert(blockChangesFlags[id] === null);
970 blockChangesFlags[id] = changesFlags; 989 blockChangesFlags[id] = changesFlags;
971 990
972 // Loop headers are part of their loop, so update the loop 991 // Loop headers are part of their loop, so update the loop
973 // changes flags accordingly. 992 // changes flags accordingly.
974 if (block.isLoopHeader()) { 993 if (block.isLoopHeader()) {
975 loopChangesFlags[id] |= changesFlags; 994 loopChangesFlags[id] |= changesFlags;
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after
1163 } 1182 }
1164 } 1183 }
1165 } 1184 }
1166 1185
1167 1186
1168 // Base class for the handling of recompilation based on inferred 1187 // Base class for the handling of recompilation based on inferred
1169 // field types. 1188 // field types.
1170 class BaseRecompilationVisitor extends HBaseVisitor { 1189 class BaseRecompilationVisitor extends HBaseVisitor {
1171 final JavaScriptBackend backend; 1190 final JavaScriptBackend backend;
1172 final WorkItem work; 1191 final WorkItem work;
1192 final HTypeMap types;
1173 Compiler get compiler() => backend.compiler; 1193 Compiler get compiler() => backend.compiler;
1174 1194
1175 BaseRecompilationVisitor(this.backend, this.work); 1195 BaseRecompilationVisitor(this.backend, this.work, this.types);
1176 1196
1177 abstract void handleFieldGet(HFieldGet node, HType type); 1197 abstract void handleFieldGet(HFieldGet node, HType type);
1178 abstract void handleFieldNumberOperation(HFieldGet field, HType type); 1198 abstract void handleFieldNumberOperation(HFieldGet field, HType type);
1179 1199
1180 // Checks if the binary invocation operates on a field and a 1200 // Checks if the binary invocation operates on a field and a
1181 // constant number. If it does [handleFieldNumberOperation] is 1201 // constant number. If it does [handleFieldNumberOperation] is
1182 // called with the field and the type inferred for the field so far. 1202 // called with the field and the type inferred for the field so far.
1183 void checkFieldNumberOperation(HInvokeBinary node) { 1203 void checkFieldNumberOperation(HInvokeBinary node) {
1184 // Determine if one of the operands is an HFieldGet. 1204 // Determine if one of the operands is an HFieldGet.
1185 HFieldGet field; 1205 HFieldGet field;
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
1235 } 1255 }
1236 } 1256 }
1237 1257
1238 1258
1239 // Visitor that registers candidates for recompilation. 1259 // Visitor that registers candidates for recompilation.
1240 class SsaRegisterRecompilationCandidates 1260 class SsaRegisterRecompilationCandidates
1241 extends BaseRecompilationVisitor implements OptimizationPhase { 1261 extends BaseRecompilationVisitor implements OptimizationPhase {
1242 final String name = "SsaRegisterRecompileCandidates"; 1262 final String name = "SsaRegisterRecompileCandidates";
1243 HGraph graph; 1263 HGraph graph;
1244 1264
1245 SsaRegisterRecompilationCandidates( 1265 SsaRegisterRecompilationCandidates(JavaScriptBackend backend,
1246 JavaScriptBackend backend, WorkItem work) : super(backend, work); 1266 WorkItem work,
1267 HTypeMap types)
1268 : super(backend, work, types);
1247 1269
1248 void visitGraph(HGraph visitee) { 1270 void visitGraph(HGraph visitee) {
1249 graph = visitee; 1271 graph = visitee;
1250 if (compiler.phase == Compiler.PHASE_COMPILING) { 1272 if (compiler.phase == Compiler.PHASE_COMPILING) {
1251 visitDominatorTree(visitee); 1273 visitDominatorTree(visitee);
1252 } 1274 }
1253 } 1275 }
1254 1276
1255 void handleFieldGet(HFieldGet node, HType type) { 1277 void handleFieldGet(HFieldGet node, HType type) {
1256 assert(compiler.phase == Compiler.PHASE_COMPILING); 1278 assert(compiler.phase == Compiler.PHASE_COMPILING);
1257 compiler.enqueuer.codegen.registerRecompilationCandidate( 1279 compiler.enqueuer.codegen.registerRecompilationCandidate(
1258 work.element); 1280 work.element);
1259 } 1281 }
1260 1282
1261 void handleFieldNumberOperation(HFieldGet node, HType type) { 1283 void handleFieldNumberOperation(HFieldGet node, HType type) {
1262 assert(compiler.phase == Compiler.PHASE_COMPILING); 1284 assert(compiler.phase == Compiler.PHASE_COMPILING);
1263 compiler.enqueuer.codegen.registerRecompilationCandidate( 1285 compiler.enqueuer.codegen.registerRecompilationCandidate(
1264 work.element); 1286 work.element);
1265 } 1287 }
1266 } 1288 }
1267 1289
1268 1290
1269 // Visitor that sets the known or suspected type of fields during 1291 // Visitor that sets the known or suspected type of fields during
1270 // recompilation. 1292 // recompilation.
1271 class SsaRecompilationFieldTypePropagator 1293 class SsaRecompilationFieldTypePropagator
1272 extends BaseRecompilationVisitor implements OptimizationPhase { 1294 extends BaseRecompilationVisitor implements OptimizationPhase {
1273 final String name = "SsaRecompilationFieldTypePropagator"; 1295 final String name = "SsaRecompilationFieldTypePropagator";
1274 HGraph graph; 1296 HGraph graph;
1275 1297
1276 SsaRecompilationFieldTypePropagator( 1298 SsaRecompilationFieldTypePropagator(JavaScriptBackend backend,
1277 JavaScriptBackend backend, WorkItem work) : super(backend, work); 1299 WorkItem work,
1300 HTypeMap types)
1301 : super(backend, work, types);
1278 1302
1279 void visitGraph(HGraph visitee) { 1303 void visitGraph(HGraph visitee) {
1280 graph = visitee; 1304 graph = visitee;
1281 if (compiler.phase == Compiler.PHASE_RECOMPILING) { 1305 if (compiler.phase == Compiler.PHASE_RECOMPILING) {
1282 visitDominatorTree(visitee); 1306 visitDominatorTree(visitee);
1283 } 1307 }
1284 } 1308 }
1285 1309
1286 void handleFieldGet(HFieldGet field, HType type) { 1310 void handleFieldGet(HFieldGet field, HType type) {
1287 assert(compiler.phase == Compiler.PHASE_RECOMPILING); 1311 assert(compiler.phase == Compiler.PHASE_RECOMPILING);
1288 if (!type.isConflicting()) { 1312 if (!type.isConflicting()) {
1289 // If there are no invoked setters with this name, the union of 1313 // If there are no invoked setters with this name, the union of
1290 // the types of the initializers and the setters is guaranteed 1314 // the types of the initializers and the setters is guaranteed
1291 // otherwise it is only speculative. 1315 // otherwise it is only speculative.
1292 Element element = field.element; 1316 Element element = field.element;
1293 assert(!element.isGenerativeConstructorBody()); 1317 assert(!element.isGenerativeConstructorBody());
1294 if (!compiler.codegenWorld.hasInvokedSetter(element, compiler)) { 1318 if (!compiler.codegenWorld.hasInvokedSetter(element, compiler)) {
1295 field.guaranteedType = 1319 field.guaranteedType =
1296 type.union(backend.fieldSettersTypeSoFar(element)); 1320 type.union(backend.fieldSettersTypeSoFar(element));
1297 } else { 1321 } else {
1298 field.propagatedType = 1322 types[field] = type.union(backend.fieldSettersTypeSoFar(element));
1299 type.union(backend.fieldSettersTypeSoFar(element));
1300 } 1323 }
1301 } 1324 }
1302 } 1325 }
1303 1326
1304 void handleFieldNumberOperation(HFieldGet field, HType type) { 1327 void handleFieldNumberOperation(HFieldGet field, HType type) {
1305 assert(compiler.phase == Compiler.PHASE_RECOMPILING); 1328 assert(compiler.phase == Compiler.PHASE_RECOMPILING);
1306 if (compiler.codegenWorld.hasInvokedSetter(field.element, compiler)) { 1329 if (compiler.codegenWorld.hasInvokedSetter(field.element, compiler)) {
1307 // If there are invoked setters we don't know for sure 1330 // If there are invoked setters we don't know for sure
1308 // that the field will hold a value of the calculated 1331 // that the field will hold a value of the calculated
1309 // type, but the fact that the class itself sticks to 1332 // type, but the fact that the class itself sticks to
1310 // this type for the field is still a strong signal 1333 // this type for the field is still a strong signal
1311 // indicating the expected type of the field. 1334 // indicating the expected type of the field.
1312 field.propagatedType = type; 1335 types[field] = type;
1313 } else { 1336 } else {
1314 // If there are no invoked setters we know the type of 1337 // If there are no invoked setters we know the type of
1315 // this field for sure. 1338 // this field for sure.
1316 field.guaranteedType = type; 1339 field.guaranteedType = type;
1317 } 1340 }
1318 } 1341 }
1319 } 1342 }
OLDNEW
« no previous file with comments | « lib/compiler/implementation/ssa/nodes.dart ('k') | lib/compiler/implementation/ssa/tracer.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698