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; |
} |