| 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 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 77 | 77 |
| 78 /** | 78 /** |
| 79 * Accumulate properties for classes and libraries, describing their | 79 * Accumulate properties for classes and libraries, describing their |
| 80 * static/top-level members. | 80 * static/top-level members. |
| 81 * Later, these members are emitted when the class or library is emitted. | 81 * Later, these members are emitted when the class or library is emitted. |
| 82 * | 82 * |
| 83 * See [getElementDescriptor]. | 83 * See [getElementDescriptor]. |
| 84 */ | 84 */ |
| 85 // TODO(ahe): Generate statics with their class, and store only libraries in | 85 // TODO(ahe): Generate statics with their class, and store only libraries in |
| 86 // this map. | 86 // this map. |
| 87 final Map<Fragment, Map<Element, ClassBuilder>> elementDescriptors = | 87 final Map<Element, ClassBuilder> elementDescriptors = |
| 88 new Map<Fragment, Map<Element, ClassBuilder>>(); | 88 new Map<Element, ClassBuilder>(); |
| 89 | 89 |
| 90 final bool generateSourceMap; | 90 final bool generateSourceMap; |
| 91 | 91 |
| 92 OldEmitter(Compiler compiler, Namer namer, this.generateSourceMap, this.task) | 92 OldEmitter(Compiler compiler, Namer namer, this.generateSourceMap, this.task) |
| 93 : this.compiler = compiler, | 93 : this.compiler = compiler, |
| 94 this.namer = namer, | 94 this.namer = namer, |
| 95 cachedEmittedConstants = compiler.cacheStrategy.newSet(), | 95 cachedEmittedConstants = compiler.cacheStrategy.newSet(), |
| 96 cachedClassBuilders = compiler.cacheStrategy.newMap(), | 96 cachedClassBuilders = compiler.cacheStrategy.newMap(), |
| 97 cachedElements = compiler.cacheStrategy.newSet() { | 97 cachedElements = compiler.cacheStrategy.newSet() { |
| 98 constantEmitter = new ConstantEmitter( | 98 constantEmitter = new ConstantEmitter( |
| (...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 427 var \$desc; | 427 var \$desc; |
| 428 #; | 428 #; |
| 429 return #; | 429 return #; |
| 430 };''', | 430 };''', |
| 431 [generateEmbeddedGlobalAccess(embeddedNames.PRECOMPILED), | 431 [generateEmbeddedGlobalAccess(embeddedNames.PRECOMPILED), |
| 432 cspPrecompiledFunctionFor(outputUnit), | 432 cspPrecompiledFunctionFor(outputUnit), |
| 433 new jsAst.ArrayInitializer( | 433 new jsAst.ArrayInitializer( |
| 434 cspPrecompiledConstructorNamesFor(outputUnit))]); | 434 cspPrecompiledConstructorNamesFor(outputUnit))]); |
| 435 } | 435 } |
| 436 | 436 |
| 437 void assembleClass(Class cls, ClassBuilder enclosingBuilder, | 437 void emitClass(Class cls, ClassBuilder enclosingBuilder) { |
| 438 Fragment fragment) { | |
| 439 ClassElement classElement = cls.element; | 438 ClassElement classElement = cls.element; |
| 440 compiler.withCurrentElement(classElement, () { | 439 compiler.withCurrentElement(classElement, () { |
| 441 if (compiler.hasIncrementalSupport) { | 440 if (compiler.hasIncrementalSupport) { |
| 442 ClassBuilder cachedBuilder = | 441 ClassBuilder cachedBuilder = |
| 443 cachedClassBuilders.putIfAbsent(classElement, () { | 442 cachedClassBuilders.putIfAbsent(classElement, () { |
| 444 ClassBuilder builder = new ClassBuilder(classElement, namer); | 443 ClassBuilder builder = new ClassBuilder(classElement, namer); |
| 445 classEmitter.emitClass(cls, builder, fragment); | 444 classEmitter.emitClass(cls, builder); |
| 446 return builder; | 445 return builder; |
| 447 }); | 446 }); |
| 448 invariant(classElement, cachedBuilder.fields.isEmpty); | 447 invariant(classElement, cachedBuilder.fields.isEmpty); |
| 449 invariant(classElement, cachedBuilder.superName == null); | 448 invariant(classElement, cachedBuilder.superName == null); |
| 450 invariant(classElement, cachedBuilder.functionType == null); | 449 invariant(classElement, cachedBuilder.functionType == null); |
| 451 invariant(classElement, cachedBuilder.fieldMetadata == null); | 450 invariant(classElement, cachedBuilder.fieldMetadata == null); |
| 452 enclosingBuilder.properties.addAll(cachedBuilder.properties); | 451 enclosingBuilder.properties.addAll(cachedBuilder.properties); |
| 453 } else { | 452 } else { |
| 454 classEmitter.emitClass(cls, enclosingBuilder, fragment); | 453 classEmitter.emitClass(cls, enclosingBuilder); |
| 455 } | 454 } |
| 456 }); | 455 }); |
| 457 } | 456 } |
| 458 | 457 |
| 459 void assembleStaticFunctions(Iterable<Method> staticFunctions, | 458 void emitStaticFunctions(Iterable<Method> staticFunctions) { |
| 460 Fragment fragment) { | |
| 461 if (staticFunctions == null) return; | 459 if (staticFunctions == null) return; |
| 462 | 460 |
| 463 for (Method method in staticFunctions) { | 461 for (Method method in staticFunctions) { |
| 464 Element element = method.element; | 462 Element element = method.element; |
| 465 // We need to filter out null-elements for the interceptors. | 463 // We need to filter out null-elements for the interceptors. |
| 466 // TODO(floitsch): use the precomputed interceptors here. | 464 // TODO(floitsch): use the precomputed interceptors here. |
| 467 if (element == null) continue; | 465 if (element == null) continue; |
| 468 ClassBuilder builder = new ClassBuilder(element, namer); | 466 ClassBuilder builder = new ClassBuilder(element, namer); |
| 469 containerBuilder.addMemberMethod(method, builder); | 467 containerBuilder.addMemberMethod(method, builder); |
| 470 getElementDescriptor(element, fragment).properties | 468 getElementDescriptor(element).properties.addAll(builder.properties); |
| 471 .addAll(builder.properties); | |
| 472 } | 469 } |
| 473 } | 470 } |
| 474 | 471 |
| 475 void emitStaticNonFinalFieldInitializations(CodeOutput output, | 472 void emitStaticNonFinalFieldInitializations(CodeOutput output, |
| 476 OutputUnit outputUnit) { | 473 OutputUnit outputUnit) { |
| 477 void emitInitialization(Element element, jsAst.Expression initialValue) { | 474 void emitInitialization(Element element, jsAst.Expression initialValue) { |
| 478 jsAst.Expression init = | 475 jsAst.Expression init = |
| 479 js('$isolateProperties.# = #', | 476 js('$isolateProperties.# = #', |
| 480 [namer.globalPropertyName(element), initialValue]); | 477 [namer.globalPropertyName(element), initialValue]); |
| 481 output.addBuffer(jsAst.prettyPrint(init, compiler, | 478 output.addBuffer(jsAst.prettyPrint(init, compiler, |
| (...skipping 467 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 949 return object.__proto__ && | 946 return object.__proto__ && |
| 950 object.__proto__.p === cls.prototype.p; | 947 object.__proto__.p === cls.prototype.p; |
| 951 })(); | 948 })(); |
| 952 '''); | 949 '''); |
| 953 } | 950 } |
| 954 | 951 |
| 955 output.addBuffer(jsAst.prettyPrint(supportsDirectProtoAccess, compiler)); | 952 output.addBuffer(jsAst.prettyPrint(supportsDirectProtoAccess, compiler)); |
| 956 output.add(N); | 953 output.add(N); |
| 957 } | 954 } |
| 958 | 955 |
| 959 void writeLibraryDescriptor(CodeOutput output, LibraryElement library, | 956 void writeLibraryDescriptor(CodeOutput output, LibraryElement library) { |
| 960 Fragment fragment) { | |
| 961 var uri = ""; | 957 var uri = ""; |
| 962 if (!compiler.enableMinification || backend.mustPreserveUris) { | 958 if (!compiler.enableMinification || backend.mustPreserveUris) { |
| 963 uri = library.canonicalUri; | 959 uri = library.canonicalUri; |
| 964 if (uri.scheme == 'file' && compiler.outputUri != null) { | 960 if (uri.scheme == 'file' && compiler.outputUri != null) { |
| 965 uri = relativize(compiler.outputUri, library.canonicalUri, false); | 961 uri = relativize(compiler.outputUri, library.canonicalUri, false); |
| 966 } | 962 } |
| 967 } | 963 } |
| 968 ClassBuilder descriptor = elementDescriptors[fragment][library]; | 964 ClassBuilder descriptor = elementDescriptors[library]; |
| 969 if (descriptor == null) { | 965 if (descriptor == null) { |
| 970 // Nothing of the library was emitted. | 966 // Nothing of the library was emitted. |
| 971 // TODO(floitsch): this should not happen. We currently have an example | 967 // TODO(floitsch): this should not happen. We currently have an example |
| 972 // with language/prefix6_negative_test.dart where we have an instance | 968 // with language/prefix6_negative_test.dart where we have an instance |
| 973 // method without its corresponding class. | 969 // method without its corresponding class. |
| 974 return; | 970 return; |
| 975 } | 971 } |
| 976 | 972 |
| 977 String libraryName = | 973 String libraryName = |
| 978 (!compiler.enableMinification || backend.mustRetainLibraryNames) ? | 974 (!compiler.enableMinification || backend.mustRetainLibraryNames) ? |
| (...skipping 18 matching lines...) Expand all Loading... |
| 997 ..add(',$_') | 993 ..add(',$_') |
| 998 ..add(namer.globalObjectFor(library)) | 994 ..add(namer.globalObjectFor(library)) |
| 999 ..add(',$_') | 995 ..add(',$_') |
| 1000 ..addBuffer(jsAst.prettyPrint(initializers, | 996 ..addBuffer(jsAst.prettyPrint(initializers, |
| 1001 compiler, | 997 compiler, |
| 1002 monitor: compiler.dumpInfoTask)) | 998 monitor: compiler.dumpInfoTask)) |
| 1003 ..add(library == compiler.mainApp ? ',${n}1' : "") | 999 ..add(library == compiler.mainApp ? ',${n}1' : "") |
| 1004 ..add('],$n'); | 1000 ..add('],$n'); |
| 1005 } | 1001 } |
| 1006 | 1002 |
| 1007 void assemblePrecompiledConstructor(OutputUnit outputUnit, | 1003 void emitPrecompiledConstructor(OutputUnit outputUnit, |
| 1008 String constructorName, | 1004 String constructorName, |
| 1009 jsAst.Expression constructorAst, | 1005 jsAst.Expression constructorAst, |
| 1010 List<String> fields) { | 1006 List<String> fields) { |
| 1011 cspPrecompiledFunctionFor(outputUnit).add( | 1007 cspPrecompiledFunctionFor(outputUnit).add( |
| 1012 new jsAst.FunctionDeclaration( | 1008 new jsAst.FunctionDeclaration( |
| 1013 new jsAst.VariableDeclaration(constructorName), constructorAst)); | 1009 new jsAst.VariableDeclaration(constructorName), constructorAst)); |
| 1014 | 1010 |
| 1015 String fieldNamesProperty = FIELD_NAMES_PROPERTY_NAME; | 1011 String fieldNamesProperty = FIELD_NAMES_PROPERTY_NAME; |
| 1016 bool hasIsolateSupport = compiler.hasIsolateSupport; | 1012 bool hasIsolateSupport = compiler.hasIsolateSupport; |
| 1017 jsAst.Node fieldNamesArray = | 1013 jsAst.Node fieldNamesArray = |
| 1018 hasIsolateSupport ? js.stringArray(fields) : new jsAst.LiteralNull(); | 1014 hasIsolateSupport ? js.stringArray(fields) : new jsAst.LiteralNull(); |
| 1019 | 1015 |
| 1020 cspPrecompiledFunctionFor(outputUnit).add(js.statement(r''' | 1016 cspPrecompiledFunctionFor(outputUnit).add(js.statement(r''' |
| 1021 { | 1017 { |
| 1022 #constructorName.builtin$cls = #constructorNameString; | 1018 #constructorName.builtin$cls = #constructorNameString; |
| 1023 if (!"name" in #constructorName) | 1019 if (!"name" in #constructorName) |
| 1024 #constructorName.name = #constructorNameString; | 1020 #constructorName.name = #constructorNameString; |
| 1025 $desc = $collectedClasses.#constructorName[1]; | 1021 $desc = $collectedClasses.#constructorName[1]; |
| 1026 #constructorName.prototype = $desc; | 1022 #constructorName.prototype = $desc; |
| 1027 ''' /* next string is not a raw string */ ''' | 1023 ''' /* next string is not a raw string */ ''' |
| 1028 if (#hasIsolateSupport) { | 1024 if (#hasIsolateSupport) { |
| 1029 #constructorName.$fieldNamesProperty = #fieldNamesArray; | 1025 #constructorName.$fieldNamesProperty = #fieldNamesArray; |
| 1030 } | 1026 } |
| 1031 }''', | 1027 }''', |
| 1032 {"constructorName": constructorName, | 1028 {"constructorName": constructorName, |
| 1033 "constructorNameString": js.string(constructorName), | 1029 "constructorNameString": js.string(constructorName), |
| 1034 "hasIsolateSupport": hasIsolateSupport, | 1030 "hasIsolateSupport": hasIsolateSupport, |
| 1035 "fieldNamesArray": fieldNamesArray})); | 1031 "fieldNamesArray": fieldNamesArray})); |
| 1036 | 1032 |
| 1037 cspPrecompiledConstructorNamesFor(outputUnit).add(js('#', constructorName)); | 1033 cspPrecompiledConstructorNamesFor(outputUnit).add(js('#', constructorName)); |
| 1038 } | 1034 } |
| 1039 | 1035 |
| 1040 void assembleTypedefs(Program program) { | 1036 void emitTypedefs() { |
| 1041 Fragment mainFragment = program.mainFragment; | 1037 OutputUnit mainOutputUnit = compiler.deferredLoadTask.mainOutputUnit; |
| 1042 OutputUnit mainOutputUnit = mainFragment.outputUnit; | |
| 1043 | 1038 |
| 1044 // Emit all required typedef declarations into the main output unit. | 1039 // Emit all required typedef declarations into the main output unit. |
| 1045 // TODO(karlklose): unify required classes and typedefs to declarations | 1040 // TODO(karlklose): unify required classes and typedefs to declarations |
| 1046 // and have builders for each kind. | 1041 // and have builders for each kind. |
| 1047 for (TypedefElement typedef in typedefsNeededForReflection) { | 1042 for (TypedefElement typedef in typedefsNeededForReflection) { |
| 1048 LibraryElement library = typedef.library; | 1043 LibraryElement library = typedef.library; |
| 1049 // TODO(karlklose): add a TypedefBuilder and move this code there. | 1044 // TODO(karlklose): add a TypedefBuilder and move this code there. |
| 1050 DartType type = typedef.alias; | 1045 DartType type = typedef.alias; |
| 1051 // TODO(zarah): reify type variables once reflection on type arguments of | 1046 // TODO(zarah): reify type variables once reflection on type arguments of |
| 1052 // typedefs is supported. | 1047 // typedefs is supported. |
| 1053 int typeIndex = | 1048 int typeIndex = |
| 1054 task.metadataCollector.reifyType(type, ignoreTypeVariables: true); | 1049 task.metadataCollector.reifyType(type, ignoreTypeVariables: true); |
| 1055 ClassBuilder builder = new ClassBuilder(typedef, namer); | 1050 ClassBuilder builder = new ClassBuilder(typedef, namer); |
| 1056 builder.addProperty(embeddedNames.TYPEDEF_TYPE_PROPERTY_NAME, | 1051 builder.addProperty(embeddedNames.TYPEDEF_TYPE_PROPERTY_NAME, |
| 1057 js.number(typeIndex)); | 1052 js.number(typeIndex)); |
| 1058 builder.addProperty(embeddedNames.TYPEDEF_PREDICATE_PROPERTY_NAME, | 1053 builder.addProperty(embeddedNames.TYPEDEF_PREDICATE_PROPERTY_NAME, |
| 1059 js.boolean(true)); | 1054 js.boolean(true)); |
| 1060 | 1055 |
| 1061 // We can be pretty sure that the objectClass is initialized, since | 1056 // We can be pretty sure that the objectClass is initialized, since |
| 1062 // typedefs are only emitted with reflection, which requires lots of | 1057 // typedefs are only emitted with reflection, which requires lots of |
| 1063 // classes. | 1058 // classes. |
| 1064 assert(compiler.objectClass != null); | 1059 assert(compiler.objectClass != null); |
| 1065 builder.superName = namer.className(compiler.objectClass); | 1060 builder.superName = namer.className(compiler.objectClass); |
| 1066 jsAst.Node declaration = builder.toObjectInitializer(); | 1061 jsAst.Node declaration = builder.toObjectInitializer(); |
| 1067 String mangledName = namer.globalPropertyName(typedef); | 1062 String mangledName = namer.globalPropertyName(typedef); |
| 1068 String reflectionName = getReflectionName(typedef, mangledName); | 1063 String reflectionName = getReflectionName(typedef, mangledName); |
| 1069 getElementDescriptor(library, mainFragment) | 1064 getElementDescriptor(library) |
| 1070 ..addProperty(mangledName, declaration) | 1065 ..addProperty(mangledName, declaration) |
| 1071 ..addProperty("+$reflectionName", js.string('')); | 1066 ..addProperty("+$reflectionName", js.string('')); |
| 1072 // Also emit a trivial constructor for CSP mode. | 1067 // Also emit a trivial constructor for CSP mode. |
| 1073 String constructorName = mangledName; | 1068 String constructorName = mangledName; |
| 1074 jsAst.Expression constructorAst = js('function() {}'); | 1069 jsAst.Expression constructorAst = js('function() {}'); |
| 1075 List<String> fieldNames = []; | 1070 List<String> fieldNames = []; |
| 1076 assemblePrecompiledConstructor(mainOutputUnit, | 1071 emitPrecompiledConstructor(mainOutputUnit, |
| 1077 constructorName, | 1072 constructorName, |
| 1078 constructorAst, | 1073 constructorAst, |
| 1079 fieldNames); | 1074 fieldNames); |
| 1080 } | 1075 } |
| 1081 } | 1076 } |
| 1082 | 1077 |
| 1083 void emitMangledNames(CodeOutput output) { | 1078 void emitMangledNames(CodeOutput output) { |
| 1084 if (!mangledFieldNames.isEmpty) { | 1079 if (!mangledFieldNames.isEmpty) { |
| 1085 var keys = mangledFieldNames.keys.toList(); | 1080 var keys = mangledFieldNames.keys.toList(); |
| 1086 keys.sort(); | 1081 keys.sort(); |
| 1087 var properties = []; | 1082 var properties = []; |
| 1088 for (String key in keys) { | 1083 for (String key in keys) { |
| 1089 var value = js.string('${mangledFieldNames[key]}'); | 1084 var value = js.string('${mangledFieldNames[key]}'); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1134 compiler.reportInfo( | 1129 compiler.reportInfo( |
| 1135 element, MessageKind.GENERIC, {'text': 'Pending statics.'})); | 1130 element, MessageKind.GENERIC, {'text': 'Pending statics.'})); |
| 1136 } | 1131 } |
| 1137 | 1132 |
| 1138 if (pendingStatics != null && !pendingStatics.isEmpty) { | 1133 if (pendingStatics != null && !pendingStatics.isEmpty) { |
| 1139 compiler.internalError(pendingStatics.first, | 1134 compiler.internalError(pendingStatics.first, |
| 1140 'Pending statics (see above).'); | 1135 'Pending statics (see above).'); |
| 1141 } | 1136 } |
| 1142 } | 1137 } |
| 1143 | 1138 |
| 1144 void assembleLibrary(Library library, Fragment fragment) { | 1139 void emitLibrary(Library library) { |
| 1145 LibraryElement libraryElement = library.element; | 1140 LibraryElement libraryElement = library.element; |
| 1146 | 1141 |
| 1147 assembleStaticFunctions(library.statics, fragment); | 1142 emitStaticFunctions(library.statics); |
| 1148 | 1143 |
| 1149 ClassBuilder libraryBuilder = | 1144 ClassBuilder libraryBuilder = getElementDescriptor(libraryElement); |
| 1150 getElementDescriptor(libraryElement, fragment); | |
| 1151 for (Class cls in library.classes) { | 1145 for (Class cls in library.classes) { |
| 1152 assembleClass(cls, libraryBuilder, fragment); | 1146 emitClass(cls, libraryBuilder); |
| 1153 } | 1147 } |
| 1154 | 1148 |
| 1155 classEmitter.emitFields(library, libraryBuilder, emitStatics: true); | 1149 classEmitter.emitFields(library, libraryBuilder, emitStatics: true); |
| 1156 } | 1150 } |
| 1157 | 1151 |
| 1158 void assembleProgram(Program program) { | |
| 1159 for (Fragment fragment in program.fragments) { | |
| 1160 for (Library library in fragment.libraries) { | |
| 1161 assembleLibrary(library, fragment); | |
| 1162 } | |
| 1163 } | |
| 1164 assembleTypedefs(program); | |
| 1165 } | |
| 1166 | |
| 1167 void emitMainOutputUnit(Program program, | 1152 void emitMainOutputUnit(Program program, |
| 1168 Map<OutputUnit, String> deferredLoadHashes) { | 1153 Map<OutputUnit, String> deferredLoadHashes) { |
| 1169 MainFragment mainFragment = program.fragments.first; | 1154 MainFragment mainFragment = program.fragments.first; |
| 1170 OutputUnit mainOutputUnit = mainFragment.outputUnit; | 1155 OutputUnit mainOutputUnit = mainFragment.outputUnit; |
| 1171 | 1156 |
| 1172 LineColumnCollector lineColumnCollector; | 1157 LineColumnCollector lineColumnCollector; |
| 1173 List<CodeOutputListener> codeOutputListeners; | 1158 List<CodeOutputListener> codeOutputListeners; |
| 1174 if (generateSourceMap) { | 1159 if (generateSourceMap) { |
| 1175 lineColumnCollector = new LineColumnCollector(); | 1160 lineColumnCollector = new LineColumnCollector(); |
| 1176 codeOutputListeners = <CodeOutputListener>[lineColumnCollector]; | 1161 codeOutputListeners = <CodeOutputListener>[lineColumnCollector]; |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1256 mainOutput.add( | 1241 mainOutput.add( |
| 1257 '${globalsHolder}.${namer.isolateName}$_=$_${namer.isolateName}$N' | 1242 '${globalsHolder}.${namer.isolateName}$_=$_${namer.isolateName}$N' |
| 1258 '${globalsHolder}.$initName$_=${_}$initName$N' | 1243 '${globalsHolder}.$initName$_=${_}$initName$N' |
| 1259 '${globalsHolder}.$setupProgramName$_=$_' | 1244 '${globalsHolder}.$setupProgramName$_=$_' |
| 1260 '$setupProgramName$N'); | 1245 '$setupProgramName$N'); |
| 1261 } | 1246 } |
| 1262 mainOutput.add('init()$N$n'); | 1247 mainOutput.add('init()$N$n'); |
| 1263 mainOutput.add('$isolateProperties$_=$_$isolatePropertiesName$N'); | 1248 mainOutput.add('$isolateProperties$_=$_$isolatePropertiesName$N'); |
| 1264 | 1249 |
| 1265 emitFunctionThatReturnsNull(mainOutput); | 1250 emitFunctionThatReturnsNull(mainOutput); |
| 1251 mainFragment.libraries.forEach(emitLibrary); |
| 1266 | 1252 |
| 1267 Iterable<LibraryElement> libraries = | 1253 Iterable<LibraryElement> libraries = |
| 1268 task.outputLibraryLists[mainOutputUnit]; | 1254 task.outputLibraryLists[mainOutputUnit]; |
| 1269 if (libraries == null) libraries = []; | 1255 if (libraries == null) libraries = []; |
| 1256 emitTypedefs(); |
| 1270 emitMangledNames(mainOutput); | 1257 emitMangledNames(mainOutput); |
| 1271 | 1258 |
| 1272 Map<Element, ClassBuilder> descriptors = elementDescriptors[mainFragment]; | 1259 checkEverythingEmitted(elementDescriptors.keys); |
| 1273 checkEverythingEmitted(descriptors.keys); | |
| 1274 | 1260 |
| 1275 CodeBuffer libraryBuffer = new CodeBuffer(); | 1261 CodeBuffer libraryBuffer = new CodeBuffer(); |
| 1276 for (LibraryElement library in Elements.sortedByPosition(libraries)) { | 1262 for (LibraryElement library in Elements.sortedByPosition(libraries)) { |
| 1277 writeLibraryDescriptor(libraryBuffer, library, mainFragment); | 1263 writeLibraryDescriptor(libraryBuffer, library); |
| 1278 descriptors.remove(library); | 1264 elementDescriptors.remove(library); |
| 1279 } | 1265 } |
| 1280 | 1266 |
| 1281 if (descriptors.isNotEmpty) { | 1267 if (elementDescriptors.isNotEmpty) { |
| 1282 List<Element> remainingLibraries = descriptors.keys | 1268 List<Element> remainingLibraries = elementDescriptors.keys |
| 1283 .where((Element e) => e is LibraryElement) | 1269 .where((Element e) => e is LibraryElement) |
| 1284 .toList(); | 1270 .toList(); |
| 1285 | 1271 |
| 1286 // The remaining descriptors are only accessible through reflection. | 1272 // The remaining descriptors are only accessible through reflection. |
| 1287 // The program builder does not collect libraries that only | 1273 // The program builder does not collect libraries that only |
| 1288 // contain typedefs that are used for reflection. | 1274 // contain typedefs that are used for reflection. |
| 1289 for (LibraryElement element in remainingLibraries) { | 1275 for (LibraryElement element in remainingLibraries) { |
| 1290 assert(element is LibraryElement || compiler.hasIncrementalSupport); | 1276 assert(element is LibraryElement || compiler.hasIncrementalSupport); |
| 1291 if (element is LibraryElement) { | 1277 if (element is LibraryElement) { |
| 1292 writeLibraryDescriptor(libraryBuffer, element, mainFragment); | 1278 writeLibraryDescriptor(libraryBuffer, element); |
| 1293 descriptors.remove(element); | 1279 elementDescriptors.remove(element); |
| 1294 } | 1280 } |
| 1295 } | 1281 } |
| 1296 } | 1282 } |
| 1297 | 1283 |
| 1298 bool needsNativeSupport = program.needsNativeSupport; | 1284 bool needsNativeSupport = program.needsNativeSupport; |
| 1299 mainOutput.addBuffer( | 1285 mainOutput.addBuffer( |
| 1300 jsAst.prettyPrint( | 1286 jsAst.prettyPrint( |
| 1301 buildSetupProgram(program, compiler, backend, namer, this), | 1287 buildSetupProgram(program, compiler, backend, namer, this), |
| 1302 compiler)); | 1288 compiler)); |
| 1303 | 1289 |
| (...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1549 /// itself. | 1535 /// itself. |
| 1550 Map<OutputUnit, String> emitDeferredOutputUnits(Program program) { | 1536 Map<OutputUnit, String> emitDeferredOutputUnits(Program program) { |
| 1551 if (!program.isSplit) return const {}; | 1537 if (!program.isSplit) return const {}; |
| 1552 | 1538 |
| 1553 Map<OutputUnit, CodeBuffer> outputBuffers = | 1539 Map<OutputUnit, CodeBuffer> outputBuffers = |
| 1554 new Map<OutputUnit, CodeBuffer>(); | 1540 new Map<OutputUnit, CodeBuffer>(); |
| 1555 | 1541 |
| 1556 for (Fragment fragment in program.deferredFragments) { | 1542 for (Fragment fragment in program.deferredFragments) { |
| 1557 OutputUnit outputUnit = fragment.outputUnit; | 1543 OutputUnit outputUnit = fragment.outputUnit; |
| 1558 | 1544 |
| 1559 Map<Element, ClassBuilder> descriptors = elementDescriptors[fragment]; | |
| 1560 | 1545 |
| 1561 if (descriptors.isNotEmpty) { | 1546 fragment.libraries.forEach(emitLibrary); |
| 1547 |
| 1548 if (elementDescriptors.isNotEmpty) { |
| 1562 Iterable<LibraryElement> libraries = | 1549 Iterable<LibraryElement> libraries = |
| 1563 task.outputLibraryLists[outputUnit]; | 1550 task.outputLibraryLists[outputUnit]; |
| 1564 if (libraries == null) libraries = []; | 1551 if (libraries == null) libraries = []; |
| 1565 | 1552 |
| 1566 // TODO(johnniwinther): Avoid creating [CodeBuffer]s. | 1553 // TODO(johnniwinther): Avoid creating [CodeBuffer]s. |
| 1567 CodeBuffer buffer = new CodeBuffer(); | 1554 CodeBuffer buffer = new CodeBuffer(); |
| 1568 outputBuffers[outputUnit] = buffer; | 1555 outputBuffers[outputUnit] = buffer; |
| 1569 for (LibraryElement library in Elements.sortedByPosition(libraries)) { | 1556 for (LibraryElement library in Elements.sortedByPosition(libraries)) { |
| 1570 writeLibraryDescriptor(buffer, library, fragment); | 1557 writeLibraryDescriptor(buffer, library); |
| 1571 descriptors.remove(library); | 1558 elementDescriptors.remove(library); |
| 1572 } | 1559 } |
| 1573 } | 1560 } |
| 1574 } | 1561 } |
| 1575 | 1562 |
| 1576 return emitDeferredCode(program, outputBuffers); | 1563 return emitDeferredCode(program, outputBuffers); |
| 1577 } | 1564 } |
| 1578 | 1565 |
| 1579 int emitProgram(ProgramBuilder programBuilder) { | 1566 int emitProgram(ProgramBuilder programBuilder) { |
| 1580 Program program = programBuilder.buildProgram( | 1567 Program program = programBuilder.buildProgram( |
| 1581 storeFunctionTypesInMetadata: true); | 1568 storeFunctionTypesInMetadata: true); |
| 1582 | 1569 |
| 1583 assembleProgram(program); | |
| 1584 | |
| 1585 // Shorten the code by using [namer.currentIsolate] as temporary. | 1570 // Shorten the code by using [namer.currentIsolate] as temporary. |
| 1586 isolateProperties = namer.currentIsolate; | 1571 isolateProperties = namer.currentIsolate; |
| 1587 | 1572 |
| 1588 // Emit deferred units first, so we have their hashes. | 1573 // Emit deferred units first, so we have their hashes. |
| 1589 // Map from OutputUnit to a hash of its content. The hash uniquely | 1574 // Map from OutputUnit to a hash of its content. The hash uniquely |
| 1590 // identifies the code of the output-unit. It does not include | 1575 // identifies the code of the output-unit. It does not include |
| 1591 // boilerplate JS code, like the sourcemap directives or the hash | 1576 // boilerplate JS code, like the sourcemap directives or the hash |
| 1592 // itself. | 1577 // itself. |
| 1593 Map<OutputUnit, String> deferredLoadHashes = | 1578 Map<OutputUnit, String> deferredLoadHashes = |
| 1594 emitDeferredOutputUnits(program); | 1579 emitDeferredOutputUnits(program); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1606 if (sourceMapUri != null && fileUri != null) { | 1591 if (sourceMapUri != null && fileUri != null) { |
| 1607 String sourceMapFileName = relativize(fileUri, sourceMapUri, false); | 1592 String sourceMapFileName = relativize(fileUri, sourceMapUri, false); |
| 1608 return ''' | 1593 return ''' |
| 1609 | 1594 |
| 1610 //# sourceMappingURL=$sourceMapFileName | 1595 //# sourceMappingURL=$sourceMapFileName |
| 1611 '''; | 1596 '''; |
| 1612 } | 1597 } |
| 1613 return ''; | 1598 return ''; |
| 1614 } | 1599 } |
| 1615 | 1600 |
| 1616 ClassBuilder getElementDescriptor(Element element, Fragment fragment) { | 1601 ClassBuilder getElementDescriptor(Element element) { |
| 1617 Element owner = element.library; | 1602 Element owner = element.library; |
| 1618 if (!element.isLibrary && !element.isTopLevel && !element.isNative) { | 1603 if (!element.isLibrary && !element.isTopLevel && !element.isNative) { |
| 1619 // For static (not top level) elements, record their code in a buffer | 1604 // For static (not top level) elements, record their code in a buffer |
| 1620 // specific to the class. For now, not supported for native classes and | 1605 // specific to the class. For now, not supported for native classes and |
| 1621 // native elements. | 1606 // native elements. |
| 1622 ClassElement cls = | 1607 ClassElement cls = |
| 1623 element.enclosingClassOrCompilationUnit.declaration; | 1608 element.enclosingClassOrCompilationUnit.declaration; |
| 1624 if (compiler.codegenWorld.directlyInstantiatedClasses.contains(cls) && | 1609 if (compiler.codegenWorld.directlyInstantiatedClasses.contains(cls) && |
| 1625 !cls.isNative && | 1610 !cls.isNative && |
| 1626 compiler.deferredLoadTask.outputUnitForElement(element) == | 1611 compiler.deferredLoadTask.outputUnitForElement(element) == |
| 1627 compiler.deferredLoadTask.outputUnitForElement(cls)) { | 1612 compiler.deferredLoadTask.outputUnitForElement(cls)) { |
| 1628 owner = cls; | 1613 owner = cls; |
| 1629 } | 1614 } |
| 1630 } | 1615 } |
| 1631 if (owner == null) { | 1616 if (owner == null) { |
| 1632 compiler.internalError(element, 'Owner is null.'); | 1617 compiler.internalError(element, 'Owner is null.'); |
| 1633 } | 1618 } |
| 1634 return elementDescriptors | 1619 return elementDescriptors.putIfAbsent( |
| 1635 .putIfAbsent(fragment, () => new Map<Element, ClassBuilder>()) | 1620 owner, |
| 1636 .putIfAbsent(owner, () => new ClassBuilder(owner, namer)); | 1621 () => new ClassBuilder(owner, namer)); |
| 1637 } | 1622 } |
| 1638 | 1623 |
| 1639 /// Emits support-code for deferred loading into [output]. | 1624 /// Emits support-code for deferred loading into [output]. |
| 1640 void emitDeferredBoilerPlate(CodeOutput output, | 1625 void emitDeferredBoilerPlate(CodeOutput output, |
| 1641 Map<OutputUnit, String> deferredLoadHashes) { | 1626 Map<OutputUnit, String> deferredLoadHashes) { |
| 1642 jsAst.Statement functions = js.statement(''' | 1627 jsAst.Statement functions = js.statement(''' |
| 1643 { | 1628 { |
| 1644 // Function for checking if a hunk is loaded given its hash. | 1629 // Function for checking if a hunk is loaded given its hash. |
| 1645 #isHunkLoaded = function(hunkHash) { | 1630 #isHunkLoaded = function(hunkHash) { |
| 1646 return !!$deferredInitializers[hunkHash]; | 1631 return !!$deferredInitializers[hunkHash]; |
| (...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1894 for (Element element in compiler.enqueuer.codegen.newlyEnqueuedElements) { | 1879 for (Element element in compiler.enqueuer.codegen.newlyEnqueuedElements) { |
| 1895 if (element.isInstanceMember) { | 1880 if (element.isInstanceMember) { |
| 1896 cachedClassBuilders.remove(element.enclosingClass); | 1881 cachedClassBuilders.remove(element.enclosingClass); |
| 1897 | 1882 |
| 1898 nativeEmitter.cachedBuilders.remove(element.enclosingClass); | 1883 nativeEmitter.cachedBuilders.remove(element.enclosingClass); |
| 1899 | 1884 |
| 1900 } | 1885 } |
| 1901 } | 1886 } |
| 1902 } | 1887 } |
| 1903 } | 1888 } |
| OLD | NEW |