| 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 |
| 198 Program buildProgram({bool storeFunctionTypesInMetadata: false}) { | 200 Program buildProgram({bool storeFunctionTypesInMetadata: false}) { |
| 199 collector.collect(); | 201 collector.collect(); |
| 200 _initializeSoftDeferredMap(); | 202 _initializeSoftDeferredMap(); |
| 201 | 203 |
| 202 this._storeFunctionTypesInMetadata = storeFunctionTypesInMetadata; | 204 this._storeFunctionTypesInMetadata = storeFunctionTypesInMetadata; |
| 203 // Note: In rare cases (mostly tests) output units can be empty. This | 205 // Note: In rare cases (mostly tests) output units can be empty. This |
| 204 // happens when the deferred code is dead-code eliminated but we still need | 206 // happens when the deferred code is dead-code eliminated but we still need |
| 205 // to check that the library has been loaded. | 207 // to check that the library has been loaded. |
| 206 _deferredLoadTask.allOutputUnits.forEach(_registry.registerOutputUnit); | 208 _deferredLoadTask.allOutputUnits.forEach(_registry.registerOutputUnit); |
| 207 collector.outputClassLists.forEach(_registry.registerClasses); | 209 collector.outputClassLists.forEach(_registry.registerClasses); |
| (...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 453 // TODO(floitsch): we shouldn't update the registry in the middle of | 455 // TODO(floitsch): we shouldn't update the registry in the middle of |
| 454 // building a static field. (Note that the static-state holder was | 456 // building a static field. (Note that the static-state holder was |
| 455 // already registered earlier, and that we just call the register to get | 457 // already registered earlier, and that we just call the register to get |
| 456 // the holder-instance. | 458 // the holder-instance. |
| 457 return new StaticField( | 459 return new StaticField( |
| 458 element, name, _registerStaticStateHolder(), code, isFinal, isLazy); | 460 element, name, _registerStaticStateHolder(), code, isFinal, isLazy); |
| 459 } | 461 } |
| 460 | 462 |
| 461 List<StaticField> _buildStaticLazilyInitializedFields( | 463 List<StaticField> _buildStaticLazilyInitializedFields( |
| 462 LibrariesMap librariesMap) { | 464 LibrariesMap librariesMap) { |
| 463 Iterable<FieldElement> lazyFields = _constantHandler | 465 Iterable<FieldEntity> lazyFields = _constantHandler |
| 464 .getLazilyInitializedFieldsForEmission() | 466 .getLazilyInitializedFieldsForEmission() |
| 465 .where((element) => | 467 .where((FieldEntity element) => |
| 466 _deferredLoadTask.outputUnitForElement(element) == | 468 _deferredLoadTask.outputUnitForMember(element) == |
| 467 librariesMap.outputUnit); | 469 librariesMap.outputUnit); |
| 468 return Elements | 470 return _sorter |
| 469 .sortedByPosition(lazyFields) | 471 .sortMembers(lazyFields) |
| 470 .map(_buildLazyField) | 472 .map(_buildLazyField) |
| 471 .where((field) => field != null) // Happens when the field was unused. | 473 .where((field) => field != null) // Happens when the field was unused. |
| 472 .toList(growable: false); | 474 .toList(growable: false); |
| 473 } | 475 } |
| 474 | 476 |
| 475 StaticField _buildLazyField(FieldElement element) { | 477 StaticField _buildLazyField(FieldEntity element) { |
| 476 js.Expression code = _generatedCode[element]; | 478 js.Expression code = _generatedCode[element]; |
| 477 // The code is null if we ended up not needing the lazily | 479 // The code is null if we ended up not needing the lazily |
| 478 // initialized field after all because of constant folding | 480 // initialized field after all because of constant folding |
| 479 // before code generation. | 481 // before code generation. |
| 480 if (code == null) return null; | 482 if (code == null) return null; |
| 481 | 483 |
| 482 js.Name name = _namer.globalPropertyNameForMember(element); | 484 js.Name name = _namer.globalPropertyNameForMember(element); |
| 483 bool isFinal = element.isFinal; | 485 bool isFinal = !element.isAssignable; |
| 484 bool isLazy = true; | 486 bool isLazy = true; |
| 485 // TODO(floitsch): we shouldn't update the registry in the middle of | 487 // TODO(floitsch): we shouldn't update the registry in the middle of |
| 486 // building a static field. (Note that the static-state holder was | 488 // building a static field. (Note that the static-state holder was |
| 487 // already registered earlier, and that we just call the register to get | 489 // already registered earlier, and that we just call the register to get |
| 488 // the holder-instance. | 490 // the holder-instance. |
| 489 return new StaticField( | 491 return new StaticField( |
| 490 element, name, _registerStaticStateHolder(), code, isFinal, isLazy); | 492 element, name, _registerStaticStateHolder(), code, isFinal, isLazy); |
| 491 } | 493 } |
| 492 | 494 |
| 493 List<Library> _buildLibraries(LibrariesMap librariesMap) { | 495 List<Library> _buildLibraries(LibrariesMap librariesMap) { |
| (...skipping 482 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 976 } | 978 } |
| 977 } | 979 } |
| 978 | 980 |
| 979 List<ParameterStubMethod> _generateParameterStubs( | 981 List<ParameterStubMethod> _generateParameterStubs( |
| 980 FunctionEntity element, bool canTearOff) { | 982 FunctionEntity element, bool canTearOff) { |
| 981 if (!_methodNeedsStubs(element)) return const <ParameterStubMethod>[]; | 983 if (!_methodNeedsStubs(element)) return const <ParameterStubMethod>[]; |
| 982 | 984 |
| 983 ParameterStubGenerator generator = new ParameterStubGenerator( | 985 ParameterStubGenerator generator = new ParameterStubGenerator( |
| 984 _commonElements, | 986 _commonElements, |
| 985 _task, | 987 _task, |
| 986 _constantHandler, | |
| 987 _namer, | 988 _namer, |
| 988 _nativeData, | 989 _nativeData, |
| 989 _interceptorData, | 990 _interceptorData, |
| 990 _worldBuilder, | 991 _worldBuilder, |
| 991 _closedWorld); | 992 _closedWorld); |
| 992 return generator.generateParameterStubs(element, canTearOff: canTearOff); | 993 return generator.generateParameterStubs(element, canTearOff: canTearOff); |
| 993 } | 994 } |
| 994 | 995 |
| 995 /// Builds a stub method. | 996 /// Builds a stub method. |
| 996 /// | 997 /// |
| 997 /// Stub methods may have an element that can be used for code-size | 998 /// Stub methods may have an element that can be used for code-size |
| 998 /// attribution. | 999 /// attribution. |
| 999 Method _buildStubMethod(js.Name name, js.Expression code, | 1000 Method _buildStubMethod(js.Name name, js.Expression code, |
| 1000 {MemberElement element}) { | 1001 {MemberElement element}) { |
| 1001 return new StubMethod(name, code, element: element); | 1002 return new StubMethod(name, code, element: element); |
| 1002 } | 1003 } |
| 1003 | 1004 |
| 1004 // The getInterceptor methods directly access the prototype of classes. | 1005 // The getInterceptor methods directly access the prototype of classes. |
| 1005 // We must evaluate these classes eagerly so that the prototype is | 1006 // We must evaluate these classes eagerly so that the prototype is |
| 1006 // accessible. | 1007 // accessible. |
| 1007 void _markEagerInterceptorClasses() { | 1008 void _markEagerInterceptorClasses() { |
| 1008 Iterable<js.Name> names = | 1009 Iterable<js.Name> names = |
| 1009 _oneShotInterceptorData.specializedGetInterceptorNames; | 1010 _oneShotInterceptorData.specializedGetInterceptorNames; |
| 1010 for (js.Name name in names) { | 1011 for (js.Name name in names) { |
| 1011 for (ClassElement element | 1012 for (ClassEntity element |
| 1012 in _oneShotInterceptorData.getSpecializedGetInterceptorsFor(name)) { | 1013 in _oneShotInterceptorData.getSpecializedGetInterceptorsFor(name)) { |
| 1013 Class cls = _classes[element]; | 1014 Class cls = _classes[element]; |
| 1014 if (cls != null) cls.isEager = true; | 1015 if (cls != null) cls.isEager = true; |
| 1015 } | 1016 } |
| 1016 } | 1017 } |
| 1017 } | 1018 } |
| 1018 | 1019 |
| 1019 Iterable<StaticStubMethod> _generateGetInterceptorMethods() { | 1020 Iterable<StaticStubMethod> _generateGetInterceptorMethods() { |
| 1020 InterceptorStubGenerator stubGenerator = new InterceptorStubGenerator( | 1021 InterceptorStubGenerator stubGenerator = new InterceptorStubGenerator( |
| 1021 _options, | 1022 _options, |
| (...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1189 Constant constant = new Constant(name, holder, constantValue); | 1190 Constant constant = new Constant(name, holder, constantValue); |
| 1190 _constants[constantValue] = constant; | 1191 _constants[constantValue] = constant; |
| 1191 } | 1192 } |
| 1192 } | 1193 } |
| 1193 | 1194 |
| 1194 Holder _registerStaticStateHolder() { | 1195 Holder _registerStaticStateHolder() { |
| 1195 return _registry.registerHolder(_namer.staticStateHolder, | 1196 return _registry.registerHolder(_namer.staticStateHolder, |
| 1196 isStaticStateHolder: true); | 1197 isStaticStateHolder: true); |
| 1197 } | 1198 } |
| 1198 } | 1199 } |
| OLD | NEW |