| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 dart2js.js_emitter; | 5 part of dart2js.js_emitter; |
| 6 | 6 |
| 7 | 7 |
| 8 class OldEmitter implements Emitter { | 8 class OldEmitter implements Emitter { |
| 9 final Compiler compiler; | 9 final Compiler compiler; |
| 10 final CodeEmitterTask task; | 10 final CodeEmitterTask task; |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 76 * dynamically. This doesn't work in CSP mode, and may impact startup time | 76 * dynamically. This doesn't work in CSP mode, and may impact startup time |
| 77 * negatively. So dart2js will emit these functions to a separate file that | 77 * negatively. So dart2js will emit these functions to a separate file that |
| 78 * can be optionally included to support CSP mode or for faster startup. | 78 * can be optionally included to support CSP mode or for faster startup. |
| 79 */ | 79 */ |
| 80 Map<OutputUnit, List<jsAst.Node>> _cspPrecompiledFunctions = | 80 Map<OutputUnit, List<jsAst.Node>> _cspPrecompiledFunctions = |
| 81 new Map<OutputUnit, List<jsAst.Node>>(); | 81 new Map<OutputUnit, List<jsAst.Node>>(); |
| 82 | 82 |
| 83 Map<OutputUnit, List<jsAst.Expression>> _cspPrecompiledConstructorNames = | 83 Map<OutputUnit, List<jsAst.Expression>> _cspPrecompiledConstructorNames = |
| 84 new Map<OutputUnit, List<jsAst.Expression>>(); | 84 new Map<OutputUnit, List<jsAst.Expression>>(); |
| 85 | 85 |
| 86 // True if Isolate.makeConstantList is needed. | |
| 87 bool hasMakeConstantList = false; | |
| 88 | |
| 89 /** | 86 /** |
| 90 * Accumulate properties for classes and libraries, describing their | 87 * Accumulate properties for classes and libraries, describing their |
| 91 * static/top-level members. | 88 * static/top-level members. |
| 92 * Later, these members are emitted when the class or library is emitted. | 89 * Later, these members are emitted when the class or library is emitted. |
| 93 * | 90 * |
| 94 * For supporting deferred loading we keep one list per output unit. | 91 * See [getElementDescriptor]. |
| 95 * | |
| 96 * See [getElementDecriptor]. | |
| 97 */ | 92 */ |
| 98 // TODO(ahe): Generate statics with their class, and store only libraries in | 93 // TODO(ahe): Generate statics with their class, and store only libraries in |
| 99 // this map. | 94 // this map. |
| 100 final Map<Element, Map<OutputUnit, ClassBuilder>> elementDescriptors | 95 final Map<Element, ClassBuilder> elementDescriptors = |
| 101 = new Map<Element, Map<OutputUnit, ClassBuilder>>(); | 96 new Map<Element, ClassBuilder>(); |
| 102 | 97 |
| 103 final bool generateSourceMap; | 98 final bool generateSourceMap; |
| 104 | 99 |
| 105 OldEmitter(Compiler compiler, Namer namer, this.generateSourceMap, this.task) | 100 OldEmitter(Compiler compiler, Namer namer, this.generateSourceMap, this.task) |
| 106 : this.compiler = compiler, | 101 : this.compiler = compiler, |
| 107 this.namer = namer, | 102 this.namer = namer, |
| 108 constantEmitter = new ConstantEmitter(compiler, namer), | 103 constantEmitter = new ConstantEmitter(compiler, namer), |
| 109 cachedEmittedConstants = compiler.cacheStrategy.newSet(), | 104 cachedEmittedConstants = compiler.cacheStrategy.newSet(), |
| 110 cachedClassBuilders = compiler.cacheStrategy.newMap(), | 105 cachedClassBuilders = compiler.cacheStrategy.newMap(), |
| 111 cachedElements = compiler.cacheStrategy.newSet() { | 106 cachedElements = compiler.cacheStrategy.newSet() { |
| (...skipping 462 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 574 } | 569 } |
| 575 | 570 |
| 576 jsAst.Fun get finishIsolateConstructorFunction { | 571 jsAst.Fun get finishIsolateConstructorFunction { |
| 577 // We replace the old Isolate function with a new one that initializes | 572 // We replace the old Isolate function with a new one that initializes |
| 578 // all its fields with the initial (and often final) value of all globals. | 573 // all its fields with the initial (and often final) value of all globals. |
| 579 // | 574 // |
| 580 // We also copy over old values like the prototype, and the | 575 // We also copy over old values like the prototype, and the |
| 581 // isolateProperties themselves. | 576 // isolateProperties themselves. |
| 582 return js(''' | 577 return js(''' |
| 583 function (oldIsolate) { | 578 function (oldIsolate) { |
| 584 var isolateProperties = oldIsolate.#; | 579 var isolateProperties = oldIsolate.#; // isolatePropertiesName |
| 585 function Isolate() { | 580 function Isolate() { |
| 586 var hasOwnProperty = Object.prototype.hasOwnProperty; | 581 var hasOwnProperty = Object.prototype.hasOwnProperty; |
| 587 for (var staticName in isolateProperties) | 582 for (var staticName in isolateProperties) |
| 588 if (hasOwnProperty.call(isolateProperties, staticName)) | 583 if (hasOwnProperty.call(isolateProperties, staticName)) |
| 589 this[staticName] = isolateProperties[staticName]; | 584 this[staticName] = isolateProperties[staticName]; |
| 590 | 585 |
| 591 // Reset lazy initializers to null. | 586 // Reset lazy initializers to null. |
| 592 // When forcing the object to fast mode (below) v8 will consider | 587 // When forcing the object to fast mode (below) v8 will consider |
| 593 // functions as part the object's map. Since we will change them | 588 // functions as part the object's map. Since we will change them |
| 594 // (after the first call to the getter), we would have a map | 589 // (after the first call to the getter), we would have a map |
| (...skipping 11 matching lines...) Expand all Loading... |
| 606 new ForceEfficientMap(); | 601 new ForceEfficientMap(); |
| 607 | 602 |
| 608 // Now, after being a fast map we can set the lazies again. | 603 // Now, after being a fast map we can set the lazies again. |
| 609 for (var lazyInit in lazies) { | 604 for (var lazyInit in lazies) { |
| 610 var lazyInitName = lazies[lazyInit]; | 605 var lazyInitName = lazies[lazyInit]; |
| 611 this[lazyInitName] = isolateProperties[lazyInitName]; | 606 this[lazyInitName] = isolateProperties[lazyInitName]; |
| 612 } | 607 } |
| 613 } | 608 } |
| 614 Isolate.prototype = oldIsolate.prototype; | 609 Isolate.prototype = oldIsolate.prototype; |
| 615 Isolate.prototype.constructor = Isolate; | 610 Isolate.prototype.constructor = Isolate; |
| 616 Isolate.# = isolateProperties; | 611 Isolate.# = isolateProperties; // isolatePropertiesName |
| 617 if (#) | 612 if (#) // needsDefineClass. |
| 618 Isolate.# = oldIsolate.#; | 613 Isolate.# = oldIsolate.#; // finishClassesProperty * 2 |
| 619 if (#) | 614 if (#) // outputContainsConstantList |
| 620 Isolate.# = oldIsolate.#; | 615 Isolate.# = oldIsolate.#; // makeConstListProperty * 2 |
| 621 return Isolate; | 616 return Isolate; |
| 622 }''', | 617 }''', |
| 623 [namer.isolatePropertiesName, namer.isolatePropertiesName, | 618 [namer.isolatePropertiesName, namer.isolatePropertiesName, |
| 624 needsDefineClass, finishClassesProperty, finishClassesProperty, | 619 needsDefineClass, finishClassesProperty, finishClassesProperty, |
| 625 hasMakeConstantList, makeConstListProperty, makeConstListProperty ]); | 620 task.outputContainsConstantList, |
| 621 makeConstListProperty, makeConstListProperty ]); |
| 626 } | 622 } |
| 627 | 623 |
| 628 jsAst.Fun get lazyInitializerFunction { | 624 jsAst.Fun get lazyInitializerFunction { |
| 629 String isolate = namer.currentIsolate; | 625 String isolate = namer.currentIsolate; |
| 630 jsAst.Expression cyclicThrow = | 626 jsAst.Expression cyclicThrow = |
| 631 namer.elementAccess(backend.getCyclicThrowHelper()); | 627 namer.elementAccess(backend.getCyclicThrowHelper()); |
| 632 jsAst.Expression laziesAccess = | 628 jsAst.Expression laziesAccess = |
| 633 generateEmbeddedGlobalAccess(embeddedNames.LAZIES); | 629 generateEmbeddedGlobalAccess(embeddedNames.LAZIES); |
| 634 | 630 |
| 635 return js(''' | 631 return js(''' |
| (...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 870 if (needsDefineClass) { | 866 if (needsDefineClass) { |
| 871 buffer.write('$finishClassesName($classesCollector,' | 867 buffer.write('$finishClassesName($classesCollector,' |
| 872 '$_$isolateProperties,' | 868 '$_$isolateProperties,' |
| 873 '${_}null)$N'); | 869 '${_}null)$N'); |
| 874 | 870 |
| 875 // Reset the map. | 871 // Reset the map. |
| 876 buffer.write("$classesCollector$_=${_}null$N$n"); | 872 buffer.write("$classesCollector$_=${_}null$N$n"); |
| 877 } | 873 } |
| 878 } | 874 } |
| 879 | 875 |
| 880 void emitStaticFunctions() { | 876 void emitStaticFunctions(List<Element> staticFunctions) { |
| 881 bool isStaticFunction(Element element) => | 877 for (Element element in staticFunctions) { |
| 882 !element.isInstanceMember && !element.isField; | |
| 883 | |
| 884 Iterable<Element> elements = | |
| 885 backend.generatedCode.keys.where(isStaticFunction); | |
| 886 | |
| 887 for (Element element in Elements.sortedByPosition(elements)) { | |
| 888 ClassBuilder builder = new ClassBuilder(element, namer); | 878 ClassBuilder builder = new ClassBuilder(element, namer); |
| 889 containerBuilder.addMember(element, builder); | 879 containerBuilder.addMember(element, builder); |
| 890 getElementDescriptor(element).properties.addAll(builder.properties); | 880 getElementDescriptor(element).properties.addAll(builder.properties); |
| 891 } | 881 } |
| 892 } | 882 } |
| 893 | 883 |
| 894 void emitStaticNonFinalFieldInitializations(CodeBuffer buffer) { | 884 void emitStaticNonFinalFieldInitializations(CodeBuffer buffer) { |
| 895 JavaScriptConstantCompiler handler = backend.constants; | 885 JavaScriptConstantCompiler handler = backend.constants; |
| 896 Iterable<VariableElement> staticNonFinalFields = | 886 Iterable<VariableElement> staticNonFinalFields = |
| 897 handler.getStaticNonFinalFieldsForEmission(); | 887 handler.getStaticNonFinalFieldsForEmission(); |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 990 bool isMainBuffer = buffer == mainBuffer; | 980 bool isMainBuffer = buffer == mainBuffer; |
| 991 if (compiler.hasIncrementalSupport && isMainBuffer) { | 981 if (compiler.hasIncrementalSupport && isMainBuffer) { |
| 992 buffer = cachedEmittedConstantsBuffer; | 982 buffer = cachedEmittedConstantsBuffer; |
| 993 } | 983 } |
| 994 for (ConstantValue constant in constants) { | 984 for (ConstantValue constant in constants) { |
| 995 if (compiler.hasIncrementalSupport && isMainBuffer) { | 985 if (compiler.hasIncrementalSupport && isMainBuffer) { |
| 996 if (cachedEmittedConstants.contains(constant)) continue; | 986 if (cachedEmittedConstants.contains(constant)) continue; |
| 997 cachedEmittedConstants.add(constant); | 987 cachedEmittedConstants.add(constant); |
| 998 } | 988 } |
| 999 String name = namer.constantName(constant); | 989 String name = namer.constantName(constant); |
| 1000 if (constant.isList) emitMakeConstantListIfNotEmitted(buffer); | |
| 1001 jsAst.Expression init = js('#.# = #', | 990 jsAst.Expression init = js('#.# = #', |
| 1002 [namer.globalObjectForConstant(constant), name, | 991 [namer.globalObjectForConstant(constant), name, |
| 1003 constantInitializerExpression(constant)]); | 992 constantInitializerExpression(constant)]); |
| 1004 buffer.write(jsAst.prettyPrint(init, compiler, | 993 buffer.write(jsAst.prettyPrint(init, compiler, |
| 1005 monitor: compiler.dumpInfoTask)); | 994 monitor: compiler.dumpInfoTask)); |
| 1006 buffer.write('$N'); | 995 buffer.write('$N'); |
| 1007 } | 996 } |
| 1008 if (compiler.hasIncrementalSupport && isMainBuffer) { | 997 if (compiler.hasIncrementalSupport && isMainBuffer) { |
| 1009 mainBuffer.add(cachedEmittedConstantsBuffer); | 998 mainBuffer.add(cachedEmittedConstantsBuffer); |
| 1010 } | 999 } |
| 1011 } | 1000 } |
| 1012 | 1001 |
| 1013 void emitMakeConstantListIfNotEmitted(CodeBuffer buffer) { | 1002 void emitMakeConstantList(CodeBuffer buffer) { |
| 1014 if (hasMakeConstantList) return; | |
| 1015 hasMakeConstantList = true; | |
| 1016 buffer.write( | 1003 buffer.write( |
| 1017 jsAst.prettyPrint( | 1004 jsAst.prettyPrint( |
| 1018 js.statement(r'''#.# = function(list) { | 1005 js.statement(r'''#.# = function(list) { |
| 1019 list.immutable$list = #; | 1006 list.immutable$list = #; |
| 1020 list.fixed$length = #; | 1007 list.fixed$length = #; |
| 1021 return list; | 1008 return list; |
| 1022 }''', | 1009 }''', |
| 1023 [namer.isolateName, makeConstListProperty, initName, | 1010 [namer.isolateName, makeConstListProperty, initName, |
| 1024 initName]), | 1011 initName]), |
| 1025 compiler, monitor: compiler.dumpInfoTask)); | 1012 compiler, monitor: compiler.dumpInfoTask)); |
| (...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1213 MyClass.prototype = properties; | 1200 MyClass.prototype = properties; |
| 1214 new MyClass(); | 1201 new MyClass(); |
| 1215 #; | 1202 #; |
| 1216 return properties; | 1203 return properties; |
| 1217 }''', [debugCode]); | 1204 }''', [debugCode]); |
| 1218 | 1205 |
| 1219 mainBuffer.add(jsAst.prettyPrint(convertToFastObject, compiler)); | 1206 mainBuffer.add(jsAst.prettyPrint(convertToFastObject, compiler)); |
| 1220 mainBuffer.add(N); | 1207 mainBuffer.add(N); |
| 1221 } | 1208 } |
| 1222 | 1209 |
| 1223 void writeLibraryDescriptors( | 1210 void writeLibraryDescriptors(CodeBuffer buffer, LibraryElement library) { |
| 1224 LibraryElement library, | |
| 1225 Map<OutputUnit, CodeBuffer> libraryDescriptorBuffers) { | |
| 1226 var uri = ""; | 1211 var uri = ""; |
| 1227 if (!compiler.enableMinification || backend.mustRetainUris) { | 1212 if (!compiler.enableMinification || backend.mustRetainUris) { |
| 1228 uri = library.canonicalUri; | 1213 uri = library.canonicalUri; |
| 1229 if (uri.scheme == 'file' && compiler.outputUri != null) { | 1214 if (uri.scheme == 'file' && compiler.outputUri != null) { |
| 1230 uri = relativize(compiler.outputUri, library.canonicalUri, false); | 1215 uri = relativize(compiler.outputUri, library.canonicalUri, false); |
| 1231 } | 1216 } |
| 1232 } | 1217 } |
| 1233 Map<OutputUnit, ClassBuilder> descriptors = elementDescriptors[library]; | 1218 ClassBuilder descriptor = elementDescriptors[library]; |
| 1219 if (descriptor == null) { |
| 1220 // Nothing of the library was emitted. |
| 1221 // TODO(floitsch): this should not happen. We currently have an example |
| 1222 // with language/prefix6_negative_test.dart where we have an instance |
| 1223 // method without its corresponding class. |
| 1224 return; |
| 1225 } |
| 1226 |
| 1234 String libraryName = | 1227 String libraryName = |
| 1235 (!compiler.enableMinification || backend.mustRetainLibraryNames) ? | 1228 (!compiler.enableMinification || backend.mustRetainLibraryNames) ? |
| 1236 library.getLibraryName() : | 1229 library.getLibraryName() : |
| 1237 ""; | 1230 ""; |
| 1238 | 1231 |
| 1239 for (OutputUnit outputUnit in compiler.deferredLoadTask.allOutputUnits) { | 1232 jsAst.Fun metadata = metadataEmitter.buildMetadataFunction(library); |
| 1240 if (!descriptors.containsKey(outputUnit)) continue; | |
| 1241 | 1233 |
| 1242 ClassBuilder descriptor = descriptors[outputUnit]; | 1234 jsAst.ObjectInitializer initializers = descriptor.toObjectInitializer(); |
| 1243 | 1235 |
| 1244 jsAst.Fun metadata = metadataEmitter.buildMetadataFunction(library); | 1236 compiler.dumpInfoTask.registerElementAst(library, metadata); |
| 1245 | 1237 compiler.dumpInfoTask.registerElementAst(library, initializers); |
| 1246 jsAst.ObjectInitializer initializers = descriptor.toObjectInitializer(); | 1238 buffer |
| 1247 | 1239 ..write('["$libraryName",$_') |
| 1248 CodeBuffer libraryDescriptorBuffer = | 1240 ..write('"${uri}",$_') |
| 1249 libraryDescriptorBuffers.putIfAbsent(outputUnit, | 1241 ..write(metadata == null ? "" : jsAst.prettyPrint(metadata, |
| 1250 () => new CodeBuffer()); | 1242 compiler, |
| 1251 | 1243 monitor: compiler.dumpInfoTask)) |
| 1252 compiler.dumpInfoTask.registerElementAst(library, metadata); | 1244 ..write(',$_') |
| 1253 compiler.dumpInfoTask.registerElementAst(library, initializers); | 1245 ..write(namer.globalObjectFor(library)) |
| 1254 libraryDescriptorBuffer | 1246 ..write(',$_') |
| 1255 ..write('["$libraryName",$_') | 1247 ..write(jsAst.prettyPrint(initializers, |
| 1256 ..write('"${uri}",$_') | 1248 compiler, |
| 1257 ..write(metadata == null ? "" : jsAst.prettyPrint(metadata, | 1249 monitor: compiler.dumpInfoTask)) |
| 1258 compiler, | 1250 ..write(library == compiler.mainApp ? ',${n}1' : "") |
| 1259 monitor: compiler.dumpInfoTask)) | 1251 ..write('],$n'); |
| 1260 ..write(',$_') | |
| 1261 ..write(namer.globalObjectFor(library)) | |
| 1262 ..write(',$_') | |
| 1263 ..write(jsAst.prettyPrint(initializers, | |
| 1264 compiler, | |
| 1265 monitor: compiler.dumpInfoTask)) | |
| 1266 ..write(library == compiler.mainApp ? ',${n}1' : "") | |
| 1267 ..write('],$n'); | |
| 1268 } | |
| 1269 } | 1252 } |
| 1270 | 1253 |
| 1271 void emitPrecompiledConstructor(OutputUnit outputUnit, | 1254 void emitPrecompiledConstructor(OutputUnit outputUnit, |
| 1272 String constructorName, | 1255 String constructorName, |
| 1273 jsAst.Expression constructorAst) { | 1256 jsAst.Expression constructorAst) { |
| 1274 cspPrecompiledFunctionFor(outputUnit).add( | 1257 cspPrecompiledFunctionFor(outputUnit).add( |
| 1275 new jsAst.FunctionDeclaration( | 1258 new jsAst.FunctionDeclaration( |
| 1276 new jsAst.VariableDeclaration(constructorName), constructorAst)); | 1259 new jsAst.VariableDeclaration(constructorName), constructorAst)); |
| 1277 cspPrecompiledFunctionFor(outputUnit).add( | 1260 cspPrecompiledFunctionFor(outputUnit).add( |
| 1278 js.statement(r'''{ | 1261 js.statement(r'''{ |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1302 String outName = outPath.substring(outPath.lastIndexOf('/') + 1); | 1285 String outName = outPath.substring(outPath.lastIndexOf('/') + 1); |
| 1303 String extension = addExtension ? ".part.js" : ""; | 1286 String extension = addExtension ? ".part.js" : ""; |
| 1304 if (outputUnit == compiler.deferredLoadTask.mainOutputUnit) { | 1287 if (outputUnit == compiler.deferredLoadTask.mainOutputUnit) { |
| 1305 return "$outName$extension"; | 1288 return "$outName$extension"; |
| 1306 } else { | 1289 } else { |
| 1307 String name = outputUnit.name; | 1290 String name = outputUnit.name; |
| 1308 return "${outName}_$name$extension"; | 1291 return "${outName}_$name$extension"; |
| 1309 } | 1292 } |
| 1310 } | 1293 } |
| 1311 | 1294 |
| 1312 void emitProgram(Program program) { | 1295 void emitLibraries(Iterable<LibraryElement> libraries) { |
| 1296 if (libraries.isEmpty) return; |
| 1297 |
| 1298 // TODO(karlklose): document what kinds of fields this loop adds to the |
| 1299 // library class builder. |
| 1300 for (LibraryElement element in libraries) { |
| 1301 LibraryElement library = element; |
| 1302 ClassBuilder builder = new ClassBuilder(library, namer); |
| 1303 if (classEmitter.emitFields(library, builder, null, emitStatics: true)) { |
| 1304 jsAst.ObjectInitializer initializer = builder.toObjectInitializer(); |
| 1305 compiler.dumpInfoTask.registerElementAst(builder.element, initializer); |
| 1306 getElementDescriptor(library).properties.addAll(initializer.properties); |
| 1307 } |
| 1308 } |
| 1309 } |
| 1310 |
| 1311 void emitTypedefs() { |
| 1312 OutputUnit mainOutputUnit = compiler.deferredLoadTask.mainOutputUnit; |
| 1313 |
| 1314 // Emit all required typedef declarations into the main output unit. |
| 1315 // TODO(karlklose): unify required classes and typedefs to declarations |
| 1316 // and have builders for each kind. |
| 1317 for (TypedefElement typedef in typedefsNeededForReflection) { |
| 1318 OutputUnit mainUnit = compiler.deferredLoadTask.mainOutputUnit; |
| 1319 LibraryElement library = typedef.library; |
| 1320 // TODO(karlklose): add a TypedefBuilder and move this code there. |
| 1321 DartType type = typedef.alias; |
| 1322 int typeIndex = metadataEmitter.reifyType(type); |
| 1323 String typeReference = |
| 1324 encoding.encodeTypedefFieldDescriptor(typeIndex); |
| 1325 jsAst.Property descriptor = new jsAst.Property( |
| 1326 js.string(namer.classDescriptorProperty), |
| 1327 js.string(typeReference)); |
| 1328 jsAst.Node declaration = new jsAst.ObjectInitializer([descriptor]); |
| 1329 String mangledName = namer.getNameX(typedef); |
| 1330 String reflectionName = getReflectionName(typedef, mangledName); |
| 1331 getElementDescriptor(library) |
| 1332 ..addProperty(mangledName, declaration) |
| 1333 ..addProperty("+$reflectionName", js.string('')); |
| 1334 // Also emit a trivial constructor for CSP mode. |
| 1335 String constructorName = mangledName; |
| 1336 jsAst.Expression constructorAst = js('function() {}'); |
| 1337 emitPrecompiledConstructor(mainOutputUnit, |
| 1338 constructorName, |
| 1339 constructorAst); |
| 1340 } |
| 1341 } |
| 1342 |
| 1343 void emitMangledNames() { |
| 1344 if (!mangledFieldNames.isEmpty) { |
| 1345 var keys = mangledFieldNames.keys.toList(); |
| 1346 keys.sort(); |
| 1347 var properties = []; |
| 1348 for (String key in keys) { |
| 1349 var value = js.string('${mangledFieldNames[key]}'); |
| 1350 properties.add(new jsAst.Property(js.string(key), value)); |
| 1351 } |
| 1352 |
| 1353 jsAst.Expression mangledNamesAccess = |
| 1354 generateEmbeddedGlobalAccess(embeddedNames.MANGLED_NAMES); |
| 1355 var map = new jsAst.ObjectInitializer(properties); |
| 1356 mainBuffer.write( |
| 1357 jsAst.prettyPrint( |
| 1358 js.statement('# = #', [mangledNamesAccess, map]), |
| 1359 compiler, |
| 1360 monitor: compiler.dumpInfoTask)); |
| 1361 if (compiler.enableMinification) { |
| 1362 mainBuffer.write(';'); |
| 1363 } |
| 1364 } |
| 1365 if (!mangledGlobalFieldNames.isEmpty) { |
| 1366 var keys = mangledGlobalFieldNames.keys.toList(); |
| 1367 keys.sort(); |
| 1368 var properties = []; |
| 1369 for (String key in keys) { |
| 1370 var value = js.string('${mangledGlobalFieldNames[key]}'); |
| 1371 properties.add(new jsAst.Property(js.string(key), value)); |
| 1372 } |
| 1373 jsAst.Expression mangledGlobalNamesAccess = |
| 1374 generateEmbeddedGlobalAccess(embeddedNames.MANGLED_GLOBAL_NAMES); |
| 1375 var map = new jsAst.ObjectInitializer(properties); |
| 1376 mainBuffer.write( |
| 1377 jsAst.prettyPrint( |
| 1378 js.statement('# = #', [mangledGlobalNamesAccess, map]), |
| 1379 compiler, |
| 1380 monitor: compiler.dumpInfoTask)); |
| 1381 if (compiler.enableMinification) { |
| 1382 mainBuffer.write(';'); |
| 1383 } |
| 1384 } |
| 1385 } |
| 1386 |
| 1387 void checkEverythingEmitted(Iterable<Element> elements) { |
| 1388 List<Element> pendingStatics; |
| 1389 if (!compiler.hasIncrementalSupport) { |
| 1390 pendingStatics = |
| 1391 Elements.sortedByPosition(elements.where((e) => !e.isLibrary)); |
| 1392 |
| 1393 pendingStatics.forEach((element) => |
| 1394 compiler.reportInfo( |
| 1395 element, MessageKind.GENERIC, {'text': 'Pending statics.'})); |
| 1396 } |
| 1397 |
| 1398 if (pendingStatics != null && !pendingStatics.isEmpty) { |
| 1399 compiler.internalError(pendingStatics.first, |
| 1400 'Pending statics (see above).'); |
| 1401 } |
| 1402 } |
| 1403 |
| 1404 void emitMainOutputUnit(Map<OutputUnit, String> deferredLoadHashes, |
| 1405 CodeBuffer nativeBuffer) { |
| 1313 bool isProgramSplit = compiler.deferredLoadTask.isProgramSplit; | 1406 bool isProgramSplit = compiler.deferredLoadTask.isProgramSplit; |
| 1314 // Maps each output unit to a codebuffers with the library descriptors of | |
| 1315 // the output unit emitted to it. | |
| 1316 Map<OutputUnit, CodeBuffer> libraryDescriptorBuffers = | |
| 1317 new Map<OutputUnit, CodeBuffer>(); | |
| 1318 | |
| 1319 OutputUnit mainOutputUnit = compiler.deferredLoadTask.mainOutputUnit; | 1407 OutputUnit mainOutputUnit = compiler.deferredLoadTask.mainOutputUnit; |
| 1320 | 1408 |
| 1321 mainBuffer.add(buildGeneratedBy()); | 1409 mainBuffer.add(buildGeneratedBy()); |
| 1322 addComment(HOOKS_API_USAGE, mainBuffer); | 1410 addComment(HOOKS_API_USAGE, mainBuffer); |
| 1323 | 1411 |
| 1324 if (isProgramSplit) { | 1412 if (isProgramSplit) { |
| 1325 /// For deferred loading we communicate the initializers via this global | 1413 /// For deferred loading we communicate the initializers via this global |
| 1326 /// variable. The deferred hunks will add their initialization to this. | 1414 /// variable. The deferred hunks will add their initialization to this. |
| 1327 /// The semicolon is important in minified mode, without it the | 1415 /// The semicolon is important in minified mode, without it the |
| 1328 /// following parenthesis looks like a call to the object literal. | 1416 /// following parenthesis looks like a call to the object literal. |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1363 } | 1451 } |
| 1364 | 1452 |
| 1365 mainBuffer.add('function ${namer.isolateName}()$_{}\n'); | 1453 mainBuffer.add('function ${namer.isolateName}()$_{}\n'); |
| 1366 if (isProgramSplit) { | 1454 if (isProgramSplit) { |
| 1367 mainBuffer | 1455 mainBuffer |
| 1368 .write('${globalsHolder}.${namer.isolateName}$_=$_' | 1456 .write('${globalsHolder}.${namer.isolateName}$_=$_' |
| 1369 '${namer.isolateName}$N' | 1457 '${namer.isolateName}$N' |
| 1370 '${globalsHolder}.$initName$_=${_}$initName$N'); | 1458 '${globalsHolder}.$initName$_=${_}$initName$N'); |
| 1371 } | 1459 } |
| 1372 mainBuffer.add('init()$N$n'); | 1460 mainBuffer.add('init()$N$n'); |
| 1373 // Shorten the code by using [namer.currentIsolate] as temporary. | 1461 mainBuffer.add('$isolateProperties$_=$_$isolatePropertiesName$N'); |
| 1374 isolateProperties = namer.currentIsolate; | |
| 1375 mainBuffer.add( | |
| 1376 '$isolateProperties$_=$_$isolatePropertiesName$N'); | |
| 1377 | 1462 |
| 1378 emitStaticFunctions(); | 1463 emitStaticFunctions(task.outputStaticLists[mainOutputUnit]); |
| 1379 | 1464 |
| 1380 // Only output the classesCollector if we actually have any classes. | 1465 // Only output the classesCollector if we actually have any classes. |
| 1381 if (!(nativeClasses.isEmpty && | 1466 if (!(nativeClasses.isEmpty && |
| 1382 compiler.codegenWorld.staticFunctionsNeedingGetter.isEmpty && | 1467 compiler.codegenWorld.staticFunctionsNeedingGetter.isEmpty && |
| 1383 outputClassLists.values.every((classList) => classList.isEmpty) && | 1468 outputClassLists.values.every((classList) => classList.isEmpty) && |
| 1384 typedefsNeededForReflection.isEmpty)) { | 1469 typedefsNeededForReflection.isEmpty)) { |
| 1385 // Shorten the code by using "$$" as temporary. | 1470 // Shorten the code by using "$$" as temporary. |
| 1386 classesCollector = r"$$"; | 1471 classesCollector = r"$$"; |
| 1387 mainBuffer.add('var $classesCollector$_=${_}Object.create(null)$N$n'); | 1472 mainBuffer.add('var $classesCollector$_=${_}Object.create(null)$N$n'); |
| 1388 } | 1473 } |
| 1389 | 1474 |
| 1390 // Emit native classes on [nativeBuffer]. | |
| 1391 final CodeBuffer nativeBuffer = new CodeBuffer(); | |
| 1392 if (!nativeClasses.isEmpty) { | 1475 if (!nativeClasses.isEmpty) { |
| 1393 addComment('Native classes', nativeBuffer); | |
| 1394 addComment('Native classes', mainBuffer); | 1476 addComment('Native classes', mainBuffer); |
| 1395 nativeEmitter.generateNativeClasses(nativeClasses, mainBuffer, | |
| 1396 additionalProperties); | |
| 1397 } | 1477 } |
| 1398 | 1478 |
| 1399 for (List<ClassElement> outputClassList in outputClassLists.values) { | 1479 List<ClassElement> classes = task.outputClassLists[mainOutputUnit]; |
| 1400 for (ClassElement element in outputClassList) { | 1480 if (classes != null) { |
| 1481 for (ClassElement element in classes) { |
| 1401 generateClass(element, getElementDescriptor(element)); | 1482 generateClass(element, getElementDescriptor(element)); |
| 1402 } | 1483 } |
| 1403 } | 1484 } |
| 1404 | 1485 |
| 1405 nativeEmitter.finishGenerateNativeClasses(); | 1486 if (compiler.enableMinification) { |
| 1406 nativeEmitter.assembleCode(nativeBuffer); | 1487 mainBuffer.write(';'); |
| 1488 } |
| 1407 | 1489 |
| 1490 if (elementDescriptors.isNotEmpty) { |
| 1491 Iterable<LibraryElement> libraries = |
| 1492 task.outputLibraryLists[mainOutputUnit]; |
| 1493 if (libraries == null) libraries = []; |
| 1494 emitLibraries(libraries); |
| 1495 emitTypedefs(); |
| 1496 emitMangledNames(); |
| 1408 | 1497 |
| 1409 // After this assignment we will produce invalid JavaScript code if we use | 1498 checkEverythingEmitted(elementDescriptors.keys); |
| 1410 // the classesCollector variable. | |
| 1411 classesCollector = 'classesCollector should not be used from now on'; | |
| 1412 | 1499 |
| 1413 // TODO(sigurdm): Need to check this for each outputUnit. | 1500 CodeBuffer libraryBuffer = new CodeBuffer(); |
| 1414 if (!elementDescriptors.isEmpty) { | 1501 for (LibraryElement library in Elements.sortedByPosition(libraries)) { |
| 1415 var oldClassesCollector = classesCollector; | 1502 writeLibraryDescriptors(libraryBuffer, library); |
| 1416 classesCollector = r"$$"; | 1503 elementDescriptors.remove(library); |
| 1417 if (compiler.enableMinification) { | |
| 1418 mainBuffer.write(';'); | |
| 1419 } | 1504 } |
| 1420 | 1505 |
| 1421 // TODO(karlklose): document what kinds of fields this loop adds to the | |
| 1422 // library class builder. | |
| 1423 for (Element element in elementDescriptors.keys) { | |
| 1424 // TODO(ahe): Should iterate over all libraries. Otherwise, we will | |
| 1425 // not see libraries that only have fields. | |
| 1426 if (element.isLibrary) { | |
| 1427 LibraryElement library = element; | |
| 1428 ClassBuilder builder = new ClassBuilder(library, namer); | |
| 1429 if (classEmitter.emitFields( | |
| 1430 library, builder, null, emitStatics: true)) { | |
| 1431 jsAst.ObjectInitializer initializer = | |
| 1432 builder.toObjectInitializer(); | |
| 1433 compiler.dumpInfoTask.registerElementAst(builder.element, | |
| 1434 initializer); | |
| 1435 getElementDescriptor(library) | |
| 1436 .properties.addAll(initializer.properties); | |
| 1437 } | |
| 1438 } | |
| 1439 } | |
| 1440 | |
| 1441 // Emit all required typedef declarations into the main output unit. | |
| 1442 // TODO(karlklose): unify required classes and typedefs to declarations | |
| 1443 // and have builders for each kind. | |
| 1444 for (TypedefElement typedef in typedefsNeededForReflection) { | |
| 1445 OutputUnit mainUnit = compiler.deferredLoadTask.mainOutputUnit; | |
| 1446 LibraryElement library = typedef.library; | |
| 1447 // TODO(karlklose): add a TypedefBuilder and move this code there. | |
| 1448 DartType type = typedef.alias; | |
| 1449 int typeIndex = metadataEmitter.reifyType(type); | |
| 1450 String typeReference = | |
| 1451 encoding.encodeTypedefFieldDescriptor(typeIndex); | |
| 1452 jsAst.Property descriptor = new jsAst.Property( | |
| 1453 js.string(namer.classDescriptorProperty), | |
| 1454 js.string(typeReference)); | |
| 1455 jsAst.Node declaration = new jsAst.ObjectInitializer([descriptor]); | |
| 1456 String mangledName = namer.getNameX(typedef); | |
| 1457 String reflectionName = getReflectionName(typedef, mangledName); | |
| 1458 getElementDescriptor(library) | |
| 1459 ..addProperty(mangledName, declaration) | |
| 1460 ..addProperty("+$reflectionName", js.string('')); | |
| 1461 // Also emit a trivial constructor for CSP mode. | |
| 1462 String constructorName = mangledName; | |
| 1463 jsAst.Expression constructorAst = js('function() {}'); | |
| 1464 emitPrecompiledConstructor(mainOutputUnit, | |
| 1465 constructorName, | |
| 1466 constructorAst); | |
| 1467 } | |
| 1468 | |
| 1469 if (!mangledFieldNames.isEmpty) { | |
| 1470 var keys = mangledFieldNames.keys.toList(); | |
| 1471 keys.sort(); | |
| 1472 var properties = []; | |
| 1473 for (String key in keys) { | |
| 1474 var value = js.string('${mangledFieldNames[key]}'); | |
| 1475 properties.add(new jsAst.Property(js.string(key), value)); | |
| 1476 } | |
| 1477 | |
| 1478 jsAst.Expression mangledNamesAccess = | |
| 1479 generateEmbeddedGlobalAccess(embeddedNames.MANGLED_NAMES); | |
| 1480 var map = new jsAst.ObjectInitializer(properties); | |
| 1481 mainBuffer.write( | |
| 1482 jsAst.prettyPrint( | |
| 1483 js.statement('# = #', [mangledNamesAccess, map]), | |
| 1484 compiler, | |
| 1485 monitor: compiler.dumpInfoTask)); | |
| 1486 if (compiler.enableMinification) { | |
| 1487 mainBuffer.write(';'); | |
| 1488 } | |
| 1489 } | |
| 1490 if (!mangledGlobalFieldNames.isEmpty) { | |
| 1491 var keys = mangledGlobalFieldNames.keys.toList(); | |
| 1492 keys.sort(); | |
| 1493 var properties = []; | |
| 1494 for (String key in keys) { | |
| 1495 var value = js.string('${mangledGlobalFieldNames[key]}'); | |
| 1496 properties.add(new jsAst.Property(js.string(key), value)); | |
| 1497 } | |
| 1498 jsAst.Expression mangledGlobalNamesAccess = | |
| 1499 generateEmbeddedGlobalAccess(embeddedNames.MANGLED_GLOBAL_NAMES); | |
| 1500 var map = new jsAst.ObjectInitializer(properties); | |
| 1501 mainBuffer.write( | |
| 1502 jsAst.prettyPrint( | |
| 1503 js.statement('# = #', [mangledGlobalNamesAccess, map]), | |
| 1504 compiler, | |
| 1505 monitor: compiler.dumpInfoTask)); | |
| 1506 if (compiler.enableMinification) { | |
| 1507 mainBuffer.write(';'); | |
| 1508 } | |
| 1509 } | |
| 1510 | |
| 1511 List<Element> sortedElements = | |
| 1512 Elements.sortedByPosition(elementDescriptors.keys); | |
| 1513 | |
| 1514 Iterable<Element> pendingStatics; | |
| 1515 if (!compiler.hasIncrementalSupport) { | |
| 1516 pendingStatics = sortedElements.where((element) { | |
| 1517 return !element.isLibrary && | |
| 1518 elementDescriptors[element].values.any((descriptor) => | |
| 1519 descriptor != null); | |
| 1520 }); | |
| 1521 | |
| 1522 pendingStatics.forEach((element) => | |
| 1523 compiler.reportInfo( | |
| 1524 element, MessageKind.GENERIC, {'text': 'Pending statics.'})); | |
| 1525 } | |
| 1526 | |
| 1527 for (LibraryElement library in sortedElements.where((element) => | |
| 1528 element.isLibrary)) { | |
| 1529 writeLibraryDescriptors(library, libraryDescriptorBuffers); | |
| 1530 elementDescriptors[library] = const {}; | |
| 1531 } | |
| 1532 if (pendingStatics != null && !pendingStatics.isEmpty) { | |
| 1533 compiler.internalError(pendingStatics.first, | |
| 1534 'Pending statics (see above).'); | |
| 1535 } | |
| 1536 mainBuffer | 1506 mainBuffer |
| 1537 ..write('(') | 1507 ..write('(') |
| 1538 ..write( | 1508 ..write( |
| 1539 jsAst.prettyPrint( | 1509 jsAst.prettyPrint( |
| 1540 getReflectionDataParser(classesCollector, backend), | 1510 getReflectionDataParser(classesCollector, backend), |
| 1541 compiler)) | 1511 compiler)) |
| 1542 ..write(')') | 1512 ..write(')') |
| 1543 ..write('([$n') | 1513 ..write('([$n') |
| 1544 ..add(libraryDescriptorBuffers[mainOutputUnit]) | 1514 ..add(libraryBuffer) |
| 1545 ..write('])$N'); | 1515 ..write('])$N'); |
| 1546 | 1516 |
| 1547 emitFinishClassesInvocationIfNecessary(mainBuffer); | 1517 emitFinishClassesInvocationIfNecessary(mainBuffer); |
| 1548 classesCollector = oldClassesCollector; | |
| 1549 } | 1518 } |
| 1519 |
| 1550 typeTestEmitter.emitRuntimeTypeSupport(mainBuffer, mainOutputUnit); | 1520 typeTestEmitter.emitRuntimeTypeSupport(mainBuffer, mainOutputUnit); |
| 1551 interceptorEmitter.emitGetInterceptorMethods(mainBuffer); | 1521 interceptorEmitter.emitGetInterceptorMethods(mainBuffer); |
| 1552 interceptorEmitter.emitOneShotInterceptors(mainBuffer); | 1522 interceptorEmitter.emitOneShotInterceptors(mainBuffer); |
| 1523 |
| 1524 if (task.outputContainsConstantList) { |
| 1525 emitMakeConstantList(mainBuffer); |
| 1526 } |
| 1527 |
| 1553 // Constants in checked mode call into RTI code to set type information | 1528 // Constants in checked mode call into RTI code to set type information |
| 1554 // which may need getInterceptor (and one-shot interceptor) methods, so | 1529 // which may need getInterceptor (and one-shot interceptor) methods, so |
| 1555 // we have to make sure that [emitGetInterceptorMethods] and | 1530 // we have to make sure that [emitGetInterceptorMethods] and |
| 1556 // [emitOneShotInterceptors] have been called. | 1531 // [emitOneShotInterceptors] have been called. |
| 1557 emitCompileTimeConstants(mainBuffer, mainOutputUnit); | 1532 emitCompileTimeConstants(mainBuffer, mainOutputUnit); |
| 1558 | 1533 |
| 1559 if (isProgramSplit) { | 1534 emitDeferredBoilerPlate(mainBuffer, deferredLoadHashes); |
| 1560 /// Map from OutputUnit to a hash of its content. The hash uniquely | |
| 1561 /// identifies the code of the output-unit. It does not include | |
| 1562 /// boilerplate JS code, like the sourcemap directives or the hash | |
| 1563 /// itself. | |
| 1564 Map<OutputUnit, String> deferredLoadHashes = | |
| 1565 emitDeferredCode(libraryDescriptorBuffers); | |
| 1566 emitDeferredBoilerPlate(mainBuffer, deferredLoadHashes); | |
| 1567 } | |
| 1568 | 1535 |
| 1569 // Static field initializations require the classes and compile-time | 1536 // Static field initializations require the classes and compile-time |
| 1570 // constants to be set up. | 1537 // constants to be set up. |
| 1571 emitStaticNonFinalFieldInitializations(mainBuffer); | 1538 emitStaticNonFinalFieldInitializations(mainBuffer); |
| 1572 interceptorEmitter.emitInterceptedNames(mainBuffer); | 1539 interceptorEmitter.emitInterceptedNames(mainBuffer); |
| 1573 interceptorEmitter.emitMapTypeToInterceptor(mainBuffer); | 1540 interceptorEmitter.emitMapTypeToInterceptor(mainBuffer); |
| 1574 emitLazilyInitializedStaticFields(mainBuffer); | 1541 emitLazilyInitializedStaticFields(mainBuffer); |
| 1575 | 1542 |
| 1543 mainBuffer.writeln(); |
| 1576 mainBuffer.add(nativeBuffer); | 1544 mainBuffer.add(nativeBuffer); |
| 1577 | 1545 |
| 1578 metadataEmitter.emitMetadata(mainBuffer); | 1546 metadataEmitter.emitMetadata(mainBuffer); |
| 1579 | 1547 |
| 1580 isolateProperties = isolatePropertiesName; | 1548 isolateProperties = isolatePropertiesName; |
| 1581 // The following code should not use the short-hand for the | 1549 // The following code should not use the short-hand for the |
| 1582 // initialStatics. | 1550 // initialStatics. |
| 1583 mainBuffer.add('${namer.currentIsolate}$_=${_}null$N'); | 1551 mainBuffer.add('${namer.currentIsolate}$_=${_}null$N'); |
| 1584 | 1552 |
| 1585 emitFinishIsolateConstructorInvocation(mainBuffer); | 1553 emitFinishIsolateConstructorInvocation(mainBuffer); |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1679 | 1647 |
| 1680 cspBuffer.write( | 1648 cspBuffer.write( |
| 1681 jsAst.prettyPrint( | 1649 jsAst.prettyPrint( |
| 1682 precompiledFunctionAst, compiler, | 1650 precompiledFunctionAst, compiler, |
| 1683 allowVariableMinification: false).getText()); | 1651 allowVariableMinification: false).getText()); |
| 1684 | 1652 |
| 1685 compiler.outputProvider('', 'precompiled.js') | 1653 compiler.outputProvider('', 'precompiled.js') |
| 1686 ..add(cspBuffer.getText()) | 1654 ..add(cspBuffer.getText()) |
| 1687 ..close(); | 1655 ..close(); |
| 1688 } | 1656 } |
| 1657 } |
| 1658 |
| 1659 /// Returns a map from OutputUnit to a hash of its content. The hash uniquely |
| 1660 /// identifies the code of the output-unit. It does not include |
| 1661 /// boilerplate JS code, like the sourcemap directives or the hash |
| 1662 /// itself. |
| 1663 Map<OutputUnit, String> emitDeferredOutputUnits() { |
| 1664 if (!compiler.deferredLoadTask.isProgramSplit) return const {}; |
| 1665 |
| 1666 Map<OutputUnit, CodeBuffer> outputBuffers = |
| 1667 new Map<OutputUnit, CodeBuffer>(); |
| 1668 |
| 1669 for (OutputUnit outputUnit in compiler.deferredLoadTask.allOutputUnits) { |
| 1670 if (outputUnit == compiler.deferredLoadTask.mainOutputUnit) continue; |
| 1671 |
| 1672 List<Element> functions = task.outputStaticLists[outputUnit]; |
| 1673 if (functions != null) { |
| 1674 emitStaticFunctions(functions); |
| 1675 } |
| 1676 |
| 1677 List<ClassElement> classes = task.outputClassLists[outputUnit]; |
| 1678 if (classes != null) { |
| 1679 for (ClassElement element in classes) { |
| 1680 generateClass(element, getElementDescriptor(element)); |
| 1681 } |
| 1682 } |
| 1683 |
| 1684 if (elementDescriptors.isNotEmpty) { |
| 1685 Iterable<LibraryElement> libraries = |
| 1686 task.outputLibraryLists[outputUnit]; |
| 1687 if (libraries == null) libraries = []; |
| 1688 emitLibraries(libraries); |
| 1689 |
| 1690 CodeBuffer buffer = new CodeBuffer(); |
| 1691 outputBuffers[outputUnit] = buffer; |
| 1692 for (LibraryElement library in Elements.sortedByPosition(libraries)) { |
| 1693 writeLibraryDescriptors(buffer, library); |
| 1694 elementDescriptors.remove(library); |
| 1695 } |
| 1696 } |
| 1697 } |
| 1698 |
| 1699 return emitDeferredCode(outputBuffers); |
| 1700 } |
| 1701 |
| 1702 CodeBuffer buildNativesBuffer() { |
| 1703 // Emit native classes on [nativeBuffer]. |
| 1704 final CodeBuffer nativeBuffer = new CodeBuffer(); |
| 1705 |
| 1706 if (nativeClasses.isEmpty) return nativeBuffer; |
| 1707 |
| 1708 |
| 1709 addComment('Native classes', nativeBuffer); |
| 1710 |
| 1711 nativeEmitter.generateNativeClasses(nativeClasses, mainBuffer, |
| 1712 additionalProperties); |
| 1713 |
| 1714 nativeEmitter.finishGenerateNativeClasses(); |
| 1715 nativeEmitter.assembleCode(nativeBuffer); |
| 1716 |
| 1717 return nativeBuffer; |
| 1718 } |
| 1719 |
| 1720 void emitProgram(Program program) { |
| 1721 // Shorten the code by using [namer.currentIsolate] as temporary. |
| 1722 isolateProperties = namer.currentIsolate; |
| 1723 |
| 1724 classesCollector = r"$$"; |
| 1725 |
| 1726 // Emit deferred units first, so we have their hashes. |
| 1727 // Map from OutputUnit to a hash of its content. The hash uniquely |
| 1728 // identifies the code of the output-unit. It does not include |
| 1729 // boilerplate JS code, like the sourcemap directives or the hash |
| 1730 // itself. |
| 1731 Map<OutputUnit, String> deferredLoadHashes = emitDeferredOutputUnits(); |
| 1732 CodeBuffer nativeBuffer = buildNativesBuffer(); |
| 1733 emitMainOutputUnit(deferredLoadHashes, nativeBuffer); |
| 1689 | 1734 |
| 1690 if (backend.requiresPreamble && | 1735 if (backend.requiresPreamble && |
| 1691 !backend.htmlLibraryIsLoaded) { | 1736 !backend.htmlLibraryIsLoaded) { |
| 1692 compiler.reportHint(NO_LOCATION_SPANNABLE, MessageKind.PREAMBLE); | 1737 compiler.reportHint(NO_LOCATION_SPANNABLE, MessageKind.PREAMBLE); |
| 1693 } | 1738 } |
| 1694 } | 1739 } |
| 1695 | 1740 |
| 1696 String generateSourceMapTag(Uri sourceMapUri, Uri fileUri) { | 1741 String generateSourceMapTag(Uri sourceMapUri, Uri fileUri) { |
| 1697 if (sourceMapUri != null && fileUri != null) { | 1742 if (sourceMapUri != null && fileUri != null) { |
| 1698 String sourceMapFileName = relativize(fileUri, sourceMapUri, false); | 1743 String sourceMapFileName = relativize(fileUri, sourceMapUri, false); |
| 1699 return ''' | 1744 return ''' |
| 1700 | 1745 |
| 1701 //# sourceMappingURL=$sourceMapFileName | 1746 //# sourceMappingURL=$sourceMapFileName |
| 1702 '''; | 1747 '''; |
| 1703 } | 1748 } |
| 1704 return ''; | 1749 return ''; |
| 1705 } | 1750 } |
| 1706 | 1751 |
| 1707 ClassBuilder getElementDescriptorForOutputUnit(Element element, | |
| 1708 OutputUnit outputUnit) { | |
| 1709 Map<OutputUnit, ClassBuilder> descriptors = | |
| 1710 elementDescriptors.putIfAbsent( | |
| 1711 element, () => new Map<OutputUnit, ClassBuilder>()); | |
| 1712 return descriptors.putIfAbsent(outputUnit, | |
| 1713 () => new ClassBuilder(element, namer)); | |
| 1714 } | |
| 1715 | |
| 1716 ClassBuilder getElementDescriptor(Element element) { | 1752 ClassBuilder getElementDescriptor(Element element) { |
| 1717 Element owner = element.library; | 1753 Element owner = element.library; |
| 1718 if (!element.isLibrary && !element.isTopLevel && !element.isNative) { | 1754 if (!element.isLibrary && !element.isTopLevel && !element.isNative) { |
| 1719 // For static (not top level) elements, record their code in a buffer | 1755 // For static (not top level) elements, record their code in a buffer |
| 1720 // specific to the class. For now, not supported for native classes and | 1756 // specific to the class. For now, not supported for native classes and |
| 1721 // native elements. | 1757 // native elements. |
| 1722 ClassElement cls = | 1758 ClassElement cls = |
| 1723 element.enclosingClassOrCompilationUnit.declaration; | 1759 element.enclosingClassOrCompilationUnit.declaration; |
| 1724 if (compiler.codegenWorld.directlyInstantiatedClasses.contains(cls) | 1760 if (compiler.codegenWorld.directlyInstantiatedClasses.contains(cls) |
| 1725 && !cls.isNative) { | 1761 && !cls.isNative) { |
| 1726 owner = cls; | 1762 owner = cls; |
| 1727 } | 1763 } |
| 1728 } | 1764 } |
| 1729 if (owner == null) { | 1765 if (owner == null) { |
| 1730 compiler.internalError(element, 'Owner is null.'); | 1766 compiler.internalError(element, 'Owner is null.'); |
| 1731 } | 1767 } |
| 1732 return getElementDescriptorForOutputUnit(owner, | 1768 return elementDescriptors.putIfAbsent( |
| 1733 compiler.deferredLoadTask.outputUnitForElement(element)); | 1769 owner, |
| 1770 () => new ClassBuilder(owner, namer)); |
| 1734 } | 1771 } |
| 1735 | 1772 |
| 1736 /// Emits support-code for deferred loading into [buffer]. | 1773 /// Emits support-code for deferred loading into [buffer]. |
| 1737 void emitDeferredBoilerPlate(CodeBuffer buffer, | 1774 void emitDeferredBoilerPlate(CodeBuffer buffer, |
| 1738 Map<OutputUnit, String> deferredLoadHashes) { | 1775 Map<OutputUnit, String> deferredLoadHashes) { |
| 1739 // Function for checking if a hunk is loaded given its hash. | 1776 // Function for checking if a hunk is loaded given its hash. |
| 1740 buffer.write(jsAst.prettyPrint( | 1777 buffer.write(jsAst.prettyPrint( |
| 1741 js('# = function(hunkHash) {' | 1778 js('# = function(hunkHash) {' |
| 1742 ' return !!$deferredInitializers[hunkHash];' | 1779 ' return !!$deferredInitializers[hunkHash];' |
| 1743 '}', generateEmbeddedGlobalAccess(embeddedNames.IS_HUNK_LOADED)), | 1780 '}', generateEmbeddedGlobalAccess(embeddedNames.IS_HUNK_LOADED)), |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1795 | 1832 |
| 1796 emitMapping(embeddedNames.DEFERRED_LIBRARY_URIS, deferredLibraryUris); | 1833 emitMapping(embeddedNames.DEFERRED_LIBRARY_URIS, deferredLibraryUris); |
| 1797 emitMapping(embeddedNames.DEFERRED_LIBRARY_HASHES, | 1834 emitMapping(embeddedNames.DEFERRED_LIBRARY_HASHES, |
| 1798 deferredLibraryHashes); | 1835 deferredLibraryHashes); |
| 1799 } | 1836 } |
| 1800 | 1837 |
| 1801 /// Emits code for all output units except the main. | 1838 /// Emits code for all output units except the main. |
| 1802 /// Returns a mapping from outputUnit to a hash of the corresponding hunk that | 1839 /// Returns a mapping from outputUnit to a hash of the corresponding hunk that |
| 1803 /// can be used for calling the initializer. | 1840 /// can be used for calling the initializer. |
| 1804 Map<OutputUnit, String> emitDeferredCode( | 1841 Map<OutputUnit, String> emitDeferredCode( |
| 1805 Map<OutputUnit, CodeBuffer> libraryDescriptorBuffers) { | 1842 Map<OutputUnit, CodeBuffer> deferredBuffers) { |
| 1806 | 1843 |
| 1807 Map<OutputUnit, String> hunkHashes = new Map<OutputUnit, String>(); | 1844 Map<OutputUnit, String> hunkHashes = new Map<OutputUnit, String>(); |
| 1808 | 1845 |
| 1809 for (OutputUnit outputUnit in compiler.deferredLoadTask.allOutputUnits) { | 1846 for (OutputUnit outputUnit in compiler.deferredLoadTask.allOutputUnits) { |
| 1810 if (outputUnit == compiler.deferredLoadTask.mainOutputUnit) continue; | 1847 if (outputUnit == compiler.deferredLoadTask.mainOutputUnit) continue; |
| 1811 | 1848 |
| 1812 CodeBuffer libraryDescriptorBuffer = libraryDescriptorBuffers[outputUnit]; | 1849 CodeBuffer libraryDescriptorBuffer = deferredBuffers[outputUnit]; |
| 1813 | 1850 |
| 1814 CodeBuffer outputBuffer = new CodeBuffer(); | 1851 CodeBuffer outputBuffer = new CodeBuffer(); |
| 1815 | 1852 |
| 1816 var oldClassesCollector = classesCollector; | |
| 1817 classesCollector = r"$$"; | |
| 1818 | |
| 1819 outputBuffer..write(buildGeneratedBy()) | 1853 outputBuffer..write(buildGeneratedBy()) |
| 1820 ..write('${deferredInitializers}.current$_=$_' | 1854 ..write('${deferredInitializers}.current$_=$_' |
| 1821 'function$_(${globalsHolder}) {$N'); | 1855 'function$_(${globalsHolder}) {$N'); |
| 1822 for (String globalObject in Namer.reservedGlobalObjectNames) { | 1856 for (String globalObject in Namer.reservedGlobalObjectNames) { |
| 1823 outputBuffer | 1857 outputBuffer |
| 1824 .write('var $globalObject$_=$_' | 1858 .write('var $globalObject$_=$_' |
| 1825 '${globalsHolder}.$globalObject$N'); | 1859 '${globalsHolder}.$globalObject$N'); |
| 1826 } | 1860 } |
| 1827 outputBuffer | 1861 outputBuffer |
| 1828 ..write('var init$_=$_${globalsHolder}.init$N') | 1862 ..write('var init$_=$_${globalsHolder}.init$N') |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1848 ..write('])$N'); | 1882 ..write('])$N'); |
| 1849 | 1883 |
| 1850 if (outputClassLists.containsKey(outputUnit)) { | 1884 if (outputClassLists.containsKey(outputUnit)) { |
| 1851 outputBuffer.write( | 1885 outputBuffer.write( |
| 1852 '$finishClassesName($classesCollector,$_${namer.currentIsolate},' | 1886 '$finishClassesName($classesCollector,$_${namer.currentIsolate},' |
| 1853 '$_$isolatePropertiesName)$N'); | 1887 '$_$isolatePropertiesName)$N'); |
| 1854 } | 1888 } |
| 1855 | 1889 |
| 1856 } | 1890 } |
| 1857 | 1891 |
| 1858 classesCollector = oldClassesCollector; | |
| 1859 | |
| 1860 // Set the currentIsolate variable to the current isolate (which is | 1892 // Set the currentIsolate variable to the current isolate (which is |
| 1861 // provided as second argument). | 1893 // provided as second argument). |
| 1862 // We need to do this, because we use the same variable for setting up | 1894 // We need to do this, because we use the same variable for setting up |
| 1863 // the isolate-properties and for storing the current isolate. During | 1895 // the isolate-properties and for storing the current isolate. During |
| 1864 // the setup (the code above this lines) we must set the variable to | 1896 // the setup (the code above this lines) we must set the variable to |
| 1865 // the isolate-properties. | 1897 // the isolate-properties. |
| 1866 // After we have done the setup (finishing with `finishClasses`) it must | 1898 // After we have done the setup (finishing with `finishClasses`) it must |
| 1867 // point to the current Isolate. Otherwise all methods/functions | 1899 // point to the current Isolate. Otherwise all methods/functions |
| 1868 // accessing isolate variables will access the wrong object. | 1900 // accessing isolate variables will access the wrong object. |
| 1869 outputBuffer.write("${namer.currentIsolate}$_=${_}arguments[1]$N"); | 1901 outputBuffer.write("${namer.currentIsolate}$_=${_}arguments[1]$N"); |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1955 for (Element element in compiler.enqueuer.codegen.newlyEnqueuedElements) { | 1987 for (Element element in compiler.enqueuer.codegen.newlyEnqueuedElements) { |
| 1956 if (element.isInstanceMember) { | 1988 if (element.isInstanceMember) { |
| 1957 cachedClassBuilders.remove(element.enclosingClass); | 1989 cachedClassBuilders.remove(element.enclosingClass); |
| 1958 | 1990 |
| 1959 nativeEmitter.cachedBuilders.remove(element.enclosingClass); | 1991 nativeEmitter.cachedBuilders.remove(element.enclosingClass); |
| 1960 | 1992 |
| 1961 } | 1993 } |
| 1962 } | 1994 } |
| 1963 } | 1995 } |
| 1964 } | 1996 } |
| OLD | NEW |