| 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 '../../closure.dart' show ClosureTask, ClosureFieldElement; | 7 import '../../closure.dart' show ClosureTask, ClosureFieldElement; |
| 8 import '../../common.dart'; | 8 import '../../common.dart'; |
| 9 import '../../common/names.dart' show Names, Selectors; | 9 import '../../common/names.dart' show Names, Selectors; |
| 10 import '../../compiler.dart' show Compiler; | |
| 11 import '../../constants/values.dart' | 10 import '../../constants/values.dart' |
| 12 show ConstantValue, InterceptorConstantValue; | 11 show ConstantValue, InterceptorConstantValue; |
| 13 import '../../common_elements.dart' show CommonElements; | 12 import '../../common_elements.dart' show CommonElements; |
| 14 import '../../elements/resolution_types.dart' | 13 import '../../elements/resolution_types.dart' |
| 15 show ResolutionDartType, ResolutionFunctionType, ResolutionTypedefType; | 14 show ResolutionDartType, ResolutionFunctionType, ResolutionTypedefType; |
| 16 import '../../deferred_load.dart' show DeferredLoadTask, OutputUnit; | 15 import '../../deferred_load.dart' show DeferredLoadTask, OutputUnit; |
| 17 import '../../elements/elements.dart' | 16 import '../../elements/elements.dart' |
| 18 show | 17 show |
| 19 ClassElement, | 18 ClassElement, |
| 20 Element, | 19 Element, |
| 21 Elements, | 20 Elements, |
| 22 FieldElement, | 21 FieldElement, |
| 23 FunctionElement, | 22 FunctionElement, |
| 24 FunctionSignature, | 23 FunctionSignature, |
| 25 GetterElement, | 24 GetterElement, |
| 26 LibraryElement, | 25 LibraryElement, |
| 27 MemberElement, | 26 MemberElement, |
| 28 MethodElement, | 27 MethodElement, |
| 29 ParameterElement, | 28 ParameterElement, |
| 30 TypedefElement, | 29 TypedefElement, |
| 31 VariableElement; | 30 VariableElement; |
| 32 import '../../elements/entities.dart'; | 31 import '../../elements/entities.dart'; |
| 33 import '../../elements/resolution_types.dart' show Types; | 32 import '../../elements/resolution_types.dart' show Types; |
| 34 import '../../elements/types.dart' show DartType; | 33 import '../../elements/types.dart' show DartType; |
| 35 import '../../js/js.dart' as js; | 34 import '../../js/js.dart' as js; |
| 36 import '../../js_backend/backend.dart' | 35 import '../../js_backend/backend.dart' |
| 37 show | 36 show |
| 38 JavaScriptBackend, | |
| 39 RuntimeTypesChecks, | 37 RuntimeTypesChecks, |
| 40 RuntimeTypesNeed, | 38 RuntimeTypesNeed, |
| 41 RuntimeTypesEncoder, | 39 RuntimeTypesEncoder, |
| 42 RuntimeTypesSubstitutions, | 40 RuntimeTypesSubstitutions, |
| 43 SuperMemberData; | 41 SuperMemberData; |
| 44 import '../../js_backend/backend_usage.dart'; | 42 import '../../js_backend/backend_usage.dart'; |
| 45 import '../../js_backend/constant_handler_javascript.dart' | 43 import '../../js_backend/constant_handler_javascript.dart' |
| 46 show JavaScriptConstantCompiler; | 44 show JavaScriptConstantCompiler; |
| 47 import '../../js_backend/custom_elements_analysis.dart'; | 45 import '../../js_backend/custom_elements_analysis.dart'; |
| 48 import '../../js_backend/namer.dart' show Namer, StringBackedName; | 46 import '../../js_backend/namer.dart' show Namer, StringBackedName; |
| (...skipping 20 matching lines...) Expand all Loading... |
| 69 TypeTestProperties; | 67 TypeTestProperties; |
| 70 import '../model.dart'; | 68 import '../model.dart'; |
| 71 | 69 |
| 72 part 'collector.dart'; | 70 part 'collector.dart'; |
| 73 part 'field_visitor.dart'; | 71 part 'field_visitor.dart'; |
| 74 part 'registry.dart'; | 72 part 'registry.dart'; |
| 75 | 73 |
| 76 /// Builds a self-contained representation of the program that can then be | 74 /// Builds a self-contained representation of the program that can then be |
| 77 /// emitted more easily by the individual emitters. | 75 /// emitted more easily by the individual emitters. |
| 78 class ProgramBuilder { | 76 class ProgramBuilder { |
| 79 final Compiler _compiler; | 77 final CompilerOptions _options; |
| 78 final CommonElements _commonElements; |
| 79 final Types _types; |
| 80 final DeferredLoadTask _deferredLoadTask; |
| 81 final ClosureTask _closureToClassMapper; |
| 82 final CodegenWorldBuilder _worldBuilder; |
| 83 final NativeCodegenEnqueuer _nativeCodegenEnqueuer; |
| 84 final BackendUsage _backendUsage; |
| 85 final JavaScriptConstantCompiler _constantHandler; |
| 86 final NativeData _nativeData; |
| 87 final RuntimeTypesNeed _rtiNeed; |
| 88 final MirrorsData _mirrorsData; |
| 89 final InterceptorData _interceptorData; |
| 90 final SuperMemberData _superMemberData; |
| 91 final RuntimeTypesChecks _rtiChecks; |
| 92 final RuntimeTypesEncoder _rtiEncoder; |
| 93 final RuntimeTypesSubstitutions _rtiSubstitutions; |
| 94 final JsInteropAnalysis _jsInteropAnalysis; |
| 95 final OneShotInterceptorData _oneShotInterceptorData; |
| 96 final CustomElementsCodegenAnalysis _customElementsCodegenAnalysis; |
| 97 final Map<MemberElement, js.Expression> _generatedCode; |
| 80 final Namer _namer; | 98 final Namer _namer; |
| 81 final CodeEmitterTask _task; | 99 final CodeEmitterTask _task; |
| 82 final ClosedWorld _closedWorld; | 100 final ClosedWorld _closedWorld; |
| 83 | 101 |
| 84 /// Contains the collected information the program builder used to build | 102 /// Contains the collected information the program builder used to build |
| 85 /// the model. | 103 /// the model. |
| 86 // The collector will be filled on the first call to `buildProgram`. | 104 // The collector will be filled on the first call to `buildProgram`. |
| 87 // It is stored and publicly exposed for backwards compatibility. New code | 105 // It is stored and publicly exposed for backwards compatibility. New code |
| 88 // (and in particular new emitters) should not use it. | 106 // (and in particular new emitters) should not use it. |
| 89 final Collector collector; | 107 final Collector collector; |
| 90 | 108 |
| 91 final Registry _registry; | 109 final Registry _registry; |
| 92 | 110 |
| 111 final FunctionEntity _mainFunction; |
| 112 final bool _isMockCompilation; |
| 113 |
| 93 /// True if the program should store function types in the metadata. | 114 /// True if the program should store function types in the metadata. |
| 94 bool _storeFunctionTypesInMetadata = false; | 115 bool _storeFunctionTypesInMetadata = false; |
| 95 | 116 |
| 96 ProgramBuilder(Compiler compiler, Namer _namer, this._task, Emitter emitter, | 117 ProgramBuilder( |
| 97 ClosedWorld closedWorld, Set<ClassElement> rtiNeededClasses) | 118 this._options, |
| 98 : this._compiler = compiler, | 119 this._commonElements, |
| 99 this._namer = _namer, | 120 this._types, |
| 100 this._closedWorld = closedWorld, | 121 this._deferredLoadTask, |
| 122 this._closureToClassMapper, |
| 123 this._worldBuilder, |
| 124 this._nativeCodegenEnqueuer, |
| 125 this._backendUsage, |
| 126 this._constantHandler, |
| 127 this._nativeData, |
| 128 this._rtiNeed, |
| 129 this._mirrorsData, |
| 130 this._interceptorData, |
| 131 this._superMemberData, |
| 132 this._rtiChecks, |
| 133 this._rtiEncoder, |
| 134 this._rtiSubstitutions, |
| 135 this._jsInteropAnalysis, |
| 136 this._oneShotInterceptorData, |
| 137 this._customElementsCodegenAnalysis, |
| 138 this._generatedCode, |
| 139 this._namer, |
| 140 this._task, |
| 141 this._closedWorld, |
| 142 Set<ClassElement> rtiNeededClasses, |
| 143 this._mainFunction, |
| 144 {bool isMockCompilation}) |
| 145 : this._isMockCompilation = isMockCompilation, |
| 101 this.collector = new Collector( | 146 this.collector = new Collector( |
| 102 compiler, _namer, closedWorld, rtiNeededClasses, emitter), | 147 _options, |
| 103 this._registry = new Registry(compiler); | 148 _commonElements, |
| 104 | 149 _deferredLoadTask, |
| 105 JavaScriptBackend get _backend => _compiler.backend; | 150 _worldBuilder, |
| 106 CodegenWorldBuilder get _worldBuilder => _compiler.codegenWorldBuilder; | 151 _namer, |
| 107 DeferredLoadTask get _deferredLoadTask => _compiler.deferredLoadTask; | 152 _task.emitter, |
| 108 Types get _types => _compiler.types; | 153 _constantHandler, |
| 109 CommonElements get _commonElements => _compiler.commonElements; | 154 _nativeData, |
| 110 CompilerOptions get _options => _compiler.options; | 155 _interceptorData, |
| 111 ClosureTask get _closureToClassMapper => _compiler.closureToClassMapper; | 156 _oneShotInterceptorData, |
| 112 NativeCodegenEnqueuer get _nativeCodegenEnqueuer => | 157 _mirrorsData, |
| 113 _backend.nativeCodegenEnqueuer; | 158 _closedWorld, |
| 114 BackendUsage get _backendUsage => _backend.backendUsage; | 159 rtiNeededClasses, |
| 115 JavaScriptConstantCompiler get _constantHandler => _backend.constants; | 160 _generatedCode), |
| 116 NativeData get _nativeData => _backend.nativeData; | 161 this._registry = new Registry(_deferredLoadTask); |
| 117 RuntimeTypesNeed get _rtiNeed => _backend.rtiNeed; | |
| 118 MirrorsData get _mirrorsData => _backend.mirrorsData; | |
| 119 InterceptorData get _interceptorData => _backend.interceptorData; | |
| 120 SuperMemberData get _superMemberData => _backend.superMemberData; | |
| 121 RuntimeTypesChecks get _rtiChecks => _backend.rtiChecks; | |
| 122 RuntimeTypesEncoder get _rtiEncoder => _backend.rtiEncoder; | |
| 123 RuntimeTypesSubstitutions get _rtiSubstitutions => _backend.rtiSubstitutions; | |
| 124 JsInteropAnalysis get _jsInteropAnalysis => _backend.jsInteropAnalysis; | |
| 125 OneShotInterceptorData get _oneShotInterceptorData => | |
| 126 _backend.oneShotInterceptorData; | |
| 127 CustomElementsCodegenAnalysis get _customElementsCodegenAnalysis => | |
| 128 _backend.customElementsCodegenAnalysis; | |
| 129 | 162 |
| 130 /// Mapping from [ClassElement] to constructed [Class]. We need this to | 163 /// Mapping from [ClassElement] to constructed [Class]. We need this to |
| 131 /// update the superclass in the [Class]. | 164 /// update the superclass in the [Class]. |
| 132 final Map<ClassElement, Class> _classes = <ClassElement, Class>{}; | 165 final Map<ClassElement, Class> _classes = <ClassElement, Class>{}; |
| 133 | 166 |
| 134 /// Mapping from [OutputUnit] to constructed [Fragment]. We need this to | 167 /// Mapping from [OutputUnit] to constructed [Fragment]. We need this to |
| 135 /// generate the deferredLoadingMap (to know which hunks to load). | 168 /// generate the deferredLoadingMap (to know which hunks to load). |
| 136 final Map<OutputUnit, Fragment> _outputs = <OutputUnit, Fragment>{}; | 169 final Map<OutputUnit, Fragment> _outputs = <OutputUnit, Fragment>{}; |
| 137 | 170 |
| 138 /// Mapping from [ConstantValue] to constructed [Constant]. We need this to | 171 /// Mapping from [ConstantValue] to constructed [Constant]. We need this to |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 272 _buildInvokeMain(), | 305 _buildInvokeMain(), |
| 273 _buildLibraries(librariesMap), | 306 _buildLibraries(librariesMap), |
| 274 _buildStaticNonFinalFields(librariesMap), | 307 _buildStaticNonFinalFields(librariesMap), |
| 275 _buildStaticLazilyInitializedFields(librariesMap), | 308 _buildStaticLazilyInitializedFields(librariesMap), |
| 276 _buildConstants(librariesMap)); | 309 _buildConstants(librariesMap)); |
| 277 _outputs[librariesMap.outputUnit] = result; | 310 _outputs[librariesMap.outputUnit] = result; |
| 278 return result; | 311 return result; |
| 279 } | 312 } |
| 280 | 313 |
| 281 js.Statement _buildInvokeMain() { | 314 js.Statement _buildInvokeMain() { |
| 282 if (_compiler.isMockCompilation) return js.js.comment("Mock compilation"); | 315 if (_isMockCompilation) return js.js.comment("Mock compilation"); |
| 283 | 316 |
| 284 MainCallStubGenerator generator = new MainCallStubGenerator( | 317 MainCallStubGenerator generator = new MainCallStubGenerator( |
| 285 _commonElements, _task.emitter, _backendUsage); | 318 _commonElements, _task.emitter, _backendUsage); |
| 286 return generator.generateInvokeMain(_compiler.mainFunction); | 319 return generator.generateInvokeMain(_mainFunction); |
| 287 } | 320 } |
| 288 | 321 |
| 289 DeferredFragment _buildDeferredFragment(LibrariesMap librariesMap) { | 322 DeferredFragment _buildDeferredFragment(LibrariesMap librariesMap) { |
| 290 DeferredFragment result = new DeferredFragment( | 323 DeferredFragment result = new DeferredFragment( |
| 291 librariesMap.outputUnit, | 324 librariesMap.outputUnit, |
| 292 _backend.deferredPartFileName(librariesMap.name, addExtension: false), | 325 _deferredLoadTask.deferredPartFileName(librariesMap.name, |
| 326 addExtension: false), |
| 293 librariesMap.name, | 327 librariesMap.name, |
| 294 _buildLibraries(librariesMap), | 328 _buildLibraries(librariesMap), |
| 295 _buildStaticNonFinalFields(librariesMap), | 329 _buildStaticNonFinalFields(librariesMap), |
| 296 _buildStaticLazilyInitializedFields(librariesMap), | 330 _buildStaticLazilyInitializedFields(librariesMap), |
| 297 _buildConstants(librariesMap)); | 331 _buildConstants(librariesMap)); |
| 298 _outputs[librariesMap.outputUnit] = result; | 332 _outputs[librariesMap.outputUnit] = result; |
| 299 return result; | 333 return result; |
| 300 } | 334 } |
| 301 | 335 |
| 302 List<Constant> _buildConstants(LibrariesMap librariesMap) { | 336 List<Constant> _buildConstants(LibrariesMap librariesMap) { |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 344 _deferredLoadTask.outputUnitForElement(element) == | 378 _deferredLoadTask.outputUnitForElement(element) == |
| 345 librariesMap.outputUnit); | 379 librariesMap.outputUnit); |
| 346 return Elements | 380 return Elements |
| 347 .sortedByPosition(lazyFields) | 381 .sortedByPosition(lazyFields) |
| 348 .map(_buildLazyField) | 382 .map(_buildLazyField) |
| 349 .where((field) => field != null) // Happens when the field was unused. | 383 .where((field) => field != null) // Happens when the field was unused. |
| 350 .toList(growable: false); | 384 .toList(growable: false); |
| 351 } | 385 } |
| 352 | 386 |
| 353 StaticField _buildLazyField(FieldElement element) { | 387 StaticField _buildLazyField(FieldElement element) { |
| 354 js.Expression code = _backend.generatedCode[element]; | 388 js.Expression code = _generatedCode[element]; |
| 355 // The code is null if we ended up not needing the lazily | 389 // The code is null if we ended up not needing the lazily |
| 356 // initialized field after all because of constant folding | 390 // initialized field after all because of constant folding |
| 357 // before code generation. | 391 // before code generation. |
| 358 if (code == null) return null; | 392 if (code == null) return null; |
| 359 | 393 |
| 360 js.Name name = _namer.globalPropertyName(element); | 394 js.Name name = _namer.globalPropertyName(element); |
| 361 bool isFinal = element.isFinal; | 395 bool isFinal = element.isFinal; |
| 362 bool isLazy = true; | 396 bool isLazy = true; |
| 363 // TODO(floitsch): we shouldn't update the registry in the middle of | 397 // TODO(floitsch): we shouldn't update the registry in the middle of |
| 364 // building a static field. (Note that the static-state holder was | 398 // building a static field. (Note that the static-state holder was |
| (...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 648 typeTests.properties.forEach((js.Name name, js.Node code) { | 682 typeTests.properties.forEach((js.Name name, js.Node code) { |
| 649 _classes[_commonElements.jsInterceptorClass] | 683 _classes[_commonElements.jsInterceptorClass] |
| 650 .isChecks | 684 .isChecks |
| 651 .add(_buildStubMethod(name, code)); | 685 .add(_buildStubMethod(name, code)); |
| 652 }); | 686 }); |
| 653 } else { | 687 } else { |
| 654 for (Field field in instanceFields) { | 688 for (Field field in instanceFields) { |
| 655 if (field.needsCheckedSetter) { | 689 if (field.needsCheckedSetter) { |
| 656 assert(!field.needsUncheckedSetter); | 690 assert(!field.needsUncheckedSetter); |
| 657 FieldElement element = field.element; | 691 FieldElement element = field.element; |
| 658 js.Expression code = _backend.generatedCode[element]; | 692 js.Expression code = _generatedCode[element]; |
| 659 assert(code != null); | 693 assert(code != null); |
| 660 js.Name name = _namer.deriveSetterName(field.accessorName); | 694 js.Name name = _namer.deriveSetterName(field.accessorName); |
| 661 checkedSetters.add(_buildStubMethod(name, code, element: element)); | 695 checkedSetters.add(_buildStubMethod(name, code, element: element)); |
| 662 } | 696 } |
| 663 } | 697 } |
| 664 | 698 |
| 665 typeTests.properties.forEach((js.Name name, js.Node code) { | 699 typeTests.properties.forEach((js.Name name, js.Node code) { |
| 666 isChecks.add(_buildStubMethod(name, code)); | 700 isChecks.add(_buildStubMethod(name, code)); |
| 667 }); | 701 }); |
| 668 } | 702 } |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 746 _constantHandler.getConstantValue(parameter.constant); | 780 _constantHandler.getConstantValue(parameter.constant); |
| 747 optionalParameterDefaultValues.add(def); | 781 optionalParameterDefaultValues.add(def); |
| 748 }); | 782 }); |
| 749 } | 783 } |
| 750 return optionalParameterDefaultValues; | 784 return optionalParameterDefaultValues; |
| 751 } | 785 } |
| 752 | 786 |
| 753 DartMethod _buildMethod(MethodElement element) { | 787 DartMethod _buildMethod(MethodElement element) { |
| 754 assert(element.isDeclaration); | 788 assert(element.isDeclaration); |
| 755 js.Name name = _namer.methodPropertyName(element); | 789 js.Name name = _namer.methodPropertyName(element); |
| 756 js.Expression code = _backend.generatedCode[element]; | 790 js.Expression code = _generatedCode[element]; |
| 757 | 791 |
| 758 // TODO(kasperl): Figure out under which conditions code is null. | 792 // TODO(kasperl): Figure out under which conditions code is null. |
| 759 if (code == null) return null; | 793 if (code == null) return null; |
| 760 | 794 |
| 761 bool canTearOff = false; | 795 bool canTearOff = false; |
| 762 js.Name tearOffName; | 796 js.Name tearOffName; |
| 763 bool isClosureCallMethod = false; | 797 bool isClosureCallMethod = false; |
| 764 bool isNotApplyTarget = !element.isFunction || element.isAccessor; | 798 bool isNotApplyTarget = !element.isFunction || element.isAccessor; |
| 765 | 799 |
| 766 bool canBeReflected = _methodCanBeReflected(element); | 800 bool canBeReflected = _methodCanBeReflected(element); |
| (...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 992 List<js.Name> names = _oneShotInterceptorData.oneShotInterceptorNames; | 1026 List<js.Name> names = _oneShotInterceptorData.oneShotInterceptorNames; |
| 993 return names.map((js.Name name) { | 1027 return names.map((js.Name name) { |
| 994 js.Expression code = stubGenerator.generateOneShotInterceptor(name); | 1028 js.Expression code = stubGenerator.generateOneShotInterceptor(name); |
| 995 return new StaticStubMethod(name, holder, code); | 1029 return new StaticStubMethod(name, holder, code); |
| 996 }); | 1030 }); |
| 997 } | 1031 } |
| 998 | 1032 |
| 999 StaticDartMethod _buildStaticMethod(MethodElement element) { | 1033 StaticDartMethod _buildStaticMethod(MethodElement element) { |
| 1000 js.Name name = _namer.methodPropertyName(element); | 1034 js.Name name = _namer.methodPropertyName(element); |
| 1001 String holder = _namer.globalObjectFor(element); | 1035 String holder = _namer.globalObjectFor(element); |
| 1002 js.Expression code = _backend.generatedCode[element]; | 1036 js.Expression code = _generatedCode[element]; |
| 1003 | 1037 |
| 1004 bool isApplyTarget = !element.isConstructor && !element.isAccessor; | 1038 bool isApplyTarget = !element.isConstructor && !element.isAccessor; |
| 1005 bool canBeApplied = _methodCanBeApplied(element); | 1039 bool canBeApplied = _methodCanBeApplied(element); |
| 1006 bool canBeReflected = _methodCanBeReflected(element); | 1040 bool canBeReflected = _methodCanBeReflected(element); |
| 1007 | 1041 |
| 1008 bool needsTearOff = isApplyTarget && | 1042 bool needsTearOff = isApplyTarget && |
| 1009 (canBeReflected || | 1043 (canBeReflected || |
| 1010 _worldBuilder.staticFunctionsNeedingGetter.contains(element)); | 1044 _worldBuilder.staticFunctionsNeedingGetter.contains(element)); |
| 1011 | 1045 |
| 1012 js.Name tearOffName = | 1046 js.Name tearOffName = |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1061 Constant constant = new Constant(name, holder, constantValue); | 1095 Constant constant = new Constant(name, holder, constantValue); |
| 1062 _constants[constantValue] = constant; | 1096 _constants[constantValue] = constant; |
| 1063 } | 1097 } |
| 1064 } | 1098 } |
| 1065 | 1099 |
| 1066 Holder _registerStaticStateHolder() { | 1100 Holder _registerStaticStateHolder() { |
| 1067 return _registry.registerHolder(_namer.staticStateHolder, | 1101 return _registry.registerHolder(_namer.staticStateHolder, |
| 1068 isStaticStateHolder: true); | 1102 isStaticStateHolder: true); |
| 1069 } | 1103 } |
| 1070 } | 1104 } |
| OLD | NEW |