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

Side by Side Diff: sdk/lib/_internal/compiler/implementation/js_emitter/code_emitter_task.dart

Issue 367613003: Revert "Add runtime_data.dart to the whitelist of files with unused members." and "Emit declaration… (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 part of dart2js.js_emitter; 5 part of dart2js.js_emitter;
6 6
7 /** 7 /**
8 * Generates the code for all used classes in the program. Static fields (even 8 * Generates the code for all used classes in the program. Static fields (even
9 * in classes) are ignored, since they can be treated as non-class elements. 9 * in classes) are ignored, since they can be treated as non-class elements.
10 * 10 *
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
48 final Map<ClassElement, Map<String, jsAst.Expression>> additionalProperties = 48 final Map<ClassElement, Map<String, jsAst.Expression>> additionalProperties =
49 new Map<ClassElement, Map<String, jsAst.Expression>>(); 49 new Map<ClassElement, Map<String, jsAst.Expression>>();
50 50
51 /// Records if a type variable is read dynamically for type tests. 51 /// Records if a type variable is read dynamically for type tests.
52 final Set<TypeVariableElement> readTypeVariables = 52 final Set<TypeVariableElement> readTypeVariables =
53 new Set<TypeVariableElement>(); 53 new Set<TypeVariableElement>();
54 54
55 // TODO(ngeoffray): remove this field. 55 // TODO(ngeoffray): remove this field.
56 Set<ClassElement> instantiatedClasses; 56 Set<ClassElement> instantiatedClasses;
57 57
58 List<TypedefElement> typedefsNeededForReflection;
59
60 JavaScriptBackend get backend => compiler.backend; 58 JavaScriptBackend get backend => compiler.backend;
61 TypeVariableHandler get typeVariableHandler => backend.typeVariableHandler; 59 TypeVariableHandler get typeVariableHandler => backend.typeVariableHandler;
62 60
63 String get _ => space; 61 String get _ => space;
64 String get space => compiler.enableMinification ? "" : " "; 62 String get space => compiler.enableMinification ? "" : " ";
65 String get n => compiler.enableMinification ? "" : "\n"; 63 String get n => compiler.enableMinification ? "" : "\n";
66 String get N => compiler.enableMinification ? "\n" : ";\n"; 64 String get N => compiler.enableMinification ? "\n" : ";\n";
67 65
68 CodeBuffer getBuffer(OutputUnit outputUnit) {
69 return outputBuffers.putIfAbsent(outputUnit, () => new CodeBuffer());
70 }
71
72 CodeBuffer get mainBuffer { 66 CodeBuffer get mainBuffer {
73 return getBuffer(compiler.deferredLoadTask.mainOutputUnit); 67 return outputBuffers.putIfAbsent(compiler.deferredLoadTask.mainOutputUnit,
68 () => new CodeBuffer());
74 } 69 }
75 70
76 /** 71 /**
77 * List of expressions and statements that will be included in the 72 * List of expressions and statements that will be included in the
78 * precompiled function. 73 * precompiled function.
79 * 74 *
80 * To save space, dart2js normally generates constructors and accessors 75 * To save space, dart2js normally generates constructors and accessors
81 * 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
82 * 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
83 * 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.
(...skipping 772 matching lines...) Expand 10 before | Expand all | Expand 10 after
856 void emitStaticFunctions() { 851 void emitStaticFunctions() {
857 bool isStaticFunction(Element element) => 852 bool isStaticFunction(Element element) =>
858 !element.isInstanceMember && !element.isField; 853 !element.isInstanceMember && !element.isField;
859 854
860 Iterable<Element> elements = 855 Iterable<Element> elements =
861 backend.generatedCode.keys.where(isStaticFunction); 856 backend.generatedCode.keys.where(isStaticFunction);
862 857
863 for (Element element in Elements.sortedByPosition(elements)) { 858 for (Element element in Elements.sortedByPosition(elements)) {
864 ClassBuilder builder = new ClassBuilder(namer); 859 ClassBuilder builder = new ClassBuilder(namer);
865 containerBuilder.addMember(element, builder); 860 containerBuilder.addMember(element, builder);
866 getElementDescriptor(element).properties.addAll(builder.properties); 861 getElementDecriptor(element).properties.addAll(builder.properties);
867 } 862 }
868 } 863 }
869 864
870 void emitStaticNonFinalFieldInitializations(CodeBuffer buffer) { 865 void emitStaticNonFinalFieldInitializations(CodeBuffer buffer) {
871 JavaScriptConstantCompiler handler = backend.constants; 866 JavaScriptConstantCompiler handler = backend.constants;
872 Iterable<VariableElement> staticNonFinalFields = 867 Iterable<VariableElement> staticNonFinalFields =
873 handler.getStaticNonFinalFieldsForEmission(); 868 handler.getStaticNonFinalFieldsForEmission();
874 for (Element element in Elements.sortedByPosition(staticNonFinalFields)) { 869 for (Element element in Elements.sortedByPosition(staticNonFinalFields)) {
875 // [:interceptedNames:] is handled in [emitInterceptedNames]. 870 // [:interceptedNames:] is handled in [emitInterceptedNames].
876 if (element == backend.interceptedNames) continue; 871 if (element == backend.interceptedNames) continue;
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after
1142 // The back-end introduces some constants, like "InterceptorConstant" or 1137 // The back-end introduces some constants, like "InterceptorConstant" or
1143 // some list constants. They are emitted in the main output-unit. 1138 // some list constants. They are emitted in the main output-unit.
1144 // TODO(sigurdm): We should track those constants. 1139 // TODO(sigurdm): We should track those constants.
1145 constantUnit = compiler.deferredLoadTask.mainOutputUnit; 1140 constantUnit = compiler.deferredLoadTask.mainOutputUnit;
1146 } 1141 }
1147 outputConstantLists.putIfAbsent(constantUnit, () => new List<Constant>()) 1142 outputConstantLists.putIfAbsent(constantUnit, () => new List<Constant>())
1148 .add(constant); 1143 .add(constant);
1149 } 1144 }
1150 } 1145 }
1151 1146
1152 /// Compute all the classes and typedefs that must be emitted. 1147 /**
1153 void computeNeededDeclarations() { 1148 * Compute all the classes that must be emitted.
1154 // Compute needed typedefs. 1149 */
1155 typedefsNeededForReflection = Elements.sortedByPosition( 1150 void computeNeededClasses() {
1156 compiler.world.allTypedefs
1157 .where(backend.isNeededForReflection)
1158 .toList());
1159
1160 // Compute needed classes.
1161 instantiatedClasses = 1151 instantiatedClasses =
1162 compiler.codegenWorld.instantiatedClasses.where(computeClassFilter()) 1152 compiler.codegenWorld.instantiatedClasses.where(computeClassFilter())
1163 .toSet(); 1153 .toSet();
1164 1154
1165 void addClassWithSuperclasses(ClassElement cls) { 1155 void addClassWithSuperclasses(ClassElement cls) {
1166 neededClasses.add(cls); 1156 neededClasses.add(cls);
1167 for (ClassElement superclass = cls.superclass; 1157 for (ClassElement superclass = cls.superclass;
1168 superclass != null; 1158 superclass != null;
1169 superclass = superclass.superclass) { 1159 superclass = superclass.superclass) {
1170 neededClasses.add(superclass); 1160 neededClasses.add(superclass);
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
1305 1295
1306 mainBuffer.add(jsAst.prettyPrint(convertToFastObject, compiler)); 1296 mainBuffer.add(jsAst.prettyPrint(convertToFastObject, compiler));
1307 mainBuffer.add(N); 1297 mainBuffer.add(N);
1308 } 1298 }
1309 1299
1310 void writeLibraryDescriptors(LibraryElement library) { 1300 void writeLibraryDescriptors(LibraryElement library) {
1311 var uri = library.canonicalUri; 1301 var uri = library.canonicalUri;
1312 if (uri.scheme == 'file' && compiler.outputUri != null) { 1302 if (uri.scheme == 'file' && compiler.outputUri != null) {
1313 uri = relativize(compiler.outputUri, library.canonicalUri, false); 1303 uri = relativize(compiler.outputUri, library.canonicalUri, false);
1314 } 1304 }
1315 Map<OutputUnit, ClassBuilder> descriptors = elementDescriptors[library]; 1305 Map<OutputUnit, ClassBuilder> descriptors =
1306 elementDescriptors[library];
1316 1307
1317 for (OutputUnit outputUnit in compiler.deferredLoadTask.allOutputUnits) { 1308 for (OutputUnit outputUnit in compiler.deferredLoadTask.allOutputUnits) {
1318 if (!descriptors.containsKey(outputUnit)) continue; 1309 ClassBuilder descriptor =
1319 1310 descriptors.putIfAbsent(outputUnit, () => new ClassBuilder(namer));
1320 ClassBuilder descriptor = descriptors[outputUnit]; 1311 if (descriptor.properties.isEmpty) continue;
1312 bool isDeferred =
1313 outputUnit != compiler.deferredLoadTask.mainOutputUnit;
1321 jsAst.Fun metadata = metadataEmitter.buildMetadataFunction(library); 1314 jsAst.Fun metadata = metadataEmitter.buildMetadataFunction(library);
1322 1315
1323 jsAst.ObjectInitializer initializers = descriptor.toObjectInitializer(); 1316 jsAst.ObjectInitializer initializers =
1324 CodeBuffer outputBuffer = getBuffer(outputUnit); 1317 descriptor.toObjectInitializer();
1325 1318 CodeBuffer outputBuffer =
1319 outputBuffers.putIfAbsent(outputUnit, () => new CodeBuffer());
1326 int sizeBefore = outputBuffer.length; 1320 int sizeBefore = outputBuffer.length;
1327 outputBuffers[outputUnit] 1321 outputBuffers[outputUnit]
1328 ..write('["${library.getLibraryName()}",$_') 1322 ..write('["${library.getLibraryName()}",$_')
1329 ..write('"${uri}",$_') 1323 ..write('"${uri}",$_')
1330 ..write(metadata == null ? "" : jsAst.prettyPrint(metadata, compiler)) 1324 ..write(metadata == null ? "" : jsAst.prettyPrint(metadata, compiler))
1331 ..write(',$_') 1325 ..write(',$_')
1332 ..write(namer.globalObjectFor(library)) 1326 ..write(namer.globalObjectFor(library))
1333 ..write(',$_') 1327 ..write(',$_')
1334 ..write(jsAst.prettyPrint(initializers, compiler)) 1328 ..write(jsAst.prettyPrint(initializers, compiler))
1335 ..write(library == compiler.mainApp ? ',${n}1' : "") 1329 ..write(library == compiler.mainApp ? ',${n}1' : "")
1336 ..write('],$n'); 1330 ..write('],$n');
1337 int sizeAfter = outputBuffer.length; 1331 int sizeAfter = outputBuffer.length;
1338 compiler.dumpInfoTask.codeSizeCounter 1332 compiler.dumpInfoTask.codeSizeCounter
1339 .countCode(library, sizeAfter - sizeBefore); 1333 .countCode(library, sizeAfter - sizeBefore);
1340 } 1334 }
1341 } 1335 }
1342 1336
1343 String assembleProgram() { 1337 String assembleProgram() {
1344 measure(() { 1338 measure(() {
1345 invalidateCaches(); 1339 invalidateCaches();
1346 1340
1347 // Compute the required type checks to know which classes need a 1341 // Compute the required type checks to know which classes need a
1348 // 'is$' method. 1342 // 'is$' method.
1349 typeTestEmitter.computeRequiredTypeChecks(); 1343 typeTestEmitter.computeRequiredTypeChecks();
1350 1344
1351 computeNeededDeclarations(); 1345 computeNeededClasses();
1352 1346
1353 mainBuffer.add(buildGeneratedBy()); 1347 mainBuffer.add(buildGeneratedBy());
1354 addComment(HOOKS_API_USAGE, mainBuffer); 1348 addComment(HOOKS_API_USAGE, mainBuffer);
1355 1349
1356 if (!compiler.deferredLoadTask.splitProgram) { 1350 if (!compiler.deferredLoadTask.splitProgram) {
1357 mainBuffer.add('(function(${namer.currentIsolate})$_{$n'); 1351 mainBuffer.add('(function(${namer.currentIsolate})$_{$n');
1358 } 1352 }
1359 1353
1360 // Using a named function here produces easier to read stack traces in 1354 // Using a named function here produces easier to read stack traces in
1361 // Chrome/V8. 1355 // Chrome/V8.
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
1400 } 1394 }
1401 1395
1402 // As a side-effect, emitting classes will produce "bound closures" in 1396 // As a side-effect, emitting classes will produce "bound closures" in
1403 // [methodClosures]. The bound closures are JS AST nodes that add 1397 // [methodClosures]. The bound closures are JS AST nodes that add
1404 // properties to $$ [classesCollector]. The bound closures are not 1398 // properties to $$ [classesCollector]. The bound closures are not
1405 // emitted until we have emitted all other classes (native or not). 1399 // emitted until we have emitted all other classes (native or not).
1406 1400
1407 // Might create methodClosures. 1401 // Might create methodClosures.
1408 for (List<ClassElement> outputClassList in outputClassLists.values) { 1402 for (List<ClassElement> outputClassList in outputClassLists.values) {
1409 for (ClassElement element in outputClassList) { 1403 for (ClassElement element in outputClassList) {
1410 generateClass(element, getElementDescriptor(element)); 1404 generateClass(element, getElementDecriptor(element));
1411 } 1405 }
1412 } 1406 }
1413 1407
1414 nativeEmitter.finishGenerateNativeClasses(); 1408 nativeEmitter.finishGenerateNativeClasses();
1415 nativeEmitter.assembleCode(nativeBuffer); 1409 nativeEmitter.assembleCode(nativeBuffer);
1416 1410
1417 1411
1418 // After this assignment we will produce invalid JavaScript code if we use 1412 // After this assignment we will produce invalid JavaScript code if we use
1419 // the classesCollector variable. 1413 // the classesCollector variable.
1420 classesCollector = 'classesCollector should not be used from now on'; 1414 classesCollector = 'classesCollector should not be used from now on';
1421 1415
1422 // TODO(sigurdm): Need to check this for each outputUnit. 1416 // TODO(sigurdm): Need to check this for each outputUnit.
1423 if (!elementDescriptors.isEmpty) { 1417 if (!elementDescriptors.isEmpty) {
1424 var oldClassesCollector = classesCollector; 1418 var oldClassesCollector = classesCollector;
1425 classesCollector = r"$$"; 1419 classesCollector = r"$$";
1426 if (compiler.enableMinification) { 1420 if (compiler.enableMinification) {
1427 mainBuffer.write(';'); 1421 mainBuffer.write(';');
1428 } 1422 }
1429 1423
1430 // TODO(karlklose): document what kinds of fields this loop adds to the
1431 // library class builder.
1432 for (Element element in elementDescriptors.keys) { 1424 for (Element element in elementDescriptors.keys) {
1433 // TODO(ahe): Should iterate over all libraries. Otherwise, we will 1425 // TODO(ahe): Should iterate over all libraries. Otherwise, we will
1434 // not see libraries that only have fields. 1426 // not see libraries that only have fields.
1435 if (element.isLibrary) { 1427 if (element.isLibrary) {
1436 LibraryElement library = element; 1428 LibraryElement library = element;
1437 ClassBuilder builder = new ClassBuilder(namer); 1429 ClassBuilder builder = new ClassBuilder(namer);
1438 if (classEmitter.emitFields( 1430 if (classEmitter.emitFields(
1439 library, builder, null, emitStatics: true)) { 1431 library, builder, null, emitStatics: true)) {
1440 OutputUnit mainUnit = compiler.deferredLoadTask.mainOutputUnit; 1432 OutputUnit mainUnit = compiler.deferredLoadTask.mainOutputUnit;
1441 getElementDescriptorForOutputUnit(library, mainUnit) 1433 getElementDescriptorForOutputUnit(library, mainUnit)
1442 .properties.addAll(builder.toObjectInitializer().properties); 1434 .properties.addAll(builder.toObjectInitializer().properties);
1443 } 1435 }
1444 } 1436 }
1445 } 1437 }
1446 1438
1447 // Emit all required typedef declarations into the main output unit.
1448 // TODO(karlklose): unify required classes and typedefs to declarations
1449 // and have builders for each kind.
1450 for (TypedefElement typedef in typedefsNeededForReflection) {
1451 OutputUnit mainUnit = compiler.deferredLoadTask.mainOutputUnit;
1452 LibraryElement library = typedef.library;
1453 // TODO(karlklose): add a TypedefBuilder and move this code there.
1454 DartType type = typedef.alias;
1455 int typeIndex = metadataEmitter.reifyType(type);
1456 String typeReference =
1457 encoding.encodeTypedefFieldDescriptor(typeIndex);
1458 jsAst.Property descriptor = new jsAst.Property(
1459 js.string(namer.classDescriptorProperty),
1460 js.string(typeReference));
1461 jsAst.Node declaration = new jsAst.ObjectInitializer([descriptor]);
1462 ClassBuilder builder;
1463 getElementDescriptorForOutputUnit(library, mainUnit)
1464 .addProperty(namer.getNameX(typedef), declaration);
1465 }
1466
1467 if (!mangledFieldNames.isEmpty) { 1439 if (!mangledFieldNames.isEmpty) {
1468 var keys = mangledFieldNames.keys.toList(); 1440 var keys = mangledFieldNames.keys.toList();
1469 keys.sort(); 1441 keys.sort();
1470 var properties = []; 1442 var properties = [];
1471 for (String key in keys) { 1443 for (String key in keys) {
1472 var value = js.string('${mangledFieldNames[key]}'); 1444 var value = js.string('${mangledFieldNames[key]}');
1473 properties.add(new jsAst.Property(js.string(key), value)); 1445 properties.add(new jsAst.Property(js.string(key), value));
1474 } 1446 }
1475 var map = new jsAst.ObjectInitializer(properties); 1447 var map = new jsAst.ObjectInitializer(properties);
1476 mainBuffer.write( 1448 mainBuffer.write(
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after
1713 1685
1714 ClassBuilder getElementDescriptorForOutputUnit(Element element, 1686 ClassBuilder getElementDescriptorForOutputUnit(Element element,
1715 OutputUnit outputUnit) { 1687 OutputUnit outputUnit) {
1716 Map<OutputUnit, ClassBuilder> descriptors = 1688 Map<OutputUnit, ClassBuilder> descriptors =
1717 elementDescriptors.putIfAbsent( 1689 elementDescriptors.putIfAbsent(
1718 element, () => new Map<OutputUnit, ClassBuilder>()); 1690 element, () => new Map<OutputUnit, ClassBuilder>());
1719 return descriptors.putIfAbsent(outputUnit, 1691 return descriptors.putIfAbsent(outputUnit,
1720 () => new ClassBuilder(namer)); 1692 () => new ClassBuilder(namer));
1721 } 1693 }
1722 1694
1723 ClassBuilder getElementDescriptor(Element element) { 1695 ClassBuilder getElementDecriptor(Element element) {
1724 Element owner = element.library; 1696 Element owner = element.library;
1725 if (!element.isTopLevel && !element.isNative) { 1697 if (!element.isTopLevel && !element.isNative) {
1726 // For static (not top level) elements, record their code in a buffer 1698 // For static (not top level) elements, record their code in a buffer
1727 // specific to the class. For now, not supported for native classes and 1699 // specific to the class. For now, not supported for native classes and
1728 // native elements. 1700 // native elements.
1729 ClassElement cls = 1701 ClassElement cls =
1730 element.enclosingClassOrCompilationUnit.declaration; 1702 element.enclosingClassOrCompilationUnit.declaration;
1731 if (compiler.codegenWorld.instantiatedClasses.contains(cls) 1703 if (compiler.codegenWorld.instantiatedClasses.contains(cls)
1732 && !cls.isNative) { 1704 && !cls.isNative) {
1733 owner = cls; 1705 owner = cls;
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
1828 for (Element element in compiler.enqueuer.codegen.newlyEnqueuedElements) { 1800 for (Element element in compiler.enqueuer.codegen.newlyEnqueuedElements) {
1829 if (element.isInstanceMember) { 1801 if (element.isInstanceMember) {
1830 cachedClassBuilders.remove(element.enclosingClass); 1802 cachedClassBuilders.remove(element.enclosingClass);
1831 1803
1832 nativeEmitter.cachedBuilders.remove(element.enclosingClass); 1804 nativeEmitter.cachedBuilders.remove(element.enclosingClass);
1833 1805
1834 } 1806 }
1835 } 1807 }
1836 } 1808 }
1837 } 1809 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698