| OLD | NEW |
| 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.program_builder; | 5 part of dart2js.js_emitter.program_builder; |
| 6 | 6 |
| 7 /** | 7 /** |
| 8 * Generates the code for all used classes in the program. Static fields (even | 8 * Generates the code for all used classes in the program. Static fields (even |
| 9 * in classes) are ignored, since they can be treated as non-class elements. | 9 * in classes) are ignored, since they can be treated as non-class elements. |
| 10 * | 10 * |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 61 } | 61 } |
| 62 } | 62 } |
| 63 return classes; | 63 return classes; |
| 64 } | 64 } |
| 65 | 65 |
| 66 /** | 66 /** |
| 67 * Return a function that returns true if its argument is a class | 67 * Return a function that returns true if its argument is a class |
| 68 * that needs to be emitted. | 68 * that needs to be emitted. |
| 69 */ | 69 */ |
| 70 Function computeClassFilter() { | 70 Function computeClassFilter() { |
| 71 if (backend.isTreeShakingDisabled) return (ClassElement cls) => true; | 71 if (backend.mirrorsData.isTreeShakingDisabled) { |
| 72 return (ClassElement cls) => true; |
| 73 } |
| 72 | 74 |
| 73 Set<ClassElement> unneededClasses = new Set<ClassElement>(); | 75 Set<ClassElement> unneededClasses = new Set<ClassElement>(); |
| 74 // The [Bool] class is not marked as abstract, but has a factory | 76 // The [Bool] class is not marked as abstract, but has a factory |
| 75 // constructor that always throws. We never need to emit it. | 77 // constructor that always throws. We never need to emit it. |
| 76 unneededClasses.add(commonElements.boolClass); | 78 unneededClasses.add(commonElements.boolClass); |
| 77 | 79 |
| 78 // Go over specialized interceptors and then constants to know which | 80 // Go over specialized interceptors and then constants to know which |
| 79 // interceptors are needed. | 81 // interceptors are needed. |
| 80 Set<ClassElement> needed = new Set<ClassElement>(); | 82 Set<ClassElement> needed = new Set<ClassElement>(); |
| 81 backend.interceptorData.specializedGetInterceptors | 83 backend.interceptorData.specializedGetInterceptors |
| (...skipping 23 matching lines...) Expand all Loading... |
| 105 | 107 |
| 106 return (ClassElement cls) => !unneededClasses.contains(cls); | 108 return (ClassElement cls) => !unneededClasses.contains(cls); |
| 107 } | 109 } |
| 108 | 110 |
| 109 /** | 111 /** |
| 110 * Compute all the constants that must be emitted. | 112 * Compute all the constants that must be emitted. |
| 111 */ | 113 */ |
| 112 void computeNeededConstants() { | 114 void computeNeededConstants() { |
| 113 // Make sure we retain all metadata of all elements. This could add new | 115 // Make sure we retain all metadata of all elements. This could add new |
| 114 // constants to the handler. | 116 // constants to the handler. |
| 115 if (backend.mustRetainMetadata) { | 117 if (backend.mirrorsData.mustRetainMetadata) { |
| 116 // TODO(floitsch): verify that we don't run through the same elements | 118 // TODO(floitsch): verify that we don't run through the same elements |
| 117 // multiple times. | 119 // multiple times. |
| 118 for (Element element in backend.generatedCode.keys) { | 120 for (Element element in backend.generatedCode.keys) { |
| 119 if (backend.isAccessibleByReflection(element)) { | 121 if (backend.mirrorsData.isAccessibleByReflection(element)) { |
| 120 bool shouldRetainMetadata = backend.retainMetadataOf(element); | 122 bool shouldRetainMetadata = |
| 123 backend.mirrorsData.retainMetadataOf(element); |
| 121 if (shouldRetainMetadata && | 124 if (shouldRetainMetadata && |
| 122 (element.isFunction || | 125 (element.isFunction || |
| 123 element.isConstructor || | 126 element.isConstructor || |
| 124 element.isSetter)) { | 127 element.isSetter)) { |
| 125 FunctionElement function = element; | 128 FunctionElement function = element; |
| 126 function.functionSignature | 129 function.functionSignature |
| 127 .forEachParameter(backend.retainMetadataOf); | 130 .forEachParameter(backend.mirrorsData.retainMetadataOf); |
| 128 } | 131 } |
| 129 } | 132 } |
| 130 } | 133 } |
| 131 for (ClassElement cls in neededClasses) { | 134 for (ClassElement cls in neededClasses) { |
| 132 final onlyForRti = classesOnlyNeededForRti.contains(cls); | 135 final onlyForRti = classesOnlyNeededForRti.contains(cls); |
| 133 if (!onlyForRti) { | 136 if (!onlyForRti) { |
| 134 backend.retainMetadataOf(cls); | 137 backend.mirrorsData.retainMetadataOf(cls); |
| 135 new FieldVisitor(compiler, namer, closedWorld).visitFields(cls, false, | 138 new FieldVisitor(compiler, namer, closedWorld).visitFields(cls, false, |
| 136 (Element member, js.Name name, js.Name accessorName, | 139 (Element member, js.Name name, js.Name accessorName, |
| 137 bool needsGetter, bool needsSetter, bool needsCheckedSetter) { | 140 bool needsGetter, bool needsSetter, bool needsCheckedSetter) { |
| 138 bool needsAccessor = needsGetter || needsSetter; | 141 bool needsAccessor = needsGetter || needsSetter; |
| 139 if (needsAccessor && backend.isAccessibleByReflection(member)) { | 142 if (needsAccessor && |
| 140 backend.retainMetadataOf(member); | 143 backend.mirrorsData.isAccessibleByReflection(member)) { |
| 144 backend.mirrorsData.retainMetadataOf(member); |
| 141 } | 145 } |
| 142 }); | 146 }); |
| 143 } | 147 } |
| 144 } | 148 } |
| 145 typedefsNeededForReflection.forEach(backend.retainMetadataOf); | 149 typedefsNeededForReflection.forEach(backend.mirrorsData.retainMetadataOf); |
| 146 } | 150 } |
| 147 | 151 |
| 148 JavaScriptConstantCompiler handler = backend.constants; | 152 JavaScriptConstantCompiler handler = backend.constants; |
| 149 List<ConstantValue> constants = | 153 List<ConstantValue> constants = |
| 150 handler.getConstantsForEmission(emitter.compareConstants); | 154 handler.getConstantsForEmission(emitter.compareConstants); |
| 151 for (ConstantValue constant in constants) { | 155 for (ConstantValue constant in constants) { |
| 152 if (emitter.isConstantInlinedOrAlreadyEmitted(constant)) continue; | 156 if (emitter.isConstantInlinedOrAlreadyEmitted(constant)) continue; |
| 153 | 157 |
| 154 if (constant.isList) outputContainsConstantList = true; | 158 if (constant.isList) outputContainsConstantList = true; |
| 155 | 159 |
| 156 OutputUnit constantUnit = | 160 OutputUnit constantUnit = |
| 157 compiler.deferredLoadTask.outputUnitForConstant(constant); | 161 compiler.deferredLoadTask.outputUnitForConstant(constant); |
| 158 if (constantUnit == null) { | 162 if (constantUnit == null) { |
| 159 // The back-end introduces some constants, like "InterceptorConstant" or | 163 // The back-end introduces some constants, like "InterceptorConstant" or |
| 160 // some list constants. They are emitted in the main output-unit. | 164 // some list constants. They are emitted in the main output-unit. |
| 161 // TODO(sigurdm): We should track those constants. | 165 // TODO(sigurdm): We should track those constants. |
| 162 constantUnit = compiler.deferredLoadTask.mainOutputUnit; | 166 constantUnit = compiler.deferredLoadTask.mainOutputUnit; |
| 163 } | 167 } |
| 164 outputConstantLists | 168 outputConstantLists |
| 165 .putIfAbsent(constantUnit, () => new List<ConstantValue>()) | 169 .putIfAbsent(constantUnit, () => new List<ConstantValue>()) |
| 166 .add(constant); | 170 .add(constant); |
| 167 } | 171 } |
| 168 } | 172 } |
| 169 | 173 |
| 170 /// Compute all the classes and typedefs that must be emitted. | 174 /// Compute all the classes and typedefs that must be emitted. |
| 171 void computeNeededDeclarations() { | 175 void computeNeededDeclarations() { |
| 172 // Compute needed typedefs. | 176 // Compute needed typedefs. |
| 173 typedefsNeededForReflection = Elements.sortedByPosition(closedWorld | 177 typedefsNeededForReflection = Elements.sortedByPosition(closedWorld |
| 174 .allTypedefs | 178 .allTypedefs |
| 175 .where(backend.isAccessibleByReflection) | 179 .where(backend.mirrorsData.isAccessibleByReflection) |
| 176 .toList()); | 180 .toList()); |
| 177 | 181 |
| 178 // Compute needed classes. | 182 // Compute needed classes. |
| 179 Set<ClassElement> instantiatedClasses = compiler | 183 Set<ClassElement> instantiatedClasses = compiler |
| 180 // TODO(johnniwinther): This should be accessed from a codegen closed | 184 // TODO(johnniwinther): This should be accessed from a codegen closed |
| 181 // world. | 185 // world. |
| 182 .codegenWorldBuilder | 186 .codegenWorldBuilder |
| 183 .directlyInstantiatedClasses | 187 .directlyInstantiatedClasses |
| 184 .where(computeClassFilter()) | 188 .where(computeClassFilter()) |
| 185 .toSet(); | 189 .toSet(); |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 294 .allReferencedStaticFields | 298 .allReferencedStaticFields |
| 295 .where((FieldElement field) { | 299 .where((FieldElement field) { |
| 296 if (!field.isConst) { | 300 if (!field.isConst) { |
| 297 return field.isField && | 301 return field.isField && |
| 298 !field.isInstanceMember && | 302 !field.isInstanceMember && |
| 299 !field.isFinal && | 303 !field.isFinal && |
| 300 field.constant != null; | 304 field.constant != null; |
| 301 } else { | 305 } else { |
| 302 // We also need to emit static const fields if they are available for | 306 // We also need to emit static const fields if they are available for |
| 303 // reflection. | 307 // reflection. |
| 304 return backend.isAccessibleByReflection(field); | 308 return backend.mirrorsData.isAccessibleByReflection(field); |
| 305 } | 309 } |
| 306 }); | 310 }); |
| 307 | 311 |
| 308 Elements.sortedByPosition(fields).forEach(addToOutputUnit); | 312 Elements.sortedByPosition(fields).forEach(addToOutputUnit); |
| 309 } | 313 } |
| 310 | 314 |
| 311 void computeNeededLibraries() { | 315 void computeNeededLibraries() { |
| 312 void addSurroundingLibraryToSet(Element element) { | 316 void addSurroundingLibraryToSet(Element element) { |
| 313 OutputUnit unit = compiler.deferredLoadTask.outputUnitForElement(element); | 317 OutputUnit unit = compiler.deferredLoadTask.outputUnitForElement(element); |
| 314 LibraryElement library = element.library; | 318 LibraryElement library = element.library; |
| 315 outputLibraryLists | 319 outputLibraryLists |
| 316 .putIfAbsent(unit, () => new Set<LibraryElement>()) | 320 .putIfAbsent(unit, () => new Set<LibraryElement>()) |
| 317 .add(library); | 321 .add(library); |
| 318 } | 322 } |
| 319 | 323 |
| 320 backend.generatedCode.keys.forEach(addSurroundingLibraryToSet); | 324 backend.generatedCode.keys.forEach(addSurroundingLibraryToSet); |
| 321 neededClasses.forEach(addSurroundingLibraryToSet); | 325 neededClasses.forEach(addSurroundingLibraryToSet); |
| 322 } | 326 } |
| 323 | 327 |
| 324 void collect() { | 328 void collect() { |
| 325 computeNeededDeclarations(); | 329 computeNeededDeclarations(); |
| 326 computeNeededConstants(); | 330 computeNeededConstants(); |
| 327 computeNeededStatics(); | 331 computeNeededStatics(); |
| 328 computeNeededStaticNonFinalFields(); | 332 computeNeededStaticNonFinalFields(); |
| 329 computeNeededLibraries(); | 333 computeNeededLibraries(); |
| 330 } | 334 } |
| 331 } | 335 } |
| OLD | NEW |