| Index: pkg/compiler/lib/src/js_emitter/old_emitter/type_test_emitter.dart
|
| diff --git a/pkg/compiler/lib/src/js_emitter/old_emitter/type_test_emitter.dart b/pkg/compiler/lib/src/js_emitter/old_emitter/type_test_emitter.dart
|
| index 4421165ba728c96b39436ab788e60a600c9cf6fa..26af03df262d2647310093d729b16a3ceb2dc819 100644
|
| --- a/pkg/compiler/lib/src/js_emitter/old_emitter/type_test_emitter.dart
|
| +++ b/pkg/compiler/lib/src/js_emitter/old_emitter/type_test_emitter.dart
|
| @@ -4,7 +4,7 @@
|
|
|
| part of dart2js.js_emitter;
|
|
|
| -class TypeTestEmitter extends CodeEmitterHelper {
|
| +class TypeTestRegistry {
|
| /**
|
| * Raw ClassElement symbols occuring in is-checks and type assertions. If the
|
| * program contains parameterized checks `x is Set<int>` and
|
| @@ -36,6 +36,142 @@ class TypeTestEmitter extends CodeEmitterHelper {
|
| return cachedClassesUsingTypeVariableTests;
|
| }
|
|
|
| + final Compiler compiler;
|
| +
|
| + TypeTestRegistry(this.compiler);
|
| +
|
| + JavaScriptBackend get backend => compiler.backend;
|
| +
|
| + /**
|
| + * Returns the classes with constructors used as a 'holder' in
|
| + * [emitRuntimeTypeSupport].
|
| + * TODO(9556): Some cases will go away when the class objects are created as
|
| + * complete. Not all classes will go away while constructors are referenced
|
| + * from type substitutions.
|
| + */
|
| + Set<ClassElement> classesModifiedByEmitRuntimeTypeSupport() {
|
| + TypeChecks typeChecks = backend.rti.requiredChecks;
|
| + Set<ClassElement> result = new Set<ClassElement>();
|
| + for (ClassElement cls in typeChecks) {
|
| + for (TypeCheck check in typeChecks[cls]) {
|
| + result.add(cls);
|
| + break;
|
| + }
|
| + }
|
| + return result;
|
| + }
|
| +
|
| + Set<ClassElement> computeRtiNeededClasses() {
|
| + void addClassWithSuperclasses(ClassElement cls) {
|
| + rtiNeededClasses.add(cls);
|
| + for (ClassElement superclass = cls.superclass;
|
| + superclass != null;
|
| + superclass = superclass.superclass) {
|
| + rtiNeededClasses.add(superclass);
|
| + }
|
| + }
|
| +
|
| + void addClassesWithSuperclasses(Iterable<ClassElement> classes) {
|
| + for (ClassElement cls in classes) {
|
| + addClassWithSuperclasses(cls);
|
| + }
|
| + }
|
| +
|
| + // 1. Add classes that are referenced by type arguments or substitutions in
|
| + // argument checks.
|
| + // TODO(karlklose): merge this case with 2 when unifying argument and
|
| + // object checks.
|
| + RuntimeTypes rti = backend.rti;
|
| + rti.getRequiredArgumentClasses(backend)
|
| + .forEach(addClassWithSuperclasses);
|
| +
|
| + // 2. Add classes that are referenced by substitutions in object checks and
|
| + // their superclasses.
|
| + TypeChecks requiredChecks =
|
| + rti.computeChecks(rtiNeededClasses, checkedClasses);
|
| + Set<ClassElement> classesUsedInSubstitutions =
|
| + rti.getClassesUsedInSubstitutions(backend, requiredChecks);
|
| + addClassesWithSuperclasses(classesUsedInSubstitutions);
|
| +
|
| + // 3. Add classes that contain checked generic function types. These are
|
| + // needed to store the signature encoding.
|
| + for (FunctionType type in checkedFunctionTypes) {
|
| + ClassElement contextClass = Types.getClassContext(type);
|
| + if (contextClass != null) {
|
| + rtiNeededClasses.add(contextClass);
|
| + }
|
| + }
|
| +
|
| + bool canTearOff(Element function) {
|
| + if (!function.isFunction ||
|
| + function.isConstructor ||
|
| + function.isAccessor) {
|
| + return false;
|
| + } else if (function.isInstanceMember) {
|
| + if (!function.enclosingClass.isClosure) {
|
| + return compiler.codegenWorld.hasInvokedGetter(
|
| + function, compiler.world);
|
| + }
|
| + }
|
| + return false;
|
| + }
|
| +
|
| + bool canBeReflectedAsFunction(Element element) {
|
| + return element.kind == ElementKind.FUNCTION ||
|
| + element.kind == ElementKind.GETTER ||
|
| + element.kind == ElementKind.SETTER ||
|
| + element.kind == ElementKind.GENERATIVE_CONSTRUCTOR;
|
| + }
|
| +
|
| + bool canBeReified(Element element) {
|
| + return (canTearOff(element) || backend.isAccessibleByReflection(element));
|
| + }
|
| +
|
| + // Find all types referenced from the types of elements that can be
|
| + // reflected on 'as functions'.
|
| + backend.generatedCode.keys.where((element) {
|
| + return canBeReflectedAsFunction(element) && canBeReified(element);
|
| + }).forEach((FunctionElement function) {
|
| + DartType type = function.computeType(compiler);
|
| + for (ClassElement cls in backend.rti.getReferencedClasses(type)) {
|
| + while (cls != null) {
|
| + rtiNeededClasses.add(cls);
|
| + cls = cls.superclass;
|
| + }
|
| + }
|
| + });
|
| +
|
| + return rtiNeededClasses;
|
| + }
|
| +
|
| + void computeRequiredTypeChecks() {
|
| + assert(checkedClasses == null && checkedFunctionTypes == null);
|
| +
|
| + backend.rti.addImplicitChecks(compiler.codegenWorld,
|
| + classesUsingTypeVariableTests);
|
| +
|
| + checkedClasses = new Set<ClassElement>();
|
| + checkedFunctionTypes = new Set<FunctionType>();
|
| + compiler.codegenWorld.isChecks.forEach((DartType t) {
|
| + if (t is InterfaceType) {
|
| + checkedClasses.add(t.element);
|
| + } else if (t is FunctionType) {
|
| + checkedFunctionTypes.add(t);
|
| + }
|
| + });
|
| + }
|
| +}
|
| +
|
| +class TypeTestEmitter extends CodeEmitterHelper {
|
| + Set<ClassElement> get checkedClasses =>
|
| + emitter.typeTestRegistry.checkedClasses;
|
| +
|
| + Iterable<ClassElement> get classesUsingTypeVariableTests =>
|
| + emitter.typeTestRegistry.classesUsingTypeVariableTests;
|
| +
|
| + Set<FunctionType> get checkedFunctionTypes =>
|
| + emitter.typeTestRegistry.checkedFunctionTypes;
|
| +
|
| void emitIsTests(ClassElement classElement, ClassBuilder builder) {
|
| assert(invariant(classElement, classElement.isDeclaration));
|
|
|
| @@ -269,123 +405,4 @@ class TypeTestEmitter extends CodeEmitterHelper {
|
| buffer.write('$N');
|
| }
|
| }
|
| -
|
| - /**
|
| - * Returns the classes with constructors used as a 'holder' in
|
| - * [emitRuntimeTypeSupport].
|
| - * TODO(9556): Some cases will go away when the class objects are created as
|
| - * complete. Not all classes will go away while constructors are referenced
|
| - * from type substitutions.
|
| - */
|
| - Set<ClassElement> classesModifiedByEmitRuntimeTypeSupport() {
|
| - TypeChecks typeChecks = backend.rti.requiredChecks;
|
| - Set<ClassElement> result = new Set<ClassElement>();
|
| - for (ClassElement cls in typeChecks) {
|
| - for (TypeCheck check in typeChecks[cls]) {
|
| - result.add(cls);
|
| - break;
|
| - }
|
| - }
|
| - return result;
|
| - }
|
| -
|
| - Set<ClassElement> computeRtiNeededClasses() {
|
| - void addClassWithSuperclasses(ClassElement cls) {
|
| - rtiNeededClasses.add(cls);
|
| - for (ClassElement superclass = cls.superclass;
|
| - superclass != null;
|
| - superclass = superclass.superclass) {
|
| - rtiNeededClasses.add(superclass);
|
| - }
|
| - }
|
| -
|
| - void addClassesWithSuperclasses(Iterable<ClassElement> classes) {
|
| - for (ClassElement cls in classes) {
|
| - addClassWithSuperclasses(cls);
|
| - }
|
| - }
|
| -
|
| - // 1. Add classes that are referenced by type arguments or substitutions in
|
| - // argument checks.
|
| - // TODO(karlklose): merge this case with 2 when unifying argument and
|
| - // object checks.
|
| - RuntimeTypes rti = backend.rti;
|
| - rti.getRequiredArgumentClasses(backend)
|
| - .forEach(addClassWithSuperclasses);
|
| -
|
| - // 2. Add classes that are referenced by substitutions in object checks and
|
| - // their superclasses.
|
| - TypeChecks requiredChecks =
|
| - rti.computeChecks(rtiNeededClasses, checkedClasses);
|
| - Set<ClassElement> classesUsedInSubstitutions =
|
| - rti.getClassesUsedInSubstitutions(backend, requiredChecks);
|
| - addClassesWithSuperclasses(classesUsedInSubstitutions);
|
| -
|
| - // 3. Add classes that contain checked generic function types. These are
|
| - // needed to store the signature encoding.
|
| - for (FunctionType type in checkedFunctionTypes) {
|
| - ClassElement contextClass = Types.getClassContext(type);
|
| - if (contextClass != null) {
|
| - rtiNeededClasses.add(contextClass);
|
| - }
|
| - }
|
| -
|
| - bool canTearOff(Element function) {
|
| - if (!function.isFunction ||
|
| - function.isConstructor ||
|
| - function.isAccessor) {
|
| - return false;
|
| - } else if (function.isInstanceMember) {
|
| - if (!function.enclosingClass.isClosure) {
|
| - return compiler.codegenWorld.hasInvokedGetter(
|
| - function, compiler.world);
|
| - }
|
| - }
|
| - return false;
|
| - }
|
| -
|
| - bool canBeReflectedAsFunction(Element element) {
|
| - return element.kind == ElementKind.FUNCTION ||
|
| - element.kind == ElementKind.GETTER ||
|
| - element.kind == ElementKind.SETTER ||
|
| - element.kind == ElementKind.GENERATIVE_CONSTRUCTOR;
|
| - }
|
| -
|
| - bool canBeReified(Element element) {
|
| - return (canTearOff(element) || backend.isAccessibleByReflection(element));
|
| - }
|
| -
|
| - // Find all types referenced from the types of elements that can be
|
| - // reflected on 'as functions'.
|
| - backend.generatedCode.keys.where((element) {
|
| - return canBeReflectedAsFunction(element) && canBeReified(element);
|
| - }).forEach((FunctionElement function) {
|
| - DartType type = function.computeType(compiler);
|
| - for (ClassElement cls in backend.rti.getReferencedClasses(type)) {
|
| - while (cls != null) {
|
| - rtiNeededClasses.add(cls);
|
| - cls = cls.superclass;
|
| - }
|
| - }
|
| - });
|
| -
|
| - return rtiNeededClasses;
|
| - }
|
| -
|
| - void computeRequiredTypeChecks() {
|
| - assert(checkedClasses == null && checkedFunctionTypes == null);
|
| -
|
| - backend.rti.addImplicitChecks(compiler.codegenWorld,
|
| - classesUsingTypeVariableTests);
|
| -
|
| - checkedClasses = new Set<ClassElement>();
|
| - checkedFunctionTypes = new Set<FunctionType>();
|
| - compiler.codegenWorld.isChecks.forEach((DartType t) {
|
| - if (t is InterfaceType) {
|
| - checkedClasses.add(t.element);
|
| - } else if (t is FunctionType) {
|
| - checkedFunctionTypes.add(t);
|
| - }
|
| - });
|
| - }
|
| }
|
|
|