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 51be7e59f755541d7a427f0ef6ce0238e3ce28bf..79813e19ed6495a9630215926b9482049ce7dc72 100644 |
--- a/sdk/lib/_internal/compiler/implementation/js_backend/runtime_types.dart |
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/runtime_types.dart |
@@ -18,6 +18,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; |
@@ -28,6 +29,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>(); |
@@ -104,9 +106,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); |
karlklose
2013/03/22 13:17:46
Long line.
Johnni Winther
2013/06/21 12:19:14
Done.
|
+ compiler.resolverWorld.genericCallMethods.forEach(analyzeMethod); |
+ } |
} |
}); |
// Add the classes that need RTI because they use a type variable as |
@@ -288,6 +304,42 @@ class RuntimeTypes { |
} |
} |
+ 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.CURRENT_ISOLATE}.' |
+ '$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. |
@@ -327,6 +379,9 @@ class TypeRepresentationGenerator extends DartTypeVisitor { |
OnVariableCallback onVariable; |
StringBuffer builder; |
+ JavaScriptBackend get backend => compiler.backend; |
+ Namer get namer => backend.namer; |
+ |
TypeRepresentationGenerator(Compiler this.compiler); |
/** |
@@ -344,8 +399,6 @@ class TypeRepresentationGenerator extends DartTypeVisitor { |
} |
String getJsName(Element element) { |
- JavaScriptBackend backend = compiler.backend; |
- Namer namer = backend.namer; |
return namer.isolateAccess(element); |
} |
@@ -386,25 +439,25 @@ class TypeRepresentationGenerator extends DartTypeVisitor { |
} |
visitFunctionType(FunctionType type, _) { |
- builder.write('{func: true'); |
+ builder.write('{${namer.functionTypeTag()}: true'); |
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; |