| OLD | NEW |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, 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 { |
| (...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 286 } | 286 } |
| 287 | 287 |
| 288 if (left.isNonPrimitive() && node.operation.isUserDefinable()) { | 288 if (left.isNonPrimitive() && node.operation.isUserDefinable()) { |
| 289 SourceString methodName = Elements.constructOperatorName( | 289 SourceString methodName = Elements.constructOperatorName( |
| 290 const SourceString('operator'), node.operation.name); | 290 const SourceString('operator'), node.operation.name); |
| 291 return fromInterceptorToDynamicInvocation(node, methodName); | 291 return fromInterceptorToDynamicInvocation(node, methodName); |
| 292 } | 292 } |
| 293 return node; | 293 return node; |
| 294 } | 294 } |
| 295 | 295 |
| 296 HInstruction handleIdentityCheck(HInvokeBinary node) { |
| 297 HInstruction left = node.left; |
| 298 HInstruction right = node.right; |
| 299 HType leftType = left.propagatedType; |
| 300 HType rightType = right.propagatedType; |
| 301 assert(!leftType.isConflicting() && !rightType.isConflicting()); |
| 302 |
| 303 // We don't optimize on numbers to preserve the runtime semantics. |
| 304 if (!(left.isNumber() && right.isNumber()) && |
| 305 leftType.intersection(rightType).isConflicting()) { |
| 306 return graph.addConstantBool(false); |
| 307 } |
| 308 |
| 309 if (left.isConstantBoolean() && right.isBoolean()) { |
| 310 HConstant constant = left; |
| 311 if (constant.constant.isTrue()) { |
| 312 return right; |
| 313 } else { |
| 314 return new HNot(right); |
| 315 } |
| 316 } |
| 317 |
| 318 if (right.isConstantBoolean() && left.isBoolean()) { |
| 319 HConstant constant = right; |
| 320 if (constant.constant.isTrue()) { |
| 321 return left; |
| 322 } else { |
| 323 return new HNot(left); |
| 324 } |
| 325 } |
| 326 |
| 327 return null; |
| 328 } |
| 329 |
| 330 HInstruction visitIdentity(HIdentity node) { |
| 331 HInstruction newInstruction = handleIdentityCheck(node); |
| 332 return newInstruction === null ? super.visitIdentity(node) : newInstruction; |
| 333 } |
| 334 |
| 335 HInstruction foldBuiltinEqualsCheck(HEquals node) { |
| 336 // TODO(floitsch): cache interceptors. |
| 337 HInstruction newInstruction = handleIdentityCheck(node); |
| 338 if (newInstruction === null) { |
| 339 HStatic target = new HStatic( |
| 340 compiler.builder.interceptors.getTripleEqualsInterceptor()); |
| 341 node.block.addBefore(node, target); |
| 342 return new HIdentity(target, node.left, node.right); |
| 343 } else { |
| 344 return newInstruction; |
| 345 } |
| 346 } |
| 347 |
| 296 HInstruction visitEquals(HEquals node) { | 348 HInstruction visitEquals(HEquals node) { |
| 297 HInstruction left = node.left; | 349 HInstruction left = node.left; |
| 298 HInstruction right = node.right; | 350 HInstruction right = node.right; |
| 299 | 351 |
| 352 if (node.builtin) { |
| 353 return foldBuiltinEqualsCheck(node); |
| 354 } |
| 355 |
| 300 if (left.isConstant() && right.isConstant()) { | 356 if (left.isConstant() && right.isConstant()) { |
| 301 return visitInvokeBinary(node); | 357 return visitInvokeBinary(node); |
| 302 } | 358 } |
| 303 | 359 |
| 304 if (left.isNonPrimitive()) { | 360 if (left.isNonPrimitive()) { |
| 305 HNonPrimitiveType type = left.propagatedType; | 361 HNonPrimitiveType type = left.propagatedType; |
| 306 Element element = type.lookupMember(Namer.OPERATOR_EQUALS); | 362 Element element = type.lookupMember(Namer.OPERATOR_EQUALS); |
| 307 if (element !== null) { | 363 if (element !== null) { |
| 308 // If the left-hand side is guaranteed to be a non-primitive | 364 // If the left-hand side is guaranteed to be a non-primitive |
| 309 // type and and it defines operator==, we emit a call to that | 365 // type and and it defines operator==, we emit a call to that |
| 310 // operator. | 366 // operator. |
| 311 return visitInvokeBinary(node); | 367 return visitInvokeBinary(node); |
| 312 } else if (right.isConstantNull()) { | 368 } else if (right.isConstantNull()) { |
| 313 return graph.addConstantBool(false); | 369 return graph.addConstantBool(false); |
| 314 } else { | 370 } else { |
| 315 // We can just emit an identity check because the type does | 371 // We can just emit an identity check because the type does |
| 316 // not implement operator=. | 372 // not implement operator=. |
| 317 // TODO(floitsch): cache interceptors. | 373 return foldBuiltinEqualsCheck(node); |
| 318 HStatic target = new HStatic( | |
| 319 compiler.builder.interceptors.getTripleEqualsInterceptor()); | |
| 320 node.block.addBefore(node, target); | |
| 321 return new HIdentity(target, left, right); | |
| 322 } | 374 } |
| 323 } | 375 } |
| 324 | 376 |
| 325 | |
| 326 if (right.isConstantNull()) { | 377 if (right.isConstantNull()) { |
| 327 if (left.propagatedType.isUseful()) { | 378 if (left.propagatedType.isUseful()) { |
| 328 return graph.addConstantBool(false); | 379 return graph.addConstantBool(false); |
| 329 } else { | 380 } else { |
| 330 // TODO(floitsch): cache interceptors. | 381 // TODO(floitsch): cache interceptors. |
| 331 HStatic target = new HStatic( | 382 HStatic target = new HStatic( |
| 332 compiler.builder.interceptors.getEqualsNullInterceptor()); | 383 compiler.builder.interceptors.getEqualsNullInterceptor()); |
| 333 node.block.addBefore(node, target); | 384 node.block.addBefore(node, target); |
| 334 return new HEquals(target, node.left, node.right); | 385 return new HEquals(target, node.left, node.right); |
| 335 } | 386 } |
| (...skipping 529 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 865 } | 916 } |
| 866 } | 917 } |
| 867 if (!canBeMoved) continue; | 918 if (!canBeMoved) continue; |
| 868 | 919 |
| 869 // This is safe because we are running after GVN. | 920 // This is safe because we are running after GVN. |
| 870 // TODO(ngeoffray): ensure GVN has been run. | 921 // TODO(ngeoffray): ensure GVN has been run. |
| 871 set_.add(current); | 922 set_.add(current); |
| 872 } | 923 } |
| 873 } | 924 } |
| 874 } | 925 } |
| OLD | NEW |