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