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

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

Issue 1235973004: dart2js: Use the correct hashes for deferred code in the startup-emitter. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Address comments. 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
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 245 matching lines...) Expand 10 before | Expand all | Expand 10 after
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.
265 const String deferredBoilerplate = ''' 265 const String deferredBoilerplate = '''
266 {
267 #deferredInitializers.current =
268 function(inherit, mixin, lazy, makeConstList, installTearOff, 266 function(inherit, mixin, lazy, makeConstList, installTearOff,
269 updateHolder, updateTypes, 267 updateHolder, updateTypes,
270 setOrUpdateInterceptorsByTag, setOrUpdateLeafTags, 268 setOrUpdateInterceptorsByTag, setOrUpdateLeafTags,
271 #embeddedGlobalsObject, holdersList, #staticState) { 269 #embeddedGlobalsObject, holdersList, #staticState) {
272 270
273 // Builds the holders. They only contain the data for new holders. 271 // Builds the holders. They only contain the data for new holders.
274 #holders; 272 #holders;
275 // Updates the holders of the main-fragment. Uses the provided holdersList to 273 // Updates the holders of the main-fragment. Uses the provided holdersList to
276 // access the main holders. 274 // access the main holders.
277 // The local holders are replaced by the combined holders. This is necessary 275 // The local holders are replaced by the combined holders. This is necessary
(...skipping 14 matching lines...) Expand all
292 #constants; 290 #constants;
293 // Initializes the static non-final fields (with their constant values). 291 // Initializes the static non-final fields (with their constant values).
294 #staticNonFinalFields; 292 #staticNonFinalFields;
295 // Creates lazy getters for statics that must run initializers on first access. 293 // Creates lazy getters for statics that must run initializers on first access.
296 #lazyStatics; 294 #lazyStatics;
297 295
298 updateTypes(#types); 296 updateTypes(#types);
299 297
300 // Native-support uses setOrUpdateInterceptorsByTag and setOrUpdateLeafTags. 298 // Native-support uses setOrUpdateInterceptorsByTag and setOrUpdateLeafTags.
301 #nativeSupport; 299 #nativeSupport;
302 };
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.
305 #deferredInitializers[#hash] = #deferredInitializers.current;
306 }'''; 300 }''';
307 301
308 /** 302 /**
309 * This class builds a JavaScript tree for a given fragment. 303 * This class builds a JavaScript tree for a given fragment.
310 * 304 *
311 * A fragment is generally written into a separate file so that it can be 305 * A fragment is generally written into a separate file so that it can be
312 * loaded dynamically when a deferred library is loaded. 306 * loaded dynamically when a deferred library is loaded.
313 * 307 *
314 * This class is stateless and can be reused for different fragments. 308 * This class is stateless and can be reused for different fragments.
315 */ 309 */
(...skipping 10 matching lines...) Expand all
326 js.Expression generateEmbeddedGlobalAccess(String global) => 320 js.Expression generateEmbeddedGlobalAccess(String global) =>
327 modelEmitter.generateEmbeddedGlobalAccess(global); 321 modelEmitter.generateEmbeddedGlobalAccess(global);
328 322
329 js.Expression generateConstantReference(ConstantValue value) => 323 js.Expression generateConstantReference(ConstantValue value) =>
330 modelEmitter.generateConstantReference(value); 324 modelEmitter.generateConstantReference(value);
331 325
332 js.Expression classReference(Class cls) { 326 js.Expression classReference(Class cls) {
333 return js.js('#.#', [cls.holder.name, cls.name]); 327 return js.js('#.#', [cls.holder.name, cls.name]);
334 } 328 }
335 329
336 js.Statement emitMainFragment(Program program) { 330 js.Statement emitMainFragment(
331 Program program,
332 Map<DeferredFragment, _DeferredFragmentHash> deferredLoadHashes) {
337 MainFragment fragment = program.fragments.first; 333 MainFragment fragment = program.fragments.first;
338 334
339 return js.js.statement(mainBoilerplate, 335 return js.js.statement(mainBoilerplate,
340 {'deferredInitializer': emitDeferredInitializerGlobal(program.loadMap), 336 {'deferredInitializer': emitDeferredInitializerGlobal(program.loadMap),
341 'typeNameProperty': js.string(ModelEmitter.typeNameProperty), 337 'typeNameProperty': js.string(ModelEmitter.typeNameProperty),
342 'cyclicThrow': backend.emitter.staticFunctionAccess( 338 'cyclicThrow': backend.emitter.staticFunctionAccess(
343 backend.getCyclicThrowHelper()), 339 backend.getCyclicThrowHelper()),
344 'operatorIsPrefix': js.string(namer.operatorIsPrefix), 340 'operatorIsPrefix': js.string(namer.operatorIsPrefix),
345 'tearOffCode': new js.Block(buildTearOffCode(backend)), 341 'tearOffCode': new js.Block(buildTearOffCode(backend)),
346 'embeddedTypes': generateEmbeddedGlobalAccess(TYPES), 342 'embeddedTypes': generateEmbeddedGlobalAccess(TYPES),
(...skipping 11 matching lines...) Expand all
358 'callName': js.string(namer.callNameField), 354 'callName': js.string(namer.callNameField),
359 'argumentCount': js.string(namer.requiredParameterField), 355 'argumentCount': js.string(namer.requiredParameterField),
360 'defaultArgumentValues': js.string(namer.defaultValuesField), 356 'defaultArgumentValues': js.string(namer.defaultValuesField),
361 'prototypes': emitPrototypes(fragment), 357 'prototypes': emitPrototypes(fragment),
362 'inheritance': emitInheritance(fragment), 358 'inheritance': emitInheritance(fragment),
363 'aliases': emitInstanceMethodAliases(fragment), 359 'aliases': emitInstanceMethodAliases(fragment),
364 'tearOffs': emitInstallTearOffs(fragment), 360 'tearOffs': emitInstallTearOffs(fragment),
365 'constants': emitConstants(fragment), 361 'constants': emitConstants(fragment),
366 'staticNonFinalFields': emitStaticNonFinalFields(fragment), 362 'staticNonFinalFields': emitStaticNonFinalFields(fragment),
367 'lazyStatics': emitLazilyInitializedStatics(fragment), 363 'lazyStatics': emitLazilyInitializedStatics(fragment),
368 'embeddedGlobals': emitEmbeddedGlobals(program), 364 'embeddedGlobals': emitEmbeddedGlobals(program, deferredLoadHashes),
369 'nativeSupport': program.needsNativeSupport 365 'nativeSupport': program.needsNativeSupport
370 ? emitNativeSupport(fragment) 366 ? emitNativeSupport(fragment)
371 : new js.EmptyStatement(), 367 : new js.EmptyStatement(),
372 'invokeMain': fragment.invokeMain, 368 'invokeMain': fragment.invokeMain,
373 }); 369 });
374 } 370 }
375 371
376 js.Statement emitDeferredFragment(DeferredFragment fragment, 372 js.Expression emitDeferredFragment(DeferredFragment fragment,
377 js.Expression deferredTypes, 373 js.Expression deferredTypes,
378 List<Holder> holders) { 374 List<Holder> holders) {
379 List<js.Statement> updateHolderAssignments = <js.Statement>[]; 375 List<js.Statement> updateHolderAssignments = <js.Statement>[];
380 for (int i = 0; i < holders.length; i++) { 376 for (int i = 0; i < holders.length; i++) {
381 Holder holder = holders[i]; 377 Holder holder = holders[i];
382 if (holder.isStaticStateHolder) continue; 378 if (holder.isStaticStateHolder) continue;
383 updateHolderAssignments.add(js.js.statement( 379 updateHolderAssignments.add(js.js.statement(
384 '#holder = updateHolder(holdersList[#index], #holder)', 380 '#holder = updateHolder(holdersList[#index], #holder)',
385 {'index': js.number(i), 381 {'index': js.number(i),
386 'holder': new js.VariableUse(holder.name)})); 382 'holder': new js.VariableUse(holder.name)}));
387 } 383 }
388 384
389 // TODO(floitsch): if name is not set, run through all functions and set the 385 // TODO(floitsch): if name is not set, run through all functions and set the
390 // name for IE. 386 // name for IE.
391 // TODO(floitsch): don't just reference 'init'. 387 // TODO(floitsch): don't just reference 'init'.
392 return js.js.statement(deferredBoilerplate, 388 return js.js(deferredBoilerplate,
393 {'deferredInitializers': 389 {'embeddedGlobalsObject': new js.Parameter('init'),
394 js.js('#', ModelEmitter.deferredInitializersGlobal), 390 'staticState': new js.Parameter(namer.staticStateHolder),
395 'embeddedGlobalsObject': new js.Parameter('init'), 391 'holders': emitHolders(holders, fragment),
396 'staticState': new js.Parameter(namer.staticStateHolder), 392 'updateHolders': new js.Block(updateHolderAssignments),
397 'holders': emitHolders(holders, fragment), 393 'prototypes': emitPrototypes(fragment),
398 'updateHolders': new js.Block(updateHolderAssignments), 394 'inheritance': emitInheritance(fragment),
399 'prototypes': emitPrototypes(fragment), 395 'aliases': emitInstanceMethodAliases(fragment),
400 'inheritance': emitInheritance(fragment), 396 'tearOffs': emitInstallTearOffs(fragment),
401 'aliases': emitInstanceMethodAliases(fragment), 397 'constants': emitConstants(fragment),
402 'tearOffs': emitInstallTearOffs(fragment), 398 'staticNonFinalFields': emitStaticNonFinalFields(fragment),
403 'constants': emitConstants(fragment), 399 'lazyStatics': emitLazilyInitializedStatics(fragment),
404 'staticNonFinalFields': emitStaticNonFinalFields(fragment), 400 'types': deferredTypes,
405 'lazyStatics': emitLazilyInitializedStatics(fragment), 401 // TODO(floitsch): only call emitNativeSupport if we need native.
406 'types': deferredTypes, 402 'nativeSupport': emitNativeSupport(fragment),
407 // TODO(floitsch): only call emitNativeSupport if we need native.
408 'nativeSupport': emitNativeSupport(fragment),
409 'hash': js.number(fragment.hashCode),
410 }); 403 });
411 } 404 }
412 405
413 js.Statement emitDeferredInitializerGlobal(Map loadMap) { 406 js.Statement emitDeferredInitializerGlobal(Map loadMap) {
414 if (loadMap.isEmpty) return new js.Block.empty(); 407 if (loadMap.isEmpty) return new js.Block.empty();
415 408
416 return js.js.statement(""" 409 return js.js.statement("""
417 if (typeof(${ModelEmitter.deferredInitializersGlobal}) === 'undefined') 410 if (typeof(${ModelEmitter.deferredInitializersGlobal}) === 'undefined')
418 var ${ModelEmitter.deferredInitializersGlobal} = Object.create(null);"""); 411 var ${ModelEmitter.deferredInitializersGlobal} = Object.create(null);""");
419 } 412 }
(...skipping 443 matching lines...) Expand 10 before | Expand all | Expand 10 after
863 } 856 }
864 857
865 /// Emits the embedded globals that are needed for deferred loading. 858 /// Emits the embedded globals that are needed for deferred loading.
866 /// 859 ///
867 /// This function is only invoked for the main fragment. 860 /// This function is only invoked for the main fragment.
868 /// 861 ///
869 /// The [loadMap] contains a map from load-ids (for each deferred library) 862 /// The [loadMap] contains a map from load-ids (for each deferred library)
870 /// to the list of generated fragments that must be installed when the 863 /// to the list of generated fragments that must be installed when the
871 /// deferred library is loaded. 864 /// deferred library is loaded.
872 Iterable<js.Property> emitEmbeddedGlobalsForDeferredLoading( 865 Iterable<js.Property> emitEmbeddedGlobalsForDeferredLoading(
873 Map<String, List<Fragment>> loadMap) { 866 Map<String, List<Fragment>> loadMap,
867 Map<DeferredFragment, _DeferredFragmentHash> deferredLoadHashes) {
874 if (loadMap.isEmpty) return []; 868 if (loadMap.isEmpty) return [];
875 869
876 List<js.Property> globals = <js.Property>[]; 870 List<js.Property> globals = <js.Property>[];
877 871
878 js.ArrayInitializer fragmentUris(List<Fragment> fragments) { 872 js.ArrayInitializer fragmentUris(List<Fragment> fragments) {
879 return js.stringArray(fragments.map((DeferredFragment fragment) => 873 return js.stringArray(fragments.map((DeferredFragment fragment) =>
880 "${fragment.outputFileName}.${ModelEmitter.deferredExtension}")); 874 "${fragment.outputFileName}.${ModelEmitter.deferredExtension}"));
881 } 875 }
882 js.ArrayInitializer fragmentHashes(List<Fragment> fragments) { 876 js.ArrayInitializer fragmentHashes(List<Fragment> fragments) {
883 // TODO(floitsch): the hash must depend on the generated code. 877 return new js.ArrayInitializer(
884 return js.numArray( 878 fragments
885 fragments.map((DeferredFragment fragment) => fragment.hashCode)); 879 .map((fragment) => deferredLoadHashes[fragment])
880 .toList(growable: false));
886 } 881 }
887 882
888 List<js.Property> uris = new List<js.Property>(loadMap.length); 883 List<js.Property> uris = new List<js.Property>(loadMap.length);
889 List<js.Property> hashes = new List<js.Property>(loadMap.length); 884 List<js.Property> hashes = new List<js.Property>(loadMap.length);
890 int count = 0; 885 int count = 0;
891 loadMap.forEach((String loadId, List<Fragment> fragmentList) { 886 loadMap.forEach((String loadId, List<Fragment> fragmentList) {
892 uris[count] = 887 uris[count] =
893 new js.Property(js.string(loadId), fragmentUris(fragmentList)); 888 new js.Property(js.string(loadId), fragmentUris(fragmentList));
894 hashes[count] = 889 hashes[count] =
895 new js.Property(js.string(loadId), fragmentHashes(fragmentList)); 890 new js.Property(js.string(loadId), fragmentHashes(fragmentList));
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
989 984
990 metadataGlobals.add(createGlobal(program.metadata, METADATA)); 985 metadataGlobals.add(createGlobal(program.metadata, METADATA));
991 js.Expression types = 986 js.Expression types =
992 program.metadataTypesForOutputUnit(program.mainFragment.outputUnit); 987 program.metadataTypesForOutputUnit(program.mainFragment.outputUnit);
993 metadataGlobals.add(createGlobal(types, TYPES)); 988 metadataGlobals.add(createGlobal(types, TYPES));
994 989
995 return metadataGlobals; 990 return metadataGlobals;
996 } 991 }
997 992
998 /// Emits all embedded globals. 993 /// Emits all embedded globals.
999 js.Block emitEmbeddedGlobals(Program program) { 994 js.Block emitEmbeddedGlobals(
995 Program program,
996 Map<DeferredFragment, _DeferredFragmentHash> deferredLoadHashes) {
1000 List<js.Property> globals = <js.Property>[]; 997 List<js.Property> globals = <js.Property>[];
1001 998
1002 if (program.loadMap.isNotEmpty) { 999 if (program.loadMap.isNotEmpty) {
1003 globals.addAll(emitEmbeddedGlobalsForDeferredLoading(program.loadMap)); 1000 globals.addAll(emitEmbeddedGlobalsForDeferredLoading(
1001 program.loadMap, deferredLoadHashes));
1004 } 1002 }
1005 1003
1006 if (program.typeToInterceptorMap != null) { 1004 if (program.typeToInterceptorMap != null) {
1007 globals.add(new js.Property(js.string(TYPE_TO_INTERCEPTOR_MAP), 1005 globals.add(new js.Property(js.string(TYPE_TO_INTERCEPTOR_MAP),
1008 program.typeToInterceptorMap)); 1006 program.typeToInterceptorMap));
1009 } 1007 }
1010 1008
1011 if (program.hasIsolateSupport) { 1009 if (program.hasIsolateSupport) {
1012 String staticStateName = namer.staticStateHolder; 1010 String staticStateName = namer.staticStateHolder;
1013 // TODO(floitsch): this doesn't create a new isolate, but just reuses 1011 // TODO(floitsch): this doesn't create a new isolate, but just reuses
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
1097 } 1095 }
1098 statements.add(js.js.statement("setOrUpdateInterceptorsByTag(#);", 1096 statements.add(js.js.statement("setOrUpdateInterceptorsByTag(#);",
1099 js.objectLiteral(interceptorsByTag))); 1097 js.objectLiteral(interceptorsByTag)));
1100 statements.add(js.js.statement("setOrUpdateLeafTags(#);", 1098 statements.add(js.js.statement("setOrUpdateLeafTags(#);",
1101 js.objectLiteral(leafTags))); 1099 js.objectLiteral(leafTags)));
1102 statements.add(subclassAssignment); 1100 statements.add(subclassAssignment);
1103 1101
1104 return new js.Block(statements); 1102 return new js.Block(statements);
1105 } 1103 }
1106 } 1104 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698