| OLD | NEW |
| 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 15 matching lines...) Expand all Loading... |
| 26 NativeEmitter nativeEmitter; | 26 NativeEmitter nativeEmitter; |
| 27 Map<OutputUnit, CodeBuffer> outputBuffers = new Map<OutputUnit, CodeBuffer>(); | 27 Map<OutputUnit, CodeBuffer> outputBuffers = new Map<OutputUnit, CodeBuffer>(); |
| 28 final CodeBuffer deferredConstants = new CodeBuffer(); | 28 final CodeBuffer deferredConstants = new CodeBuffer(); |
| 29 /** Shorter access to [isolatePropertiesName]. Both here in the code, as | 29 /** Shorter access to [isolatePropertiesName]. Both here in the code, as |
| 30 well as in the generated code. */ | 30 well as in the generated code. */ |
| 31 String isolateProperties; | 31 String isolateProperties; |
| 32 String classesCollector; | 32 String classesCollector; |
| 33 final Set<ClassElement> neededClasses = new Set<ClassElement>(); | 33 final Set<ClassElement> neededClasses = new Set<ClassElement>(); |
| 34 final Map<OutputUnit, List<ClassElement>> outputClassLists = | 34 final Map<OutputUnit, List<ClassElement>> outputClassLists = |
| 35 new Map<OutputUnit, List<ClassElement>>(); | 35 new Map<OutputUnit, List<ClassElement>>(); |
| 36 final Map<OutputUnit, List<Constant>> outputConstantLists = |
| 37 new Map<OutputUnit, List<Constant>>(); |
| 36 final List<ClassElement> nativeClasses = <ClassElement>[]; | 38 final List<ClassElement> nativeClasses = <ClassElement>[]; |
| 37 final Map<String, String> mangledFieldNames = <String, String>{}; | 39 final Map<String, String> mangledFieldNames = <String, String>{}; |
| 38 final Map<String, String> mangledGlobalFieldNames = <String, String>{}; | 40 final Map<String, String> mangledGlobalFieldNames = <String, String>{}; |
| 39 final Set<String> recordedMangledNames = new Set<String>(); | 41 final Set<String> recordedMangledNames = new Set<String>(); |
| 40 | 42 |
| 41 final Map<ClassElement, Map<String, jsAst.Expression>> additionalProperties = | 43 final Map<ClassElement, Map<String, jsAst.Expression>> additionalProperties = |
| 42 new Map<ClassElement, Map<String, jsAst.Expression>>(); | 44 new Map<ClassElement, Map<String, jsAst.Expression>>(); |
| 43 | 45 |
| 44 /// Records if a type variable is read dynamically for type tests. | 46 /// Records if a type variable is read dynamically for type tests. |
| 45 final Set<TypeVariableElement> readTypeVariables = | 47 final Set<TypeVariableElement> readTypeVariables = |
| (...skipping 363 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 409 var finishedClasses = {}; | 411 var finishedClasses = {}; |
| 410 init.interceptorsByTag = Object.create(null); | 412 init.interceptorsByTag = Object.create(null); |
| 411 init.leafTags = {}; | 413 init.leafTags = {}; |
| 412 | 414 |
| 413 #; // buildFinishClass(), | 415 #; // buildFinishClass(), |
| 414 | 416 |
| 415 #; // buildTrivialNsmHandlers() | 417 #; // buildTrivialNsmHandlers() |
| 416 | 418 |
| 417 for (var cls in pendingClasses) finishClass(cls); | 419 for (var cls in pendingClasses) finishClass(cls); |
| 418 }''', [ | 420 }''', [ |
| 419 DEBUG_FAST_OBJECTS, | 421 DEBUG_FAST_OBJECTS, |
| 420 backend.hasRetainedMetadata, | 422 backend.hasRetainedMetadata, |
| 421 needsMixinSupport, | 423 needsMixinSupport, |
| 422 backend.isTreeShakingDisabled, | 424 backend.isTreeShakingDisabled, |
| 423 buildFinishClass(), | 425 buildFinishClass(), |
| 424 nsmEmitter.buildTrivialNsmHandlers()]); | 426 nsmEmitter.buildTrivialNsmHandlers()]); |
| 425 | 427 |
| 426 } | 428 } |
| 427 | 429 |
| 428 jsAst.Node optional(bool condition, jsAst.Node node) { | 430 jsAst.Node optional(bool condition, jsAst.Node node) { |
| 429 return condition ? node : new jsAst.EmptyStatement(); | 431 return condition ? node : new jsAst.EmptyStatement(); |
| 430 } | 432 } |
| 431 | 433 |
| 432 jsAst.FunctionDeclaration buildFinishClass() { | 434 jsAst.FunctionDeclaration buildFinishClass() { |
| 433 String specProperty = '"${namer.nativeSpecProperty}"'; // "%" | 435 String specProperty = '"${namer.nativeSpecProperty}"'; // "%" |
| 434 | 436 |
| 435 return js.statement(''' | 437 return js.statement(''' |
| (...skipping 434 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 870 } | 872 } |
| 871 } | 873 } |
| 872 } | 874 } |
| 873 | 875 |
| 874 jsAst.Expression buildLazyInitializedGetter(VariableElement element) { | 876 jsAst.Expression buildLazyInitializedGetter(VariableElement element) { |
| 875 // Nothing to do, the 'lazy' function will create the getter. | 877 // Nothing to do, the 'lazy' function will create the getter. |
| 876 return null; | 878 return null; |
| 877 } | 879 } |
| 878 | 880 |
| 879 void emitCompileTimeConstants(CodeBuffer buffer, OutputUnit outputUnit) { | 881 void emitCompileTimeConstants(CodeBuffer buffer, OutputUnit outputUnit) { |
| 880 JavaScriptConstantCompiler handler = backend.constants; | 882 List<Constant> constants = outputConstantLists[outputUnit]; |
| 881 List<Constant> constants = handler.getConstantsForEmission( | 883 if (constants == null) return; |
| 882 compareConstants); | |
| 883 Set<Constant> outputUnitConstants = null; | |
| 884 // TODO(sigurdm): We shouldn't run through all constants for every | |
| 885 // outputUnit. | |
| 886 for (Constant constant in constants) { | 884 for (Constant constant in constants) { |
| 887 if (isConstantInlinedOrAlreadyEmitted(constant)) continue; | |
| 888 OutputUnit constantUnit = | |
| 889 compiler.deferredLoadTask.outputUnitForConstant(constant); | |
| 890 if (constantUnit != outputUnit && constantUnit != null) continue; | |
| 891 if (outputUnit != compiler.deferredLoadTask.mainOutputUnit | |
| 892 && constantUnit == null) { | |
| 893 // The back-end introduces some constants, like "InterceptorConstant" or | |
| 894 // some list constants. They are emitted in the main output-unit, and | |
| 895 // ignored otherwise. | |
| 896 // TODO(sigurdm): We should track those constants. | |
| 897 continue; | |
| 898 } | |
| 899 | |
| 900 String name = namer.constantName(constant); | 885 String name = namer.constantName(constant); |
| 901 if (constant.isList) emitMakeConstantListIfNotEmitted(buffer); | 886 if (constant.isList) emitMakeConstantListIfNotEmitted(buffer); |
| 902 jsAst.Expression init = js('#.# = #', | 887 jsAst.Expression init = js('#.# = #', |
| 903 [namer.globalObjectForConstant(constant), name, | 888 [namer.globalObjectForConstant(constant), name, |
| 904 constantInitializerExpression(constant)]); | 889 constantInitializerExpression(constant)]); |
| 905 buffer.write(jsAst.prettyPrint(init, compiler)); | 890 buffer.write(jsAst.prettyPrint(init, compiler)); |
| 906 buffer.write('$N'); | 891 buffer.write('$N'); |
| 907 } | 892 } |
| 908 } | 893 } |
| 909 | 894 |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1070 if (typeof dartMainRunner === "function") { | 1055 if (typeof dartMainRunner === "function") { |
| 1071 dartMainRunner(${mainCallClosure}, []); | 1056 dartMainRunner(${mainCallClosure}, []); |
| 1072 } else { | 1057 } else { |
| 1073 ${mainCallClosure}([]); | 1058 ${mainCallClosure}([]); |
| 1074 } | 1059 } |
| 1075 })$N'''); | 1060 })$N'''); |
| 1076 addComment('END invoke [main].', buffer); | 1061 addComment('END invoke [main].', buffer); |
| 1077 } | 1062 } |
| 1078 | 1063 |
| 1079 /** | 1064 /** |
| 1065 * Compute all the constants that must be emitted. |
| 1066 */ |
| 1067 void computeNeededConstants() { |
| 1068 JavaScriptConstantCompiler handler = backend.constants; |
| 1069 List<Constant> constants = handler.getConstantsForEmission( |
| 1070 compareConstants); |
| 1071 for (Constant constant in constants) { |
| 1072 if (isConstantInlinedOrAlreadyEmitted(constant)) continue; |
| 1073 OutputUnit constantUnit = |
| 1074 compiler.deferredLoadTask.outputUnitForConstant(constant); |
| 1075 if (constantUnit == null) { |
| 1076 // The back-end introduces some constants, like "InterceptorConstant" or |
| 1077 // some list constants. They are emitted in the main output-unit. |
| 1078 // TODO(sigurdm): We should track those constants. |
| 1079 constantUnit = compiler.deferredLoadTask.mainOutputUnit; |
| 1080 } |
| 1081 outputConstantLists.putIfAbsent(constantUnit, () => new List<Constant>()) |
| 1082 .add(constant); |
| 1083 } |
| 1084 } |
| 1085 |
| 1086 /** |
| 1080 * Compute all the classes that must be emitted. | 1087 * Compute all the classes that must be emitted. |
| 1081 */ | 1088 */ |
| 1082 void computeNeededClasses() { | 1089 void computeNeededClasses() { |
| 1083 instantiatedClasses = | 1090 instantiatedClasses = |
| 1084 compiler.codegenWorld.instantiatedClasses.where(computeClassFilter()) | 1091 compiler.codegenWorld.instantiatedClasses.where(computeClassFilter()) |
| 1085 .toSet(); | 1092 .toSet(); |
| 1086 | 1093 |
| 1087 void addClassWithSuperclasses(ClassElement cls) { | 1094 void addClassWithSuperclasses(ClassElement cls) { |
| 1088 neededClasses.add(cls); | 1095 neededClasses.add(cls); |
| 1089 for (ClassElement superclass = cls.superclass; | 1096 for (ClassElement superclass = cls.superclass; |
| (...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1419 classesCollector = oldClassesCollector; | 1426 classesCollector = oldClassesCollector; |
| 1420 } | 1427 } |
| 1421 OutputUnit mainOutputUnit = compiler.deferredLoadTask.mainOutputUnit; | 1428 OutputUnit mainOutputUnit = compiler.deferredLoadTask.mainOutputUnit; |
| 1422 typeTestEmitter.emitRuntimeTypeSupport(mainBuffer, mainOutputUnit); | 1429 typeTestEmitter.emitRuntimeTypeSupport(mainBuffer, mainOutputUnit); |
| 1423 interceptorEmitter.emitGetInterceptorMethods(mainBuffer); | 1430 interceptorEmitter.emitGetInterceptorMethods(mainBuffer); |
| 1424 interceptorEmitter.emitOneShotInterceptors(mainBuffer); | 1431 interceptorEmitter.emitOneShotInterceptors(mainBuffer); |
| 1425 // Constants in checked mode call into RTI code to set type information | 1432 // Constants in checked mode call into RTI code to set type information |
| 1426 // which may need getInterceptor (and one-shot interceptor) methods, so | 1433 // which may need getInterceptor (and one-shot interceptor) methods, so |
| 1427 // we have to make sure that [emitGetInterceptorMethods] and | 1434 // we have to make sure that [emitGetInterceptorMethods] and |
| 1428 // [emitOneShotInterceptors] have been called. | 1435 // [emitOneShotInterceptors] have been called. |
| 1436 computeNeededConstants(); |
| 1429 emitCompileTimeConstants(mainBuffer, mainOutputUnit); | 1437 emitCompileTimeConstants(mainBuffer, mainOutputUnit); |
| 1430 | 1438 |
| 1431 // Write a javascript mapping from Deferred import load ids (derrived from | 1439 // Write a javascript mapping from Deferred import load ids (derrived from |
| 1432 // the import prefix.) to a list of lists of js hunks to load. | 1440 // the import prefix.) to a list of lists of js hunks to load. |
| 1433 // TODO(sigurdm): Create a syntax tree for this. | 1441 // TODO(sigurdm): Create a syntax tree for this. |
| 1434 // TODO(sigurdm): Also find out where to place it. | 1442 // TODO(sigurdm): Also find out where to place it. |
| 1435 mainBuffer.write("\$.libraries_to_load = {"); | 1443 mainBuffer.write("\$.libraries_to_load = {"); |
| 1436 for (String loadId in compiler.deferredLoadTask.hunksToLoad.keys) { | 1444 for (String loadId in compiler.deferredLoadTask.hunksToLoad.keys) { |
| 1437 // TODO(sigurdm): Escape these strings. | 1445 // TODO(sigurdm): Escape these strings. |
| 1438 mainBuffer.write('"$loadId":['); | 1446 mainBuffer.write('"$loadId":['); |
| (...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1700 String sourceMap = sourceMapBuilder.build(); | 1708 String sourceMap = sourceMapBuilder.build(); |
| 1701 compiler.outputProvider(name, 'js.map') | 1709 compiler.outputProvider(name, 'js.map') |
| 1702 ..add(sourceMap) | 1710 ..add(sourceMap) |
| 1703 ..close(); | 1711 ..close(); |
| 1704 } | 1712 } |
| 1705 | 1713 |
| 1706 void registerReadTypeVariable(TypeVariableElement element) { | 1714 void registerReadTypeVariable(TypeVariableElement element) { |
| 1707 readTypeVariables.add(element); | 1715 readTypeVariables.add(element); |
| 1708 } | 1716 } |
| 1709 } | 1717 } |
| OLD | NEW |