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

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

Powered by Google App Engine
This is Rietveld 408576698