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..014c50ceca76f78996d9f66391e71704f5397c51 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; |
@@ -715,7 +716,13 @@ 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. Cases where this is needed |
+ /// are for classes that are: |
+ /// (1) used in a is check with type variables, |
+ /// (2) dependencies of classes in (1), |
+ /// (3) subclasses of (2) and (3). |
sra1
2016/11/17 23:51:41
The code is now a little bit too general, since it
Emily Fortuna
2016/11/18 01:30:35
Done.
|
+ HInstruction setRuntimeTypeInfoIfNeeded( |
+ HInstruction object, ir.ListLiteral listLiteral) { |
InterfaceType type = localsHandler |
.substInContext(elements.getType(astAdapter.getNode(listLiteral))); |
if (!backend.classNeedsRti(type.element) || type.treatAsRaw) { |
@@ -744,7 +751,8 @@ class KernelSsaBuilder extends ir.Visitor with GraphBuilder { |
} |
listInstruction = new HLiteralList(elements, backend.extendableArrayType); |
add(listInstruction); |
- listInstruction = setRtiIfNeeded(listInstruction, listLiteral); |
+ listInstruction = |
+ setRuntimeTypeInfoIfNeeded(listInstruction, listLiteral); |
} |
TypeMask type = astAdapter.typeOfNewList(targetElement, listLiteral); |
@@ -783,8 +791,51 @@ 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); |
+ |
+ // TODO(efortuna): Inlining. |
Siggi Cherem (dart-lang)
2016/11/17 23:56:53
Let's change the TODO to explicitly say this is fo
Emily Fortuna
2016/11/18 01:30:35
hmmmm. I added them, but I'm not certain that this
Siggi Cherem (dart-lang)
2016/11/18 15:47:06
Stephen/Johnni - please confirm, but I believe we
|
+ _pushStaticInvocation(constructor, inputs, instructionType); |
} |
@override |