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 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
69 if (backend.isTreeShakingDisabled) return (ClassElement cls) => true; | 69 if (backend.isTreeShakingDisabled) return (ClassElement cls) => true; |
70 | 70 |
71 Set<ClassElement> unneededClasses = new Set<ClassElement>(); | 71 Set<ClassElement> unneededClasses = new Set<ClassElement>(); |
72 // The [Bool] class is not marked as abstract, but has a factory | 72 // The [Bool] class is not marked as abstract, but has a factory |
73 // constructor that always throws. We never need to emit it. | 73 // constructor that always throws. We never need to emit it. |
74 unneededClasses.add(coreClasses.boolClass); | 74 unneededClasses.add(coreClasses.boolClass); |
75 | 75 |
76 // Go over specialized interceptors and then constants to know which | 76 // Go over specialized interceptors and then constants to know which |
77 // interceptors are needed. | 77 // interceptors are needed. |
78 Set<ClassElement> needed = new Set<ClassElement>(); | 78 Set<ClassElement> needed = new Set<ClassElement>(); |
79 backend.specializedGetInterceptors.forEach( | 79 backend.specializedGetInterceptors |
80 (_, Iterable<ClassElement> elements) { | 80 .forEach((_, Iterable<ClassElement> elements) { |
81 needed.addAll(elements); | 81 needed.addAll(elements); |
82 } | 82 }); |
83 ); | |
84 | 83 |
85 // Add interceptors referenced by constants. | 84 // Add interceptors referenced by constants. |
86 needed.addAll(computeInterceptorsReferencedFromConstants()); | 85 needed.addAll(computeInterceptorsReferencedFromConstants()); |
87 | 86 |
88 // Add unneeded interceptors to the [unneededClasses] set. | 87 // Add unneeded interceptors to the [unneededClasses] set. |
89 for (ClassElement interceptor in backend.interceptedClasses) { | 88 for (ClassElement interceptor in backend.interceptedClasses) { |
90 if (!needed.contains(interceptor) | 89 if (!needed.contains(interceptor) && |
91 && interceptor != coreClasses.objectClass) { | 90 interceptor != coreClasses.objectClass) { |
92 unneededClasses.add(interceptor); | 91 unneededClasses.add(interceptor); |
93 } | 92 } |
94 } | 93 } |
95 | 94 |
96 // These classes are just helpers for the backend's type system. | 95 // These classes are just helpers for the backend's type system. |
97 unneededClasses.add(helpers.jsMutableArrayClass); | 96 unneededClasses.add(helpers.jsMutableArrayClass); |
98 unneededClasses.add(helpers.jsFixedArrayClass); | 97 unneededClasses.add(helpers.jsFixedArrayClass); |
99 unneededClasses.add(helpers.jsExtendableArrayClass); | 98 unneededClasses.add(helpers.jsExtendableArrayClass); |
100 unneededClasses.add(helpers.jsUInt32Class); | 99 unneededClasses.add(helpers.jsUInt32Class); |
101 unneededClasses.add(helpers.jsUInt31Class); | 100 unneededClasses.add(helpers.jsUInt31Class); |
102 unneededClasses.add(helpers.jsPositiveIntClass); | 101 unneededClasses.add(helpers.jsPositiveIntClass); |
103 | 102 |
104 return (ClassElement cls) => !unneededClasses.contains(cls); | 103 return (ClassElement cls) => !unneededClasses.contains(cls); |
105 } | 104 } |
106 | 105 |
107 /** | 106 /** |
108 * Compute all the constants that must be emitted. | 107 * Compute all the constants that must be emitted. |
109 */ | 108 */ |
110 void computeNeededConstants() { | 109 void computeNeededConstants() { |
111 // Make sure we retain all metadata of all elements. This could add new | 110 // Make sure we retain all metadata of all elements. This could add new |
112 // constants to the handler. | 111 // constants to the handler. |
113 if (backend.mustRetainMetadata) { | 112 if (backend.mustRetainMetadata) { |
114 // TODO(floitsch): verify that we don't run through the same elements | 113 // TODO(floitsch): verify that we don't run through the same elements |
115 // multiple times. | 114 // multiple times. |
116 for (Element element in backend.generatedCode.keys) { | 115 for (Element element in backend.generatedCode.keys) { |
117 if (backend.isAccessibleByReflection(element)) { | 116 if (backend.isAccessibleByReflection(element)) { |
118 bool shouldRetainMetadata = backend.retainMetadataOf(element); | 117 bool shouldRetainMetadata = backend.retainMetadataOf(element); |
119 if (shouldRetainMetadata && | 118 if (shouldRetainMetadata && |
120 (element.isFunction || element.isConstructor || | 119 (element.isFunction || |
121 element.isSetter)) { | 120 element.isConstructor || |
| 121 element.isSetter)) { |
122 FunctionElement function = element; | 122 FunctionElement function = element; |
123 function.functionSignature.forEachParameter( | 123 function.functionSignature |
124 backend.retainMetadataOf); | 124 .forEachParameter(backend.retainMetadataOf); |
125 } | 125 } |
126 } | 126 } |
127 } | 127 } |
128 for (ClassElement cls in neededClasses) { | 128 for (ClassElement cls in neededClasses) { |
129 final onlyForRti = classesOnlyNeededForRti.contains(cls); | 129 final onlyForRti = classesOnlyNeededForRti.contains(cls); |
130 if (!onlyForRti) { | 130 if (!onlyForRti) { |
131 backend.retainMetadataOf(cls); | 131 backend.retainMetadataOf(cls); |
132 new FieldVisitor(compiler, namer).visitFields(cls, false, | 132 new FieldVisitor(compiler, namer).visitFields(cls, false, |
133 (Element member, | 133 (Element member, js.Name name, js.Name accessorName, |
134 js.Name name, | 134 bool needsGetter, bool needsSetter, bool needsCheckedSetter) { |
135 js.Name accessorName, | |
136 bool needsGetter, | |
137 bool needsSetter, | |
138 bool needsCheckedSetter) { | |
139 bool needsAccessor = needsGetter || needsSetter; | 135 bool needsAccessor = needsGetter || needsSetter; |
140 if (needsAccessor && backend.isAccessibleByReflection(member)) { | 136 if (needsAccessor && backend.isAccessibleByReflection(member)) { |
141 backend.retainMetadataOf(member); | 137 backend.retainMetadataOf(member); |
142 } | 138 } |
143 }); | 139 }); |
144 } | 140 } |
145 } | 141 } |
146 typedefsNeededForReflection.forEach(backend.retainMetadataOf); | 142 typedefsNeededForReflection.forEach(backend.retainMetadataOf); |
147 } | 143 } |
148 | 144 |
149 JavaScriptConstantCompiler handler = backend.constants; | 145 JavaScriptConstantCompiler handler = backend.constants; |
150 List<ConstantValue> constants = handler.getConstantsForEmission( | 146 List<ConstantValue> constants = handler.getConstantsForEmission(compiler |
151 compiler.options.hasIncrementalSupport ? null | 147 .options.hasIncrementalSupport ? null : emitter.compareConstants); |
152 : emitter.compareConstants); | |
153 for (ConstantValue constant in constants) { | 148 for (ConstantValue constant in constants) { |
154 if (emitter.isConstantInlinedOrAlreadyEmitted(constant)) continue; | 149 if (emitter.isConstantInlinedOrAlreadyEmitted(constant)) continue; |
155 | 150 |
156 if (constant.isList) outputContainsConstantList = true; | 151 if (constant.isList) outputContainsConstantList = true; |
157 | 152 |
158 OutputUnit constantUnit = | 153 OutputUnit constantUnit = |
159 compiler.deferredLoadTask.outputUnitForConstant(constant); | 154 compiler.deferredLoadTask.outputUnitForConstant(constant); |
160 if (constantUnit == null) { | 155 if (constantUnit == null) { |
161 // The back-end introduces some constants, like "InterceptorConstant" or | 156 // The back-end introduces some constants, like "InterceptorConstant" or |
162 // some list constants. They are emitted in the main output-unit. | 157 // some list constants. They are emitted in the main output-unit. |
163 // TODO(sigurdm): We should track those constants. | 158 // TODO(sigurdm): We should track those constants. |
164 constantUnit = compiler.deferredLoadTask.mainOutputUnit; | 159 constantUnit = compiler.deferredLoadTask.mainOutputUnit; |
165 } | 160 } |
166 outputConstantLists.putIfAbsent( | 161 outputConstantLists |
167 constantUnit, () => new List<ConstantValue>()).add(constant); | 162 .putIfAbsent(constantUnit, () => new List<ConstantValue>()) |
| 163 .add(constant); |
168 } | 164 } |
169 } | 165 } |
170 | 166 |
171 /// Compute all the classes and typedefs that must be emitted. | 167 /// Compute all the classes and typedefs that must be emitted. |
172 void computeNeededDeclarations() { | 168 void computeNeededDeclarations() { |
173 // Compute needed typedefs. | 169 // Compute needed typedefs. |
174 typedefsNeededForReflection = Elements.sortedByPosition( | 170 typedefsNeededForReflection = Elements.sortedByPosition(compiler |
175 compiler.world.allTypedefs | 171 .world.allTypedefs |
176 .where(backend.isAccessibleByReflection) | 172 .where(backend.isAccessibleByReflection) |
177 .toList()); | 173 .toList()); |
178 | 174 |
179 // Compute needed classes. | 175 // Compute needed classes. |
180 Set<ClassElement> instantiatedClasses = | 176 Set<ClassElement> instantiatedClasses = compiler |
181 compiler.codegenWorld.directlyInstantiatedClasses | 177 .codegenWorld.directlyInstantiatedClasses |
182 .where(computeClassFilter()).toSet(); | 178 .where(computeClassFilter()) |
| 179 .toSet(); |
183 | 180 |
184 void addClassWithSuperclasses(ClassElement cls) { | 181 void addClassWithSuperclasses(ClassElement cls) { |
185 neededClasses.add(cls); | 182 neededClasses.add(cls); |
186 for (ClassElement superclass = cls.superclass; | 183 for (ClassElement superclass = cls.superclass; |
187 superclass != null; | 184 superclass != null; |
188 superclass = superclass.superclass) { | 185 superclass = superclass.superclass) { |
189 neededClasses.add(superclass); | 186 neededClasses.add(superclass); |
190 } | 187 } |
191 } | 188 } |
192 | 189 |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
238 } | 235 } |
239 | 236 |
240 // 4. Finally, sort the classes. | 237 // 4. Finally, sort the classes. |
241 List<ClassElement> sortedClasses = Elements.sortedByPosition(neededClasses); | 238 List<ClassElement> sortedClasses = Elements.sortedByPosition(neededClasses); |
242 | 239 |
243 for (ClassElement element in sortedClasses) { | 240 for (ClassElement element in sortedClasses) { |
244 if (backend.isNativeOrExtendsNative(element) && | 241 if (backend.isNativeOrExtendsNative(element) && |
245 !classesOnlyNeededForRti.contains(element)) { | 242 !classesOnlyNeededForRti.contains(element)) { |
246 // For now, native classes and related classes cannot be deferred. | 243 // For now, native classes and related classes cannot be deferred. |
247 nativeClassesAndSubclasses.add(element); | 244 nativeClassesAndSubclasses.add(element); |
248 assert(invariant(element, | 245 assert( |
249 !compiler.deferredLoadTask.isDeferred(element))); | 246 invariant(element, !compiler.deferredLoadTask.isDeferred(element))); |
250 outputClassLists.putIfAbsent(compiler.deferredLoadTask.mainOutputUnit, | 247 outputClassLists |
251 () => new List<ClassElement>()).add(element); | 248 .putIfAbsent(compiler.deferredLoadTask.mainOutputUnit, |
| 249 () => new List<ClassElement>()) |
| 250 .add(element); |
252 } else { | 251 } else { |
253 outputClassLists.putIfAbsent( | 252 outputClassLists |
254 compiler.deferredLoadTask.outputUnitForElement(element), | 253 .putIfAbsent( |
255 () => new List<ClassElement>()) | 254 compiler.deferredLoadTask.outputUnitForElement(element), |
| 255 () => new List<ClassElement>()) |
256 .add(element); | 256 .add(element); |
257 } | 257 } |
258 } | 258 } |
259 } | 259 } |
260 | 260 |
261 void computeNeededStatics() { | 261 void computeNeededStatics() { |
262 bool isStaticFunction(Element element) => | 262 bool isStaticFunction(Element element) => |
263 !element.isInstanceMember && !element.isField; | 263 !element.isInstanceMember && !element.isField; |
264 | 264 |
265 Iterable<Element> elements = | 265 Iterable<Element> elements = |
266 backend.generatedCode.keys.where(isStaticFunction); | 266 backend.generatedCode.keys.where(isStaticFunction); |
267 | 267 |
268 for (Element element in Elements.sortedByPosition(elements)) { | 268 for (Element element in Elements.sortedByPosition(elements)) { |
269 List<Element> list = outputStaticLists.putIfAbsent( | 269 List<Element> list = outputStaticLists.putIfAbsent( |
270 compiler.deferredLoadTask.outputUnitForElement(element), | 270 compiler.deferredLoadTask.outputUnitForElement(element), |
271 () => new List<Element>()); | 271 () => new List<Element>()); |
272 list.add(element); | 272 list.add(element); |
273 } | 273 } |
274 } | 274 } |
275 | 275 |
276 void computeNeededStaticNonFinalFields() { | 276 void computeNeededStaticNonFinalFields() { |
277 JavaScriptConstantCompiler handler = backend.constants; | 277 JavaScriptConstantCompiler handler = backend.constants; |
278 addToOutputUnit(Element element) { | 278 addToOutputUnit(Element element) { |
279 List<VariableElement> list = outputStaticNonFinalFieldLists.putIfAbsent( | 279 List<VariableElement> list = outputStaticNonFinalFieldLists.putIfAbsent( |
280 compiler.deferredLoadTask.outputUnitForElement(element), | 280 compiler.deferredLoadTask.outputUnitForElement(element), |
281 () => new List<VariableElement>()); | 281 () => new List<VariableElement>()); |
282 list.add(element); | 282 list.add(element); |
283 } | 283 } |
284 | 284 |
285 Iterable<VariableElement> staticNonFinalFields = handler | 285 Iterable<VariableElement> staticNonFinalFields = handler |
286 .getStaticNonFinalFieldsForEmission() | 286 .getStaticNonFinalFieldsForEmission() |
287 .where(compiler.codegenWorld.allReferencedStaticFields.contains); | 287 .where(compiler.codegenWorld.allReferencedStaticFields.contains); |
288 | 288 |
289 Elements.sortedByPosition(staticNonFinalFields).forEach(addToOutputUnit); | 289 Elements.sortedByPosition(staticNonFinalFields).forEach(addToOutputUnit); |
290 | 290 |
291 // We also need to emit static const fields if they are available for | 291 // We also need to emit static const fields if they are available for |
292 // reflection. | 292 // reflection. |
293 compiler.codegenWorld.allReferencedStaticFields | 293 compiler.codegenWorld.allReferencedStaticFields |
294 .where((FieldElement field) => field.isConst) | 294 .where((FieldElement field) => field.isConst) |
295 .where(backend.isAccessibleByReflection) | 295 .where(backend.isAccessibleByReflection) |
296 .forEach(addToOutputUnit); | 296 .forEach(addToOutputUnit); |
297 } | 297 } |
298 | 298 |
299 void computeNeededLibraries() { | 299 void computeNeededLibraries() { |
300 void addSurroundingLibraryToSet(Element element) { | 300 void addSurroundingLibraryToSet(Element element) { |
301 OutputUnit unit = compiler.deferredLoadTask.outputUnitForElement(element); | 301 OutputUnit unit = compiler.deferredLoadTask.outputUnitForElement(element); |
302 LibraryElement library = element.library; | 302 LibraryElement library = element.library; |
303 outputLibraryLists.putIfAbsent(unit, () => new Set<LibraryElement>()) | 303 outputLibraryLists |
| 304 .putIfAbsent(unit, () => new Set<LibraryElement>()) |
304 .add(library); | 305 .add(library); |
305 } | 306 } |
306 | 307 |
307 backend.generatedCode.keys.forEach(addSurroundingLibraryToSet); | 308 backend.generatedCode.keys.forEach(addSurroundingLibraryToSet); |
308 neededClasses.forEach(addSurroundingLibraryToSet); | 309 neededClasses.forEach(addSurroundingLibraryToSet); |
309 } | 310 } |
310 | 311 |
311 void collect() { | 312 void collect() { |
312 computeNeededDeclarations(); | 313 computeNeededDeclarations(); |
313 computeNeededConstants(); | 314 computeNeededConstants(); |
314 computeNeededStatics(); | 315 computeNeededStatics(); |
315 computeNeededStaticNonFinalFields(); | 316 computeNeededStaticNonFinalFields(); |
316 computeNeededLibraries(); | 317 computeNeededLibraries(); |
317 } | 318 } |
318 } | 319 } |
OLD | NEW |