| 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
|
|
|