| 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 62b069c00b92df0ad751d4a22d463613b07c6835..5ae62cbaaffb935e163fa76b6c6740c41f539220 100644
|
| --- a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
|
| +++ b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
|
| @@ -2587,7 +2587,6 @@ class SsaBuilder extends ResolvedVisitor implements Visitor {
|
| HInstruction runtimeType = getTypeArgument(variable);
|
| add(runtimeType);
|
| inputs.add(runtimeType);
|
| - return '#';
|
| });
|
| HInstruction representation = createForeignArray(template, inputs);
|
| add(representation);
|
| @@ -2641,25 +2640,34 @@ class SsaBuilder extends ResolvedVisitor implements Visitor {
|
| if (type.element.isTypeVariable() ||
|
| RuntimeTypeInformation.hasTypeArguments(type)) {
|
| HInstruction typeInfo = getRuntimeTypeInfo(expression);
|
| - Element helper =
|
| - compiler.findHelper(const SourceString('checkArguments'));
|
| - HInstruction helperCall = new HStatic(helper);
|
| - add(helperCall);
|
| + // TODO(karlklose): make isSubtype a HInstruction to enable
|
| + // optimizations?
|
| + Element helper = compiler.findHelper(const SourceString('isSubtype'));
|
| + HInstruction isSubtype = new HStatic(helper);
|
| + add(isSubtype);
|
| + // Build a list of representations for the type arguments.
|
| List<HInstruction> representations =
|
| buildTypeArgumentRepresentations(type);
|
| - String substitution = backend.namer.substitutionName(type.element);
|
| - HInstruction fieldGet =
|
| - createForeign('#.$substitution', HType.UNKNOWN, [expression]);
|
| - HInstruction representationList = new HLiteralList(representations);
|
| - add(fieldGet);
|
| - add(representationList);
|
| - List<HInstruction> inputs = <HInstruction>[helperCall,
|
| - fieldGet,
|
| - typeInfo,
|
| - representationList];
|
| - HInstruction check = new HInvokeStatic(inputs);
|
| - add(check);
|
| - instruction = new HIs(type, <HInstruction>[expression, check]);
|
| + // For each type argument, build a call to isSubtype, with the type
|
| + // argument as first and the representation of the tested type as
|
| + // second argument.
|
| + List<HInstruction> checks = <HInstruction>[];
|
| + int index = 0;
|
| + representations.forEach((HInstruction representation) {
|
| + HInstruction position = graph.addConstantInt(index, constantSystem);
|
| + // Get the index'th type argument from the runtime type information.
|
| + HInstruction typeArgument =
|
| + createForeign('#[#]', HType.UNKNOWN, [typeInfo, position]);
|
| + add(typeArgument);
|
| + // Create the call to isSubtype.
|
| + List<HInstruction> inputs =
|
| + <HInstruction>[isSubtype, typeArgument, representation];
|
| + HInstruction call = new HInvokeStatic(inputs);
|
| + add(call);
|
| + checks.add(call);
|
| + index++;
|
| + });
|
| + instruction = new HIs(type, <HInstruction>[expression]..addAll(checks));
|
| } else {
|
| instruction = new HIs(type, <HInstruction>[expression]);
|
| }
|
| @@ -3005,8 +3013,6 @@ class SsaBuilder extends ResolvedVisitor implements Visitor {
|
| handleForeignCreateIsolate(node);
|
| } else if (name == const SourceString('JS_OPERATOR_IS_PREFIX')) {
|
| stack.add(addConstantString(node, backend.namer.operatorIsPrefix()));
|
| - } else if (name == const SourceString('JS_OPERATOR_AS_PREFIX')) {
|
| - stack.add(addConstantString(node, backend.namer.operatorAsPrefix()));
|
| } else {
|
| throw "Unknown foreign: ${selector}";
|
| }
|
| @@ -3125,13 +3131,14 @@ class SsaBuilder extends ResolvedVisitor implements Visitor {
|
| return graph.addConstantNull(constantSystem);
|
| }
|
|
|
| - // The inputs are shared between invocations of the helper.
|
| + // These variables are shared between invocations of the helper.
|
| + HInstruction typeInfo;
|
| List<HInstruction> inputs = <HInstruction>[];
|
|
|
| /**
|
| * Helper to create an instruction that gets the value of a type variable.
|
| */
|
| - String addTypeVariableReference(TypeVariableType type) {
|
| + void addTypeVariableReference(TypeVariableType type) {
|
| Element member = currentElement;
|
| if (member.enclosingElement.isClosure()) {
|
| ClosureClassElement closureClass = member.enclosingElement;
|
| @@ -3139,23 +3146,27 @@ class SsaBuilder extends ResolvedVisitor implements Visitor {
|
| member = member.getOutermostEnclosingMemberOrTopLevel();
|
| }
|
| if (member.isFactoryConstructor()) {
|
| - // The type variable is stored in a parameter of the method.
|
| + // The type variable is stored in a parameter of the factory.
|
| inputs.add(localsHandler.readLocal(type.element));
|
| - } else if (member.isInstanceMember() ||
|
| - member.isGenerativeConstructor()) {
|
| + } else if (member.isInstanceMember()
|
| + || member.isGenerativeConstructor()) {
|
| // The type variable is stored in [this].
|
| + if (typeInfo == null) {
|
| + pushInvokeHelper1(backend.getGetRuntimeTypeInfo(),
|
| + localsHandler.readThis());
|
| + typeInfo = pop();
|
| + }
|
| int index = RuntimeTypeInformation.getTypeVariableIndex(type);
|
| - pushInvokeHelper2(backend.getGetRuntimeTypeArgument(),
|
| - localsHandler.readThis(),
|
| - graph.addConstantInt(index, constantSystem));
|
| - inputs.add(pop());
|
| + HInstruction foreign = createForeign('#[$index]', HType.STRING,
|
| + <HInstruction>[typeInfo]);
|
| + add(foreign);
|
| + inputs.add(foreign);
|
| } else {
|
| // TODO(ngeoffray): Match the VM behavior and throw an
|
| // exception at runtime.
|
| compiler.cancel('Unimplemented unresolved type variable',
|
| node: currentNode);
|
| }
|
| - return '#';
|
| }
|
|
|
| String template = rti.getTypeRepresentation(argument,
|
| @@ -3169,13 +3180,13 @@ class SsaBuilder extends ResolvedVisitor implements Visitor {
|
| Node currentNode,
|
| HInstruction newObject) {
|
| if (!compiler.world.needsRti(type.element)) return;
|
| + List<HInstruction> inputs = <HInstruction>[];
|
| if (!type.isRaw) {
|
| - List<HInstruction> inputs = <HInstruction>[];
|
| type.typeArguments.forEach((DartType argument) {
|
| inputs.add(analyzeTypeArgument(argument, currentNode));
|
| });
|
| - callSetRuntimeTypeInfo(type.element, inputs, newObject);
|
| }
|
| + callSetRuntimeTypeInfo(type.element, inputs, newObject);
|
| }
|
|
|
| void callSetRuntimeTypeInfo(ClassElement element,
|
|
|