| OLD | NEW |
| 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 part of ssa; | 5 part of ssa; |
| 6 | 6 |
| 7 abstract class OptimizationPhase { | 7 abstract class OptimizationPhase { |
| 8 String get name; | 8 String get name; |
| 9 void visitGraph(HGraph graph); | 9 void visitGraph(HGraph graph); |
| 10 } | 10 } |
| (...skipping 371 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 382 HInstruction visitInvokeStatic(HInvokeStatic node) { | 382 HInstruction visitInvokeStatic(HInvokeStatic node) { |
| 383 if (isFixedSizeListConstructor(node)) { | 383 if (isFixedSizeListConstructor(node)) { |
| 384 node.guaranteedType = HType.FIXED_ARRAY; | 384 node.guaranteedType = HType.FIXED_ARRAY; |
| 385 } | 385 } |
| 386 return node; | 386 return node; |
| 387 } | 387 } |
| 388 | 388 |
| 389 HInstruction visitInvokeDynamicMethod(HInvokeDynamicMethod node) { | 389 HInstruction visitInvokeDynamicMethod(HInvokeDynamicMethod node) { |
| 390 if (node.isInterceptorCall) return handleInterceptorCall(node); | 390 if (node.isInterceptorCall) return handleInterceptorCall(node); |
| 391 HType receiverType = types[node.receiver]; | 391 HType receiverType = types[node.receiver]; |
| 392 if (receiverType.isExact()) { | 392 Element element = receiverType.lookupSingleTarget(node.selector, compiler); |
| 393 Element element = receiverType.lookupMember(node.selector.name, compiler); | 393 // TODO(ngeoffray): Also fold if it's a getter or variable. |
| 394 // TODO(ngeoffray): Also fold if it's a getter or variable. | 394 if (element != null && element.isFunction()) { |
| 395 if (element != null && element.isFunction()) { | 395 FunctionElement method = element; |
| 396 if (node.selector.applies(element, compiler)) { | 396 FunctionSignature parameters = method.computeSignature(compiler); |
| 397 FunctionElement method = element; | 397 // TODO(ngeoffray): If the method has optional parameters, |
| 398 FunctionSignature parameters = method.computeSignature(compiler); | 398 // we should pass the default values. |
| 399 if (parameters.optionalParameterCount == 0) { | 399 if (parameters.optionalParameterCount == 0 |
| 400 node.element = element; | 400 || parameters.parameterCount == node.selector.argumentCount) { |
| 401 } | 401 node.element = element; |
| 402 // TODO(ngeoffray): If the method has optional parameters, | |
| 403 // we should pass the default values here. | |
| 404 } | |
| 405 } | 402 } |
| 406 } | 403 } |
| 407 return node; | 404 return node; |
| 408 } | 405 } |
| 409 | 406 |
| 410 HInstruction visitIntegerCheck(HIntegerCheck node) { | 407 HInstruction visitIntegerCheck(HIntegerCheck node) { |
| 411 HInstruction value = node.value; | 408 HInstruction value = node.value; |
| 412 if (value.isInteger(types)) return value; | 409 if (value.isInteger(types)) return value; |
| 413 if (value.isConstant()) { | 410 if (value.isConstant()) { |
| 414 HConstant constantInstruction = value; | 411 HConstant constantInstruction = value; |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 596 return node; | 593 return node; |
| 597 } | 594 } |
| 598 HType combinedType = types[value].intersection(types[node], compiler); | 595 HType combinedType = types[value].intersection(types[node], compiler); |
| 599 return (combinedType == types[value]) ? value : node; | 596 return (combinedType == types[value]) ? value : node; |
| 600 } | 597 } |
| 601 | 598 |
| 602 Element findConcreteFieldForDynamicAccess(HInstruction receiver, | 599 Element findConcreteFieldForDynamicAccess(HInstruction receiver, |
| 603 Selector selector) { | 600 Selector selector) { |
| 604 HType receiverType = types[receiver]; | 601 HType receiverType = types[receiver]; |
| 605 if (!receiverType.isUseful()) return null; | 602 if (!receiverType.isUseful()) return null; |
| 606 if (receiverType.canBeNull()) return null; | |
| 607 DartType type = receiverType.computeType(compiler); | 603 DartType type = receiverType.computeType(compiler); |
| 608 if (type == null) return null; | 604 if (type == null) return null; |
| 605 if (Elements.isErroneousElement(type.element)) return null; |
| 609 return compiler.world.locateSingleField(type, selector); | 606 return compiler.world.locateSingleField(type, selector); |
| 610 } | 607 } |
| 611 | 608 |
| 612 HInstruction visitFieldGet(HFieldGet node) { | 609 HInstruction visitFieldGet(HFieldGet node) { |
| 613 if (node.element == backend.jsArrayLength) { | 610 if (node.element == backend.jsArrayLength) { |
| 614 if (node.receiver is HInvokeStatic) { | 611 if (node.receiver is HInvokeStatic) { |
| 615 // Try to recognize the length getter with input | 612 // Try to recognize the length getter with input |
| 616 // [:new List.fixedLength(int):]. | 613 // [:new List.fixedLength(int):]. |
| 617 HInvokeStatic call = node.receiver; | 614 HInvokeStatic call = node.receiver; |
| 618 if (isFixedSizeListConstructor(call)) { | 615 if (isFixedSizeListConstructor(call)) { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 632 | 629 |
| 633 Modifiers modifiers = field.modifiers; | 630 Modifiers modifiers = field.modifiers; |
| 634 bool isFinalOrConst = modifiers.isFinal() || modifiers.isConst(); | 631 bool isFinalOrConst = modifiers.isFinal() || modifiers.isConst(); |
| 635 if (!compiler.resolverWorld.hasInvokedSetter(field, compiler)) { | 632 if (!compiler.resolverWorld.hasInvokedSetter(field, compiler)) { |
| 636 // If no setter is ever used for this field it is only initialized in the | 633 // If no setter is ever used for this field it is only initialized in the |
| 637 // initializer list. | 634 // initializer list. |
| 638 isFinalOrConst = true; | 635 isFinalOrConst = true; |
| 639 } | 636 } |
| 640 HFieldGet result = new HFieldGet( | 637 HFieldGet result = new HFieldGet( |
| 641 field, node.inputs[0], isAssignable: !isFinalOrConst); | 638 field, node.inputs[0], isAssignable: !isFinalOrConst); |
| 642 HType type = backend.optimisticFieldType(field); | 639 |
| 643 if (type != null) { | 640 if (field.getEnclosingClass().isNative()) { |
| 644 result.guaranteedType = type; | 641 result.guaranteedType = |
| 645 backend.registerFieldTypesOptimization( | 642 new HType.subtype(field.computeType(compiler), compiler); |
| 646 work.element, field, result.guaranteedType); | 643 } else { |
| 644 HType type = backend.optimisticFieldType(field); |
| 645 if (type != null) { |
| 646 backend.registerFieldTypesOptimization( |
| 647 work.element, field, result.guaranteedType); |
| 648 result.guaranteedType = type; |
| 649 } |
| 647 } | 650 } |
| 648 return result; | 651 return result; |
| 649 } | 652 } |
| 650 | 653 |
| 651 HInstruction visitInvokeDynamicSetter(HInvokeDynamicSetter node) { | 654 HInstruction visitInvokeDynamicSetter(HInvokeDynamicSetter node) { |
| 652 if (node.isInterceptorCall) return handleInterceptorCall(node); | 655 if (node.isInterceptorCall) return handleInterceptorCall(node); |
| 653 | 656 |
| 654 Element field = | 657 Element field = |
| 655 findConcreteFieldForDynamicAccess(node.receiver, node.selector); | 658 findConcreteFieldForDynamicAccess(node.receiver, node.selector); |
| 656 if (field == null || !field.isAssignable()) return node; | 659 if (field == null || !field.isAssignable()) return node; |
| (...skipping 885 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1542 HBasicBlock block = user.block; | 1545 HBasicBlock block = user.block; |
| 1543 block.addAfter(user, interceptor); | 1546 block.addAfter(user, interceptor); |
| 1544 block.rewrite(user, interceptor); | 1547 block.rewrite(user, interceptor); |
| 1545 block.remove(user); | 1548 block.remove(user); |
| 1546 | 1549 |
| 1547 // The interceptor will be removed in the dead code elimination | 1550 // The interceptor will be removed in the dead code elimination |
| 1548 // phase. Note that removing it here would not work because of how | 1551 // phase. Note that removing it here would not work because of how |
| 1549 // the [visitBasicBlock] is implemented. | 1552 // the [visitBasicBlock] is implemented. |
| 1550 } | 1553 } |
| 1551 } | 1554 } |
| OLD | NEW |