| 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 3f407cab4f35bd7c4a41ab38c29c0d1ebc10b184..7050eae76ef968d6972f3464167f9e0ea2b1f566 100644
|
| --- a/pkg/compiler/lib/src/ssa/builder_kernel.dart
|
| +++ b/pkg/compiler/lib/src/ssa/builder_kernel.dart
|
| @@ -29,6 +29,7 @@ import 'loop_handler.dart';
|
| import 'nodes.dart';
|
| import 'ssa_branch_builder.dart';
|
| import 'type_builder.dart';
|
| +import 'types.dart' show TypeMaskFactory;
|
|
|
| class SsaKernelBuilderTask extends CompilerTask {
|
| final JavaScriptBackend backend;
|
| @@ -57,6 +58,14 @@ class KernelSsaBuilder extends ir.Visitor with GraphBuilder {
|
| final ResolvedAst resolvedAst;
|
| final CodegenRegistry registry;
|
|
|
| + /// A stack of [DartType]s that have been seen during inlining of factory
|
| + /// constructors. These types are preserved in [HInvokeStatic]s and
|
| + /// [HCreate]s inside the inline code and registered during code generation
|
| + /// for these nodes.
|
| + // TODO(karlklose): consider removing this and keeping the (substituted) types
|
| + // of the type variables in an environment (like the [LocalsHandler]).
|
| + final List<DartType> currentImplicitInstantiations = <DartType>[];
|
| +
|
| @override
|
| JavaScriptBackend get backend => compiler.backend;
|
|
|
| @@ -320,6 +329,18 @@ class KernelSsaBuilder extends ir.Visitor with GraphBuilder {
|
| closeFunction();
|
| }
|
|
|
| + void addImplicitInstantiation(DartType type) {
|
| + if (type != null) {
|
| + currentImplicitInstantiations.add(type);
|
| + }
|
| + }
|
| +
|
| + void removeImplicitInstantiation(DartType type) {
|
| + if (type != null) {
|
| + currentImplicitInstantiations.removeLast();
|
| + }
|
| + }
|
| +
|
| void openFunction() {
|
| HBasicBlock block = graph.addNewBlock();
|
| open(graph.entry);
|
| @@ -715,7 +736,9 @@ class KernelSsaBuilder extends ir.Visitor with GraphBuilder {
|
| stack.add(graph.addConstantNull(compiler));
|
| }
|
|
|
| - HInstruction setRtiIfNeeded(HInstruction object, ir.ListLiteral listLiteral) {
|
| + /// Set the runtime type information if necessary.
|
| + HInstruction setListRuntimeTypeInfoIfNeeded(
|
| + HInstruction object, ir.ListLiteral listLiteral) {
|
| InterfaceType type = localsHandler
|
| .substInContext(elements.getType(astAdapter.getNode(listLiteral)));
|
| if (!backend.classNeedsRti(type.element) || type.treatAsRaw) {
|
| @@ -744,7 +767,8 @@ class KernelSsaBuilder extends ir.Visitor with GraphBuilder {
|
| }
|
| listInstruction = new HLiteralList(elements, backend.extendableArrayType);
|
| add(listInstruction);
|
| - listInstruction = setRtiIfNeeded(listInstruction, listLiteral);
|
| + listInstruction =
|
| + setListRuntimeTypeInfoIfNeeded(listInstruction, listLiteral);
|
| }
|
|
|
| TypeMask type = astAdapter.typeOfNewList(targetElement, listLiteral);
|
| @@ -783,8 +807,52 @@ class KernelSsaBuilder extends ir.Visitor with GraphBuilder {
|
| inputs.add(argList);
|
| }
|
|
|
| - // TODO(het): Add type information
|
| - _pushStaticInvocation(constructor, inputs, backend.dynamicType);
|
| + assert(constructor.kind == ir.ProcedureKind.Factory);
|
| +
|
| + InterfaceType type = localsHandler
|
| + .substInContext(elements.getType(astAdapter.getNode(mapLiteral)));
|
| +
|
| + ir.Class cls = constructor.enclosingClass;
|
| +
|
| + if (backend.classNeedsRti(astAdapter.getElement(cls))) {
|
| + List<HInstruction> typeInputs = <HInstruction>[];
|
| + type.typeArguments.forEach((DartType argument) {
|
| + typeInputs
|
| + .add(typeBuilder.analyzeTypeArgument(argument, sourceElement));
|
| + });
|
| +
|
| + // We lift this common call pattern into a helper function to save space
|
| + // in the output.
|
| + if (typeInputs.every((HInstruction input) => input.isNull())) {
|
| + if (constructorArgs.isEmpty) {
|
| + constructor = astAdapter.mapLiteralUntypedEmptyMaker;
|
| + } else {
|
| + constructor = astAdapter.mapLiteralUntypedMaker;
|
| + }
|
| + } else {
|
| + inputs.addAll(typeInputs);
|
| + }
|
| + }
|
| +
|
| + // If runtime type information is needed and the map literal has no type
|
| + // parameters, 'constructor' is a static function that forwards the call to
|
| + // the factory constructor without type parameters.
|
| + assert(constructor.kind == ir.ProcedureKind.Factory);
|
| +
|
| + // The instruction type will always be a subtype of the mapLiteralClass, but
|
| + // type inference might discover a more specific type, or find nothing (in
|
| + // dart2js unit tests).
|
| + TypeMask mapType = new TypeMask.nonNullSubtype(
|
| + astAdapter.getElement(astAdapter.mapLiteralClass),
|
| + compiler.closedWorld);
|
| + TypeMask returnTypeMask = TypeMaskFactory.inferredReturnTypeForElement(
|
| + astAdapter.getElement(constructor), compiler);
|
| + TypeMask instructionType =
|
| + mapType.intersection(returnTypeMask, compiler.closedWorld);
|
| +
|
| + addImplicitInstantiation(type);
|
| + _pushStaticInvocation(constructor, inputs, instructionType);
|
| + removeImplicitInstantiation(type);
|
| }
|
|
|
| @override
|
| @@ -917,6 +985,10 @@ class KernelSsaBuilder extends ir.Visitor with GraphBuilder {
|
| HInstruction instruction = new HInvokeStatic(
|
| astAdapter.getMember(target), arguments, typeMask,
|
| targetCanThrow: astAdapter.getCanThrow(target));
|
| + if (currentImplicitInstantiations.isNotEmpty) {
|
| + instruction.instantiatedTypes =
|
| + new List<DartType>.from(currentImplicitInstantiations);
|
| + }
|
| instruction.sideEffects = astAdapter.getSideEffects(target);
|
|
|
| push(instruction);
|
|
|