Index: pkg/compiler/lib/src/ssa/builder_kernel.dart |
diff --git a/pkg/compiler/lib/src/ssa/builder_kernel.dart b/pkg/compiler/lib/src/ssa/builder_kernel.dart |
index 7c92668d3bc5630a4107d735214fef475073b9ce..682a2dc9049fa31209d53f152278d03c818213ec 100644 |
--- a/pkg/compiler/lib/src/ssa/builder_kernel.dart |
+++ b/pkg/compiler/lib/src/ssa/builder_kernel.dart |
@@ -223,6 +223,18 @@ class KernelSsaBuilder extends ir.Visitor with GraphBuilder { |
return result; |
} |
+ void _addClassTypeVariablesIfNeeded(ir.Member constructor) { |
+ var enclosing = astAdapter.getElement(constructor).enclosingElement; |
+ if (backend.classNeedsRti(enclosing)) { |
+ enclosing.typeVariables.forEach((TypeVariableType typeVariable) { |
+ HParameterValue param = |
+ addParameter(typeVariable.element, commonMasks.nonNullType); |
+ localsHandler.directLocals[ |
+ localsHandler.getTypeVariableAsLocal(typeVariable)] = param; |
+ }); |
+ } |
+ } |
+ |
/// Builds generative constructors. |
/// |
/// Generative constructors are built in two stages. |
@@ -233,6 +245,7 @@ class KernelSsaBuilder extends ir.Visitor with GraphBuilder { |
/// constructor bodies for all constructors in the hierarchy. |
void buildConstructor(ir.Constructor constructor) { |
openFunction(); |
+ _addClassTypeVariablesIfNeeded(constructor); |
// Collect field values for the current class. |
// TODO(het): Does kernel always put field initializers in the constructor |
@@ -399,6 +412,11 @@ class KernelSsaBuilder extends ir.Visitor with GraphBuilder { |
/// Procedures. |
void buildFunctionNode(ir.FunctionNode functionNode) { |
openFunction(); |
+ if (functionNode.parent is ir.Procedure && |
+ (functionNode.parent as ir.Procedure).kind == |
+ ir.ProcedureKind.Factory) { |
+ _addClassTypeVariablesIfNeeded(functionNode.parent); |
+ } |
functionNode.body.accept(this); |
closeFunction(); |
} |
@@ -1942,49 +1960,82 @@ class KernelSsaBuilder extends ir.Visitor with GraphBuilder { |
} |
HInstruction buildIsNode( |
- ir.Node node, ir.DartType dart_type, HInstruction expression) { |
- // TODO(sra): Convert the type testing logic here to use ir.DartType. |
- DartType type = astAdapter.getDartType(dart_type); |
- |
- type = localsHandler.substInContext(type).unaliased; |
- |
- if (type is MethodTypeVariableType) { |
- return graph.addConstantBool(true, closedWorld); |
- } |
- |
- if (type is MalformedType) { |
- ErroneousElement element = type.element; |
- generateTypeError(node, element.message); |
- return new HIs.compound(type, expression, pop(), commonMasks.boolType); |
- } |
- |
- if (type.isFunctionType) { |
- List arguments = <HInstruction>[buildFunctionType(type), expression]; |
- _pushDynamicInvocation(node, commonMasks.boolType, arguments, |
+ ir.Node node, ir.DartType type, HInstruction expression) { |
+ // Note: The call to "unalias" this type like in the original SSA builder is |
+ // unnecessary in kernel because Kernel has no notion of typedef. |
+ // TODO(efortuna): Add test for this. |
+ DartType typeValue = localsHandler.substInContext( |
+ astAdapter.getDartType(type)); |
+ if (type is ir.InvalidType) { |
+ generateTypeError(node, (typeValue.element as ErroneousElement).message); |
+ return new HIs.compound( |
+ typeValue, expression, pop(), commonMasks.boolType); |
+ } |
+ |
+ if (type is ir.FunctionType) { |
+ List arguments = [buildFunctionType(typeValue), expression]; |
+ _pushDynamicInvocation(node, null, arguments, |
selector: new Selector.call( |
- new PrivateName('_isTest', astAdapter.jsHelperLibrary), |
+ new PrivateName('_isTest', backend.helpers.jsHelperLibrary), |
CallStructure.ONE_ARG)); |
- return new HIs.compound(type, expression, pop(), commonMasks.boolType); |
+ return new HIs.compound( |
+ typeValue, expression, pop(), commonMasks.boolType); |
} |
- if (type.isTypeVariable) { |
+ if (type is ir.TypeParameterType) { |
HInstruction runtimeType = |
- typeBuilder.addTypeVariableReference(type, sourceElement); |
+ typeBuilder.addTypeVariableReference(typeValue, sourceElement); |
_pushStaticInvocation(astAdapter.checkSubtypeOfRuntimeType, |
<HInstruction>[expression, runtimeType], commonMasks.boolType); |
- return new HIs.variable(type, expression, pop(), commonMasks.boolType); |
+ return new HIs.variable( |
+ typeValue, expression, pop(), commonMasks.boolType); |
+ } |
+ |
+ if (_isInterfaceWithNoDynamicTypes(type)) { |
+ HInstruction representations = typeBuilder |
+ .buildTypeArgumentRepresentations(typeValue, sourceElement); |
+ add(representations); |
+ ClassElement element = typeValue.element; |
+ js.Name operator = backend.namer.operatorIs(element); |
+ HInstruction isFieldName = |
+ graph.addConstantStringFromName(operator, closedWorld); |
+ HInstruction asFieldName = closedWorld.hasAnyStrictSubtype(element) |
+ ? graph.addConstantStringFromName( |
+ backend.namer.substitutionName(element), closedWorld) |
+ : graph.addConstantNull(closedWorld); |
+ List<HInstruction> inputs = <HInstruction>[ |
+ expression, |
+ isFieldName, |
+ representations, |
+ asFieldName |
+ ]; |
+ _pushStaticInvocation( |
+ astAdapter.checkSubtype, inputs, commonMasks.boolType); |
+ return new HIs.compound( |
+ typeValue, expression, pop(), commonMasks.boolType); |
} |
- // TODO(sra): Type with type parameters. |
- |
- if (backend.hasDirectCheckFor(type)) { |
- return new HIs.direct(type, expression, commonMasks.boolType); |
+ if (backend.hasDirectCheckFor(typeValue)) { |
+ return new HIs.direct(typeValue, expression, commonMasks.boolType); |
} |
- |
// The interceptor is not always needed. It is removed by optimization |
// when the receiver type or tested type permit. |
- HInterceptor interceptor = _interceptorFor(expression); |
- return new HIs.raw(type, expression, interceptor, commonMasks.boolType); |
+ return new HIs.raw(typeValue, expression, _interceptorFor(expression), |
+ commonMasks.boolType); |
+ } |
+ |
+ bool _isInterfaceWithNoDynamicTypes(ir.DartType type) { |
+ bool isMethodTypeVariableType(ir.DartType typeArgType) { |
+ return (typeArgType is ir.TypeParameterType && |
+ typeArgType.parameter.parent is ir.FunctionNode); |
+ } |
+ |
+ return type is ir.InterfaceType && |
+ (type as ir.InterfaceType).typeArguments.any( |
+ (ir.DartType typeArgType) => |
+ typeArgType is! ir.DynamicType && |
+ typeArgType is! ir.InvalidType && |
+ !isMethodTypeVariableType(type)); |
} |
@override |