| Index: sdk/lib/_internal/compiler/implementation/js_backend/runtime_types.dart
|
| diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/runtime_types.dart b/sdk/lib/_internal/compiler/implementation/js_backend/runtime_types.dart
|
| index d23b1e438cc87a3ecf281c0ed5e76e9877d7d8a7..236f38f51b591032534d7f2c794a386ea38f999c 100644
|
| --- a/sdk/lib/_internal/compiler/implementation/js_backend/runtime_types.dart
|
| +++ b/sdk/lib/_internal/compiler/implementation/js_backend/runtime_types.dart
|
| @@ -52,6 +52,54 @@ class RuntimeTypes {
|
| classes.add(dependency);
|
| }
|
|
|
| + bool usingFactoryWithTypeArguments = false;
|
| +
|
| + /**
|
| + * Compute type arguments of classes that use one of their type variables in
|
| + * is-checks and add the is-checks that they imply.
|
| + *
|
| + * This function must be called after all is-checks have been registered.
|
| + *
|
| + * TODO(karlklose): move these computations into a function producing an
|
| + * immutable datastructure.
|
| + */
|
| + void addImplicitChecks(Universe universe,
|
| + Iterable<ClassElement> classesUsingChecks) {
|
| + // If there are no classes that use their variables in checks, there is
|
| + // nothing to do.
|
| + if (classesUsingChecks.isEmpty) return;
|
| + if (universe.usingFactoryWithTypeArguments) {
|
| + for (DartType type in universe.instantiatedTypes) {
|
| + if (type.kind != TypeKind.INTERFACE) continue;
|
| + InterfaceType interface = type;
|
| + for (DartType argument in interface.typeArguments) {
|
| + universe.isChecks.add(argument);
|
| + }
|
| + }
|
| + } else {
|
| + // Find all instantiated types that are a subtype of a class that uses
|
| + // one of its type arguments in an is-check and add the arguments to the
|
| + // set of is-checks.
|
| + // TODO(karlklose): replace this with code that uses a subtype lookup
|
| + // datastructure in the world.
|
| + for (DartType type in universe.instantiatedTypes) {
|
| + if (type.kind != TypeKind.INTERFACE) continue;
|
| + InterfaceType classType = type;
|
| + for (ClassElement cls in classesUsingChecks) {
|
| + // We need the type as instance of its superclass anyway, so we just
|
| + // try to compute the substitution; if the result is [:null:], the
|
| + // classes are not related.
|
| + InterfaceType instance = classType.asInstanceOf(cls);
|
| + if (instance == null) continue;
|
| + Link<DartType> typeArguments = instance.typeArguments;
|
| + for (DartType argument in typeArguments) {
|
| + universe.isChecks.add(argument);
|
| + }
|
| + }
|
| + }
|
| + }
|
| + }
|
| +
|
| void computeClassesNeedingRti() {
|
| // Find the classes that need runtime type information. Such
|
| // classes are:
|
| @@ -88,7 +136,7 @@ class RuntimeTypes {
|
| }
|
| });
|
| // Add is-checks that result from classes using type variables in checks.
|
| - compiler.resolverWorld.addImplicitChecks(classesUsingTypeVariableTests);
|
| + addImplicitChecks(compiler.resolverWorld, classesUsingTypeVariableTests);
|
| // Add the rti dependencies that are implicit in the way the backend
|
| // generates code: when we create a new [List], we actually create
|
| // a JSArray in the backend and we need to add type arguments to
|
| @@ -121,10 +169,12 @@ class RuntimeTypes {
|
| if (cachedRequiredChecks != null) return cachedRequiredChecks;
|
|
|
| // Get all types used in type arguments of instantiated types.
|
| - Set<ClassElement> instantiatedArguments = getInstantiatedArguments();
|
| + Set<ClassElement> instantiatedArguments =
|
| + getInstantiatedArguments(compiler.codegenWorld);
|
|
|
| // Collect all type arguments used in is-checks.
|
| - Set<ClassElement> checkedArguments = getCheckedArguments();
|
| + Set<ClassElement> checkedArguments =
|
| + getCheckedArguments(compiler.codegenWorld);
|
|
|
| // Precompute the set of all seen type arguments for use in the emitter.
|
| allArguments = new Set<ClassElement>.from(instantiatedArguments)
|
| @@ -158,9 +208,9 @@ class RuntimeTypes {
|
| * have a type check against this supertype that includes a check against
|
| * the type arguments.
|
| */
|
| - Set<ClassElement> getInstantiatedArguments() {
|
| + Set<ClassElement> getInstantiatedArguments(Universe universe) {
|
| ArgumentCollector collector = new ArgumentCollector();
|
| - for (DartType type in instantiatedTypes) {
|
| + for (DartType type in universe.instantiatedTypes) {
|
| collector.collect(type);
|
| ClassElement cls = type.element;
|
| for (DartType supertype in cls.allSupertypes) {
|
| @@ -176,22 +226,14 @@ class RuntimeTypes {
|
| }
|
|
|
| /// Collects all type arguments used in is-checks.
|
| - Set<ClassElement> getCheckedArguments() {
|
| + Set<ClassElement> getCheckedArguments(Universe universe) {
|
| ArgumentCollector collector = new ArgumentCollector();
|
| - for (DartType type in isChecks) {
|
| + for (DartType type in universe.isChecks) {
|
| collector.collect(type);
|
| }
|
| return collector.classes;
|
| }
|
|
|
| - Iterable<DartType> get isChecks {
|
| - return compiler.enqueuer.resolution.universe.isChecks;
|
| - }
|
| -
|
| - Iterable<DartType> get instantiatedTypes {
|
| - return compiler.codegenWorld.instantiatedTypes;
|
| - }
|
| -
|
| /// Return the unique name for the element as an unquoted string.
|
| String getNameAsString(Element element) {
|
| JavaScriptBackend backend = compiler.backend;
|
|
|