| 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 /** | 7 /** |
| 8 * A special element for the extra parameter taken by intercepted | 8 * A special element for the extra parameter taken by intercepted |
| 9 * methods. We need to override [Element.computeType] because our | 9 * methods. We need to override [Element.computeType] because our |
| 10 * optimizers may look at its declared type. | 10 * optimizers may look at its declared type. |
| (...skipping 2564 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2575 } | 2575 } |
| 2576 | 2576 |
| 2577 HInstruction getRuntimeTypeInfo(HInstruction target) { | 2577 HInstruction getRuntimeTypeInfo(HInstruction target) { |
| 2578 pushInvokeHelper1(backend.getGetRuntimeTypeInfo(), target, HType.UNKNOWN); | 2578 pushInvokeHelper1(backend.getGetRuntimeTypeInfo(), target, HType.UNKNOWN); |
| 2579 return pop(); | 2579 return pop(); |
| 2580 } | 2580 } |
| 2581 | 2581 |
| 2582 // TODO(karlklose): change construction of the representations to be GVN'able | 2582 // TODO(karlklose): change construction of the representations to be GVN'able |
| 2583 // (dartbug.com/7182). | 2583 // (dartbug.com/7182). |
| 2584 List<HInstruction> buildTypeArgumentRepresentations(DartType type) { | 2584 List<HInstruction> buildTypeArgumentRepresentations(DartType type) { |
| 2585 HInstruction createForeignArray(String code, inputs) { | |
| 2586 return createForeign(code, HType.READABLE_ARRAY, inputs); | |
| 2587 } | |
| 2588 | |
| 2589 // Compute the representation of the type arguments, including access | 2585 // Compute the representation of the type arguments, including access |
| 2590 // to the runtime type information for type variables as instructions. | 2586 // to the runtime type information for type variables as instructions. |
| 2591 HInstruction representations; | 2587 HInstruction representations; |
| 2592 if (type.element.isTypeVariable()) { | 2588 if (type.kind == TypeKind.TYPE_VARIABLE) { |
| 2593 return <HInstruction>[addTypeVariableReference(type)]; | 2589 return <HInstruction>[addTypeVariableReference(type)]; |
| 2594 } else { | 2590 } else { |
| 2595 assert(type.element.isClass()); | 2591 assert(type.element.isClass()); |
| 2596 List<HInstruction> arguments = <HInstruction>[]; | 2592 List<HInstruction> arguments = <HInstruction>[]; |
| 2597 InterfaceType interface = type; | 2593 InterfaceType interface = type; |
| 2598 for (DartType argument in interface.typeArguments) { | 2594 for (DartType argument in interface.typeArguments) { |
| 2599 List<HInstruction> inputs = <HInstruction>[]; | 2595 List<HInstruction> inputs = <HInstruction>[]; |
| 2600 String template = rti.getTypeRepresentation(argument, (variable) { | 2596 String template = rti.getTypeRepresentation(argument, (variable) { |
| 2601 HInstruction runtimeType = addTypeVariableReference(variable); | 2597 HInstruction runtimeType = addTypeVariableReference(variable); |
| 2602 inputs.add(runtimeType); | 2598 inputs.add(runtimeType); |
| 2603 }); | 2599 }); |
| 2604 HInstruction representation = createForeignArray(template, inputs); | 2600 HInstruction representation = |
| 2601 createForeign(template, HType.READABLE_ARRAY, inputs); |
| 2605 add(representation); | 2602 add(representation); |
| 2606 arguments.add(representation); | 2603 arguments.add(representation); |
| 2607 } | 2604 } |
| 2608 return arguments; | 2605 return arguments; |
| 2609 } | 2606 } |
| 2610 } | 2607 } |
| 2611 | 2608 |
| 2612 visitOperatorSend(node) { | 2609 visitOperatorSend(node) { |
| 2613 Operator op = node.selector; | 2610 Operator op = node.selector; |
| 2614 if (const SourceString("[]") == op.source) { | 2611 if (const SourceString("[]") == op.source) { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 2626 Node argument = node.arguments.head; | 2623 Node argument = node.arguments.head; |
| 2627 TypeAnnotation typeAnnotation = argument.asTypeAnnotation(); | 2624 TypeAnnotation typeAnnotation = argument.asTypeAnnotation(); |
| 2628 bool isNot = false; | 2625 bool isNot = false; |
| 2629 // TODO(ngeoffray): Duplicating pattern in resolver. We should | 2626 // TODO(ngeoffray): Duplicating pattern in resolver. We should |
| 2630 // add a new kind of node. | 2627 // add a new kind of node. |
| 2631 if (typeAnnotation == null) { | 2628 if (typeAnnotation == null) { |
| 2632 typeAnnotation = argument.asSend().receiver; | 2629 typeAnnotation = argument.asSend().receiver; |
| 2633 isNot = true; | 2630 isNot = true; |
| 2634 } | 2631 } |
| 2635 DartType type = elements.getType(typeAnnotation); | 2632 DartType type = elements.getType(typeAnnotation); |
| 2633 compiler.enqueuer.codegen.registerIsCheck(type); |
| 2636 if (type.isMalformed) { | 2634 if (type.isMalformed) { |
| 2637 String reasons = Types.fetchReasonsFromMalformedType(type); | 2635 String reasons = Types.fetchReasonsFromMalformedType(type); |
| 2638 if (compiler.enableTypeAssertions) { | 2636 if (compiler.enableTypeAssertions) { |
| 2639 generateMalformedSubtypeError(node, expression, type, reasons); | 2637 generateMalformedSubtypeError(node, expression, type, reasons); |
| 2640 } else { | 2638 } else { |
| 2641 generateRuntimeError(node, '$type is malformed: $reasons'); | 2639 generateRuntimeError(node, '$type is malformed: $reasons'); |
| 2642 } | 2640 } |
| 2643 return; | 2641 return; |
| 2644 } | 2642 } |
| 2645 if (type.element.isTypeVariable()) { | |
| 2646 // TODO(karlklose): remove this check when the backend can deal with | |
| 2647 // checks of the form [:o is T:] where [:T:] is a type variable. | |
| 2648 stack.add(graph.addConstantBool(true, constantSystem)); | |
| 2649 return; | |
| 2650 } | |
| 2651 | 2643 |
| 2652 HInstruction instruction; | 2644 HInstruction instruction; |
| 2653 if (type.element.isTypeVariable() || | 2645 if (type.kind == TypeKind.TYPE_VARIABLE) { |
| 2654 RuntimeTypeInformation.hasTypeArguments(type)) { | 2646 List<HInstruction> representations = |
| 2647 buildTypeArgumentRepresentations(type); |
| 2648 assert(representations.length == 1); |
| 2649 HInstruction runtimeType = addTypeVariableReference(type); |
| 2650 Element helper = |
| 2651 compiler.findHelper(const SourceString('objectIsSubtype')); |
| 2652 HInstruction helperCall = new HStatic(helper); |
| 2653 add(helperCall); |
| 2654 List<HInstruction> inputs = <HInstruction>[helperCall, expression, |
| 2655 runtimeType]; |
| 2656 instruction = new HInvokeStatic(inputs, HType.BOOLEAN); |
| 2657 add(instruction); |
| 2658 |
| 2659 } else if (RuntimeTypeInformation.hasTypeArguments(type)) { |
| 2655 | 2660 |
| 2656 void argumentsCheck() { | 2661 void argumentsCheck() { |
| 2657 HInstruction typeInfo = getRuntimeTypeInfo(expression); | 2662 HInstruction typeInfo = getRuntimeTypeInfo(expression); |
| 2658 Element helper = backend.getCheckArguments(); | 2663 Element helper = backend.getCheckArguments(); |
| 2659 HInstruction helperCall = new HStatic(helper); | 2664 HInstruction helperCall = new HStatic(helper); |
| 2660 add(helperCall); | 2665 add(helperCall); |
| 2661 List<HInstruction> representations = | 2666 List<HInstruction> representations = |
| 2662 buildTypeArgumentRepresentations(type); | 2667 buildTypeArgumentRepresentations(type); |
| 2663 Element element = type.element; | 2668 Element element = type.element; |
| 2664 String substitution = backend.namer.substitutionName(element); | 2669 String substitution = backend.namer.substitutionName(element); |
| 2665 if (backend.emitter.nativeEmitter.requiresNativeIsCheck(element)) { | 2670 if (backend.emitter.nativeEmitter.requiresNativeIsCheck(element)) { |
| 2666 substitution = '$substitution()'; | 2671 substitution = '$substitution()'; |
| 2667 } | 2672 } |
| 2668 HInstruction fieldGet = | 2673 HInstruction fieldGet = |
| 2669 createForeign('#.$substitution', HType.UNKNOWN, [expression]); | 2674 createForeign('#.$substitution', HType.UNKNOWN, [expression]); |
| 2670 HInstruction representationList = new HLiteralList(representations); | 2675 HInstruction representationList = new HLiteralList(representations); |
| 2671 add(fieldGet); | 2676 add(fieldGet); |
| 2672 add(representationList); | 2677 add(representationList); |
| 2673 List<HInstruction> inputs = <HInstruction>[helperCall, | 2678 List<HInstruction> inputs = <HInstruction>[helperCall, |
| 2674 fieldGet, | 2679 fieldGet, |
| 2675 typeInfo, | 2680 typeInfo, |
| 2676 representationList]; | 2681 representationList]; |
| 2677 push(new HInvokeStatic(inputs, HType.UNKNOWN)); | 2682 push(new HInvokeStatic(inputs, HType.UNKNOWN)); |
| 2678 } | 2683 } |
| 2679 | 2684 |
| 2680 void classCheck() { push(new HIs(type, <HInstruction>[expression])); } | 2685 void classCheck() { push(new HIs(type, <HInstruction>[expression])); } |
| 2681 | 2686 |
| 2682 SsaBranchBuilder branchBuilder = new SsaBranchBuilder(this, node); | 2687 SsaBranchBuilder branchBuilder = new SsaBranchBuilder(this, node); |
| 2683 branchBuilder.handleLogicalAndOr(classCheck, argumentsCheck, isAnd: true
); | 2688 branchBuilder.handleLogicalAndOr(classCheck, argumentsCheck, |
| 2689 isAnd: true); |
| 2684 instruction = pop(); | 2690 instruction = pop(); |
| 2685 } else { | 2691 } else { |
| 2686 instruction = new HIs(type, <HInstruction>[expression]); | 2692 instruction = new HIs(type, <HInstruction>[expression]); |
| 2687 add(instruction); | 2693 add(instruction); |
| 2688 } | 2694 } |
| 2689 if (isNot) { | 2695 if (isNot) { |
| 2690 instruction = new HNot(instruction); | 2696 instruction = new HNot(instruction); |
| 2691 add(instruction); | 2697 add(instruction); |
| 2692 } | 2698 } |
| 2693 stack.add(instruction); | 2699 stack.add(instruction); |
| (...skipping 2378 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5072 new HSubGraphBlockInformation(elseBranch.graph)); | 5078 new HSubGraphBlockInformation(elseBranch.graph)); |
| 5073 | 5079 |
| 5074 HBasicBlock conditionStartBlock = conditionBranch.block; | 5080 HBasicBlock conditionStartBlock = conditionBranch.block; |
| 5075 conditionStartBlock.setBlockFlow(info, joinBlock); | 5081 conditionStartBlock.setBlockFlow(info, joinBlock); |
| 5076 SubGraph conditionGraph = conditionBranch.graph; | 5082 SubGraph conditionGraph = conditionBranch.graph; |
| 5077 HIf branch = conditionGraph.end.last; | 5083 HIf branch = conditionGraph.end.last; |
| 5078 assert(branch is HIf); | 5084 assert(branch is HIf); |
| 5079 branch.blockInformation = conditionStartBlock.blockFlow; | 5085 branch.blockInformation = conditionStartBlock.blockFlow; |
| 5080 } | 5086 } |
| 5081 } | 5087 } |
| OLD | NEW |