| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 library dart2js.js_emitter.program_builder; | 5 library dart2js.js_emitter.program_builder; |
| 6 | 6 |
| 7 import 'dart:io'; | 7 import 'dart:io'; |
| 8 import 'dart:convert' show JSON; | 8 import 'dart:convert' show JSON; |
| 9 | 9 |
| 10 import '../../closure.dart' show ClosureConversionTask, ClosureFieldElement; | 10 import '../../closure.dart' show ClosureConversionTask, ClosureFieldElement; |
| (...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 188 Set<Class> _unneededNativeClasses; | 188 Set<Class> _unneededNativeClasses; |
| 189 | 189 |
| 190 /// Classes that have been allocated during a profile run. | 190 /// Classes that have been allocated during a profile run. |
| 191 /// | 191 /// |
| 192 /// These classes should not be soft-deferred. | 192 /// These classes should not be soft-deferred. |
| 193 /// | 193 /// |
| 194 /// Also contains classes that are not tracked by the profile run (like | 194 /// Also contains classes that are not tracked by the profile run (like |
| 195 /// interceptors, ...). | 195 /// interceptors, ...). |
| 196 Set<ClassElement> _notSoftDeferred; | 196 Set<ClassElement> _notSoftDeferred; |
| 197 | 197 |
| 198 Sorter get _sorter => _task.sorter; | |
| 199 | |
| 200 Program buildProgram({bool storeFunctionTypesInMetadata: false}) { | 198 Program buildProgram({bool storeFunctionTypesInMetadata: false}) { |
| 201 collector.collect(); | 199 collector.collect(); |
| 202 _initializeSoftDeferredMap(); | 200 _initializeSoftDeferredMap(); |
| 203 | 201 |
| 204 this._storeFunctionTypesInMetadata = storeFunctionTypesInMetadata; | 202 this._storeFunctionTypesInMetadata = storeFunctionTypesInMetadata; |
| 205 // Note: In rare cases (mostly tests) output units can be empty. This | 203 // Note: In rare cases (mostly tests) output units can be empty. This |
| 206 // happens when the deferred code is dead-code eliminated but we still need | 204 // happens when the deferred code is dead-code eliminated but we still need |
| 207 // to check that the library has been loaded. | 205 // to check that the library has been loaded. |
| 208 _deferredLoadTask.allOutputUnits.forEach(_registry.registerOutputUnit); | 206 _deferredLoadTask.allOutputUnits.forEach(_registry.registerOutputUnit); |
| 209 collector.outputClassLists.forEach(_registry.registerClasses); | 207 collector.outputClassLists.forEach(_registry.registerClasses); |
| (...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 433 } | 431 } |
| 434 | 432 |
| 435 List<StaticField> _buildStaticNonFinalFields(LibrariesMap librariesMap) { | 433 List<StaticField> _buildStaticNonFinalFields(LibrariesMap librariesMap) { |
| 436 List<FieldEntity> staticNonFinalFields = | 434 List<FieldEntity> staticNonFinalFields = |
| 437 collector.outputStaticNonFinalFieldLists[librariesMap.outputUnit]; | 435 collector.outputStaticNonFinalFieldLists[librariesMap.outputUnit]; |
| 438 if (staticNonFinalFields == null) return const <StaticField>[]; | 436 if (staticNonFinalFields == null) return const <StaticField>[]; |
| 439 | 437 |
| 440 return staticNonFinalFields.map(_buildStaticField).toList(growable: false); | 438 return staticNonFinalFields.map(_buildStaticField).toList(growable: false); |
| 441 } | 439 } |
| 442 | 440 |
| 443 StaticField _buildStaticField(FieldEntity element) { | 441 StaticField _buildStaticField(FieldElement element) { |
| 444 ConstantValue initialValue = | 442 ConstantValue initialValue = |
| 445 _worldBuilder.getConstantFieldInitializer(element); | 443 _constantHandler.getConstantValue(element.constant); |
| 446 // TODO(zarah): The holder should not be registered during building of | 444 // TODO(zarah): The holder should not be registered during building of |
| 447 // a static field. | 445 // a static field. |
| 448 _registry.registerHolder(_namer.globalObjectForConstant(initialValue), | 446 _registry.registerHolder(_namer.globalObjectForConstant(initialValue), |
| 449 isConstantsHolder: true); | 447 isConstantsHolder: true); |
| 450 js.Expression code = _task.emitter.constantReference(initialValue); | 448 js.Expression code = _task.emitter.constantReference(initialValue); |
| 451 js.Name name = _namer.globalPropertyNameForMember(element); | 449 js.Name name = _namer.globalPropertyNameForMember(element); |
| 452 bool isFinal = false; | 450 bool isFinal = false; |
| 453 bool isLazy = false; | 451 bool isLazy = false; |
| 454 | 452 |
| 455 // TODO(floitsch): we shouldn't update the registry in the middle of | 453 // TODO(floitsch): we shouldn't update the registry in the middle of |
| 456 // building a static field. (Note that the static-state holder was | 454 // building a static field. (Note that the static-state holder was |
| 457 // already registered earlier, and that we just call the register to get | 455 // already registered earlier, and that we just call the register to get |
| 458 // the holder-instance. | 456 // the holder-instance. |
| 459 return new StaticField( | 457 return new StaticField( |
| 460 element, name, _registerStaticStateHolder(), code, isFinal, isLazy); | 458 element, name, _registerStaticStateHolder(), code, isFinal, isLazy); |
| 461 } | 459 } |
| 462 | 460 |
| 463 List<StaticField> _buildStaticLazilyInitializedFields( | 461 List<StaticField> _buildStaticLazilyInitializedFields( |
| 464 LibrariesMap librariesMap) { | 462 LibrariesMap librariesMap) { |
| 465 Iterable<FieldEntity> lazyFields = _constantHandler | 463 Iterable<FieldElement> lazyFields = _constantHandler |
| 466 .getLazilyInitializedFieldsForEmission() | 464 .getLazilyInitializedFieldsForEmission() |
| 467 .where((FieldEntity element) => | 465 .where((element) => |
| 468 _deferredLoadTask.outputUnitForMember(element) == | 466 _deferredLoadTask.outputUnitForElement(element) == |
| 469 librariesMap.outputUnit); | 467 librariesMap.outputUnit); |
| 470 return _sorter | 468 return Elements |
| 471 .sortMembers(lazyFields) | 469 .sortedByPosition(lazyFields) |
| 472 .map(_buildLazyField) | 470 .map(_buildLazyField) |
| 473 .where((field) => field != null) // Happens when the field was unused. | 471 .where((field) => field != null) // Happens when the field was unused. |
| 474 .toList(growable: false); | 472 .toList(growable: false); |
| 475 } | 473 } |
| 476 | 474 |
| 477 StaticField _buildLazyField(FieldEntity element) { | 475 StaticField _buildLazyField(FieldElement element) { |
| 478 js.Expression code = _generatedCode[element]; | 476 js.Expression code = _generatedCode[element]; |
| 479 // The code is null if we ended up not needing the lazily | 477 // The code is null if we ended up not needing the lazily |
| 480 // initialized field after all because of constant folding | 478 // initialized field after all because of constant folding |
| 481 // before code generation. | 479 // before code generation. |
| 482 if (code == null) return null; | 480 if (code == null) return null; |
| 483 | 481 |
| 484 js.Name name = _namer.globalPropertyNameForMember(element); | 482 js.Name name = _namer.globalPropertyNameForMember(element); |
| 485 bool isFinal = !element.isAssignable; | 483 bool isFinal = element.isFinal; |
| 486 bool isLazy = true; | 484 bool isLazy = true; |
| 487 // TODO(floitsch): we shouldn't update the registry in the middle of | 485 // TODO(floitsch): we shouldn't update the registry in the middle of |
| 488 // building a static field. (Note that the static-state holder was | 486 // building a static field. (Note that the static-state holder was |
| 489 // already registered earlier, and that we just call the register to get | 487 // already registered earlier, and that we just call the register to get |
| 490 // the holder-instance. | 488 // the holder-instance. |
| 491 return new StaticField( | 489 return new StaticField( |
| 492 element, name, _registerStaticStateHolder(), code, isFinal, isLazy); | 490 element, name, _registerStaticStateHolder(), code, isFinal, isLazy); |
| 493 } | 491 } |
| 494 | 492 |
| 495 List<Library> _buildLibraries(LibrariesMap librariesMap) { | 493 List<Library> _buildLibraries(LibrariesMap librariesMap) { |
| (...skipping 482 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 978 } | 976 } |
| 979 } | 977 } |
| 980 | 978 |
| 981 List<ParameterStubMethod> _generateParameterStubs( | 979 List<ParameterStubMethod> _generateParameterStubs( |
| 982 FunctionEntity element, bool canTearOff) { | 980 FunctionEntity element, bool canTearOff) { |
| 983 if (!_methodNeedsStubs(element)) return const <ParameterStubMethod>[]; | 981 if (!_methodNeedsStubs(element)) return const <ParameterStubMethod>[]; |
| 984 | 982 |
| 985 ParameterStubGenerator generator = new ParameterStubGenerator( | 983 ParameterStubGenerator generator = new ParameterStubGenerator( |
| 986 _commonElements, | 984 _commonElements, |
| 987 _task, | 985 _task, |
| 986 _constantHandler, |
| 988 _namer, | 987 _namer, |
| 989 _nativeData, | 988 _nativeData, |
| 990 _interceptorData, | 989 _interceptorData, |
| 991 _worldBuilder, | 990 _worldBuilder, |
| 992 _closedWorld); | 991 _closedWorld); |
| 993 return generator.generateParameterStubs(element, canTearOff: canTearOff); | 992 return generator.generateParameterStubs(element, canTearOff: canTearOff); |
| 994 } | 993 } |
| 995 | 994 |
| 996 /// Builds a stub method. | 995 /// Builds a stub method. |
| 997 /// | 996 /// |
| 998 /// Stub methods may have an element that can be used for code-size | 997 /// Stub methods may have an element that can be used for code-size |
| 999 /// attribution. | 998 /// attribution. |
| 1000 Method _buildStubMethod(js.Name name, js.Expression code, | 999 Method _buildStubMethod(js.Name name, js.Expression code, |
| 1001 {MemberElement element}) { | 1000 {MemberElement element}) { |
| 1002 return new StubMethod(name, code, element: element); | 1001 return new StubMethod(name, code, element: element); |
| 1003 } | 1002 } |
| 1004 | 1003 |
| 1005 // The getInterceptor methods directly access the prototype of classes. | 1004 // The getInterceptor methods directly access the prototype of classes. |
| 1006 // We must evaluate these classes eagerly so that the prototype is | 1005 // We must evaluate these classes eagerly so that the prototype is |
| 1007 // accessible. | 1006 // accessible. |
| 1008 void _markEagerInterceptorClasses() { | 1007 void _markEagerInterceptorClasses() { |
| 1009 Iterable<js.Name> names = | 1008 Iterable<js.Name> names = |
| 1010 _oneShotInterceptorData.specializedGetInterceptorNames; | 1009 _oneShotInterceptorData.specializedGetInterceptorNames; |
| 1011 for (js.Name name in names) { | 1010 for (js.Name name in names) { |
| 1012 for (ClassEntity element | 1011 for (ClassElement element |
| 1013 in _oneShotInterceptorData.getSpecializedGetInterceptorsFor(name)) { | 1012 in _oneShotInterceptorData.getSpecializedGetInterceptorsFor(name)) { |
| 1014 Class cls = _classes[element]; | 1013 Class cls = _classes[element]; |
| 1015 if (cls != null) cls.isEager = true; | 1014 if (cls != null) cls.isEager = true; |
| 1016 } | 1015 } |
| 1017 } | 1016 } |
| 1018 } | 1017 } |
| 1019 | 1018 |
| 1020 Iterable<StaticStubMethod> _generateGetInterceptorMethods() { | 1019 Iterable<StaticStubMethod> _generateGetInterceptorMethods() { |
| 1021 InterceptorStubGenerator stubGenerator = new InterceptorStubGenerator( | 1020 InterceptorStubGenerator stubGenerator = new InterceptorStubGenerator( |
| 1022 _options, | 1021 _options, |
| (...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1190 Constant constant = new Constant(name, holder, constantValue); | 1189 Constant constant = new Constant(name, holder, constantValue); |
| 1191 _constants[constantValue] = constant; | 1190 _constants[constantValue] = constant; |
| 1192 } | 1191 } |
| 1193 } | 1192 } |
| 1194 | 1193 |
| 1195 Holder _registerStaticStateHolder() { | 1194 Holder _registerStaticStateHolder() { |
| 1196 return _registry.registerHolder(_namer.staticStateHolder, | 1195 return _registry.registerHolder(_namer.staticStateHolder, |
| 1197 isStaticStateHolder: true); | 1196 isStaticStateHolder: true); |
| 1198 } | 1197 } |
| 1199 } | 1198 } |
| OLD | NEW |