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

Side by Side Diff: pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart

Issue 1233693002: dart2js: Add embedded globals to startup emitter. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Fix another reference to the moved global. Created 5 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
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, 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.startup_emitter.model_emitter; 5 part of dart2js.js_emitter.startup_emitter.model_emitter;
6 6
7 /// The fast startup emitter's goal is to minimize the amount of work that the 7 /// The fast startup emitter's goal is to minimize the amount of work that the
8 /// JavaScript engine has to do before it can start running user code. 8 /// JavaScript engine has to do before it can start running user code.
9 /// 9 ///
10 /// Whenever possible, the emitter uses object literals instead of updating 10 /// Whenever possible, the emitter uses object literals instead of updating
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after
230 230
231 // Sets the prototypes of classes. 231 // Sets the prototypes of classes.
232 #prototypes; 232 #prototypes;
233 // Sets aliases of methods (on the prototypes of classes). 233 // Sets aliases of methods (on the prototypes of classes).
234 #aliases; 234 #aliases;
235 // Installs the tear-offs of functions. 235 // Installs the tear-offs of functions.
236 #tearOffs; 236 #tearOffs;
237 // Builds the inheritance structure. 237 // Builds the inheritance structure.
238 #inheritance; 238 #inheritance;
239 239
240 // Emits the embedded globals.
241 #embeddedGlobals;
242
243 // Sets up the native support.
244 // Native-support uses setOrUpdateInterceptorsByTag and setOrUpdateLeafTags.
245 #nativeSupport;
246
247 // Instantiates all constants. 240 // Instantiates all constants.
248 #constants; 241 #constants;
249 // Initializes the static non-final fields (with their constant values). 242 // Initializes the static non-final fields (with their constant values).
250 #staticNonFinalFields; 243 #staticNonFinalFields;
251 // Creates lazy getters for statics that must run initializers on first access. 244 // Creates lazy getters for statics that must run initializers on first access.
252 #lazyStatics; 245 #lazyStatics;
253 246
247 // Emits the embedded globals.
248 #embeddedGlobals;
249
250 // Sets up the native support.
251 // Native-support uses setOrUpdateInterceptorsByTag and setOrUpdateLeafTags.
252 #nativeSupport;
253
254 // Invokes main (making sure that it records the 'current-script' value). 254 // Invokes main (making sure that it records the 'current-script' value).
255 #invokeMain; 255 #invokeMain;
256 })(); 256 })();
257 }'''; 257 }''';
258 258
259 /// Deferred fragments (aka 'hunks') are built similarly to the main fragment. 259 /// Deferred fragments (aka 'hunks') are built similarly to the main fragment.
260 /// 260 ///
261 /// However, at specific moments they need to contribute their data. 261 /// However, at specific moments they need to contribute their data.
262 /// For example, once the holders have been created, they are included into 262 /// For example, once the holders have been created, they are included into
263 /// the main holders. 263 /// the main holders.
(...skipping 14 matching lines...) Expand all
278 #updateHolders; 278 #updateHolders;
279 // Sets the prototypes of the new classes. 279 // Sets the prototypes of the new classes.
280 #prototypes; 280 #prototypes;
281 // Sets aliases of methods (on the prototypes of classes). 281 // Sets aliases of methods (on the prototypes of classes).
282 #aliases; 282 #aliases;
283 // Installs the tear-offs of functions. 283 // Installs the tear-offs of functions.
284 #tearOffs; 284 #tearOffs;
285 // Builds the inheritance structure. 285 // Builds the inheritance structure.
286 #inheritance; 286 #inheritance;
287 287
288 updateTypes(#types);
289
290 // Native-support uses setOrUpdateInterceptorsByTag and setOrUpdateLeafTags.
291 #nativeSupport;
292
293 // Instantiates all constants of this deferred fragment. 288 // Instantiates all constants of this deferred fragment.
294 // Note that the constant-holder has been updated earlier and storing the 289 // Note that the constant-holder has been updated earlier and storing the
295 // constant values in the constant-holder makes them available globally. 290 // constant values in the constant-holder makes them available globally.
296 #constants; 291 #constants;
297 // Initializes the static non-final fields (with their constant values). 292 // Initializes the static non-final fields (with their constant values).
298 #staticNonFinalFields; 293 #staticNonFinalFields;
299 // Creates lazy getters for statics that must run initializers on first access. 294 // Creates lazy getters for statics that must run initializers on first access.
300 #lazyStatics; 295 #lazyStatics;
296
297 updateTypes(#types);
298
299 // Native-support uses setOrUpdateInterceptorsByTag and setOrUpdateLeafTags.
300 #nativeSupport;
301 }; 301 };
302 // TODO(floitsch): this last line should be outside the AST, since it 302 // TODO(floitsch): this last line should be outside the AST, since it
303 // requires to know the hash of the part of the code above this comment. 303 // requires to know the hash of the part of the code above this comment.
304 #deferredInitializers[#hash] = #deferredInitializers.current; 304 #deferredInitializers[#hash] = #deferredInitializers.current;
305 }'''; 305 }''';
306 306
307 /** 307 /**
308 * This class builds a JavaScript tree for a given fragment. 308 * This class builds a JavaScript tree for a given fragment.
309 * 309 *
310 * A fragment is generally written into a separate file so that it can be 310 * A fragment is generally written into a separate file so that it can be
(...skipping 543 matching lines...) Expand 10 before | Expand all | Expand 10 after
854 return js.js.statement("lazy(#, #, #, #);", 854 return js.js.statement("lazy(#, #, #, #);",
855 [field.holder.name, 855 [field.holder.name,
856 js.quoteName(field.name), 856 js.quoteName(field.name),
857 js.quoteName(namer.deriveLazyInitializerName(field.name)), 857 js.quoteName(namer.deriveLazyInitializerName(field.name)),
858 field.code]); 858 field.code]);
859 }); 859 });
860 860
861 return new js.Block(statements.toList()); 861 return new js.Block(statements.toList());
862 } 862 }
863 863
864 emitEmbeddedGlobals(program) { 864 /// Emits the embedded globals that are needed for deferred loading.
865 throw new UnimplementedError('emitEmbeddedGlobals'); 865 ///
866 /// This function is only invoked for the main fragment.
867 ///
868 /// The [loadMap] contains a map from load-ids (for each deferred library)
869 /// to the list of generated fragments that must be installed when the
870 /// deferred library is loaded.
871 Iterable<js.Property> emitEmbeddedGlobalsForDeferredLoading(
872 Map<String, List<Fragment>> loadMap) {
873 if (loadMap.isEmpty) return [];
874
875 List<js.Property> globals = <js.Property>[];
876
877 js.ArrayInitializer fragmentUris(List<Fragment> fragments) {
878 return js.stringArray(fragments.map((DeferredFragment fragment) =>
879 "${fragment.outputFileName}.${ModelEmitter.deferredExtension}"));
880 }
881 js.ArrayInitializer fragmentHashes(List<Fragment> fragments) {
882 // TODO(floitsch): the hash must depend on the generated code.
883 return js.numArray(
884 fragments.map((DeferredFragment fragment) => fragment.hashCode));
885 }
886
887 List<js.Property> uris = new List<js.Property>(loadMap.length);
888 List<js.Property> hashes = new List<js.Property>(loadMap.length);
889 int count = 0;
890 loadMap.forEach((String loadId, List<Fragment> fragmentList) {
891 uris[count] =
892 new js.Property(js.string(loadId), fragmentUris(fragmentList));
893 hashes[count] =
894 new js.Property(js.string(loadId), fragmentHashes(fragmentList));
895 count++;
896 });
897
898 globals.add(new js.Property(js.string(DEFERRED_LIBRARY_URIS),
899 new js.ObjectInitializer(uris)));
900 globals.add(new js.Property(js.string(DEFERRED_LIBRARY_HASHES),
901 new js.ObjectInitializer(hashes)));
902 globals.add(new js.Property(js.string(DEFERRED_INITIALIZED),
903 js.js("Object.create(null)")));
904
905 String deferredGlobal = ModelEmitter.deferredInitializersGlobal;
906 js.Expression isHunkLoadedFunction =
907 js.js("function(hash) { return !!$deferredGlobal[hash]; }");
908 globals.add(new js.Property(js.string(IS_HUNK_LOADED),
909 isHunkLoadedFunction));
910
911 js.Expression isHunkInitializedFunction =
912 js.js("function(hash) { return !!#deferredInitialized[hash]; }",
913 {'deferredInitialized':
914 generateEmbeddedGlobalAccess(DEFERRED_INITIALIZED)});
915 globals.add(new js.Property(js.string(IS_HUNK_INITIALIZED),
916 isHunkInitializedFunction));
917
918 /// See [emitEmbeddedGlobalsForDeferredLoading] for the format of the
919 /// deferred hunk.
920 js.Expression initializeLoadedHunkFunction =
921 js.js("""
922 function(hash) {
923 initializeDeferredHunk($deferredGlobal[hash]);
924 #deferredInitialized[hash] = true;
925 }""", {'deferredInitialized':
926 generateEmbeddedGlobalAccess(DEFERRED_INITIALIZED)});
927
928 globals.add(new js.Property(js.string(INITIALIZE_LOADED_HUNK),
929 initializeLoadedHunkFunction));
930
931 return globals;
932 }
933
934 /// Emits the [MANGLED_GLOBAL_NAMES] embedded global.
935 ///
936 /// This global maps minified names for selected classes (some important
937 /// core classes, and some native classes) to their unminified names.
938 js.Property emitMangledGlobalNames() {
939 List<js.Property> names = <js.Property>[];
940
941 // We want to keep the original names for the most common core classes when
942 // calling toString on them.
943 List<ClassElement> nativeClassesNeedingUnmangledName =
944 [compiler.intClass, compiler.doubleClass, compiler.numClass,
945 compiler.stringClass, compiler.boolClass, compiler.nullClass,
946 compiler.listClass];
947 // TODO(floitsch): this should probably be on a per-fragment basis.
948 nativeClassesNeedingUnmangledName.forEach((element) {
949 names.add(new js.Property(js.quoteName(namer.className(element)),
950 js.string(element.name)));
951 });
952
953 return new js.Property(js.string(MANGLED_GLOBAL_NAMES),
954 new js.ObjectInitializer(names));
955 }
956
957 /// Emits the [GET_TYPE_FROM_NAME] embedded global.
958 ///
959 /// This embedded global provides a way to go from a class name (which is
960 /// also the constructor's name) to the constructor itself.
961 js.Property emitGetTypeFromName() {
962 // TODO(floitsch): Fix getTypeFromName. It's too inefficient.
963 // The current implementation relies on the fact that the names in holders
964 // are unique across all holders.
965 // TODO(floitsch): constants and other globals may share the same name.
966 // If a global happens to have the same (minified) name this code breaks.
967 // A follow-up CL has a fix for this.
968 js.Expression function =
969 js.js( """function(name) {
970 for (var i = 0; i < holders.length; i++) {
971 // Relies on the fact that all variables are unique.
972 if (holders[i][name]) return holders[i][name];
973 }
974 }""");
975 return new js.Property(js.string(GET_TYPE_FROM_NAME), function);
976 }
977
978 /// Emits the [METADATA] embedded global.
979 ///
980 /// The metadata itself has already been computed earlier and is stored in
981 /// the [program].
982 List<js.Property> emitMetadata(Program program) {
983 List<js.Property> metadataGlobals = <js.Property>[];
984
985 js.Property createGlobal(js.Expression metadata, String global) {
986 return new js.Property(js.string(global), metadata);
987 }
988
989 metadataGlobals.add(createGlobal(program.metadata, METADATA));
990 js.Expression types =
991 program.metadataTypesForOutputUnit(program.mainFragment.outputUnit);
992 metadataGlobals.add(createGlobal(types, TYPES));
993
994 return metadataGlobals;
995 }
996
997 /// Emits all embedded globals.
998 js.Block emitEmbeddedGlobals(Program program) {
999 List<js.Property> globals = <js.Property>[];
1000
1001 if (program.loadMap.isNotEmpty) {
1002 globals.addAll(emitEmbeddedGlobalsForDeferredLoading(program.loadMap));
1003 }
1004
1005 if (program.typeToInterceptorMap != null) {
1006 globals.add(new js.Property(js.string(TYPE_TO_INTERCEPTOR_MAP),
1007 program.typeToInterceptorMap));
1008 }
1009
1010 if (program.hasIsolateSupport) {
1011 String staticStateName = namer.staticStateHolder;
1012 // TODO(floitsch): this doesn't create a new isolate, but just reuses
1013 // the current static state. Since we don't run multiple isolates in the
1014 // same JavaScript context (except for testing) this shouldn't have any
1015 // impact on real-world programs, though.
1016 globals.add(
1017 new js.Property(js.string(CREATE_NEW_ISOLATE),
1018 js.js('function () { return $staticStateName; }')));
1019 // TODO(floitsch): add remaining isolate functions.
1020 }
1021
1022 globals.add(emitMangledGlobalNames());
1023
1024 globals.add(emitGetTypeFromName());
1025
1026 globals.addAll(emitMetadata(program));
1027
1028 if (program.needsNativeSupport) {
1029 globals.add(new js.Property(js.string(INTERCEPTORS_BY_TAG),
1030 new js.LiteralNull()));
1031 globals.add(new js.Property(js.string(LEAF_TAGS),
1032 new js.LiteralNull()));
1033 }
1034
1035 js.ObjectInitializer globalsObject = new js.ObjectInitializer(globals);
1036
1037 List<js.Statement> statements =
1038 [new js.ExpressionStatement(
1039 new js.VariableDeclarationList(
1040 [new js.VariableInitialization(
1041 new js.VariableDeclaration("init", allowRename: false),
1042 globalsObject)]))];
Siggi Cherem (dart-lang) 2015/07/22 23:16:29 this makes me wonder if there are more features we
floitsch 2015/07/29 17:47:59 I actually think that we should be able to rename
1043 return new js.Block(statements);
866 } 1044 }
867 1045
868 emitNativeSupport(fragment) { 1046 emitNativeSupport(fragment) {
869 throw new UnimplementedError('emitNativeSupport'); 1047 throw new UnimplementedError('emitNativeSupport');
870 } 1048 }
871 } 1049 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698