| Index: pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart
|
| diff --git a/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart b/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart
|
| index 692676b58445d4f8d4c11e4d0109e089604a7e89..c9d418f3e2f036ab2433b1768ef91c695e4188f3 100644
|
| --- a/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart
|
| +++ b/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart
|
| @@ -8,11 +8,9 @@ import '../closure.dart'
|
| show ClosureRepresentationInfo, ClosureFieldElement, ClosureConversionTask;
|
| import '../common.dart';
|
| import '../common/names.dart' show Identifiers;
|
| -import '../common_elements.dart' show CommonElements;
|
| -import '../elements/resolution_types.dart'
|
| - show ResolutionDartType, ResolutionFunctionType, ResolutionInterfaceType;
|
| +import '../common_elements.dart' show CommonElements, ElementEnvironment;
|
| import '../elements/elements.dart'
|
| - show ClassElement, Element, FunctionElement, MixinApplicationElement;
|
| + show ClassElement, MethodElement, MixinApplicationElement;
|
| import '../elements/entities.dart';
|
| import '../elements/types.dart';
|
| import '../js/js.dart' as jsAst;
|
| @@ -30,15 +28,16 @@ import '../js_backend/runtime_types.dart'
|
| TypeCheck,
|
| TypeChecks;
|
| import '../util/util.dart' show Setlet;
|
| +import '../world.dart';
|
|
|
| import 'code_emitter_task.dart' show CodeEmitterTask;
|
| import 'type_test_registry.dart' show TypeTestRegistry;
|
|
|
| // Function signatures used in the generation of runtime type information.
|
| typedef void FunctionTypeSignatureEmitter(
|
| - Element method, ResolutionFunctionType methodType);
|
| + FunctionEntity method, FunctionType methodType);
|
|
|
| -typedef void SubstitutionEmitter(Element element, {bool emitNull});
|
| +typedef void SubstitutionEmitter(ClassEntity element, {bool emitNull});
|
|
|
| class TypeTestProperties {
|
| /// The index of the function type into the metadata.
|
| @@ -51,13 +50,16 @@ class TypeTestProperties {
|
| jsAst.Expression functionTypeIndex;
|
|
|
| /// The properties that must be installed on the prototype of the
|
| - /// JS constructor of the [ClassElement] for which the is checks were
|
| + /// JS constructor of the [ClassEntity] for which the is checks were
|
| /// generated.
|
| final Map<jsAst.Name, jsAst.Node> properties = <jsAst.Name, jsAst.Node>{};
|
| }
|
|
|
| class RuntimeTypeGenerator {
|
| + final ElementEnvironment _elementEnvironment;
|
| final CommonElements _commonElements;
|
| + final DartTypes _types;
|
| + final ClosedWorld _closedWorld;
|
| final ClosureConversionTask _closureDataLookup;
|
| final CodeEmitterTask emitterTask;
|
| final Namer _namer;
|
| @@ -69,7 +71,10 @@ class RuntimeTypeGenerator {
|
| final JsInteropAnalysis _jsInteropAnalysis;
|
|
|
| RuntimeTypeGenerator(
|
| + this._elementEnvironment,
|
| this._commonElements,
|
| + this._types,
|
| + this._closedWorld,
|
| this._closureDataLookup,
|
| this.emitterTask,
|
| this._namer,
|
| @@ -100,30 +105,28 @@ class RuntimeTypeGenerator {
|
| /// type (if class has one) in the metadata object and stores its index in
|
| /// the result. This is only possible for function types that do not contain
|
| /// type variables.
|
| - TypeTestProperties generateIsTests(ClassEntity cls,
|
| + TypeTestProperties generateIsTests(ClassEntity classElement,
|
| {bool storeFunctionTypeInMetadata: true}) {
|
| TypeTestProperties result = new TypeTestProperties();
|
| - if (cls is! ClassElement) return result;
|
|
|
| - // TODO(johnniwinther): Handle class entities.
|
| - ClassElement classElement = cls;
|
| - assert(classElement.isDeclaration, failedAt(classElement));
|
| + assert(!(classElement is ClassElement && !classElement.isDeclaration),
|
| + failedAt(classElement));
|
|
|
| /// Generates an is-test if the test is not inherited from a superclass
|
| /// This assumes that for every class an is-tests is generated
|
| /// dynamically at runtime. We also always generate tests against
|
| /// native classes.
|
| /// TODO(herhut): Generate tests for native classes dynamically, as well.
|
| - void generateIsTest(ClassElement other) {
|
| + void generateIsTest(ClassEntity other) {
|
| if (_nativeData.isNativeClass(classElement) ||
|
| - !classElement.isSubclassOf(other)) {
|
| + !_closedWorld.isSubclassOf(classElement, other)) {
|
| result.properties[_namer.operatorIs(other)] = js('1');
|
| }
|
| }
|
|
|
| void generateFunctionTypeSignature(
|
| - FunctionElement method, ResolutionFunctionType type) {
|
| - assert(method.isImplementation);
|
| + FunctionEntity method, FunctionType type) {
|
| + assert(!(method is MethodElement && !method.isImplementation));
|
| jsAst.Expression thisAccess = new jsAst.This();
|
| if (!method.isAbstract) {
|
| ClosureRepresentationInfo closureData =
|
| @@ -148,8 +151,8 @@ class RuntimeTypeGenerator {
|
| }
|
| }
|
|
|
| - void generateSubstitution(ClassElement cls, {bool emitNull: false}) {
|
| - if (cls.typeVariables.isEmpty) return;
|
| + void generateSubstitution(ClassEntity cls, {bool emitNull: false}) {
|
| + if (!_elementEnvironment.isGenericClass(cls)) return;
|
| jsAst.Expression expression;
|
| bool needsNativeCheck =
|
| emitterTask.nativeEmitter.requiresNativeIsCheck(cls);
|
| @@ -168,7 +171,7 @@ class RuntimeTypeGenerator {
|
| }
|
|
|
| void generateTypeCheck(TypeCheck check) {
|
| - ClassElement checkedClass = check.cls;
|
| + ClassEntity checkedClass = check.cls;
|
| generateIsTest(checkedClass);
|
| Substitution substitution = check.substitution;
|
| if (substitution != null) {
|
| @@ -178,12 +181,11 @@ class RuntimeTypeGenerator {
|
| }
|
| }
|
|
|
| - _generateIsTestsOn(classElement, (Element e) {
|
| - generateIsTest(e);
|
| - }, (Element e, ResolutionFunctionType t) {
|
| - generateFunctionTypeSignature(e, t);
|
| - },
|
| - (Element e, {bool emitNull: false}) =>
|
| + _generateIsTestsOn(
|
| + classElement,
|
| + generateIsTest,
|
| + generateFunctionTypeSignature,
|
| + (ClassEntity e, {bool emitNull: false}) =>
|
| generateSubstitution(e, emitNull: emitNull),
|
| generateTypeCheck);
|
|
|
| @@ -208,12 +210,12 @@ class RuntimeTypeGenerator {
|
| * substitutions, because they may have changed.
|
| */
|
| void _generateIsTestsOn(
|
| - ClassElement cls,
|
| - void generateIsTest(Element element),
|
| + ClassEntity cls,
|
| + void generateIsTest(ClassEntity element),
|
| FunctionTypeSignatureEmitter generateFunctionTypeSignature,
|
| SubstitutionEmitter generateSubstitution,
|
| void emitTypeCheck(TypeCheck check)) {
|
| - Setlet<ClassElement> generated = new Setlet<ClassElement>();
|
| + Setlet<ClassEntity> generated = new Setlet<ClassEntity>();
|
|
|
| if (checkedClasses.contains(cls)) {
|
| generateIsTest(cls);
|
| @@ -233,9 +235,9 @@ class RuntimeTypeGenerator {
|
| }
|
| }
|
|
|
| - ClassElement superclass = cls.superclass;
|
| + ClassEntity superclass = _elementEnvironment.getSuperClass(cls);
|
|
|
| - bool haveSameTypeVariables(ClassElement a, ClassElement b) {
|
| + bool haveSameTypeVariables(ClassEntity a, ClassEntity b) {
|
| if (a.isClosure) return true;
|
| return _rtiSubstitutions.isTrivialSubstitution(a, b);
|
| }
|
| @@ -257,7 +259,7 @@ class RuntimeTypeGenerator {
|
| generateSubstitution(superclass, emitNull: true);
|
| generated.add(superclass);
|
| }
|
| - superclass = superclass.superclass;
|
| + superclass = _elementEnvironment.getSuperClass(superclass);
|
| }
|
| supertypesNeedSubstitutions = true;
|
| }
|
| @@ -267,9 +269,9 @@ class RuntimeTypeGenerator {
|
| }
|
|
|
| if (supertypesNeedSubstitutions) {
|
| - for (ResolutionInterfaceType supertype in cls.allSupertypes) {
|
| - ClassElement superclass = supertype.element;
|
| - if (generated.contains(superclass)) continue;
|
| + _elementEnvironment.forEachSupertype(cls, (InterfaceType supertype) {
|
| + ClassEntity superclass = supertype.element;
|
| + if (generated.contains(superclass)) return;
|
|
|
| if (classesUsingTypeVariableTests.contains(superclass) ||
|
| _rtiNeed.classUsesTypeVariableExpression(superclass) ||
|
| @@ -279,7 +281,7 @@ class RuntimeTypeGenerator {
|
| // super classes.
|
| generateSubstitution(superclass, emitNull: true);
|
| }
|
| - }
|
| + });
|
|
|
| void emitNothing(_, {emitNull}) {}
|
|
|
| @@ -290,25 +292,25 @@ class RuntimeTypeGenerator {
|
| // [Function] and needs checks for all typedefs that are used in is-checks.
|
| if (checkedClasses.contains(_commonElements.functionClass) ||
|
| checkedFunctionTypes.isNotEmpty) {
|
| - Element call = cls.lookupLocalMember(Identifiers.call);
|
| - if (call == null) {
|
| - // If [cls] is a closure, it has a synthetic call operator method.
|
| - call = cls.lookupConstructorBody(Identifiers.call);
|
| - }
|
| + MemberEntity call =
|
| + _elementEnvironment.lookupClassMember(cls, Identifiers.call);
|
| if (call != null && call.isFunction) {
|
| - FunctionElement callFunction = call;
|
| + FunctionEntity callFunction = call;
|
| // A superclass might already implement the Function interface. In such
|
| - // a case, we can avoid emiting the is test here.
|
| - if (!cls.superclass.implementsFunction(_commonElements)) {
|
| + // a case, we can avoid emitting the is test here.
|
| + ClassEntity superclass = _elementEnvironment.getSuperClass(cls);
|
| + if (!_closedWorld.isSubclassOf(
|
| + superclass, _commonElements.functionClass)) {
|
| _generateInterfacesIsTests(_commonElements.functionClass,
|
| generateIsTest, generateSubstitution, generated);
|
| }
|
| - ResolutionFunctionType callType = callFunction.type;
|
| + FunctionType callType =
|
| + _elementEnvironment.getFunctionType(callFunction);
|
| generateFunctionTypeSignature(callFunction, callType);
|
| }
|
| }
|
|
|
| - for (ResolutionDartType interfaceType in cls.interfaces) {
|
| + for (InterfaceType interfaceType in _types.getInterfaces(cls)) {
|
| _generateInterfacesIsTests(interfaceType.element, generateIsTest,
|
| generateSubstitution, generated);
|
| }
|
| @@ -318,11 +320,11 @@ class RuntimeTypeGenerator {
|
| * Generate "is tests" where [cls] is being implemented.
|
| */
|
| void _generateInterfacesIsTests(
|
| - ClassElement cls,
|
| - void generateIsTest(ClassElement element),
|
| + ClassEntity cls,
|
| + void generateIsTest(ClassEntity element),
|
| SubstitutionEmitter generateSubstitution,
|
| - Set<Element> alreadyGenerated) {
|
| - void tryEmitTest(ClassElement check) {
|
| + Set<ClassEntity> alreadyGenerated) {
|
| + void tryEmitTest(ClassEntity check) {
|
| if (!alreadyGenerated.contains(check) && checkedClasses.contains(check)) {
|
| alreadyGenerated.add(check);
|
| generateIsTest(check);
|
| @@ -332,15 +334,15 @@ class RuntimeTypeGenerator {
|
|
|
| tryEmitTest(cls);
|
|
|
| - for (ResolutionDartType interfaceType in cls.interfaces) {
|
| - Element element = interfaceType.element;
|
| + for (InterfaceType interfaceType in _types.getInterfaces(cls)) {
|
| + ClassEntity element = interfaceType.element;
|
| tryEmitTest(element);
|
| _generateInterfacesIsTests(
|
| element, generateIsTest, generateSubstitution, alreadyGenerated);
|
| }
|
|
|
| // We need to also emit "is checks" for the superclass and its supertypes.
|
| - ClassElement superclass = cls.superclass;
|
| + ClassEntity superclass = _elementEnvironment.getSuperClass(cls);
|
| if (superclass != null) {
|
| tryEmitTest(superclass);
|
| _generateInterfacesIsTests(
|
|
|