Chromium Code Reviews| Index: sdk/lib/_internal/compiler/implementation/ssa/builder.dart |
| diff --git a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart |
| index 297c1068ab794322802f9b365489914ef512d4d2..ae5875bfd2f1d922d544108f9ac397450fef88a2 100644 |
| --- a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart |
| +++ b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart |
| @@ -2633,6 +2633,55 @@ class SsaBuilder extends ResolvedVisitor implements Visitor { |
| push(result); |
| } |
| + createForeign(String code, String type, List<HInstruction> inputs) { |
| + return new HForeign(new LiteralDartString(code), |
| + new LiteralDartString(type), |
| + inputs); |
| + } |
| + |
| + 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
|
| + HInstruction createForeignArray(String code, inputs) { |
| + return createForeign(code, 'JSArray', inputs); |
| + } |
| + HInstruction typeInfo; |
| + |
| + /// Helper to create an instruction that contains the runtime value of |
| + /// the type variable [variable]. |
| + HInstruction getTypeArgument(TypeVariableType variable) { |
| + if (typeInfo == null) { |
| + HInstruction context = localsHandler.readThis(); |
| + pushInvokeHelper1(interceptors.getGetRuntimeTypeInfo(), context); |
| + typeInfo = pop(); |
| + } |
| + int intIndex = RuntimeTypeInformation.getTypeVariableIndex(variable); |
| + HInstruction index = graph.addConstantInt(intIndex, constantSystem); |
| + return createForeignArray('#[#]', <HInstruction>[typeInfo, index]); |
| + } |
| + |
| + // Compute the representation of the type arguments, including access |
| + // to the runtime type information for type variables as instructions. |
| + HInstruction representations; |
| + if (type.element.isTypeVariable()) { |
| + return <HInstruction>[getTypeArgument(type)]; |
| + } else { |
| + assert(type.element.isClass()); |
| + List<HInstruction> arguments = <HInstruction>[]; |
| + InterfaceType interface = type; |
| + for (DartType argument in interface.typeArguments) { |
| + List<HInstruction> inputs = <HInstruction>[]; |
| + String template = rti.getTypeRepresentation(argument, (variable) { |
| + HInstruction runtimeType = getTypeArgument(variable); |
| + add(runtimeType); |
| + inputs.add(runtimeType); |
| + }); |
| + HInstruction representation = createForeignArray(template, inputs); |
| + add(representation); |
| + arguments.add(representation); |
| + } |
| + return arguments; |
| + } |
| + } |
| + |
| visitOperatorSend(node) { |
| assert(node.selector is Operator); |
| if (!methodInterceptionEnabled) { |
| @@ -2668,7 +2717,6 @@ class SsaBuilder extends ResolvedVisitor implements Visitor { |
| typeAnnotation = argument.asSend().receiver; |
| isNot = true; |
| } |
| - |
| DartType type = elements.getType(typeAnnotation); |
| if (type.isMalformed) { |
| String reasons = fetchReasonsFromMalformedType(type); |
| @@ -2679,29 +2727,44 @@ class SsaBuilder extends ResolvedVisitor implements Visitor { |
| } |
| return; |
| } |
| - HInstruction typeInfo = null; |
| - if (RuntimeTypeInformation.hasTypeArguments(type)) { |
| - pushInvokeHelper1(interceptors.getGetRuntimeTypeInfo(), expression); |
| - typeInfo = pop(); |
| - } |
| if (type.element.isTypeVariable()) { |
| - // TODO(karlklose): We currently answer true to any is check |
| - // involving a type variable -- both is T and is !T -- until |
| - // we have a proper implementation of reified generics. |
| + // 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.
|
| stack.add(graph.addConstantBool(true, constantSystem)); |
| + return; |
| + } |
| + |
| + HInstruction instruction; |
| + if (RuntimeTypeInformation.hasTypeArguments(type) || |
| + type.element.isTypeVariable()) { |
| + 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.
|
| + HInstruction typeInfo = pop(); |
| + 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
|
| + HInstruction isSubtype = new HStatic(helper); |
| + add(isSubtype); |
| + List<HInstruction> representations = buildRepresentations(type); |
| + List<HInstruction> checks = <HInstruction>[]; |
| + int index = 0; |
| + 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.
|
| + HInstruction position = graph.addConstantInt(index, constantSystem); |
| + 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
|
| + createForeign('#[#]', 'Object', [typeInfo, position]); |
| + add(typeArgument); |
| + List<HInstruction> inputs = |
| + <HInstruction>[isSubtype, typeArgument, representation]; |
| + HInstruction call = new HInvokeStatic(inputs); |
| + add(call); |
| + checks.add(call); |
| + index++; |
| + }); |
| + instruction = new HIs.withArgumentChecks(type, expression, checks); |
| } else { |
| - HInstruction instruction; |
| - if (typeInfo != null) { |
| - instruction = new HIs.withTypeInfoCall(type, expression, typeInfo); |
| - } else { |
| - instruction = new HIs(type, expression); |
| - } |
| - if (isNot) { |
| - add(instruction); |
| - instruction = new HNot(instruction); |
| - } |
| - push(instruction); |
| + instruction = new HIs(type, expression); |
| + } |
| + if (isNot) { |
| + add(instruction); |
| + instruction = new HNot(instruction); |
| } |
| + push(instruction); |
| } else if (const SourceString("as") == op.source) { |
| visit(node.receiver); |
| HInstruction expression = pop(); |
| @@ -3104,9 +3167,14 @@ class SsaBuilder extends ResolvedVisitor implements Visitor { |
| return graph.addConstantNull(constantSystem); |
| } |
| - // These variables are shared between invocations of the helper methods. |
| + createForeignString(template, inputs) { |
|
kasperl
2012/12/06 09:51:04
Use createForeign?
karlklose
2012/12/06 13:30:03
Done.
|
| + return new HForeign(new LiteralDartString(template), |
| + new LiteralDartString('String'), |
| + inputs); |
| + } |
| + |
| + // These variables are shared between invocations of the helper. |
| HInstruction typeInfo; |
| - StringBuffer template = new StringBuffer(); |
| List<HInstruction> inputs = <HInstruction>[]; |
| /** |
| @@ -3131,10 +3199,8 @@ class SsaBuilder extends ResolvedVisitor implements Visitor { |
| typeInfo = pop(); |
| } |
| int index = RuntimeTypeInformation.getTypeVariableIndex(type); |
| - HInstruction foreign = new HForeign( |
| - new LiteralDartString('#[$index]'), |
| - new LiteralDartString('String'), |
| - <HInstruction>[typeInfo]); |
| + HInstruction foreign = createForeignString('#[$index]', |
| + <HInstruction>[typeInfo]); |
| add(foreign); |
| inputs.add(foreign); |
| } else { |
| @@ -3145,53 +3211,9 @@ class SsaBuilder extends ResolvedVisitor implements Visitor { |
| } |
| } |
| - /** |
| - * Helper to build an instruction that builds the string representation for |
| - * this type, where type variables are substituted by their runtime value. |
| - * |
| - * Examples: |
| - * Type Template Inputs |
| - * int 'int' [] |
| - * C<int, int> 'C<int, int>' [] |
| - * Var # [getRuntimeType(this).Var] |
| - * C<int, D<Var>> 'C<int, D<' + # + '>>' [getRuntimeType(this).Var] |
| - */ |
| - void buildTypeString(DartType type, {isInQuotes: false}) { |
| - if (type is TypeVariableType) { |
| - addTypeVariableReference(type); |
| - template.add(isInQuotes ? "' + # +'" : "#"); |
| - } else if (type is InterfaceType) { |
| - bool isFirstVariable = true; |
| - InterfaceType interfaceType = type; |
| - bool hasTypeArguments = !interfaceType.isRaw; |
| - if (!isInQuotes) template.add("'"); |
| - template.add(backend.namer.getName(type.element)); |
| - if (hasTypeArguments) { |
| - template.add("<"); |
| - for (DartType argument in interfaceType.typeArguments) { |
| - if (!isFirstVariable) { |
| - template.add(", "); |
| - } else { |
| - isFirstVariable = false; |
| - } |
| - buildTypeString(argument, isInQuotes: true); |
| - } |
| - template.add(">"); |
| - } |
| - if (!isInQuotes) template.add("'"); |
| - } else { |
| - assert(type is TypedefType); |
| - if (!isInQuotes) template.add("'"); |
| - template.add(backend.namer.getName(argument.element)); |
| - if (!isInQuotes) template.add("'"); |
| - } |
| - } |
| - |
| - buildTypeString(argument, isInQuotes: false); |
| - HInstruction result = |
| - new HForeign(new LiteralDartString("$template"), |
| - new LiteralDartString('String'), |
| - inputs); |
| + String template = rti.getTypeRepresentation(argument, |
| + addTypeVariableReference); |
| + HInstruction result = createForeignString(template, inputs); |
| add(result); |
| return result; |
| } |