Chromium Code Reviews| 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; |