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

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: Allow to rename "init". Created 5 years, 4 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 220 matching lines...) Expand 10 before | Expand all | Expand 10 after
231 231
232 // Sets the prototypes of classes. 232 // Sets the prototypes of classes.
233 #prototypes; 233 #prototypes;
234 // Sets aliases of methods (on the prototypes of classes). 234 // Sets aliases of methods (on the prototypes of classes).
235 #aliases; 235 #aliases;
236 // Installs the tear-offs of functions. 236 // Installs the tear-offs of functions.
237 #tearOffs; 237 #tearOffs;
238 // Builds the inheritance structure. 238 // Builds the inheritance structure.
239 #inheritance; 239 #inheritance;
240 240
241 // Emits the embedded globals.
242 #embeddedGlobals;
243
244 // Sets up the native support.
245 // Native-support uses setOrUpdateInterceptorsByTag and setOrUpdateLeafTags.
246 #nativeSupport;
247
248 // Instantiates all constants. 241 // Instantiates all constants.
249 #constants; 242 #constants;
250 // Initializes the static non-final fields (with their constant values). 243 // Initializes the static non-final fields (with their constant values).
251 #staticNonFinalFields; 244 #staticNonFinalFields;
252 // Creates lazy getters for statics that must run initializers on first access. 245 // Creates lazy getters for statics that must run initializers on first access.
253 #lazyStatics; 246 #lazyStatics;
254 247
248 // Emits the embedded globals.
249 #embeddedGlobals;
250
251 // Sets up the native support.
252 // Native-support uses setOrUpdateInterceptorsByTag and setOrUpdateLeafTags.
253 #nativeSupport;
254
255 // Invokes main (making sure that it records the 'current-script' value). 255 // Invokes main (making sure that it records the 'current-script' value).
256 #invokeMain; 256 #invokeMain;
257 })(); 257 })();
258 }'''; 258 }''';
259 259
260 /// Deferred fragments (aka 'hunks') are built similarly to the main fragment. 260 /// Deferred fragments (aka 'hunks') are built similarly to the main fragment.
261 /// 261 ///
262 /// However, at specific moments they need to contribute their data. 262 /// However, at specific moments they need to contribute their data.
263 /// For example, once the holders have been created, they are included into 263 /// For example, once the holders have been created, they are included into
264 /// the main holders. 264 /// the main holders.
(...skipping 14 matching lines...) Expand all
279 #updateHolders; 279 #updateHolders;
280 // Sets the prototypes of the new classes. 280 // Sets the prototypes of the new classes.
281 #prototypes; 281 #prototypes;
282 // Sets aliases of methods (on the prototypes of classes). 282 // Sets aliases of methods (on the prototypes of classes).
283 #aliases; 283 #aliases;
284 // Installs the tear-offs of functions. 284 // Installs the tear-offs of functions.
285 #tearOffs; 285 #tearOffs;
286 // Builds the inheritance structure. 286 // Builds the inheritance structure.
287 #inheritance; 287 #inheritance;
288 288
289 updateTypes(#types);
290
291 // Native-support uses setOrUpdateInterceptorsByTag and setOrUpdateLeafTags.
292 #nativeSupport;
293
294 // Instantiates all constants of this deferred fragment. 289 // Instantiates all constants of this deferred fragment.
295 // Note that the constant-holder has been updated earlier and storing the 290 // Note that the constant-holder has been updated earlier and storing the
296 // constant values in the constant-holder makes them available globally. 291 // constant values in the constant-holder makes them available globally.
297 #constants; 292 #constants;
298 // Initializes the static non-final fields (with their constant values). 293 // Initializes the static non-final fields (with their constant values).
299 #staticNonFinalFields; 294 #staticNonFinalFields;
300 // Creates lazy getters for statics that must run initializers on first access. 295 // Creates lazy getters for statics that must run initializers on first access.
301 #lazyStatics; 296 #lazyStatics;
297
298 updateTypes(#types);
299
300 // Native-support uses setOrUpdateInterceptorsByTag and setOrUpdateLeafTags.
301 #nativeSupport;
302 }; 302 };
303 // TODO(floitsch): this last line should be outside the AST, since it 303 // TODO(floitsch): this last line should be outside the AST, since it
304 // requires to know the hash of the part of the code above this comment. 304 // requires to know the hash of the part of the code above this comment.
305 #deferredInitializers[#hash] = #deferredInitializers.current; 305 #deferredInitializers[#hash] = #deferredInitializers.current;
306 }'''; 306 }''';
307 307
308 /** 308 /**
309 * This class builds a JavaScript tree for a given fragment. 309 * This class builds a JavaScript tree for a given fragment.
310 * 310 *
311 * A fragment is generally written into a separate file so that it can be 311 * A fragment is generally written into a separate file so that it can be
(...skipping 542 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.Statement 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 return js.js.statement('var init = #;', globalsObject);
866 } 1038 }
867 1039
868 emitNativeSupport(fragment) { 1040 emitNativeSupport(fragment) {
869 throw new UnimplementedError('emitNativeSupport'); 1041 throw new UnimplementedError('emitNativeSupport');
870 } 1042 }
871 } 1043 }
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