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

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: Address comments. 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) {
ngeoffray 2012/12/06 23:21:45 HForeign createForeign
karlklose 2012/12/07 07:46:35 Done.
2637 return new HForeign(new LiteralDartString(code),
2638 new LiteralDartString(type),
2639 inputs);
2640 }
2641
2642 HInstruction getRuntimeTypeInfo(HInstruction target) {
2643 pushInvokeHelper1(interceptors.getGetRuntimeTypeInfo(), target);
2644 return pop();
2645 }
2646
2647 // TODO(karlklose): change construction of the representations to be GVN'able.
ngeoffray 2012/12/06 23:21:45 You can also reference the bug number.
karlklose 2012/12/07 07:46:35 Done.
2648 List<HInstruction> buildTypeArgumentRepresentations(DartType type) {
2649 HInstruction createForeignArray(String code, inputs) {
2650 return createForeign(code, 'JSArray', inputs);
ngeoffray 2012/12/06 23:21:45 Should be '=List' but i plan on fixing that.
karlklose 2012/12/07 07:46:35 I changed it to '=List'.
2651 }
2652 HInstruction typeInfo;
2653
2654 /// Helper to create an instruction that contains the runtime value of
2655 /// the type variable [variable].
2656 HInstruction getTypeArgument(TypeVariableType variable) {
2657 if (typeInfo == null) {
2658 typeInfo = getRuntimeTypeInfo(localsHandler.readThis());
2659 }
2660 int intIndex = RuntimeTypeInformation.getTypeVariableIndex(variable);
2661 HInstruction index = graph.addConstantInt(intIndex, constantSystem);
2662 return createForeignArray('#[#]', <HInstruction>[typeInfo, index]);
2663 }
2664
2665 // Compute the representation of the type arguments, including access
2666 // to the runtime type information for type variables as instructions.
2667 HInstruction representations;
2668 if (type.element.isTypeVariable()) {
2669 return <HInstruction>[getTypeArgument(type)];
2670 } else {
2671 assert(type.element.isClass());
2672 List<HInstruction> arguments = <HInstruction>[];
2673 InterfaceType interface = type;
2674 for (DartType argument in interface.typeArguments) {
2675 List<HInstruction> inputs = <HInstruction>[];
2676 String template = rti.getTypeRepresentation(argument, (variable) {
2677 HInstruction runtimeType = getTypeArgument(variable);
2678 add(runtimeType);
2679 inputs.add(runtimeType);
2680 });
2681 HInstruction representation = createForeignArray(template, inputs);
2682 add(representation);
2683 arguments.add(representation);
2684 }
2685 return arguments;
2686 }
2687 }
2688
2636 visitOperatorSend(node) { 2689 visitOperatorSend(node) {
2637 assert(node.selector is Operator); 2690 assert(node.selector is Operator);
2638 if (!methodInterceptionEnabled) { 2691 if (!methodInterceptionEnabled) {
2639 visitDynamicSend(node); 2692 visitDynamicSend(node);
2640 return; 2693 return;
2641 } 2694 }
2642 2695
2643 Operator op = node.selector; 2696 Operator op = node.selector;
2644 if (const SourceString("[]") == op.source) { 2697 if (const SourceString("[]") == op.source) {
2645 HStatic target = new HStatic(interceptors.getIndexInterceptor()); 2698 HStatic target = new HStatic(interceptors.getIndexInterceptor());
(...skipping 15 matching lines...) Expand all
2661 HInstruction expression = pop(); 2714 HInstruction expression = pop();
2662 Node argument = node.arguments.head; 2715 Node argument = node.arguments.head;
2663 TypeAnnotation typeAnnotation = argument.asTypeAnnotation(); 2716 TypeAnnotation typeAnnotation = argument.asTypeAnnotation();
2664 bool isNot = false; 2717 bool isNot = false;
2665 // TODO(ngeoffray): Duplicating pattern in resolver. We should 2718 // TODO(ngeoffray): Duplicating pattern in resolver. We should
2666 // add a new kind of node. 2719 // add a new kind of node.
2667 if (typeAnnotation == null) { 2720 if (typeAnnotation == null) {
2668 typeAnnotation = argument.asSend().receiver; 2721 typeAnnotation = argument.asSend().receiver;
2669 isNot = true; 2722 isNot = true;
2670 } 2723 }
2671
2672 DartType type = elements.getType(typeAnnotation); 2724 DartType type = elements.getType(typeAnnotation);
2673 if (type.isMalformed) { 2725 if (type.isMalformed) {
2674 String reasons = fetchReasonsFromMalformedType(type); 2726 String reasons = fetchReasonsFromMalformedType(type);
2675 if (compiler.enableTypeAssertions) { 2727 if (compiler.enableTypeAssertions) {
2676 generateMalformedSubtypeError(node, expression, type, reasons); 2728 generateMalformedSubtypeError(node, expression, type, reasons);
2677 } else { 2729 } else {
2678 generateRuntimeError(node, '$type is malformed: $reasons'); 2730 generateRuntimeError(node, '$type is malformed: $reasons');
2679 } 2731 }
2680 return; 2732 return;
2681 } 2733 }
2682 HInstruction typeInfo = null; 2734 if (type.element.isTypeVariable()) {
2683 if (RuntimeTypeInformation.hasTypeArguments(type)) { 2735 // TODO(karlklose): remove this check when the backend can deal with
2684 pushInvokeHelper1(interceptors.getGetRuntimeTypeInfo(), expression); 2736 // checks of the form [:o is T:] where [:T:] is a type variable.
2685 typeInfo = pop(); 2737 stack.add(graph.addConstantBool(true, constantSystem));
2738 return;
2686 } 2739 }
2687 if (type.element.isTypeVariable()) { 2740
2688 // TODO(karlklose): We currently answer true to any is check 2741 HInstruction instruction;
2689 // involving a type variable -- both is T and is !T -- until 2742 if (RuntimeTypeInformation.hasTypeArguments(type) ||
2690 // we have a proper implementation of reified generics. 2743 type.element.isTypeVariable()) {
ngeoffray 2012/12/06 23:21:45 I don't think this can happen (see line 2734 and 2
karlklose 2012/12/07 07:46:35 You are right, this is a left-over from trying to
2691 stack.add(graph.addConstantBool(true, constantSystem)); 2744 HInstruction typeInfo = getRuntimeTypeInfo(expression);
2745 // TODO(karlklose): make isSubtype a HInstruction to enable
2746 // optimizations?
ngeoffray 2012/12/06 23:21:45 No, I think we need to put compiler flags on the m
karlklose 2012/12/07 07:46:35 I will remove the comment. Let's chat about dartbu
2747 Element helper = compiler.findHelper(const SourceString('isSubtype'));
2748 HInstruction isSubtype = new HStatic(helper);
2749 add(isSubtype);
2750 // Build a list of representations for the type arguments.
2751 List<HInstruction> representations =
2752 buildTypeArgumentRepresentations(type);
2753 // For each type argument, build a call to isSubtype, with the type
2754 // argument as first and the representation of the tested type as
2755 // second argument.
2756 List<HInstruction> checks = <HInstruction>[];
2757 int index = 0;
2758 representations.forEach((HInstruction representation) {
2759 HInstruction position = graph.addConstantInt(index, constantSystem);
2760 // Get the index'th type argument from the runtime type information.
2761 HInstruction typeArgument =
2762 createForeign('#[#]', 'Object', [typeInfo, position]);
2763 add(typeArgument);
2764 // Create the call to isSubtype.
2765 List<HInstruction> inputs =
2766 <HInstruction>[isSubtype, typeArgument, representation];
2767 HInstruction call = new HInvokeStatic(inputs);
2768 add(call);
2769 checks.add(call);
2770 index++;
2771 });
2772 instruction = new HIs.withArgumentChecks(type, expression, checks);
2692 } else { 2773 } else {
2693 HInstruction instruction; 2774 instruction = new HIs(type, expression);
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 } 2775 }
2776 if (isNot) {
2777 add(instruction);
2778 instruction = new HNot(instruction);
2779 }
2780 push(instruction);
2705 } else if (const SourceString("as") == op.source) { 2781 } else if (const SourceString("as") == op.source) {
2706 visit(node.receiver); 2782 visit(node.receiver);
2707 HInstruction expression = pop(); 2783 HInstruction expression = pop();
2708 Node argument = node.arguments.head; 2784 Node argument = node.arguments.head;
2709 TypeAnnotation typeAnnotation = argument.asTypeAnnotation(); 2785 TypeAnnotation typeAnnotation = argument.asTypeAnnotation();
2710 DartType type = elements.getType(typeAnnotation); 2786 DartType type = elements.getType(typeAnnotation);
2711 HInstruction converted = expression.convertType( 2787 HInstruction converted = expression.convertType(
2712 compiler, type, HTypeConversion.CAST_TYPE_CHECK); 2788 compiler, type, HTypeConversion.CAST_TYPE_CHECK);
2713 if (converted != expression) add(converted); 2789 if (converted != expression) add(converted);
2714 stack.add(converted); 2790 stack.add(converted);
(...skipping 382 matching lines...) Expand 10 before | Expand all | Expand 10 after
3097 */ 3173 */
3098 HInstruction analyzeTypeArgument(DartType argument, Node currentNode) { 3174 HInstruction analyzeTypeArgument(DartType argument, Node currentNode) {
3099 assert(invariant(currentNode, 3175 assert(invariant(currentNode,
3100 !compiler.enableTypeAssertions || !argument.isMalformed, 3176 !compiler.enableTypeAssertions || !argument.isMalformed,
3101 message: '$argument is malformed in checked mode')); 3177 message: '$argument is malformed in checked mode'));
3102 if (argument == compiler.types.dynamicType || argument.isMalformed) { 3178 if (argument == compiler.types.dynamicType || argument.isMalformed) {
3103 // Represent [dynamic] as [null]. 3179 // Represent [dynamic] as [null].
3104 return graph.addConstantNull(constantSystem); 3180 return graph.addConstantNull(constantSystem);
3105 } 3181 }
3106 3182
3107 // These variables are shared between invocations of the helper methods. 3183 // These variables are shared between invocations of the helper.
3108 HInstruction typeInfo; 3184 HInstruction typeInfo;
3109 StringBuffer template = new StringBuffer();
3110 List<HInstruction> inputs = <HInstruction>[]; 3185 List<HInstruction> inputs = <HInstruction>[];
3111 3186
3112 /** 3187 /**
3113 * Helper to create an instruction that gets the value of a type variable. 3188 * Helper to create an instruction that gets the value of a type variable.
3114 */ 3189 */
3115 void addTypeVariableReference(TypeVariableType type) { 3190 void addTypeVariableReference(TypeVariableType type) {
3116 Element member = work.element; 3191 Element member = work.element;
3117 if (member.enclosingElement.isClosure()) { 3192 if (member.enclosingElement.isClosure()) {
3118 ClosureClassElement closureClass = member.enclosingElement; 3193 ClosureClassElement closureClass = member.enclosingElement;
3119 member = closureClass.methodElement; 3194 member = closureClass.methodElement;
3120 member = member.getOutermostEnclosingMemberOrTopLevel(); 3195 member = member.getOutermostEnclosingMemberOrTopLevel();
3121 } 3196 }
3122 if (member.isFactoryConstructor()) { 3197 if (member.isFactoryConstructor()) {
3123 // The type variable is stored in a parameter of the factory. 3198 // The type variable is stored in a parameter of the factory.
3124 inputs.add(localsHandler.readLocal(type.element)); 3199 inputs.add(localsHandler.readLocal(type.element));
3125 } else if (member.isInstanceMember() 3200 } else if (member.isInstanceMember()
3126 || member.isGenerativeConstructor()) { 3201 || member.isGenerativeConstructor()) {
3127 // The type variable is stored in [this]. 3202 // The type variable is stored in [this].
3128 if (typeInfo == null) { 3203 if (typeInfo == null) {
3129 pushInvokeHelper1(interceptors.getGetRuntimeTypeInfo(), 3204 pushInvokeHelper1(interceptors.getGetRuntimeTypeInfo(),
3130 localsHandler.readThis()); 3205 localsHandler.readThis());
3131 typeInfo = pop(); 3206 typeInfo = pop();
3132 } 3207 }
3133 int index = RuntimeTypeInformation.getTypeVariableIndex(type); 3208 int index = RuntimeTypeInformation.getTypeVariableIndex(type);
3134 HInstruction foreign = new HForeign( 3209 HInstruction foreign = createForeign('#[$index]', 'String',
3135 new LiteralDartString('#[$index]'), 3210 <HInstruction>[typeInfo]);
3136 new LiteralDartString('String'),
3137 <HInstruction>[typeInfo]);
3138 add(foreign); 3211 add(foreign);
3139 inputs.add(foreign); 3212 inputs.add(foreign);
3140 } else { 3213 } else {
3141 // TODO(ngeoffray): Match the VM behavior and throw an 3214 // TODO(ngeoffray): Match the VM behavior and throw an
3142 // exception at runtime. 3215 // exception at runtime.
3143 compiler.cancel('Unimplemented unresolved type variable', 3216 compiler.cancel('Unimplemented unresolved type variable',
3144 node: currentNode); 3217 node: currentNode);
3145 } 3218 }
3146 } 3219 }
3147 3220
3148 /** 3221 String template = rti.getTypeRepresentation(argument,
3149 * Helper to build an instruction that builds the string representation for 3222 addTypeVariableReference);
3150 * this type, where type variables are substituted by their runtime value. 3223 HInstruction result = createForeign(template, 'String', 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); 3224 add(result);
3196 return result; 3225 return result;
3197 } 3226 }
3198 3227
3199 void handleListConstructor(InterfaceType type, 3228 void handleListConstructor(InterfaceType type,
3200 Node currentNode, 3229 Node currentNode,
3201 HInstruction newObject) { 3230 HInstruction newObject) {
3202 if (!compiler.world.needsRti(type.element)) return; 3231 if (!compiler.world.needsRti(type.element)) return;
3203 List<HInstruction> inputs = <HInstruction>[]; 3232 List<HInstruction> inputs = <HInstruction>[];
3204 if (!type.isRaw) { 3233 if (!type.isRaw) {
(...skipping 1756 matching lines...) Expand 10 before | Expand all | Expand 10 after
4961 new HSubGraphBlockInformation(elseBranch.graph)); 4990 new HSubGraphBlockInformation(elseBranch.graph));
4962 4991
4963 HBasicBlock conditionStartBlock = conditionBranch.block; 4992 HBasicBlock conditionStartBlock = conditionBranch.block;
4964 conditionStartBlock.setBlockFlow(info, joinBlock); 4993 conditionStartBlock.setBlockFlow(info, joinBlock);
4965 SubGraph conditionGraph = conditionBranch.graph; 4994 SubGraph conditionGraph = conditionBranch.graph;
4966 HIf branch = conditionGraph.end.last; 4995 HIf branch = conditionGraph.end.last;
4967 assert(branch is HIf); 4996 assert(branch is HIf);
4968 branch.blockInformation = conditionStartBlock.blockFlow; 4997 branch.blockInformation = conditionStartBlock.blockFlow;
4969 } 4998 }
4970 } 4999 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698