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

Side by Side Diff: sdk/lib/_internal/compiler/implementation/ssa/builder.dart

Issue 11448009: Represent runtime type information as nested lists. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Minor edits. Created 8 years 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
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 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 2615 matching lines...) Expand 10 before | Expand all | Expand 10 after
2626 2626
2627 void pushInvokeHelper4(Element helper, HInstruction a0, HInstruction a1, 2627 void pushInvokeHelper4(Element helper, HInstruction a0, HInstruction a1,
2628 HInstruction a2, HInstruction a3) { 2628 HInstruction a2, HInstruction a3) {
2629 HInstruction reference = new HStatic(helper); 2629 HInstruction reference = new HStatic(helper);
2630 add(reference); 2630 add(reference);
2631 List<HInstruction> inputs = <HInstruction>[reference, a0, a1, a2, a3]; 2631 List<HInstruction> inputs = <HInstruction>[reference, a0, a1, a2, a3];
2632 HInstruction result = new HInvokeStatic(inputs); 2632 HInstruction result = new HInvokeStatic(inputs);
2633 push(result); 2633 push(result);
2634 } 2634 }
2635 2635
2636 createForeign(String code, String type, List<HInstruction> inputs) {
2637 return new HForeign(new LiteralDartString(code),
2638 new LiteralDartString(type),
2639 inputs);
2640 }
2641
2642 List<HInstruction> buildRepresentations(DartType type) {
kasperl 2012/12/06 09:51:04 Maybe give this function a more telling name? Also
karlklose 2012/12/06 13:30:03 Renamed and added a comment for making the constru
2643 HInstruction createForeignArray(String code, inputs) {
2644 return createForeign(code, 'JSArray', inputs);
2645 }
2646 HInstruction typeInfo;
2647
2648 /// Helper to create an instruction that contains the runtime value of
2649 /// the type variable [variable].
2650 HInstruction getTypeArgument(TypeVariableType variable) {
2651 if (typeInfo == null) {
2652 HInstruction context = localsHandler.readThis();
2653 pushInvokeHelper1(interceptors.getGetRuntimeTypeInfo(), context);
2654 typeInfo = pop();
2655 }
2656 int intIndex = RuntimeTypeInformation.getTypeVariableIndex(variable);
2657 HInstruction index = graph.addConstantInt(intIndex, constantSystem);
2658 return createForeignArray('#[#]', <HInstruction>[typeInfo, index]);
2659 }
2660
2661 // Compute the representation of the type arguments, including access
2662 // to the runtime type information for type variables as instructions.
2663 HInstruction representations;
2664 if (type.element.isTypeVariable()) {
2665 return <HInstruction>[getTypeArgument(type)];
2666 } else {
2667 assert(type.element.isClass());
2668 List<HInstruction> arguments = <HInstruction>[];
2669 InterfaceType interface = type;
2670 for (DartType argument in interface.typeArguments) {
2671 List<HInstruction> inputs = <HInstruction>[];
2672 String template = rti.getTypeRepresentation(argument, (variable) {
2673 HInstruction runtimeType = getTypeArgument(variable);
2674 add(runtimeType);
2675 inputs.add(runtimeType);
2676 });
2677 HInstruction representation = createForeignArray(template, inputs);
2678 add(representation);
2679 arguments.add(representation);
2680 }
2681 return arguments;
2682 }
2683 }
2684
2636 visitOperatorSend(node) { 2685 visitOperatorSend(node) {
2637 assert(node.selector is Operator); 2686 assert(node.selector is Operator);
2638 if (!methodInterceptionEnabled) { 2687 if (!methodInterceptionEnabled) {
2639 visitDynamicSend(node); 2688 visitDynamicSend(node);
2640 return; 2689 return;
2641 } 2690 }
2642 2691
2643 Operator op = node.selector; 2692 Operator op = node.selector;
2644 if (const SourceString("[]") == op.source) { 2693 if (const SourceString("[]") == op.source) {
2645 HStatic target = new HStatic(interceptors.getIndexInterceptor()); 2694 HStatic target = new HStatic(interceptors.getIndexInterceptor());
(...skipping 15 matching lines...) Expand all
2661 HInstruction expression = pop(); 2710 HInstruction expression = pop();
2662 Node argument = node.arguments.head; 2711 Node argument = node.arguments.head;
2663 TypeAnnotation typeAnnotation = argument.asTypeAnnotation(); 2712 TypeAnnotation typeAnnotation = argument.asTypeAnnotation();
2664 bool isNot = false; 2713 bool isNot = false;
2665 // TODO(ngeoffray): Duplicating pattern in resolver. We should 2714 // TODO(ngeoffray): Duplicating pattern in resolver. We should
2666 // add a new kind of node. 2715 // add a new kind of node.
2667 if (typeAnnotation == null) { 2716 if (typeAnnotation == null) {
2668 typeAnnotation = argument.asSend().receiver; 2717 typeAnnotation = argument.asSend().receiver;
2669 isNot = true; 2718 isNot = true;
2670 } 2719 }
2671
2672 DartType type = elements.getType(typeAnnotation); 2720 DartType type = elements.getType(typeAnnotation);
2673 if (type.isMalformed) { 2721 if (type.isMalformed) {
2674 String reasons = fetchReasonsFromMalformedType(type); 2722 String reasons = fetchReasonsFromMalformedType(type);
2675 if (compiler.enableTypeAssertions) { 2723 if (compiler.enableTypeAssertions) {
2676 generateMalformedSubtypeError(node, expression, type, reasons); 2724 generateMalformedSubtypeError(node, expression, type, reasons);
2677 } else { 2725 } else {
2678 generateRuntimeError(node, '$type is malformed: $reasons'); 2726 generateRuntimeError(node, '$type is malformed: $reasons');
2679 } 2727 }
2680 return; 2728 return;
2681 } 2729 }
2682 HInstruction typeInfo = null; 2730 if (type.element.isTypeVariable()) {
2683 if (RuntimeTypeInformation.hasTypeArguments(type)) { 2731 // TODO(karlklose): remove this check when the backend can deal with it.
kasperl 2012/12/06 09:51:04 Expand the comment to explain what you're waiting
karlklose 2012/12/06 13:30:03 Done.
2732 stack.add(graph.addConstantBool(true, constantSystem));
2733 return;
2734 }
2735
2736 HInstruction instruction;
2737 if (RuntimeTypeInformation.hasTypeArguments(type) ||
2738 type.element.isTypeVariable()) {
2684 pushInvokeHelper1(interceptors.getGetRuntimeTypeInfo(), expression); 2739 pushInvokeHelper1(interceptors.getGetRuntimeTypeInfo(), expression);
kasperl 2012/12/06 09:51:04 Could this code be put in a separate helper functi
karlklose 2012/12/06 13:30:03 Done.
2685 typeInfo = pop(); 2740 HInstruction typeInfo = pop();
2741 Element helper = compiler.findHelper(const SourceString('isSubtype'));
kasperl 2012/12/06 09:51:04 Would it make sense to have a separate HIsSubtype
karlklose 2012/12/06 13:30:03 I am not sure how much work it is to do it, but I
2742 HInstruction isSubtype = new HStatic(helper);
2743 add(isSubtype);
2744 List<HInstruction> representations = buildRepresentations(type);
2745 List<HInstruction> checks = <HInstruction>[];
2746 int index = 0;
2747 representations.forEach((HInstruction representation) {
kasperl 2012/12/06 09:51:04 Add a comment that explains the code you're buildi
karlklose 2012/12/06 13:30:03 Done.
2748 HInstruction position = graph.addConstantInt(index, constantSystem);
2749 HInstruction typeArgument =
kasperl 2012/12/06 09:51:04 I wonder if we should be creating something that w
karlklose 2012/12/06 13:30:03 As said above, I'll look into better code generati
2750 createForeign('#[#]', 'Object', [typeInfo, position]);
2751 add(typeArgument);
2752 List<HInstruction> inputs =
2753 <HInstruction>[isSubtype, typeArgument, representation];
2754 HInstruction call = new HInvokeStatic(inputs);
2755 add(call);
2756 checks.add(call);
2757 index++;
2758 });
2759 instruction = new HIs.withArgumentChecks(type, expression, checks);
2760 } else {
2761 instruction = new HIs(type, expression);
2686 } 2762 }
2687 if (type.element.isTypeVariable()) { 2763 if (isNot) {
2688 // TODO(karlklose): We currently answer true to any is check 2764 add(instruction);
2689 // involving a type variable -- both is T and is !T -- until 2765 instruction = new HNot(instruction);
2690 // we have a proper implementation of reified generics.
2691 stack.add(graph.addConstantBool(true, constantSystem));
2692 } else {
2693 HInstruction instruction;
2694 if (typeInfo != null) {
2695 instruction = new HIs.withTypeInfoCall(type, expression, typeInfo);
2696 } else {
2697 instruction = new HIs(type, expression);
2698 }
2699 if (isNot) {
2700 add(instruction);
2701 instruction = new HNot(instruction);
2702 }
2703 push(instruction);
2704 } 2766 }
2767 push(instruction);
2705 } else if (const SourceString("as") == op.source) { 2768 } else if (const SourceString("as") == op.source) {
2706 visit(node.receiver); 2769 visit(node.receiver);
2707 HInstruction expression = pop(); 2770 HInstruction expression = pop();
2708 Node argument = node.arguments.head; 2771 Node argument = node.arguments.head;
2709 TypeAnnotation typeAnnotation = argument.asTypeAnnotation(); 2772 TypeAnnotation typeAnnotation = argument.asTypeAnnotation();
2710 DartType type = elements.getType(typeAnnotation); 2773 DartType type = elements.getType(typeAnnotation);
2711 HInstruction converted = expression.convertType( 2774 HInstruction converted = expression.convertType(
2712 compiler, type, HTypeConversion.CAST_TYPE_CHECK); 2775 compiler, type, HTypeConversion.CAST_TYPE_CHECK);
2713 if (converted != expression) add(converted); 2776 if (converted != expression) add(converted);
2714 stack.add(converted); 2777 stack.add(converted);
(...skipping 382 matching lines...) Expand 10 before | Expand all | Expand 10 after
3097 */ 3160 */
3098 HInstruction analyzeTypeArgument(DartType argument, Node currentNode) { 3161 HInstruction analyzeTypeArgument(DartType argument, Node currentNode) {
3099 assert(invariant(currentNode, 3162 assert(invariant(currentNode,
3100 !compiler.enableTypeAssertions || !argument.isMalformed, 3163 !compiler.enableTypeAssertions || !argument.isMalformed,
3101 message: '$argument is malformed in checked mode')); 3164 message: '$argument is malformed in checked mode'));
3102 if (argument == compiler.types.dynamicType || argument.isMalformed) { 3165 if (argument == compiler.types.dynamicType || argument.isMalformed) {
3103 // Represent [dynamic] as [null]. 3166 // Represent [dynamic] as [null].
3104 return graph.addConstantNull(constantSystem); 3167 return graph.addConstantNull(constantSystem);
3105 } 3168 }
3106 3169
3107 // These variables are shared between invocations of the helper methods. 3170 createForeignString(template, inputs) {
kasperl 2012/12/06 09:51:04 Use createForeign?
karlklose 2012/12/06 13:30:03 Done.
3171 return new HForeign(new LiteralDartString(template),
3172 new LiteralDartString('String'),
3173 inputs);
3174 }
3175
3176 // These variables are shared between invocations of the helper.
3108 HInstruction typeInfo; 3177 HInstruction typeInfo;
3109 StringBuffer template = new StringBuffer();
3110 List<HInstruction> inputs = <HInstruction>[]; 3178 List<HInstruction> inputs = <HInstruction>[];
3111 3179
3112 /** 3180 /**
3113 * Helper to create an instruction that gets the value of a type variable. 3181 * Helper to create an instruction that gets the value of a type variable.
3114 */ 3182 */
3115 void addTypeVariableReference(TypeVariableType type) { 3183 void addTypeVariableReference(TypeVariableType type) {
3116 Element member = work.element; 3184 Element member = work.element;
3117 if (member.enclosingElement.isClosure()) { 3185 if (member.enclosingElement.isClosure()) {
3118 ClosureClassElement closureClass = member.enclosingElement; 3186 ClosureClassElement closureClass = member.enclosingElement;
3119 member = closureClass.methodElement; 3187 member = closureClass.methodElement;
3120 member = member.getOutermostEnclosingMemberOrTopLevel(); 3188 member = member.getOutermostEnclosingMemberOrTopLevel();
3121 } 3189 }
3122 if (member.isFactoryConstructor()) { 3190 if (member.isFactoryConstructor()) {
3123 // The type variable is stored in a parameter of the factory. 3191 // The type variable is stored in a parameter of the factory.
3124 inputs.add(localsHandler.readLocal(type.element)); 3192 inputs.add(localsHandler.readLocal(type.element));
3125 } else if (member.isInstanceMember() 3193 } else if (member.isInstanceMember()
3126 || member.isGenerativeConstructor()) { 3194 || member.isGenerativeConstructor()) {
3127 // The type variable is stored in [this]. 3195 // The type variable is stored in [this].
3128 if (typeInfo == null) { 3196 if (typeInfo == null) {
3129 pushInvokeHelper1(interceptors.getGetRuntimeTypeInfo(), 3197 pushInvokeHelper1(interceptors.getGetRuntimeTypeInfo(),
3130 localsHandler.readThis()); 3198 localsHandler.readThis());
3131 typeInfo = pop(); 3199 typeInfo = pop();
3132 } 3200 }
3133 int index = RuntimeTypeInformation.getTypeVariableIndex(type); 3201 int index = RuntimeTypeInformation.getTypeVariableIndex(type);
3134 HInstruction foreign = new HForeign( 3202 HInstruction foreign = createForeignString('#[$index]',
3135 new LiteralDartString('#[$index]'), 3203 <HInstruction>[typeInfo]);
3136 new LiteralDartString('String'),
3137 <HInstruction>[typeInfo]);
3138 add(foreign); 3204 add(foreign);
3139 inputs.add(foreign); 3205 inputs.add(foreign);
3140 } else { 3206 } else {
3141 // TODO(ngeoffray): Match the VM behavior and throw an 3207 // TODO(ngeoffray): Match the VM behavior and throw an
3142 // exception at runtime. 3208 // exception at runtime.
3143 compiler.cancel('Unimplemented unresolved type variable', 3209 compiler.cancel('Unimplemented unresolved type variable',
3144 node: currentNode); 3210 node: currentNode);
3145 } 3211 }
3146 } 3212 }
3147 3213
3148 /** 3214 String template = rti.getTypeRepresentation(argument,
3149 * Helper to build an instruction that builds the string representation for 3215 addTypeVariableReference);
3150 * this type, where type variables are substituted by their runtime value. 3216 HInstruction result = createForeignString(template, inputs);
3151 *
3152 * Examples:
3153 * Type Template Inputs
3154 * int 'int' []
3155 * C<int, int> 'C<int, int>' []
3156 * Var # [getRuntimeType(this).Var]
3157 * C<int, D<Var>> 'C<int, D<' + # + '>>' [getRuntimeType(this).Var]
3158 */
3159 void buildTypeString(DartType type, {isInQuotes: false}) {
3160 if (type is TypeVariableType) {
3161 addTypeVariableReference(type);
3162 template.add(isInQuotes ? "' + # +'" : "#");
3163 } else if (type is InterfaceType) {
3164 bool isFirstVariable = true;
3165 InterfaceType interfaceType = type;
3166 bool hasTypeArguments = !interfaceType.isRaw;
3167 if (!isInQuotes) template.add("'");
3168 template.add(backend.namer.getName(type.element));
3169 if (hasTypeArguments) {
3170 template.add("<");
3171 for (DartType argument in interfaceType.typeArguments) {
3172 if (!isFirstVariable) {
3173 template.add(", ");
3174 } else {
3175 isFirstVariable = false;
3176 }
3177 buildTypeString(argument, isInQuotes: true);
3178 }
3179 template.add(">");
3180 }
3181 if (!isInQuotes) template.add("'");
3182 } else {
3183 assert(type is TypedefType);
3184 if (!isInQuotes) template.add("'");
3185 template.add(backend.namer.getName(argument.element));
3186 if (!isInQuotes) template.add("'");
3187 }
3188 }
3189
3190 buildTypeString(argument, isInQuotes: false);
3191 HInstruction result =
3192 new HForeign(new LiteralDartString("$template"),
3193 new LiteralDartString('String'),
3194 inputs);
3195 add(result); 3217 add(result);
3196 return result; 3218 return result;
3197 } 3219 }
3198 3220
3199 void handleListConstructor(InterfaceType type, 3221 void handleListConstructor(InterfaceType type,
3200 Node currentNode, 3222 Node currentNode,
3201 HInstruction newObject) { 3223 HInstruction newObject) {
3202 if (!compiler.world.needsRti(type.element)) return; 3224 if (!compiler.world.needsRti(type.element)) return;
3203 List<HInstruction> inputs = <HInstruction>[]; 3225 List<HInstruction> inputs = <HInstruction>[];
3204 if (!type.isRaw) { 3226 if (!type.isRaw) {
(...skipping 1756 matching lines...) Expand 10 before | Expand all | Expand 10 after
4961 new HSubGraphBlockInformation(elseBranch.graph)); 4983 new HSubGraphBlockInformation(elseBranch.graph));
4962 4984
4963 HBasicBlock conditionStartBlock = conditionBranch.block; 4985 HBasicBlock conditionStartBlock = conditionBranch.block;
4964 conditionStartBlock.setBlockFlow(info, joinBlock); 4986 conditionStartBlock.setBlockFlow(info, joinBlock);
4965 SubGraph conditionGraph = conditionBranch.graph; 4987 SubGraph conditionGraph = conditionBranch.graph;
4966 HIf branch = conditionGraph.end.last; 4988 HIf branch = conditionGraph.end.last;
4967 assert(branch is HIf); 4989 assert(branch is HIf);
4968 branch.blockInformation = conditionStartBlock.blockFlow; 4990 branch.blockInformation = conditionStartBlock.blockFlow;
4969 } 4991 }
4970 } 4992 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698