Chromium Code Reviews| 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 |
|
Johnni Winther
2014/10/16 08:04:50
Maybe we should change [js] to take a map of argum
floitsch
2014/10/16 11:53:36
Thought the same thing.
I might look into this lat
| |
| 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 CodeBuffer libraryDescriptorBuffer = buffer; |
|
Johnni Winther
2014/10/16 08:04:50
Remove and use [buffer] below.
floitsch
2014/10/16 11:53:36
Was to make diff easier. Wasn't really worth it...
| |
| 1245 | 1237 |
| 1246 jsAst.ObjectInitializer initializers = descriptor.toObjectInitializer(); | 1238 compiler.dumpInfoTask.registerElementAst(library, metadata); |
| 1247 | 1239 compiler.dumpInfoTask.registerElementAst(library, initializers); |
| 1248 CodeBuffer libraryDescriptorBuffer = | 1240 libraryDescriptorBuffer |
| 1249 libraryDescriptorBuffers.putIfAbsent(outputUnit, | 1241 ..write('["$libraryName",$_') |
| 1250 () => new CodeBuffer()); | 1242 ..write('"${uri}",$_') |
| 1251 | 1243 ..write(metadata == null ? "" : jsAst.prettyPrint(metadata, |
| 1252 compiler.dumpInfoTask.registerElementAst(library, metadata); | 1244 compiler, |
| 1253 compiler.dumpInfoTask.registerElementAst(library, initializers); | 1245 monitor: compiler.dumpInfoTask)) |
| 1254 libraryDescriptorBuffer | 1246 ..write(',$_') |
| 1255 ..write('["$libraryName",$_') | 1247 ..write(namer.globalObjectFor(library)) |
| 1256 ..write('"${uri}",$_') | 1248 ..write(',$_') |
| 1257 ..write(metadata == null ? "" : jsAst.prettyPrint(metadata, | 1249 ..write(jsAst.prettyPrint(initializers, |
| 1258 compiler, | 1250 compiler, |
| 1259 monitor: compiler.dumpInfoTask)) | 1251 monitor: compiler.dumpInfoTask)) |
| 1260 ..write(',$_') | 1252 ..write(library == compiler.mainApp ? ',${n}1' : "") |
| 1261 ..write(namer.globalObjectFor(library)) | 1253 ..write('],$n'); |
| 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 } | 1254 } |
| 1270 | 1255 |
| 1271 void emitPrecompiledConstructor(OutputUnit outputUnit, | 1256 void emitPrecompiledConstructor(OutputUnit outputUnit, |
| 1272 String constructorName, | 1257 String constructorName, |
| 1273 jsAst.Expression constructorAst) { | 1258 jsAst.Expression constructorAst) { |
| 1274 cspPrecompiledFunctionFor(outputUnit).add( | 1259 cspPrecompiledFunctionFor(outputUnit).add( |
| 1275 new jsAst.FunctionDeclaration( | 1260 new jsAst.FunctionDeclaration( |
| 1276 new jsAst.VariableDeclaration(constructorName), constructorAst)); | 1261 new jsAst.VariableDeclaration(constructorName), constructorAst)); |
| 1277 cspPrecompiledFunctionFor(outputUnit).add( | 1262 cspPrecompiledFunctionFor(outputUnit).add( |
| 1278 js.statement(r'''{ | 1263 js.statement(r'''{ |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 1302 String outName = outPath.substring(outPath.lastIndexOf('/') + 1); | 1287 String outName = outPath.substring(outPath.lastIndexOf('/') + 1); |
| 1303 String extension = addExtension ? ".part.js" : ""; | 1288 String extension = addExtension ? ".part.js" : ""; |
| 1304 if (outputUnit == compiler.deferredLoadTask.mainOutputUnit) { | 1289 if (outputUnit == compiler.deferredLoadTask.mainOutputUnit) { |
| 1305 return "$outName$extension"; | 1290 return "$outName$extension"; |
| 1306 } else { | 1291 } else { |
| 1307 String name = outputUnit.name; | 1292 String name = outputUnit.name; |
| 1308 return "${outName}_$name$extension"; | 1293 return "${outName}_$name$extension"; |
| 1309 } | 1294 } |
| 1310 } | 1295 } |
| 1311 | 1296 |
| 1312 void emitProgram(Program program) { | 1297 void emitLibraries(Iterable<LibraryElement> libraries) { |
| 1298 if (libraries.isEmpty) return; | |
| 1299 | |
| 1300 // TODO(karlklose): document what kinds of fields this loop adds to the | |
| 1301 // library class builder. | |
| 1302 for (LibraryElement element in libraries) { | |
| 1303 LibraryElement library = element; | |
| 1304 ClassBuilder builder = new ClassBuilder(library, namer); | |
| 1305 if (classEmitter.emitFields( | |
| 1306 library, builder, null, emitStatics: true)) { | |
| 1307 jsAst.ObjectInitializer initializer = | |
| 1308 builder.toObjectInitializer(); | |
|
Johnni Winther
2014/10/16 08:04:50
Indent by 4.
floitsch
2014/10/16 11:53:36
All the statements here actually fit on one line.
| |
| 1309 compiler.dumpInfoTask.registerElementAst(builder.element, | |
| 1310 initializer); | |
| 1311 getElementDescriptor(library) | |
| 1312 .properties.addAll(initializer.properties); | |
| 1313 } | |
| 1314 } | |
| 1315 } | |
| 1316 | |
| 1317 void emitTypedefs() { | |
| 1318 OutputUnit mainOutputUnit = compiler.deferredLoadTask.mainOutputUnit; | |
| 1319 | |
| 1320 // Emit all required typedef declarations into the main output unit. | |
| 1321 // TODO(karlklose): unify required classes and typedefs to declarations | |
| 1322 // and have builders for each kind. | |
| 1323 for (TypedefElement typedef in typedefsNeededForReflection) { | |
| 1324 OutputUnit mainUnit = compiler.deferredLoadTask.mainOutputUnit; | |
| 1325 LibraryElement library = typedef.library; | |
| 1326 // TODO(karlklose): add a TypedefBuilder and move this code there. | |
| 1327 DartType type = typedef.alias; | |
| 1328 int typeIndex = metadataEmitter.reifyType(type); | |
| 1329 String typeReference = | |
| 1330 encoding.encodeTypedefFieldDescriptor(typeIndex); | |
| 1331 jsAst.Property descriptor = new jsAst.Property( | |
| 1332 js.string(namer.classDescriptorProperty), | |
| 1333 js.string(typeReference)); | |
| 1334 jsAst.Node declaration = new jsAst.ObjectInitializer([descriptor]); | |
| 1335 String mangledName = namer.getNameX(typedef); | |
| 1336 String reflectionName = getReflectionName(typedef, mangledName); | |
| 1337 getElementDescriptor(library) | |
| 1338 ..addProperty(mangledName, declaration) | |
| 1339 ..addProperty("+$reflectionName", js.string('')); | |
| 1340 // Also emit a trivial constructor for CSP mode. | |
| 1341 String constructorName = mangledName; | |
| 1342 jsAst.Expression constructorAst = js('function() {}'); | |
| 1343 emitPrecompiledConstructor(mainOutputUnit, | |
| 1344 constructorName, | |
| 1345 constructorAst); | |
| 1346 } | |
| 1347 } | |
| 1348 | |
| 1349 void emitMangledNames() { | |
| 1350 if (!mangledFieldNames.isEmpty) { | |
| 1351 var keys = mangledFieldNames.keys.toList(); | |
| 1352 keys.sort(); | |
| 1353 var properties = []; | |
| 1354 for (String key in keys) { | |
| 1355 var value = js.string('${mangledFieldNames[key]}'); | |
| 1356 properties.add(new jsAst.Property(js.string(key), value)); | |
| 1357 } | |
| 1358 | |
| 1359 jsAst.Expression mangledNamesAccess = | |
| 1360 generateEmbeddedGlobalAccess(embeddedNames.MANGLED_NAMES); | |
| 1361 var map = new jsAst.ObjectInitializer(properties); | |
| 1362 mainBuffer.write( | |
| 1363 jsAst.prettyPrint( | |
| 1364 js.statement('# = #', [mangledNamesAccess, map]), | |
| 1365 compiler, | |
| 1366 monitor: compiler.dumpInfoTask)); | |
| 1367 if (compiler.enableMinification) { | |
| 1368 mainBuffer.write(';'); | |
| 1369 } | |
| 1370 } | |
| 1371 if (!mangledGlobalFieldNames.isEmpty) { | |
| 1372 var keys = mangledGlobalFieldNames.keys.toList(); | |
| 1373 keys.sort(); | |
| 1374 var properties = []; | |
| 1375 for (String key in keys) { | |
| 1376 var value = js.string('${mangledGlobalFieldNames[key]}'); | |
| 1377 properties.add(new jsAst.Property(js.string(key), value)); | |
| 1378 } | |
| 1379 jsAst.Expression mangledGlobalNamesAccess = | |
| 1380 generateEmbeddedGlobalAccess(embeddedNames.MANGLED_GLOBAL_NAMES); | |
| 1381 var map = new jsAst.ObjectInitializer(properties); | |
| 1382 mainBuffer.write( | |
| 1383 jsAst.prettyPrint( | |
| 1384 js.statement('# = #', [mangledGlobalNamesAccess, map]), | |
| 1385 compiler, | |
| 1386 monitor: compiler.dumpInfoTask)); | |
| 1387 if (compiler.enableMinification) { | |
| 1388 mainBuffer.write(';'); | |
| 1389 } | |
| 1390 } | |
| 1391 } | |
| 1392 | |
| 1393 void checkEverythingEmitted(Iterable<Element> elements) { | |
| 1394 List<Element> pendingStatics; | |
| 1395 if (!compiler.hasIncrementalSupport) { | |
| 1396 pendingStatics = | |
| 1397 Elements.sortedByPosition(elements.where((e) => !e.isLibrary)); | |
| 1398 | |
| 1399 pendingStatics.forEach((element) => | |
| 1400 compiler.reportInfo( | |
| 1401 element, MessageKind.GENERIC, {'text': 'Pending statics.'})); | |
| 1402 } | |
| 1403 | |
| 1404 if (pendingStatics != null && !pendingStatics.isEmpty) { | |
| 1405 compiler.internalError(pendingStatics.first, | |
| 1406 'Pending statics (see above).'); | |
| 1407 } | |
| 1408 } | |
| 1409 | |
| 1410 void emitMainOutputUnit(Map<OutputUnit, String> deferredLoadHashes, | |
| 1411 CodeBuffer nativeBuffer) { | |
| 1313 bool isProgramSplit = compiler.deferredLoadTask.isProgramSplit; | 1412 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; | 1413 OutputUnit mainOutputUnit = compiler.deferredLoadTask.mainOutputUnit; |
| 1320 | 1414 |
| 1321 mainBuffer.add(buildGeneratedBy()); | 1415 mainBuffer.add(buildGeneratedBy()); |
| 1322 addComment(HOOKS_API_USAGE, mainBuffer); | 1416 addComment(HOOKS_API_USAGE, mainBuffer); |
| 1323 | 1417 |
| 1324 if (isProgramSplit) { | 1418 if (isProgramSplit) { |
| 1325 /// For deferred loading we communicate the initializers via this global | 1419 /// For deferred loading we communicate the initializers via this global |
| 1326 /// variable. The deferred hunks will add their initialization to this. | 1420 /// variable. The deferred hunks will add their initialization to this. |
| 1327 /// The semicolon is important in minified mode, without it the | 1421 /// The semicolon is important in minified mode, without it the |
| 1328 /// following parenthesis looks like a call to the object literal. | 1422 /// following parenthesis looks like a call to the object literal. |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1363 } | 1457 } |
| 1364 | 1458 |
| 1365 mainBuffer.add('function ${namer.isolateName}()$_{}\n'); | 1459 mainBuffer.add('function ${namer.isolateName}()$_{}\n'); |
| 1366 if (isProgramSplit) { | 1460 if (isProgramSplit) { |
| 1367 mainBuffer | 1461 mainBuffer |
| 1368 .write('${globalsHolder}.${namer.isolateName}$_=$_' | 1462 .write('${globalsHolder}.${namer.isolateName}$_=$_' |
| 1369 '${namer.isolateName}$N' | 1463 '${namer.isolateName}$N' |
| 1370 '${globalsHolder}.$initName$_=${_}$initName$N'); | 1464 '${globalsHolder}.$initName$_=${_}$initName$N'); |
| 1371 } | 1465 } |
| 1372 mainBuffer.add('init()$N$n'); | 1466 mainBuffer.add('init()$N$n'); |
| 1373 // Shorten the code by using [namer.currentIsolate] as temporary. | 1467 mainBuffer.add('$isolateProperties$_=$_$isolatePropertiesName$N'); |
| 1374 isolateProperties = namer.currentIsolate; | |
| 1375 mainBuffer.add( | |
| 1376 '$isolateProperties$_=$_$isolatePropertiesName$N'); | |
| 1377 | 1468 |
| 1378 emitStaticFunctions(); | 1469 emitStaticFunctions(task.outputStaticLists[mainOutputUnit]); |
| 1379 | 1470 |
| 1380 // Only output the classesCollector if we actually have any classes. | 1471 // Only output the classesCollector if we actually have any classes. |
| 1381 if (!(nativeClasses.isEmpty && | 1472 if (!(nativeClasses.isEmpty && |
| 1382 compiler.codegenWorld.staticFunctionsNeedingGetter.isEmpty && | 1473 compiler.codegenWorld.staticFunctionsNeedingGetter.isEmpty && |
| 1383 outputClassLists.values.every((classList) => classList.isEmpty) && | 1474 outputClassLists.values.every((classList) => classList.isEmpty) && |
| 1384 typedefsNeededForReflection.isEmpty)) { | 1475 typedefsNeededForReflection.isEmpty)) { |
| 1385 // Shorten the code by using "$$" as temporary. | 1476 // Shorten the code by using "$$" as temporary. |
| 1386 classesCollector = r"$$"; | 1477 classesCollector = r"$$"; |
| 1387 mainBuffer.add('var $classesCollector$_=${_}Object.create(null)$N$n'); | 1478 mainBuffer.add('var $classesCollector$_=${_}Object.create(null)$N$n'); |
| 1388 } | 1479 } |
| 1389 | 1480 |
| 1390 // Emit native classes on [nativeBuffer]. | |
| 1391 final CodeBuffer nativeBuffer = new CodeBuffer(); | |
| 1392 if (!nativeClasses.isEmpty) { | 1481 if (!nativeClasses.isEmpty) { |
| 1393 addComment('Native classes', nativeBuffer); | |
| 1394 addComment('Native classes', mainBuffer); | 1482 addComment('Native classes', mainBuffer); |
| 1395 nativeEmitter.generateNativeClasses(nativeClasses, mainBuffer, | |
| 1396 additionalProperties); | |
| 1397 } | 1483 } |
| 1398 | 1484 |
| 1399 for (List<ClassElement> outputClassList in outputClassLists.values) { | 1485 List<ClassElement> classes = task.outputClassLists[mainOutputUnit]; |
| 1400 for (ClassElement element in outputClassList) { | 1486 if (classes != null) { |
| 1487 for (ClassElement element in classes) { | |
| 1401 generateClass(element, getElementDescriptor(element)); | 1488 generateClass(element, getElementDescriptor(element)); |
| 1402 } | 1489 } |
| 1403 } | 1490 } |
| 1404 | 1491 |
| 1405 nativeEmitter.finishGenerateNativeClasses(); | 1492 if (compiler.enableMinification) { |
| 1406 nativeEmitter.assembleCode(nativeBuffer); | 1493 mainBuffer.write(';'); |
| 1494 } | |
| 1407 | 1495 |
| 1496 if (elementDescriptors.isNotEmpty) { | |
| 1497 Iterable<LibraryElement> libraries = | |
| 1498 task.outputLibraryLists[mainOutputUnit]; | |
| 1499 if (libraries == null) libraries = []; | |
| 1500 emitLibraries(libraries); | |
| 1501 emitTypedefs(); | |
| 1502 emitMangledNames(); | |
| 1408 | 1503 |
| 1409 // After this assignment we will produce invalid JavaScript code if we use | 1504 checkEverythingEmitted(elementDescriptors.keys); |
| 1410 // the classesCollector variable. | |
| 1411 classesCollector = 'classesCollector should not be used from now on'; | |
| 1412 | 1505 |
| 1413 // TODO(sigurdm): Need to check this for each outputUnit. | 1506 CodeBuffer libraryBuffer = new CodeBuffer(); |
| 1414 if (!elementDescriptors.isEmpty) { | 1507 for (LibraryElement library in Elements.sortedByPosition(libraries)) { |
| 1415 var oldClassesCollector = classesCollector; | 1508 writeLibraryDescriptors(libraryBuffer, library); |
| 1416 classesCollector = r"$$"; | 1509 elementDescriptors.remove(library); |
| 1417 if (compiler.enableMinification) { | |
| 1418 mainBuffer.write(';'); | |
| 1419 } | 1510 } |
| 1420 | 1511 |
| 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 | 1512 mainBuffer |
| 1537 ..write('(') | 1513 ..write('(') |
| 1538 ..write( | 1514 ..write( |
| 1539 jsAst.prettyPrint( | 1515 jsAst.prettyPrint( |
| 1540 getReflectionDataParser(classesCollector, backend), | 1516 getReflectionDataParser(classesCollector, backend), |
| 1541 compiler)) | 1517 compiler)) |
| 1542 ..write(')') | 1518 ..write(')') |
| 1543 ..write('([$n') | 1519 ..write('([$n') |
| 1544 ..add(libraryDescriptorBuffers[mainOutputUnit]) | 1520 ..add(libraryBuffer) |
| 1545 ..write('])$N'); | 1521 ..write('])$N'); |
| 1546 | 1522 |
| 1547 emitFinishClassesInvocationIfNecessary(mainBuffer); | 1523 emitFinishClassesInvocationIfNecessary(mainBuffer); |
| 1548 classesCollector = oldClassesCollector; | |
| 1549 } | 1524 } |
| 1525 | |
| 1550 typeTestEmitter.emitRuntimeTypeSupport(mainBuffer, mainOutputUnit); | 1526 typeTestEmitter.emitRuntimeTypeSupport(mainBuffer, mainOutputUnit); |
| 1551 interceptorEmitter.emitGetInterceptorMethods(mainBuffer); | 1527 interceptorEmitter.emitGetInterceptorMethods(mainBuffer); |
| 1552 interceptorEmitter.emitOneShotInterceptors(mainBuffer); | 1528 interceptorEmitter.emitOneShotInterceptors(mainBuffer); |
| 1529 | |
| 1530 if (task.outputContainsConstantList) { | |
| 1531 emitMakeConstantList(mainBuffer); | |
| 1532 } | |
| 1533 | |
| 1553 // Constants in checked mode call into RTI code to set type information | 1534 // Constants in checked mode call into RTI code to set type information |
| 1554 // which may need getInterceptor (and one-shot interceptor) methods, so | 1535 // which may need getInterceptor (and one-shot interceptor) methods, so |
| 1555 // we have to make sure that [emitGetInterceptorMethods] and | 1536 // we have to make sure that [emitGetInterceptorMethods] and |
| 1556 // [emitOneShotInterceptors] have been called. | 1537 // [emitOneShotInterceptors] have been called. |
| 1557 emitCompileTimeConstants(mainBuffer, mainOutputUnit); | 1538 emitCompileTimeConstants(mainBuffer, mainOutputUnit); |
| 1558 | 1539 |
| 1559 if (isProgramSplit) { | 1540 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 | 1541 |
| 1569 // Static field initializations require the classes and compile-time | 1542 // Static field initializations require the classes and compile-time |
| 1570 // constants to be set up. | 1543 // constants to be set up. |
| 1571 emitStaticNonFinalFieldInitializations(mainBuffer); | 1544 emitStaticNonFinalFieldInitializations(mainBuffer); |
| 1572 interceptorEmitter.emitInterceptedNames(mainBuffer); | 1545 interceptorEmitter.emitInterceptedNames(mainBuffer); |
| 1573 interceptorEmitter.emitMapTypeToInterceptor(mainBuffer); | 1546 interceptorEmitter.emitMapTypeToInterceptor(mainBuffer); |
| 1574 emitLazilyInitializedStaticFields(mainBuffer); | 1547 emitLazilyInitializedStaticFields(mainBuffer); |
| 1575 | 1548 |
| 1549 mainBuffer.writeln(); | |
| 1576 mainBuffer.add(nativeBuffer); | 1550 mainBuffer.add(nativeBuffer); |
| 1577 | 1551 |
| 1578 metadataEmitter.emitMetadata(mainBuffer); | 1552 metadataEmitter.emitMetadata(mainBuffer); |
| 1579 | 1553 |
| 1580 isolateProperties = isolatePropertiesName; | 1554 isolateProperties = isolatePropertiesName; |
| 1581 // The following code should not use the short-hand for the | 1555 // The following code should not use the short-hand for the |
| 1582 // initialStatics. | 1556 // initialStatics. |
| 1583 mainBuffer.add('${namer.currentIsolate}$_=${_}null$N'); | 1557 mainBuffer.add('${namer.currentIsolate}$_=${_}null$N'); |
| 1584 | 1558 |
| 1585 emitFinishIsolateConstructorInvocation(mainBuffer); | 1559 emitFinishIsolateConstructorInvocation(mainBuffer); |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1679 | 1653 |
| 1680 cspBuffer.write( | 1654 cspBuffer.write( |
| 1681 jsAst.prettyPrint( | 1655 jsAst.prettyPrint( |
| 1682 precompiledFunctionAst, compiler, | 1656 precompiledFunctionAst, compiler, |
| 1683 allowVariableMinification: false).getText()); | 1657 allowVariableMinification: false).getText()); |
| 1684 | 1658 |
| 1685 compiler.outputProvider('', 'precompiled.js') | 1659 compiler.outputProvider('', 'precompiled.js') |
| 1686 ..add(cspBuffer.getText()) | 1660 ..add(cspBuffer.getText()) |
| 1687 ..close(); | 1661 ..close(); |
| 1688 } | 1662 } |
| 1663 } | |
| 1664 | |
| 1665 /// Returns a map from OutputUnit to a hash of its content. The hash uniquely | |
| 1666 /// identifies the code of the output-unit. It does not include | |
| 1667 /// boilerplate JS code, like the sourcemap directives or the hash | |
| 1668 /// itself. | |
| 1669 Map<OutputUnit, String> emitDeferredOutputUnits() { | |
| 1670 if (!compiler.deferredLoadTask.isProgramSplit) return const {}; | |
| 1671 | |
| 1672 Map<OutputUnit, CodeBuffer> outputBuffers = | |
| 1673 new Map<OutputUnit, CodeBuffer>(); | |
| 1674 | |
| 1675 for (OutputUnit outputUnit in compiler.deferredLoadTask.allOutputUnits) { | |
| 1676 if (outputUnit == compiler.deferredLoadTask.mainOutputUnit) continue; | |
| 1677 | |
| 1678 List<Element> functions = task.outputStaticLists[outputUnit]; | |
| 1679 if (functions != null) { | |
| 1680 emitStaticFunctions(functions); | |
| 1681 } | |
| 1682 | |
| 1683 List<ClassElement> classes = task.outputClassLists[outputUnit]; | |
| 1684 if (classes != null) { | |
| 1685 for (ClassElement element in classes) { | |
| 1686 generateClass(element, getElementDescriptor(element)); | |
| 1687 } | |
| 1688 } | |
| 1689 | |
| 1690 if (elementDescriptors.isNotEmpty) { | |
| 1691 Iterable<LibraryElement> libraries = | |
| 1692 task.outputLibraryLists[outputUnit]; | |
| 1693 if (libraries == null) libraries = []; | |
| 1694 emitLibraries(libraries); | |
| 1695 | |
| 1696 CodeBuffer buffer = new CodeBuffer(); | |
| 1697 outputBuffers[outputUnit] = buffer; | |
| 1698 for (LibraryElement library in Elements.sortedByPosition(libraries)) { | |
| 1699 writeLibraryDescriptors(buffer, library); | |
| 1700 elementDescriptors.remove(library); | |
| 1701 } | |
| 1702 } | |
| 1703 } | |
| 1704 | |
| 1705 return emitDeferredCode(outputBuffers); | |
| 1706 } | |
| 1707 | |
| 1708 CodeBuffer buildNativesBuffer() { | |
| 1709 // Emit native classes on [nativeBuffer]. | |
| 1710 final CodeBuffer nativeBuffer = new CodeBuffer(); | |
| 1711 | |
| 1712 if (nativeClasses.isEmpty) return nativeBuffer; | |
| 1713 | |
| 1714 | |
| 1715 addComment('Native classes', nativeBuffer); | |
| 1716 | |
| 1717 nativeEmitter.generateNativeClasses(nativeClasses, mainBuffer, | |
| 1718 additionalProperties); | |
| 1719 | |
| 1720 nativeEmitter.finishGenerateNativeClasses(); | |
| 1721 nativeEmitter.assembleCode(nativeBuffer); | |
| 1722 | |
| 1723 return nativeBuffer; | |
| 1724 } | |
| 1725 | |
| 1726 void emitProgram(Program program) { | |
| 1727 // Shorten the code by using [namer.currentIsolate] as temporary. | |
| 1728 isolateProperties = namer.currentIsolate; | |
| 1729 | |
| 1730 classesCollector = r"$$"; | |
| 1731 | |
| 1732 // Emit deferred units first, so we have their hashes. | |
| 1733 // Map from OutputUnit to a hash of its content. The hash uniquely | |
| 1734 // identifies the code of the output-unit. It does not include | |
| 1735 // boilerplate JS code, like the sourcemap directives or the hash | |
| 1736 // itself. | |
| 1737 Map<OutputUnit, String> deferredLoadHashes = emitDeferredOutputUnits(); | |
| 1738 CodeBuffer nativeBuffer = buildNativesBuffer(); | |
| 1739 emitMainOutputUnit(deferredLoadHashes, nativeBuffer); | |
| 1689 | 1740 |
| 1690 if (backend.requiresPreamble && | 1741 if (backend.requiresPreamble && |
| 1691 !backend.htmlLibraryIsLoaded) { | 1742 !backend.htmlLibraryIsLoaded) { |
| 1692 compiler.reportHint(NO_LOCATION_SPANNABLE, MessageKind.PREAMBLE); | 1743 compiler.reportHint(NO_LOCATION_SPANNABLE, MessageKind.PREAMBLE); |
| 1693 } | 1744 } |
| 1694 } | 1745 } |
| 1695 | 1746 |
| 1696 String generateSourceMapTag(Uri sourceMapUri, Uri fileUri) { | 1747 String generateSourceMapTag(Uri sourceMapUri, Uri fileUri) { |
| 1697 if (sourceMapUri != null && fileUri != null) { | 1748 if (sourceMapUri != null && fileUri != null) { |
| 1698 String sourceMapFileName = relativize(fileUri, sourceMapUri, false); | 1749 String sourceMapFileName = relativize(fileUri, sourceMapUri, false); |
| 1699 return ''' | 1750 return ''' |
| 1700 | 1751 |
| 1701 //# sourceMappingURL=$sourceMapFileName | 1752 //# sourceMappingURL=$sourceMapFileName |
| 1702 '''; | 1753 '''; |
| 1703 } | 1754 } |
| 1704 return ''; | 1755 return ''; |
| 1705 } | 1756 } |
| 1706 | 1757 |
| 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) { | 1758 ClassBuilder getElementDescriptor(Element element) { |
| 1717 Element owner = element.library; | 1759 Element owner = element.library; |
| 1718 if (!element.isLibrary && !element.isTopLevel && !element.isNative) { | 1760 if (!element.isLibrary && !element.isTopLevel && !element.isNative) { |
| 1719 // For static (not top level) elements, record their code in a buffer | 1761 // 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 | 1762 // specific to the class. For now, not supported for native classes and |
| 1721 // native elements. | 1763 // native elements. |
| 1722 ClassElement cls = | 1764 ClassElement cls = |
| 1723 element.enclosingClassOrCompilationUnit.declaration; | 1765 element.enclosingClassOrCompilationUnit.declaration; |
| 1724 if (compiler.codegenWorld.instantiatedClasses.contains(cls) | 1766 if (compiler.codegenWorld.instantiatedClasses.contains(cls) |
| 1725 && !cls.isNative) { | 1767 && !cls.isNative) { |
| 1726 owner = cls; | 1768 owner = cls; |
| 1727 } | 1769 } |
| 1728 } | 1770 } |
| 1729 if (owner == null) { | 1771 if (owner == null) { |
| 1730 compiler.internalError(element, 'Owner is null.'); | 1772 compiler.internalError(element, 'Owner is null.'); |
| 1731 } | 1773 } |
| 1732 return getElementDescriptorForOutputUnit(owner, | 1774 return elementDescriptors.putIfAbsent( |
| 1733 compiler.deferredLoadTask.outputUnitForElement(element)); | 1775 owner, |
| 1776 () => new ClassBuilder(owner, namer)); | |
| 1734 } | 1777 } |
| 1735 | 1778 |
| 1736 /// Emits support-code for deferred loading into [buffer]. | 1779 /// Emits support-code for deferred loading into [buffer]. |
| 1737 void emitDeferredBoilerPlate(CodeBuffer buffer, | 1780 void emitDeferredBoilerPlate(CodeBuffer buffer, |
| 1738 Map<OutputUnit, String> deferredLoadHashes) { | 1781 Map<OutputUnit, String> deferredLoadHashes) { |
| 1739 // Function for checking if a hunk is loaded given its hash. | 1782 // Function for checking if a hunk is loaded given its hash. |
| 1740 buffer.write(jsAst.prettyPrint( | 1783 buffer.write(jsAst.prettyPrint( |
| 1741 js('# = function(hunkHash) {' | 1784 js('# = function(hunkHash) {' |
| 1742 ' return !!$deferredInitializers[hunkHash];' | 1785 ' return !!$deferredInitializers[hunkHash];' |
| 1743 '}', generateEmbeddedGlobalAccess(embeddedNames.IS_HUNK_LOADED)), | 1786 '}', generateEmbeddedGlobalAccess(embeddedNames.IS_HUNK_LOADED)), |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1795 | 1838 |
| 1796 emitMapping(embeddedNames.DEFERRED_LIBRARY_URIS, deferredLibraryUris); | 1839 emitMapping(embeddedNames.DEFERRED_LIBRARY_URIS, deferredLibraryUris); |
| 1797 emitMapping(embeddedNames.DEFERRED_LIBRARY_HASHES, | 1840 emitMapping(embeddedNames.DEFERRED_LIBRARY_HASHES, |
| 1798 deferredLibraryHashes); | 1841 deferredLibraryHashes); |
| 1799 } | 1842 } |
| 1800 | 1843 |
| 1801 /// Emits code for all output units except the main. | 1844 /// Emits code for all output units except the main. |
| 1802 /// Returns a mapping from outputUnit to a hash of the corresponding hunk that | 1845 /// Returns a mapping from outputUnit to a hash of the corresponding hunk that |
| 1803 /// can be used for calling the initializer. | 1846 /// can be used for calling the initializer. |
| 1804 Map<OutputUnit, String> emitDeferredCode( | 1847 Map<OutputUnit, String> emitDeferredCode( |
| 1805 Map<OutputUnit, CodeBuffer> libraryDescriptorBuffers) { | 1848 Map<OutputUnit, CodeBuffer> deferredBuffers) { |
| 1806 | 1849 |
| 1807 Map<OutputUnit, String> hunkHashes = new Map<OutputUnit, String>(); | 1850 Map<OutputUnit, String> hunkHashes = new Map<OutputUnit, String>(); |
| 1808 | 1851 |
| 1809 for (OutputUnit outputUnit in compiler.deferredLoadTask.allOutputUnits) { | 1852 for (OutputUnit outputUnit in compiler.deferredLoadTask.allOutputUnits) { |
| 1810 if (outputUnit == compiler.deferredLoadTask.mainOutputUnit) continue; | 1853 if (outputUnit == compiler.deferredLoadTask.mainOutputUnit) continue; |
| 1811 | 1854 |
| 1812 CodeBuffer libraryDescriptorBuffer = libraryDescriptorBuffers[outputUnit]; | 1855 CodeBuffer libraryDescriptorBuffer = deferredBuffers[outputUnit]; |
| 1813 | 1856 |
| 1814 CodeBuffer outputBuffer = new CodeBuffer(); | 1857 CodeBuffer outputBuffer = new CodeBuffer(); |
| 1815 | 1858 |
| 1816 var oldClassesCollector = classesCollector; | |
| 1817 classesCollector = r"$$"; | |
| 1818 | |
| 1819 outputBuffer..write(buildGeneratedBy()) | 1859 outputBuffer..write(buildGeneratedBy()) |
| 1820 ..write('${deferredInitializers}.current$_=$_' | 1860 ..write('${deferredInitializers}.current$_=$_' |
| 1821 'function$_(${globalsHolder}) {$N'); | 1861 'function$_(${globalsHolder}) {$N'); |
| 1822 for (String globalObject in Namer.reservedGlobalObjectNames) { | 1862 for (String globalObject in Namer.reservedGlobalObjectNames) { |
| 1823 outputBuffer | 1863 outputBuffer |
| 1824 .write('var $globalObject$_=$_' | 1864 .write('var $globalObject$_=$_' |
| 1825 '${globalsHolder}.$globalObject$N'); | 1865 '${globalsHolder}.$globalObject$N'); |
| 1826 } | 1866 } |
| 1827 outputBuffer | 1867 outputBuffer |
| 1828 ..write('var init$_=$_${globalsHolder}.init$N') | 1868 ..write('var init$_=$_${globalsHolder}.init$N') |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 1848 ..write('])$N'); | 1888 ..write('])$N'); |
| 1849 | 1889 |
| 1850 if (outputClassLists.containsKey(outputUnit)) { | 1890 if (outputClassLists.containsKey(outputUnit)) { |
| 1851 outputBuffer.write( | 1891 outputBuffer.write( |
| 1852 '$finishClassesName($classesCollector,$_${namer.currentIsolate},' | 1892 '$finishClassesName($classesCollector,$_${namer.currentIsolate},' |
| 1853 '$_$isolatePropertiesName)$N'); | 1893 '$_$isolatePropertiesName)$N'); |
| 1854 } | 1894 } |
| 1855 | 1895 |
| 1856 } | 1896 } |
| 1857 | 1897 |
| 1858 classesCollector = oldClassesCollector; | |
| 1859 | |
| 1860 // Set the currentIsolate variable to the current isolate (which is | 1898 // Set the currentIsolate variable to the current isolate (which is |
| 1861 // provided as second argument). | 1899 // provided as second argument). |
| 1862 // We need to do this, because we use the same variable for setting up | 1900 // 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 | 1901 // the isolate-properties and for storing the current isolate. During |
| 1864 // the setup (the code above this lines) we must set the variable to | 1902 // the setup (the code above this lines) we must set the variable to |
| 1865 // the isolate-properties. | 1903 // the isolate-properties. |
| 1866 // After we have done the setup (finishing with `finishClasses`) it must | 1904 // After we have done the setup (finishing with `finishClasses`) it must |
| 1867 // point to the current Isolate. Otherwise all methods/functions | 1905 // point to the current Isolate. Otherwise all methods/functions |
| 1868 // accessing isolate variables will access the wrong object. | 1906 // accessing isolate variables will access the wrong object. |
| 1869 outputBuffer.write("${namer.currentIsolate}$_=${_}arguments[1]$N"); | 1907 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) { | 1993 for (Element element in compiler.enqueuer.codegen.newlyEnqueuedElements) { |
| 1956 if (element.isInstanceMember) { | 1994 if (element.isInstanceMember) { |
| 1957 cachedClassBuilders.remove(element.enclosingClass); | 1995 cachedClassBuilders.remove(element.enclosingClass); |
| 1958 | 1996 |
| 1959 nativeEmitter.cachedBuilders.remove(element.enclosingClass); | 1997 nativeEmitter.cachedBuilders.remove(element.enclosingClass); |
| 1960 | 1998 |
| 1961 } | 1999 } |
| 1962 } | 2000 } |
| 1963 } | 2001 } |
| 1964 } | 2002 } |
| OLD | NEW |