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

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

Issue 10825386: Use JavaScript runtime semantics when constant folding. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Update status file. Created 8 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 | Annotate | Revision Log
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 runPhase(graph, phase); 20 runPhase(graph, phase);
21 } 21 }
22 } 22 }
23 23
24 void runPhase(HGraph graph, OptimizationPhase phase) { 24 void runPhase(HGraph graph, OptimizationPhase phase) {
25 phase.visitGraph(graph); 25 phase.visitGraph(graph);
26 compiler.tracer.traceGraph(phase.name, graph); 26 compiler.tracer.traceGraph(phase.name, graph);
27 } 27 }
28 28
29 void optimize(WorkItem work, HGraph graph) { 29 void optimize(WorkItem work, HGraph graph) {
30 ConstantSystem constantSystem =
31 compiler.constantHandler.constantSystem;
30 JavaScriptItemCompilationContext context = work.compilationContext; 32 JavaScriptItemCompilationContext context = work.compilationContext;
31 HTypeMap types = context.types; 33 HTypeMap types = context.types;
32 measure(() { 34 measure(() {
33 List<OptimizationPhase> phases = <OptimizationPhase>[ 35 List<OptimizationPhase> phases = <OptimizationPhase>[
34 // Run trivial constant folding first to optimize 36 // Run trivial constant folding first to optimize
35 // some patterns useful for type conversion. 37 // some patterns useful for type conversion.
36 new SsaConstantFolder(backend, work, types), 38 new SsaConstantFolder(constantSystem, backend, work, types),
ngeoffray 2012/09/05 11:20:36 If the constantSystem is in the backend, you don't
floitsch 2012/09/05 16:12:01 I prefer being explicit. Otherwise dependencies be
37 new SsaTypeConversionInserter(compiler), 39 new SsaTypeConversionInserter(compiler),
38 new SsaTypePropagator(compiler, types), 40 new SsaTypePropagator(compiler, types),
39 new SsaCheckInserter(backend, types), 41 new SsaCheckInserter(backend, types),
40 new SsaConstantFolder(backend, work, types), 42 new SsaConstantFolder(constantSystem, backend, work, types),
41 new SsaRedundantPhiEliminator(), 43 new SsaRedundantPhiEliminator(),
42 new SsaDeadPhiEliminator(), 44 new SsaDeadPhiEliminator(),
43 new SsaGlobalValueNumberer(compiler, types), 45 new SsaGlobalValueNumberer(compiler, types),
44 new SsaCodeMotion(), 46 new SsaCodeMotion(),
45 // Previous optimizations may have generated new 47 // Previous optimizations may have generated new
46 // opportunities for constant folding. 48 // opportunities for constant folding.
47 new SsaConstantFolder(backend, work, types), 49 new SsaConstantFolder(constantSystem, backend, work, types),
48 new SsaDeadCodeEliminator(types), 50 new SsaDeadCodeEliminator(types),
49 new SsaRegisterRecompilationCandidates(backend, work, types)]; 51 new SsaRegisterRecompilationCandidates(backend, work, types)];
50 runPhases(graph, phases); 52 runPhases(graph, phases);
51 }); 53 });
52 } 54 }
53 55
54 bool trySpeculativeOptimizations(WorkItem work, HGraph graph) { 56 bool trySpeculativeOptimizations(WorkItem work, HGraph graph) {
55 JavaScriptItemCompilationContext context = work.compilationContext; 57 JavaScriptItemCompilationContext context = work.compilationContext;
56 HTypeMap types = context.types; 58 HTypeMap types = context.types;
57 return measure(() { 59 return measure(() {
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
99 } 101 }
100 102
101 /** 103 /**
102 * If both inputs to known operations are available execute the operation at 104 * If both inputs to known operations are available execute the operation at
103 * compile-time. 105 * compile-time.
104 */ 106 */
105 class SsaConstantFolder extends HBaseVisitor implements OptimizationPhase { 107 class SsaConstantFolder extends HBaseVisitor implements OptimizationPhase {
106 final String name = "SsaConstantFolder"; 108 final String name = "SsaConstantFolder";
107 final JavaScriptBackend backend; 109 final JavaScriptBackend backend;
108 final WorkItem work; 110 final WorkItem work;
111 final ConstantSystem constantSystem;
109 final HTypeMap types; 112 final HTypeMap types;
110 HGraph graph; 113 HGraph graph;
111 Compiler get compiler => backend.compiler; 114 Compiler get compiler => backend.compiler;
112 115
113 SsaConstantFolder(this.backend, this.work, this.types); 116 SsaConstantFolder(this.constantSystem, this.backend, this.work, this.types);
114 117
115 void visitGraph(HGraph visitee) { 118 void visitGraph(HGraph visitee) {
116 graph = visitee; 119 graph = visitee;
117 visitDominatorTree(visitee); 120 visitDominatorTree(visitee);
118 } 121 }
119 122
120 visitBasicBlock(HBasicBlock block) { 123 visitBasicBlock(HBasicBlock block) {
121 HInstruction instruction = block.first; 124 HInstruction instruction = block.first;
122 while (instruction !== null) { 125 while (instruction !== null) {
123 HInstruction next = instruction.next; 126 HInstruction next = instruction.next;
(...skipping 26 matching lines...) Expand all
150 } 153 }
151 154
152 HInstruction visitBoolify(HBoolify node) { 155 HInstruction visitBoolify(HBoolify node) {
153 List<HInstruction> inputs = node.inputs; 156 List<HInstruction> inputs = node.inputs;
154 assert(inputs.length == 1); 157 assert(inputs.length == 1);
155 HInstruction input = inputs[0]; 158 HInstruction input = inputs[0];
156 if (input.isBoolean(types)) return input; 159 if (input.isBoolean(types)) return input;
157 // All values !== true are boolified to false. 160 // All values !== true are boolified to false.
158 DartType type = types[input].computeType(compiler); 161 DartType type = types[input].computeType(compiler);
159 if (type !== null && type.element !== compiler.boolClass) { 162 if (type !== null && type.element !== compiler.boolClass) {
160 return graph.addConstantBool(false); 163 return graph.addConstant(constantSystem.createBool(false));
161 } 164 }
162 return node; 165 return node;
163 } 166 }
164 167
165 HInstruction visitNot(HNot node) { 168 HInstruction visitNot(HNot node) {
166 List<HInstruction> inputs = node.inputs; 169 List<HInstruction> inputs = node.inputs;
167 assert(inputs.length == 1); 170 assert(inputs.length == 1);
168 HInstruction input = inputs[0]; 171 HInstruction input = inputs[0];
169 if (input is HConstant) { 172 if (input is HConstant) {
170 HConstant constant = input; 173 HConstant constant = input;
171 bool isTrue = constant.constant.isTrue(); 174 bool isTrue = constant.constant.isTrue();
172 return graph.addConstantBool(!isTrue); 175 return graph.addConstant(constantSystem.createBool(!isTrue));
173 } else if (input is HNot) { 176 } else if (input is HNot) {
174 return input.inputs[0]; 177 return input.inputs[0];
175 } 178 }
176 return node; 179 return node;
177 } 180 }
178 181
179 HInstruction visitInvokeUnary(HInvokeUnary node) { 182 HInstruction visitInvokeUnary(HInvokeUnary node) {
180 HInstruction operand = node.operand; 183 HInstruction operand = node.operand;
181 if (operand is HConstant) { 184 if (operand is HConstant) {
182 UnaryOperation operation = node.operation; 185 UnaryOperation operation = node.operation(constantSystem);
183 HConstant receiver = operand; 186 HConstant receiver = operand;
184 Constant folded = operation.fold(receiver.constant); 187 Constant folded = operation.fold(receiver.constant);
185 if (folded !== null) return graph.addConstant(folded); 188 if (folded !== null) return graph.addConstant(folded);
186 } 189 }
187 return node; 190 return node;
188 } 191 }
189 192
190 HInstruction visitInvokeInterceptor(HInvokeInterceptor node) { 193 HInstruction visitInvokeInterceptor(HInvokeInterceptor node) {
191 HInstruction input = node.inputs[1]; 194 HInstruction input = node.inputs[1];
192 if (node.isLengthGetter()) { 195 if (node.isLengthGetter()) {
193 if (input.isConstantString()) { 196 if (input.isConstantString()) {
194 HConstant constantInput = input; 197 HConstant constantInput = input;
195 StringConstant constant = constantInput.constant; 198 StringConstant constant = constantInput.constant;
196 return graph.addConstantInt(constant.length); 199 return graph.addConstant(constantSystem.createInt(constant.length));
197 } else if (input.isConstantList()) { 200 } else if (input.isConstantList()) {
198 HConstant constantInput = input; 201 HConstant constantInput = input;
199 ListConstant constant = constantInput.constant; 202 ListConstant constant = constantInput.constant;
200 return graph.addConstantInt(constant.length); 203 return graph.addConstant(constantSystem.createInt(constant.length));
201 } else if (input.isConstantMap()) { 204 } else if (input.isConstantMap()) {
202 HConstant constantInput = input; 205 HConstant constantInput = input;
203 MapConstant constant = constantInput.constant; 206 MapConstant constant = constantInput.constant;
204 return graph.addConstantInt(constant.length); 207 return graph.addConstant(constantSystem.createInt(constant.length));
205 } 208 }
206 } 209 }
207 210
208 if (input.isString(types) 211 if (input.isString(types)
209 && node.selector.name == const SourceString('toString')) { 212 && node.selector.name == const SourceString('toString')) {
210 return node.inputs[1]; 213 return node.inputs[1];
211 } 214 }
212 215
213 if (!input.canBePrimitive(types) && node.selector.isCall()) { 216 if (!input.canBePrimitive(types) && node.selector.isCall()) {
214 bool transformToDynamicInvocation = true; 217 bool transformToDynamicInvocation = true;
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
296 } 299 }
297 node.staticChecks = HBoundsCheck.ALWAYS_ABOVE_ZERO; 300 node.staticChecks = HBoundsCheck.ALWAYS_ABOVE_ZERO;
298 } 301 }
299 return node; 302 return node;
300 } 303 }
301 304
302 HInstruction visitIntegerCheck(HIntegerCheck node) { 305 HInstruction visitIntegerCheck(HIntegerCheck node) {
303 HInstruction value = node.value; 306 HInstruction value = node.value;
304 if (value.isInteger(types)) return value; 307 if (value.isInteger(types)) return value;
305 if (value.isConstant()) { 308 if (value.isConstant()) {
306 assert((){ 309 HConstant constantInstruction = value;
307 HConstant constantInstruction = value; 310 assert(!constantInstruction.constant.isInt());
308 return !constantInstruction.constant.isInt(); 311 if (!constantSystem.isInt(constantInstruction.constant)) {
309 }); 312 // -0.0 is a double but will pass the runtime integer check.
310 node.alwaysFalse = true; 313 node.alwaysFalse = true;
314 }
311 } 315 }
312 return node; 316 return node;
313 } 317 }
314 318
315 319
316 HInstruction visitIndex(HIndex node) { 320 HInstruction visitIndex(HIndex node) {
317 if (!node.receiver.canBePrimitive(types)) { 321 if (!node.receiver.canBePrimitive(types)) {
318 Selector selector = new Selector.index(); 322 Selector selector = new Selector.index();
319 return fromInterceptorToDynamicInvocation(node, selector); 323 return fromInterceptorToDynamicInvocation(node, selector);
320 } 324 }
321 return node; 325 return node;
322 } 326 }
323 327
324 HInstruction visitIndexAssign(HIndexAssign node) { 328 HInstruction visitIndexAssign(HIndexAssign node) {
325 if (!node.receiver.canBePrimitive(types)) { 329 if (!node.receiver.canBePrimitive(types)) {
326 Selector selector = new Selector.indexSet(); 330 Selector selector = new Selector.indexSet();
327 return fromInterceptorToDynamicInvocation(node, selector); 331 return fromInterceptorToDynamicInvocation(node, selector);
328 } 332 }
329 return node; 333 return node;
330 } 334 }
331 335
332 HInstruction visitInvokeBinary(HInvokeBinary node) { 336 HInstruction visitInvokeBinary(HInvokeBinary node) {
333 HInstruction left = node.left; 337 HInstruction left = node.left;
334 HInstruction right = node.right; 338 HInstruction right = node.right;
339 BinaryOperation operation = node.operation(constantSystem);
335 if (left is HConstant && right is HConstant) { 340 if (left is HConstant && right is HConstant) {
336 BinaryOperation operation = node.operation;
337 HConstant op1 = left; 341 HConstant op1 = left;
338 HConstant op2 = right; 342 HConstant op2 = right;
339 Constant folded = operation.fold(op1.constant, op2.constant); 343 Constant folded = operation.fold(op1.constant, op2.constant);
340 if (folded !== null) return graph.addConstant(folded); 344 if (folded !== null) return graph.addConstant(folded);
341 } 345 }
342 346
343 if (!left.canBePrimitive(types) 347 if (!left.canBePrimitive(types)
344 && node.operation.isUserDefinable() 348 && operation.isUserDefinable()
345 // The equals operation is being optimized in visitEquals. 349 // The equals operation is being optimized in visitEquals.
346 && node.operation !== const EqualsOperation()) { 350 && node is! HEquals) {
347 Selector selector = new Selector.binaryOperator(node.operation.name); 351 Selector selector = new Selector.binaryOperator(operation.name);
348 return fromInterceptorToDynamicInvocation(node, selector); 352 return fromInterceptorToDynamicInvocation(node, selector);
349 } 353 }
350 return node; 354 return node;
351 } 355 }
352 356
353 bool allUsersAreBoolifies(HInstruction instruction) { 357 bool allUsersAreBoolifies(HInstruction instruction) {
354 List<HInstruction> users = instruction.usedBy; 358 List<HInstruction> users = instruction.usedBy;
355 int length = users.length; 359 int length = users.length;
356 for (int i = 0; i < length; i++) { 360 for (int i = 0; i < length; i++) {
357 if (users[i] is! HBoolify) return false; 361 if (users[i] is! HBoolify) return false;
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
390 HInstruction handleIdentityCheck(HInvokeBinary node) { 394 HInstruction handleIdentityCheck(HInvokeBinary node) {
391 HInstruction left = node.left; 395 HInstruction left = node.left;
392 HInstruction right = node.right; 396 HInstruction right = node.right;
393 HType leftType = types[left]; 397 HType leftType = types[left];
394 HType rightType = types[right]; 398 HType rightType = types[right];
395 assert(!leftType.isConflicting() && !rightType.isConflicting()); 399 assert(!leftType.isConflicting() && !rightType.isConflicting());
396 400
397 // We don't optimize on numbers to preserve the runtime semantics. 401 // We don't optimize on numbers to preserve the runtime semantics.
398 if (!(left.isNumber(types) && right.isNumber(types)) && 402 if (!(left.isNumber(types) && right.isNumber(types)) &&
399 leftType.intersection(rightType).isConflicting()) { 403 leftType.intersection(rightType).isConflicting()) {
400 return graph.addConstantBool(false); 404 return graph.addConstant(constantSystem.createBool(false));
401 } 405 }
402 406
403 if (left.isConstantBoolean() && right.isBoolean(types)) { 407 if (left.isConstantBoolean() && right.isBoolean(types)) {
404 HConstant constant = left; 408 HConstant constant = left;
405 if (constant.constant.isTrue()) { 409 if (constant.constant.isTrue()) {
406 return right; 410 return right;
407 } else { 411 } else {
408 return new HNot(right); 412 return new HNot(right);
409 } 413 }
410 } 414 }
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
454 HType leftType = types[left]; 458 HType leftType = types[left];
455 if (leftType.isExact()) { 459 if (leftType.isExact()) {
456 HBoundedType type = leftType; 460 HBoundedType type = leftType;
457 Element element = type.lookupMember(Elements.OPERATOR_EQUALS); 461 Element element = type.lookupMember(Elements.OPERATOR_EQUALS);
458 if (element !== null) { 462 if (element !== null) {
459 // If the left-hand side is guaranteed to be a non-primitive 463 // If the left-hand side is guaranteed to be a non-primitive
460 // type and and it defines operator==, we emit a call to that 464 // type and and it defines operator==, we emit a call to that
461 // operator. 465 // operator.
462 return super.visitEquals(node); 466 return super.visitEquals(node);
463 } else if (right.isConstantNull()) { 467 } else if (right.isConstantNull()) {
464 return graph.addConstantBool(false); 468 return graph.addConstant(constantSystem.createBool(false));
465 } else { 469 } else {
466 // We can just emit an identity check because the type does 470 // We can just emit an identity check because the type does
467 // not implement operator=. 471 // not implement operator=.
468 return foldBuiltinEqualsCheck(node); 472 return foldBuiltinEqualsCheck(node);
469 } 473 }
470 } 474 }
471 475
472 if (right.isConstantNull()) { 476 if (right.isConstantNull()) {
473 if (leftType.isPrimitive()) { 477 if (leftType.isPrimitive()) {
474 return graph.addConstantBool(false); 478 return graph.addConstant(constantSystem.createBool(false));
475 } 479 }
476 } 480 }
477 481
478 // All other cases are dealt with by the [visitRelational] and 482 // All other cases are dealt with by the [visitRelational] and
479 // [visitInvokeBinary], which are visited by invoking the [super]'s 483 // [visitInvokeBinary], which are visited by invoking the [super]'s
480 // visit method. 484 // visit method.
481 return super.visitEquals(node); 485 return super.visitEquals(node);
482 } 486 }
483 487
484 HInstruction visitTypeGuard(HTypeGuard node) { 488 HInstruction visitTypeGuard(HTypeGuard node) {
485 HInstruction value = node.guarded; 489 HInstruction value = node.guarded;
486 // If the intersection of the types is still the incoming type then 490 // If the intersection of the types is still the incoming type then
487 // the incoming type was a subtype of the guarded type, and no check 491 // the incoming type was a subtype of the guarded type, and no check
488 // is required. 492 // is required.
489 HType combinedType = types[value].intersection(node.guardedType); 493 HType combinedType = types[value].intersection(node.guardedType);
490 return (combinedType == types[value]) ? value : node; 494 return (combinedType == types[value]) ? value : node;
491 } 495 }
492 496
493 HInstruction visitIs(HIs node) { 497 HInstruction visitIs(HIs node) {
494 DartType type = node.typeExpression; 498 DartType type = node.typeExpression;
495 Element element = type.element; 499 Element element = type.element;
496 if (element.kind === ElementKind.TYPE_VARIABLE) { 500 if (element.kind === ElementKind.TYPE_VARIABLE) {
497 compiler.unimplemented("visitIs for type variables"); 501 compiler.unimplemented("visitIs for type variables");
498 } 502 }
499 503
500 HType expressionType = types[node.expression]; 504 HType expressionType = types[node.expression];
501 if (element === compiler.objectClass 505 if (element === compiler.objectClass
502 || element === compiler.dynamicClass) { 506 || element === compiler.dynamicClass) {
503 return graph.addConstantBool(true); 507 return graph.addConstant(constantSystem.createBool(true));
504 } else if (expressionType.isInteger()) { 508 } else if (expressionType.isInteger()) {
505 if (element === compiler.intClass || element === compiler.numClass) { 509 if (element === compiler.intClass || element === compiler.numClass) {
506 return graph.addConstantBool(true); 510 return graph.addConstant(constantSystem.createBool(true));
507 } else if (element === compiler.doubleClass) { 511 } else if (element === compiler.doubleClass) {
508 // We let the JS semantics decide for that check. Currently 512 // We let the JS semantics decide for that check. Currently
509 // the code we emit will always return true. 513 // the code we emit will always return true.
510 return node; 514 return node;
511 } else { 515 } else {
512 return graph.addConstantBool(false); 516 return graph.addConstant(constantSystem.createBool(false));
513 } 517 }
514 } else if (expressionType.isDouble()) { 518 } else if (expressionType.isDouble()) {
515 if (element === compiler.doubleClass || element === compiler.numClass) { 519 if (element === compiler.doubleClass || element === compiler.numClass) {
516 return graph.addConstantBool(true); 520 return graph.addConstant(constantSystem.createBool(true));
517 } else if (element === compiler.intClass) { 521 } else if (element === compiler.intClass) {
518 // We let the JS semantics decide for that check. Currently 522 // We let the JS semantics decide for that check. Currently
519 // the code we emit will return true for a double that can be 523 // the code we emit will return true for a double that can be
520 // represented as a 31-bit integer. 524 // represented as a 31-bit integer and for -0.0.
521 return node; 525 return node;
522 } else { 526 } else {
523 return graph.addConstantBool(false); 527 return graph.addConstant(constantSystem.createBool(false));
524 } 528 }
525 } else if (expressionType.isNumber()) { 529 } else if (expressionType.isNumber()) {
526 if (element === compiler.numClass) { 530 if (element === compiler.numClass) {
527 return graph.addConstantBool(true); 531 return graph.addConstant(constantSystem.createBool(true));
528 } 532 }
529 // We cannot just return false, because the expression may be of 533 // We cannot just return false, because the expression may be of
530 // type int or double. 534 // type int or double.
531 } else if (expressionType.isString()) { 535 } else if (expressionType.isString()) {
532 if (element === compiler.stringClass 536 if (element === compiler.stringClass
533 || Elements.isStringSupertype(element, compiler)) { 537 || Elements.isStringSupertype(element, compiler)) {
534 return graph.addConstantBool(true); 538 return graph.addConstant(constantSystem.createBool(true));
535 } else { 539 } else {
536 return graph.addConstantBool(false); 540 return graph.addConstant(constantSystem.createBool(false));
537 } 541 }
538 } else if (expressionType.isArray()) { 542 } else if (expressionType.isArray()) {
539 if (element === compiler.listClass 543 if (element === compiler.listClass
540 || Elements.isListSupertype(element, compiler)) { 544 || Elements.isListSupertype(element, compiler)) {
541 return graph.addConstantBool(true); 545 return graph.addConstant(constantSystem.createBool(true));
542 } else { 546 } else {
543 return graph.addConstantBool(false); 547 return graph.addConstant(constantSystem.createBool(false));
544 } 548 }
545 // TODO(karlklose): remove the hasTypeArguments check. 549 // TODO(karlklose): remove the hasTypeArguments check.
546 } else if (expressionType.isUseful() 550 } else if (expressionType.isUseful()
547 && !expressionType.canBeNull() 551 && !expressionType.canBeNull()
548 && !compiler.codegenWorld.rti.hasTypeArguments(type)) { 552 && !compiler.codegenWorld.rti.hasTypeArguments(type)) {
549 DartType receiverType = expressionType.computeType(compiler); 553 DartType receiverType = expressionType.computeType(compiler);
550 if (receiverType !== null) { 554 if (receiverType !== null) {
551 if (compiler.types.isSubtype(receiverType, type)) { 555 if (compiler.types.isSubtype(receiverType, type)) {
552 return graph.addConstantBool(true); 556 return graph.addConstant(constantSystem.createBool(true));
553 } else if (expressionType.isExact()) { 557 } else if (expressionType.isExact()) {
554 return graph.addConstantBool(false); 558 return graph.addConstant(constantSystem.createBool(false));
555 } 559 }
556 } 560 }
557 } 561 }
558 return node; 562 return node;
559 } 563 }
560 564
561 HInstruction visitTypeConversion(HTypeConversion node) { 565 HInstruction visitTypeConversion(HTypeConversion node) {
562 HInstruction value = node.inputs[0]; 566 HInstruction value = node.inputs[0];
563 DartType type = types[node].computeType(compiler); 567 DartType type = types[node].computeType(compiler);
564 if (type.element === compiler.dynamicClass 568 if (type.element === compiler.dynamicClass
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
624 HInstruction visitStringConcat(HStringConcat node) { 628 HInstruction visitStringConcat(HStringConcat node) {
625 DartString folded = const LiteralDartString(""); 629 DartString folded = const LiteralDartString("");
626 for (int i = 0; i < node.inputs.length; i++) { 630 for (int i = 0; i < node.inputs.length; i++) {
627 HInstruction part = node.inputs[i]; 631 HInstruction part = node.inputs[i];
628 if (!part.isConstant()) return node; 632 if (!part.isConstant()) return node;
629 HConstant constant = part; 633 HConstant constant = part;
630 if (!constant.constant.isPrimitive()) return node; 634 if (!constant.constant.isPrimitive()) return node;
631 PrimitiveConstant primitive = constant.constant; 635 PrimitiveConstant primitive = constant.constant;
632 folded = new DartString.concat(folded, primitive.toDartString()); 636 folded = new DartString.concat(folded, primitive.toDartString());
633 } 637 }
634 return graph.addConstantString(folded, node.node); 638 return graph.addConstant(constantSystem.createString(folded, node.node));
635 } 639 }
636 } 640 }
637 641
638 class SsaCheckInserter extends HBaseVisitor implements OptimizationPhase { 642 class SsaCheckInserter extends HBaseVisitor implements OptimizationPhase {
639 final HTypeMap types; 643 final HTypeMap types;
640 final String name = "SsaCheckInserter"; 644 final String name = "SsaCheckInserter";
641 Element lengthInterceptor; 645 Element lengthInterceptor;
642 646
643 SsaCheckInserter(JavaScriptBackend backend, this.types) { 647 SsaCheckInserter(JavaScriptBackend backend, this.types) {
644 SourceString lengthString = const SourceString('length'); 648 SourceString lengthString = const SourceString('length');
(...skipping 682 matching lines...) Expand 10 before | Expand all | Expand 10 after
1327 // this type for the field is still a strong signal 1331 // this type for the field is still a strong signal
1328 // indicating the expected type of the field. 1332 // indicating the expected type of the field.
1329 types[field] = type; 1333 types[field] = type;
1330 } else { 1334 } else {
1331 // If there are no invoked setters we know the type of 1335 // If there are no invoked setters we know the type of
1332 // this field for sure. 1336 // this field for sure.
1333 field.guaranteedType = type; 1337 field.guaranteedType = type;
1334 } 1338 }
1335 } 1339 }
1336 } 1340 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698