Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(168)

Side by Side Diff: sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart

Issue 11598006: Concept of how dart:mirrors LibraryMirror, ClassMirror can be implemented in dart2js. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Added enough closure support to get tests/lib/mirrors/mirrors_test.dart pass. Created 7 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 part of js_backend; 5 part of js_backend;
6 6
7 /** 7 /**
8 * A function element that represents a closure call. The signature is copied 8 * A function element that represents a closure call. The signature is copied
9 * from the given element. 9 * from the given element.
10 */ 10 */
(...skipping 30 matching lines...) Expand all
41 CodeBuffer boundClosureBuffer; 41 CodeBuffer boundClosureBuffer;
42 CodeBuffer mainBuffer; 42 CodeBuffer mainBuffer;
43 /** Shorter access to [isolatePropertiesName]. Both here in the code, as 43 /** Shorter access to [isolatePropertiesName]. Both here in the code, as
44 well as in the generated code. */ 44 well as in the generated code. */
45 String isolateProperties; 45 String isolateProperties;
46 String classesCollector; 46 String classesCollector;
47 Set<ClassElement> neededClasses; 47 Set<ClassElement> neededClasses;
48 // TODO(ngeoffray): remove this field. 48 // TODO(ngeoffray): remove this field.
49 Set<ClassElement> instantiatedClasses; 49 Set<ClassElement> instantiatedClasses;
50 50
51 List<js.Expression> libraryMirrorsParametersList;
52 Map<String, int> libraryMirrorsIndices;
53
51 String get _ => compiler.enableMinification ? "" : " "; 54 String get _ => compiler.enableMinification ? "" : " ";
52 String get n => compiler.enableMinification ? "" : "\n"; 55 String get n => compiler.enableMinification ? "" : "\n";
53 String get N => compiler.enableMinification ? "\n" : ";\n"; 56 String get N => compiler.enableMinification ? "\n" : ";\n";
54 57
55 /** 58 /**
56 * A cache of closures that are used to closurize instance methods. 59 * A cache of closures that are used to closurize instance methods.
57 * A closure is dynamically bound to the instance used when 60 * A closure is dynamically bound to the instance used when
58 * closurized. 61 * closurized.
59 */ 62 */
60 final Map<int, String> boundClosureCache; 63 final Map<int, String> boundClosureCache;
(...skipping 962 matching lines...) Expand 10 before | Expand all | Expand 10 after
1023 generateGetter(member, name, accessorName, buffer); 1026 generateGetter(member, name, accessorName, buffer);
1024 } 1027 }
1025 if (needsSetter) { 1028 if (needsSetter) {
1026 emitComma(); 1029 emitComma();
1027 generateSetter(member, name, accessorName, buffer); 1030 generateSetter(member, name, accessorName, buffer);
1028 } 1031 }
1029 } 1032 }
1030 }); 1033 });
1031 } 1034 }
1032 1035
1036 void emitClassLibraryGetter(ClassElement classElement, CodeBuffer buffer) {
1037 var name = classElement.getLibrary().getLibraryOrScriptName();
1038 // Some builtin classes come from js_helper libraries, which are
1039 // not in libraryMirrorsIndices collection. At this point we
1040 // will ignore them.
1041 if (libraryMirrorsIndices.containsKey(name)) {
1042 buffer.add(",$n$_${_}builtin\$library:$_${libraryMirrorsIndices[name]}");
1043 }
1044 }
1045
1033 /** 1046 /**
1034 * Documentation wanted -- johnniwinther 1047 * Documentation wanted -- johnniwinther
1035 * 1048 *
1036 * Invariant: [classElement] must be a declaration element. 1049 * Invariant: [classElement] must be a declaration element.
1037 */ 1050 */
1038 void generateClass(ClassElement classElement, CodeBuffer buffer) { 1051 void generateClass(ClassElement classElement, CodeBuffer buffer) {
1039 assert(invariant(classElement, classElement.isDeclaration)); 1052 assert(invariant(classElement, classElement.isDeclaration));
1040 if (classElement.isNative()) { 1053 if (classElement.isNative()) {
1041 nativeEmitter.generateNativeClass(classElement); 1054 nativeEmitter.generateNativeClass(classElement);
1042 return; 1055 return;
(...skipping 15 matching lines...) Expand all
1058 buffer.add('$classesCollector.$className$_=$_{'); 1071 buffer.add('$classesCollector.$className$_=$_{');
1059 emitClassConstructor(classElement, buffer); 1072 emitClassConstructor(classElement, buffer);
1060 emitSuper(superName, buffer); 1073 emitSuper(superName, buffer);
1061 emitClassFields(classElement, buffer, false, 1074 emitClassFields(classElement, buffer, false,
1062 superClass: superName, classIsNative: false); 1075 superClass: superName, classIsNative: false);
1063 // TODO(floitsch): the emitInstanceMember should simply always emit a ',\n'. 1076 // TODO(floitsch): the emitInstanceMember should simply always emit a ',\n'.
1064 // That does currently not work because the native classes have a different 1077 // That does currently not work because the native classes have a different
1065 // syntax. 1078 // syntax.
1066 emitClassGettersSetters(classElement, buffer, true); 1079 emitClassGettersSetters(classElement, buffer, true);
1067 emitInstanceMembers(classElement, buffer, true); 1080 emitInstanceMembers(classElement, buffer, true);
1081 if (compiler.hasMirrorsSupport()) {
1082 emitClassLibraryGetter(classElement, buffer);
1083 }
1068 buffer.add('$n}$N$n'); 1084 buffer.add('$n}$N$n');
1069 } 1085 }
1070 1086
1071 bool get getterAndSetterCanBeImplementedByFieldSpec => true; 1087 bool get getterAndSetterCanBeImplementedByFieldSpec => true;
1072 1088
1073 void emitInterceptorMethods( 1089 void emitInterceptorMethods(
1074 void defineInstanceMember(String name, StringBuffer memberBuffer)) { 1090 void defineInstanceMember(String name, StringBuffer memberBuffer)) {
1075 JavaScriptBackend backend = compiler.backend; 1091 JavaScriptBackend backend = compiler.backend;
1076 // Emit forwarders for the ObjectInterceptor class. We need to 1092 // Emit forwarders for the ObjectInterceptor class. We need to
1077 // emit all possible sends on intercepted methods. 1093 // emit all possible sends on intercepted methods.
(...skipping 1022 matching lines...) Expand 10 before | Expand all | Expand 10 after
2100 for (ClassElement element in instantiatedClasses) { 2116 for (ClassElement element in instantiatedClasses) {
2101 for (ClassElement superclass = element.superclass; 2117 for (ClassElement superclass = element.superclass;
2102 superclass != null; 2118 superclass != null;
2103 superclass = superclass.superclass) { 2119 superclass = superclass.superclass) {
2104 if (neededClasses.contains(superclass)) break; 2120 if (neededClasses.contains(superclass)) break;
2105 neededClasses.add(superclass); 2121 neededClasses.add(superclass);
2106 } 2122 }
2107 } 2123 }
2108 } 2124 }
2109 2125
2126 Collection<js.Expression> extract(listElements, filterToApply) {
2127 return new js.ArrayInitializer.from(
2128 listElements
2129 .filter(filterToApply)
2130 .map((member) => js.string(namer.getName(member))));
2131 }
2132
2133 Collection extractClasses(listElements) {
2134 var classDescriptions = [];
2135 var classes = listElements.filter((e) => Elements.isClass(e));
2136 for (Element classElement in classes) {
2137 var classMembers = [];
2138 for (var classMember in classElement.localMembers) {
2139 var prefixType;
2140 var name;
2141 if (classMember.isGetter()) {
2142 prefixType = 'G';
2143 name = qualifiedFunctionName(classMember);
2144 } else if (classMember.isSetter()) {
2145 prefixType = 'S';
2146 name = qualifiedFunctionName(classMember);
2147 } else if (classMember.isField()) {
2148 prefixType = 'V';
2149 name = qualifiedVariableName(classMember);
2150 } else if (classMember.isConstructor()) {
2151 prefixType = 'C';
2152 name = namer.getName(classMember);
2153 } else if (classMember.isTypeVariable()) {
2154 prefixType = 'T';
2155 name = namer.getName(classMember);
2156 } else if (classMember.isParameter()) {
2157 prefixType = 'A';
2158 name = namer.getName(classMember);
2159 } else {
2160 prefixType = 'M';
2161 name = qualifiedFunctionName(classMember);
2162 }
2163 var originalName = classMember.name.slowToString();
2164 if (name != originalName) {
2165 name = "$name[$originalName]";
2166 }
2167 classMembers.add(js.string("$prefixType:$name"));
2168 }
2169 classDescriptions.add(
2170 new js.ArrayInitializer.from(
2171 [js.string(namer.getName(classElement)),
2172 new js.ArrayInitializer.from(classMembers)]));
2173 }
2174 return new js.ArrayInitializer.from(classDescriptions);
2175 }
2176
2177 String qualifiedFunctionName(Element functionElement) {
2178 String prefixType;
2179 if (functionElement.modifiers.isStatic()) {
2180 prefixType = 'S';
2181 } else {
2182 prefixType = 'I';
2183 }
2184 var typeName = "";
2185 var libraryID = "";
2186 assert(functionElement.type != null);
2187 DartType dt = functionElement.type;
2188 // Ignore types that weren't computed.
2189 if (dt != null) {
2190 if (dt.kind == TypeKind.FUNCTION) {
2191 typeName = dt.returnType.name.slowToString();
2192 if (typeName == 'void' || typeName == 'dynamic') {
2193 libraryID = "";
2194 } else {
2195 var library = dt.returnType.element.getLibrary();
2196 var libraryName = library.getLibraryOrScriptName();
2197 libraryID = libraryMirrorsIndices[libraryName];
2198 }
2199 }
2200 }
2201 return "$prefixType:$libraryID:$typeName:${namer.getName(functionElement)}";
2202 }
2203
2204 Collection extractMethods(listElements, filterToApply) {
2205 var methodsDescription =
2206 listElements
2207 .filter(filterToApply)
2208 .map((e) => js.string(qualifiedFunctionName(e)));
2209 return new js.ArrayInitializer.from(methodsDescription);
2210 }
2211
2212 String qualifiedVariableName(Element fieldElement) {
2213 String prefixType;
2214 if (fieldElement.modifiers.isStatic()) {
2215 prefixType = 'S';
2216 } else {
2217 prefixType = 'I';
2218 }
2219 // Use case to indicate whether field is final or not.
2220 // Is it too fancy?
2221 if (fieldElement.modifiers.isFinal()) {
2222 prefixType = prefixType.toLowerCase();
2223 }
2224 var name = namer.getName(fieldElement);
2225 var originalName = fieldElement.name.slowToString();
2226 if (name != originalName) {
2227 name = "$name[$originalName]";
2228 }
2229 return "$prefixType:$name";
2230 }
2231
2232 Collection extractVariables(listElements) {
2233 var fieldsDescription =
2234 listElements
2235 .filter((e) => e.isField())
2236 .map((e) => js.string(qualifiedVariableName(e)));
2237 return new js.ArrayInitializer.from(fieldsDescription);
2238 }
2239
2240 Collection extractClosures(Collection<ClosureClassMap> listClosures) {
2241 var closuresDescriptions =
2242 listClosures.map(
2243 (map) => js.string(
2244 "${namer.getName(map.closureClassElement)}:"
2245 "${namer.getName(map.callElement)}:"
2246 "${map.callElement.functionSignature.requiredParameterCount}:"
2247 "${map.callElement.functionSignature.optionalParameterCount}:"));
2248 return new js.ArrayInitializer.from(closuresDescriptions);
2249 }
2250
2251 void computeLibraryMirrors() {
2252 int index = 0;
2253 libraryMirrorsParametersList = new List<js.Expression>();
2254 libraryMirrorsIndices = new Map<String, int>();
2255 for (LibraryElement libraryElement in compiler.libraries.values) {
2256 //
2257 // [lib1,
2258 // [[class1, classConstructor, [member1,...]]
2259 // ...],
2260 // [function1...],
2261 // [getter1...]
2262 // [setter1...]
2263 // [variable1...]
2264 // [closure1...]
2265 // ]...
2266 //
2267 var elements =
2268 new List<Element>.from(libraryElement.localMembers);
2269 var libraryName = libraryElement.getLibraryOrScriptName();
2270 libraryMirrorsParametersList.add(
2271 new js.ArrayInitializer.from(
2272 <js.Expression>[
2273 js.string(libraryName),
2274 extractClasses(elements),
2275 extractMethods(elements, (e) => e.isFunction()),
2276 extractMethods(elements, (e) => e.isGetter()),
2277 extractMethods(elements, (e) => e.isSetter()),
2278 extractVariables(elements),
2279 extractClosures(
2280 new List<ClassElement>.from(
2281 compiler.closureToClassMapper
2282 .closureMappingCache.values
2283 .filter((map) => map.closureElement != null
2284 && map.closureElement.getLibrary()
2285 == libraryElement)))
2286 ]));
2287 libraryMirrorsIndices[libraryName] = index++;
2288 }
2289 }
2290
2291 void emitMirrorsSupport(CodeBuffer buffer) {
2292 Element createMirrorSystem =
2293 compiler.mirrorsLibrary.find(Compiler.CREATE_MIRROR_SYSTEM);
2294 String isolateCreateMirrorSystem =
2295 namer.isolateAccess(createMirrorSystem);
2296
2297 // createMirrorSystem([library1, library2, ...])
2298 var createMirrorSystemCall =
2299 new js.ExpressionStatement(
2300 js.call(
2301 js.use(isolateCreateMirrorSystem),
2302 [new js.ArrayInitializer.from(libraryMirrorsParametersList)]));
2303 mainBuffer.add(js.prettyPrint(createMirrorSystemCall, compiler));
2304 }
2305
2110 String assembleProgram() { 2306 String assembleProgram() {
2111 measure(() { 2307 measure(() {
2112 computeNeededClasses(); 2308 computeNeededClasses();
2309 if (compiler.hasMirrorsSupport()) {
2310 // Create library mirror structure up front so that we can refer to
2311 // library elements during class construction by array index.
2312 computeLibraryMirrors();
2313 }
2113 2314
2114 mainBuffer.add(GENERATED_BY); 2315 mainBuffer.add(GENERATED_BY);
2115 if (!compiler.enableMinification) mainBuffer.add(HOOKS_API_USAGE); 2316 if (!compiler.enableMinification) mainBuffer.add(HOOKS_API_USAGE);
2116 mainBuffer.add('function ${namer.isolateName}()$_{}\n'); 2317 mainBuffer.add('function ${namer.isolateName}()$_{}\n');
2117 mainBuffer.add('init()$N$n'); 2318 mainBuffer.add('init()$N$n');
2118 // Shorten the code by using "$$" as temporary. 2319 // Shorten the code by using "$$" as temporary.
2119 classesCollector = r"$$"; 2320 classesCollector = r"$$";
2120 mainBuffer.add('var $classesCollector$_=$_{}$N'); 2321 mainBuffer.add('var $classesCollector$_=$_{}$N');
2121 // Shorten the code by using [namer.CURRENT_ISOLATE] as temporary. 2322 // Shorten the code by using [namer.CURRENT_ISOLATE] as temporary.
2122 isolateProperties = namer.CURRENT_ISOLATE; 2323 isolateProperties = namer.CURRENT_ISOLATE;
2123 mainBuffer.add( 2324 mainBuffer.add(
2124 'var $isolateProperties$_=$_$isolatePropertiesName$N'); 2325 'var $isolateProperties$_=$_$isolatePropertiesName$N');
2125 emitClasses(mainBuffer); 2326 emitClasses(mainBuffer);
2126 mainBuffer.add(boundClosureBuffer); 2327 mainBuffer.add(boundClosureBuffer);
2127 // Clear the buffer, so that we can reuse it for the native classes. 2328 // Clear the buffer, so that we can reuse it for the native classes.
2128 boundClosureBuffer.clear(); 2329 boundClosureBuffer.clear();
2129 emitStaticFunctions(mainBuffer); 2330 emitStaticFunctions(mainBuffer);
2130 emitStaticFunctionGetters(mainBuffer); 2331 emitStaticFunctionGetters(mainBuffer);
2131 // We need to finish the classes before we construct compile time 2332 // We need to finish the classes before we construct compile time
2132 // constants. 2333 // constants.
2133 emitFinishClassesInvocationIfNecessary(mainBuffer); 2334 emitFinishClassesInvocationIfNecessary(mainBuffer);
2134 emitRuntimeClassesAndTests(mainBuffer); 2335 emitRuntimeClassesAndTests(mainBuffer);
2135 emitCompileTimeConstants(mainBuffer); 2336 emitCompileTimeConstants(mainBuffer);
2136 // Static field initializations require the classes and compile-time 2337 // Static field initializations require the classes and compile-time
2137 // constants to be set up. 2338 // constants to be set up.
2138 emitStaticNonFinalFieldInitializations(mainBuffer); 2339 emitStaticNonFinalFieldInitializations(mainBuffer);
2139 emitGetInterceptorMethods(mainBuffer); 2340 emitGetInterceptorMethods(mainBuffer);
2140 emitLazilyInitializedStaticFields(mainBuffer); 2341 emitLazilyInitializedStaticFields(mainBuffer);
2141 2342
2343 if (compiler.hasMirrorsSupport()) {
2344 emitMirrorsSupport(mainBuffer);
2345 }
2346
2142 isolateProperties = isolatePropertiesName; 2347 isolateProperties = isolatePropertiesName;
2143 // The following code should not use the short-hand for the 2348 // The following code should not use the short-hand for the
2144 // initialStatics. 2349 // initialStatics.
2145 mainBuffer.add('var ${namer.CURRENT_ISOLATE}$_=${_}null$N'); 2350 mainBuffer.add('var ${namer.CURRENT_ISOLATE}$_=${_}null$N');
2146 mainBuffer.add(boundClosureBuffer); 2351 mainBuffer.add(boundClosureBuffer);
2147 emitFinishClassesInvocationIfNecessary(mainBuffer); 2352 emitFinishClassesInvocationIfNecessary(mainBuffer);
2148 // After this assignment we will produce invalid JavaScript code if we use 2353 // After this assignment we will produce invalid JavaScript code if we use
2149 // the classesCollector variable. 2354 // the classesCollector variable.
2150 classesCollector = 'classesCollector should not be used from now on'; 2355 classesCollector = 'classesCollector should not be used from now on';
2151 2356
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
2190 """; 2395 """;
2191 const String HOOKS_API_USAGE = """ 2396 const String HOOKS_API_USAGE = """
2192 // The code supports the following hooks: 2397 // The code supports the following hooks:
2193 // dartPrint(message) - if this function is defined it is called 2398 // dartPrint(message) - if this function is defined it is called
2194 // instead of the Dart [print] method. 2399 // instead of the Dart [print] method.
2195 // dartMainRunner(main) - if this function is defined, the Dart [main] 2400 // dartMainRunner(main) - if this function is defined, the Dart [main]
2196 // method will not be invoked directly. 2401 // method will not be invoked directly.
2197 // Instead, a closure that will invoke [main] is 2402 // Instead, a closure that will invoke [main] is
2198 // passed to [dartMainRunner]. 2403 // passed to [dartMainRunner].
2199 """; 2404 """;
OLDNEW
« no previous file with comments | « sdk/lib/_internal/compiler/implementation/enqueue.dart ('k') | sdk/lib/_internal/compiler/implementation/lib/js_helper.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698