| 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 bool allUsersAreBoolifies(HInstruction instruction) { |
| 297 List<HInstruction> users = instruction.usedBy; |
| 298 int length = users.length; |
| 299 for (int i = 0; i < length; i++) { |
| 300 if (users[i] is! HBoolify) return false; |
| 301 } |
| 302 return true; |
| 303 } |
| 304 |
| 305 HInstruction visitRelational(HRelational node) { |
| 306 if (allUsersAreBoolifies(node)) { |
| 307 Interceptors interceptors = compiler.builder.interceptors; |
| 308 HStatic oldTarget = node.target; |
| 309 Element boolifiedInterceptor = |
| 310 interceptors.getBoolifiedVersionOf(oldTarget.element); |
| 311 if (boolifiedInterceptor !== null) { |
| 312 HStatic boolifiedTarget = new HStatic(boolifiedInterceptor); |
| 313 // We don't remove the [oldTarget] in case it is used by other |
| 314 // instructions. If it is unused it will be treated as dead code and |
| 315 // discarded. |
| 316 oldTarget.block.addAfter(oldTarget, boolifiedTarget); |
| 317 // Remove us as user from the [oldTarget]. |
| 318 HBasicBlock.removeUser(oldTarget, node); |
| 319 // Replace old target with boolified target. |
| 320 assert(node.target == node.inputs[0]); |
| 321 node.inputs[0] = boolifiedTarget; |
| 322 boolifiedTarget.usedBy.add(node); |
| 323 node.usesBoolifiedInterceptor = true; |
| 324 node.propagatedType = HType.BOOLEAN; |
| 325 } |
| 326 // This node stays the same, but the Boolify node will go away. |
| 327 } |
| 328 // Note that we still have to call [super] to make sure that we end up |
| 329 // in the remaining optimizations. |
| 330 return super.visitRelational(node); |
| 331 } |
| 332 |
| 296 HInstruction visitEquals(HEquals node) { | 333 HInstruction visitEquals(HEquals node) { |
| 297 HInstruction left = node.left; | 334 HInstruction left = node.left; |
| 298 HInstruction right = node.right; | 335 HInstruction right = node.right; |
| 299 | 336 |
| 300 if (left.isConstant() && right.isConstant()) { | 337 if (left.isConstant() && right.isConstant()) { |
| 301 return visitInvokeBinary(node); | 338 return super.visitEquals(node); |
| 302 } | 339 } |
| 303 | 340 |
| 304 if (left.isNonPrimitive()) { | 341 if (left.isNonPrimitive()) { |
| 305 HNonPrimitiveType type = left.propagatedType; | 342 HNonPrimitiveType type = left.propagatedType; |
| 306 Element element = type.lookupMember(Namer.OPERATOR_EQUALS); | 343 Element element = type.lookupMember(Namer.OPERATOR_EQUALS); |
| 307 if (element !== null) { | 344 if (element !== null) { |
| 308 // If the left-hand side is guaranteed to be a non-primitive | 345 // 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 | 346 // type and and it defines operator==, we emit a call to that |
| 310 // operator. | 347 // operator. |
| 311 return visitInvokeBinary(node); | 348 return super.visitEquals(node); |
| 312 } else if (right.isConstantNull()) { | 349 } else if (right.isConstantNull()) { |
| 313 return graph.addConstantBool(false); | 350 return graph.addConstantBool(false); |
| 314 } else { | 351 } else { |
| 315 // We can just emit an identity check because the type does | 352 // We can just emit an identity check because the type does |
| 316 // not implement operator=. | 353 // not implement operator=. |
| 317 // TODO(floitsch): cache interceptors. | 354 // TODO(floitsch): cache interceptors. |
| 318 HStatic target = new HStatic( | 355 HStatic target = new HStatic( |
| 319 compiler.builder.interceptors.getTripleEqualsInterceptor()); | 356 compiler.builder.interceptors.getTripleEqualsInterceptor()); |
| 320 node.block.addBefore(node, target); | 357 node.block.addBefore(node, target); |
| 321 return new HIdentity(target, left, right); | 358 return new HIdentity(target, left, right); |
| 322 } | 359 } |
| 323 } | 360 } |
| 324 | 361 |
| 325 | 362 |
| 326 if (right.isConstantNull()) { | 363 if (right.isConstantNull()) { |
| 327 if (left.propagatedType.isUseful()) { | 364 if (left.propagatedType.isUseful()) { |
| 328 return graph.addConstantBool(false); | 365 return graph.addConstantBool(false); |
| 329 } else { | 366 } else { |
| 330 // TODO(floitsch): cache interceptors. | 367 // TODO(floitsch): cache interceptors. |
| 331 HStatic target = new HStatic( | 368 Interceptors interceptors = compiler.builder.interceptors; |
| 332 compiler.builder.interceptors.getEqualsNullInterceptor()); | 369 Element targetElement = interceptors.getEqualsNullInterceptor(); |
| 370 bool onlyUsedInBoolify = allUsersAreBoolifies(node); |
| 371 if (onlyUsedInBoolify) { |
| 372 targetElement = interceptors.getBoolifiedVersionOf(targetElement); |
| 373 } |
| 374 HStatic target = new HStatic(targetElement); |
| 333 node.block.addBefore(node, target); | 375 node.block.addBefore(node, target); |
| 334 return new HEquals(target, node.left, node.right); | 376 HEquals result = new HEquals(target, node.left, node.right); |
| 377 if (onlyUsedInBoolify) { |
| 378 result.usesBoolifiedInterceptor = true; |
| 379 result.propagatedType = HType.BOOLEAN; |
| 380 } |
| 381 return result; |
| 335 } | 382 } |
| 336 } | 383 } |
| 337 | 384 |
| 338 // All other cases are dealt with by the [visitInvokeBinary]. | 385 // All other cases are dealt with by the [visitRelational] and |
| 339 return visitInvokeBinary(node); | 386 // [visitInvokeBinary], which are visited by invoking the [super]'s |
| 387 // visit method. |
| 388 return super.visitEquals(node); |
| 340 } | 389 } |
| 341 | 390 |
| 342 HInstruction visitTypeGuard(HTypeGuard node) { | 391 HInstruction visitTypeGuard(HTypeGuard node) { |
| 343 HInstruction value = node.guarded; | 392 HInstruction value = node.guarded; |
| 344 HType combinedType = value.propagatedType.combine(node.guardedType); | 393 HType combinedType = value.propagatedType.combine(node.guardedType); |
| 345 return (combinedType == value.propagatedType) ? value : node; | 394 return (combinedType == value.propagatedType) ? value : node; |
| 346 } | 395 } |
| 347 | 396 |
| 348 HInstruction visitIs(HIs node) { | 397 HInstruction visitIs(HIs node) { |
| 349 Type type = node.typeName; | 398 Type type = node.typeName; |
| (...skipping 513 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 863 } | 912 } |
| 864 } | 913 } |
| 865 if (!canBeMoved) continue; | 914 if (!canBeMoved) continue; |
| 866 | 915 |
| 867 // This is safe because we are running after GVN. | 916 // This is safe because we are running after GVN. |
| 868 // TODO(ngeoffray): ensure GVN has been run. | 917 // TODO(ngeoffray): ensure GVN has been run. |
| 869 set_.add(current); | 918 set_.add(current); |
| 870 } | 919 } |
| 871 } | 920 } |
| 872 } | 921 } |
| OLD | NEW |