| 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 c162f557c6dbe96572cbfae62df10b7f1c0d00b9..6e715a75bb1f9d41ac187e876c110b9565fe7444 100644
|
| --- a/sdk/lib/_internal/compiler/implementation/js_backend/runtime_types.dart
|
| +++ b/sdk/lib/_internal/compiler/implementation/js_backend/runtime_types.dart
|
| @@ -20,6 +20,7 @@ class RuntimeTypes {
|
|
|
| final Map<ClassElement, Set<ClassElement>> rtiDependencies;
|
| final Set<ClassElement> classesNeedingRti;
|
| + final Set<Element> methodsNeedingRti;
|
| // The set of classes that use one of their type variables as expressions
|
| // to get the runtime type.
|
| final Set<ClassElement> classesUsingTypeVariableExpression;
|
| @@ -30,6 +31,7 @@ class RuntimeTypes {
|
| : this.compiler = compiler,
|
| representationGenerator = new TypeRepresentationGenerator(compiler),
|
| classesNeedingRti = new Set<ClassElement>(),
|
| + methodsNeedingRti = new Set<Element>(),
|
| rtiDependencies = new Map<ClassElement, Set<ClassElement>>(),
|
| classesUsingTypeVariableExpression = new Set<ClassElement>();
|
|
|
| @@ -77,7 +79,7 @@ class RuntimeTypes {
|
| InterfaceType interface = type;
|
| do {
|
| for (DartType argument in interface.typeArguments) {
|
| - universe.isChecks.add(argument);
|
| + universe.isChecks.add(argument.unalias(compiler));
|
| }
|
| interface = interface.element.supertype;
|
| } while (interface != null && !instantiatedTypes.contains(interface));
|
| @@ -100,7 +102,7 @@ class RuntimeTypes {
|
| InterfaceType instance = current.asInstanceOf(cls);
|
| if (instance == null) break;
|
| for (DartType argument in instance.typeArguments) {
|
| - universe.isChecks.add(argument);
|
| + universe.isChecks.add(argument.unalias(compiler));
|
| }
|
| current = current.element.supertype;
|
| } while (current != null && !instantiatedTypes.contains(current));
|
| @@ -162,9 +164,23 @@ class RuntimeTypes {
|
| if (!itf.isRaw) {
|
| potentiallyAddForRti(itf.element);
|
| }
|
| - } else if (type.kind == TypeKind.TYPE_VARIABLE) {
|
| - TypeVariableElement variable = type.element;
|
| - potentiallyAddForRti(variable.enclosingElement);
|
| + } else {
|
| + ClassElement contextClass = Types.getClassContext(type);
|
| + if (contextClass != null) {
|
| + potentiallyAddForRti(contextClass);
|
| + } else if (type.kind == TypeKind.FUNCTION) {
|
| + void analyzeMethod(Element method) {
|
| + DartType memberType = method.computeType(compiler);
|
| + contextClass = Types.getClassContext(memberType);
|
| + if (contextClass != null &&
|
| + compiler.types.isPotentialSubtype(memberType, type)) {
|
| + potentiallyAddForRti(contextClass);
|
| + methodsNeedingRti.add(method);
|
| + }
|
| + }
|
| + compiler.resolverWorld.closurizedGenericMembers.forEach(analyzeMethod);
|
| + compiler.resolverWorld.genericCallMethods.forEach(analyzeMethod);
|
| + }
|
| }
|
| });
|
| // Add the classes that need RTI because they use a type variable as
|
| @@ -392,6 +408,41 @@ class RuntimeTypes {
|
| return '[$code]';
|
| }
|
|
|
| + String getTypeEncoding(DartType type,
|
| + {bool alwaysGenerateFunction: false}) {
|
| + ClassElement contextClass = Types.getClassContext(type);
|
| + String onVariable(TypeVariableType v) {
|
| + return v.toString();
|
| + };
|
| + String encoding = _getTypeRepresentation(type, onVariable);
|
| + if (contextClass == null && !alwaysGenerateFunction) {
|
| + return encoding;
|
| + } else {
|
| + String parameters = contextClass != null
|
| + ? contextClass.typeVariables.toList().join(', ')
|
| + : '';
|
| + return 'function ($parameters) { return $encoding; }';
|
| + }
|
| + }
|
| +
|
| + String getSignatureEncoding(DartType type, String generateThis()) {
|
| + ClassElement contextClass = Types.getClassContext(type);
|
| + String encoding = getTypeEncoding(type, alwaysGenerateFunction: true);
|
| + if (contextClass != null) {
|
| + String this_ = generateThis();
|
| + JavaScriptBackend backend = compiler.backend;
|
| + String applySignature =
|
| + backend.namer.getName(backend.getApplySignature());
|
| + String contextName = backend.namer.getName(contextClass);
|
| + return 'function () {'
|
| + ' return ${backend.namer.SETUP_OBJECT}.'
|
| + '$applySignature($encoding, $this_, "$contextName"); '
|
| + '}';
|
| + } else {
|
| + return encoding;
|
| + }
|
| + }
|
| +
|
| String getTypeRepresentation(DartType type, void onVariable(variable)) {
|
| // Create a type representation. For type variables call the original
|
| // callback for side effects and return a template placeholder.
|
| @@ -432,6 +483,9 @@ class TypeRepresentationGenerator extends DartTypeVisitor {
|
| OnVariableCallback onVariable;
|
| StringBuffer builder;
|
|
|
| + JavaScriptBackend get backend => compiler.backend;
|
| + Namer get namer => backend.namer;
|
| +
|
| TypeRepresentationGenerator(Compiler this.compiler);
|
|
|
| /**
|
| @@ -449,8 +503,6 @@ class TypeRepresentationGenerator extends DartTypeVisitor {
|
| }
|
|
|
| String getJsName(Element element) {
|
| - JavaScriptBackend backend = compiler.backend;
|
| - Namer namer = backend.namer;
|
| return namer.isolateAccess(backend.getImplementationClass(element));
|
| }
|
|
|
| @@ -491,25 +543,26 @@ class TypeRepresentationGenerator extends DartTypeVisitor {
|
| }
|
|
|
| visitFunctionType(FunctionType type, _) {
|
| - builder.write('{func: true');
|
| + builder.write('{${namer.functionTypeTag()}:'
|
| + ' "${namer.getFunctionTypeName(type)}"');
|
| if (type.returnType.isVoid) {
|
| - builder.write(', retvoid: true');
|
| + builder.write(', ${namer.functionTypeVoidReturnTag()}: true');
|
| } else if (!type.returnType.isDynamic) {
|
| - builder.write(', ret: ');
|
| + builder.write(', ${namer.functionTypeReturnTypeTag()}: ');
|
| visit(type.returnType);
|
| }
|
| if (!type.parameterTypes.isEmpty) {
|
| - builder.write(', args: [');
|
| + builder.write(', ${namer.functionTypeRequiredParametersTag()}: [');
|
| visitList(type.parameterTypes);
|
| builder.write(']');
|
| }
|
| if (!type.optionalParameterTypes.isEmpty) {
|
| - builder.write(', opt: [');
|
| + builder.write(', ${namer.functionTypeOptionalParametersTag()}: [');
|
| visitList(type.optionalParameterTypes);
|
| builder.write(']');
|
| }
|
| if (!type.namedParameterTypes.isEmpty) {
|
| - builder.write(', named: {');
|
| + builder.write(', ${namer.functionTypeNamedParametersTag()}: {');
|
| bool first = true;
|
| Link<SourceString> names = type.namedParameters;
|
| Link<DartType> types = type.namedParameterTypes;
|
| @@ -632,7 +685,7 @@ class Substitution {
|
| String formals = parameters.toList().map(variableName).join(', ');
|
| return 'function ($formals) { return $code; }';
|
| } else if (ensureIsFunction) {
|
| - return 'function() { return $code; }';
|
| + return 'function () { return $code; }';
|
| } else {
|
| return code;
|
| }
|
|
|