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 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
111 | 111 |
112 /** | 112 /** |
113 * Compute all the constants that must be emitted. | 113 * Compute all the constants that must be emitted. |
114 */ | 114 */ |
115 void computeNeededConstants() { | 115 void computeNeededConstants() { |
116 // Make sure we retain all metadata of all elements. This could add new | 116 // Make sure we retain all metadata of all elements. This could add new |
117 // constants to the handler. | 117 // constants to the handler. |
118 if (backend.mirrorsData.mustRetainMetadata) { | 118 if (backend.mirrorsData.mustRetainMetadata) { |
119 // TODO(floitsch): verify that we don't run through the same elements | 119 // TODO(floitsch): verify that we don't run through the same elements |
120 // multiple times. | 120 // multiple times. |
121 for (Element element in backend.generatedCode.keys) { | 121 for (MemberElement element in backend.generatedCode.keys) { |
122 if (backend.mirrorsData.isAccessibleByReflection(element)) { | 122 if (backend.mirrorsData.isMemberAccessibleByReflection(element)) { |
123 bool shouldRetainMetadata = | 123 bool shouldRetainMetadata = |
124 backend.mirrorsData.retainMetadataOf(element); | 124 backend.mirrorsData.retainMetadataOfMember(element); |
125 if (shouldRetainMetadata && | 125 if (shouldRetainMetadata && |
126 (element.isFunction || | 126 (element.isFunction || |
127 element.isConstructor || | 127 element.isConstructor || |
128 element.isSetter)) { | 128 element.isSetter)) { |
129 FunctionElement function = element; | 129 MethodElement function = element; |
130 function.functionSignature | 130 function.functionSignature.forEachParameter( |
131 .forEachParameter(backend.mirrorsData.retainMetadataOf); | 131 backend.mirrorsData.retainMetadataOfParameter); |
132 } | 132 } |
133 } | 133 } |
134 } | 134 } |
135 for (ClassElement cls in neededClasses) { | 135 for (ClassElement cls in neededClasses) { |
136 final onlyForRti = classesOnlyNeededForRti.contains(cls); | 136 final onlyForRti = classesOnlyNeededForRti.contains(cls); |
137 if (!onlyForRti) { | 137 if (!onlyForRti) { |
138 backend.mirrorsData.retainMetadataOf(cls); | 138 backend.mirrorsData.retainMetadataOfClass(cls); |
139 new FieldVisitor(compiler, namer, closedWorld).visitFields(cls, false, | 139 new FieldVisitor(compiler, namer, closedWorld).visitFields(cls, false, |
140 (Element member, js.Name name, js.Name accessorName, | 140 (FieldElement member, js.Name name, js.Name accessorName, |
141 bool needsGetter, bool needsSetter, bool needsCheckedSetter) { | 141 bool needsGetter, bool needsSetter, bool needsCheckedSetter) { |
142 bool needsAccessor = needsGetter || needsSetter; | 142 bool needsAccessor = needsGetter || needsSetter; |
143 if (needsAccessor && | 143 if (needsAccessor && |
144 backend.mirrorsData.isAccessibleByReflection(member)) { | 144 backend.mirrorsData.isMemberAccessibleByReflection(member)) { |
145 backend.mirrorsData.retainMetadataOf(member); | 145 backend.mirrorsData.retainMetadataOfMember(member); |
146 } | 146 } |
147 }); | 147 }); |
148 } | 148 } |
149 } | 149 } |
150 typedefsNeededForReflection.forEach(backend.mirrorsData.retainMetadataOf); | 150 typedefsNeededForReflection |
| 151 .forEach(backend.mirrorsData.retainMetadataOfTypedef); |
151 } | 152 } |
152 | 153 |
153 JavaScriptConstantCompiler handler = backend.constants; | 154 JavaScriptConstantCompiler handler = backend.constants; |
154 List<ConstantValue> constants = | 155 List<ConstantValue> constants = |
155 handler.getConstantsForEmission(emitter.compareConstants); | 156 handler.getConstantsForEmission(emitter.compareConstants); |
156 for (ConstantValue constant in constants) { | 157 for (ConstantValue constant in constants) { |
157 if (emitter.isConstantInlinedOrAlreadyEmitted(constant)) continue; | 158 if (emitter.isConstantInlinedOrAlreadyEmitted(constant)) continue; |
158 | 159 |
159 if (constant.isList) outputContainsConstantList = true; | 160 if (constant.isList) outputContainsConstantList = true; |
160 | 161 |
161 OutputUnit constantUnit = | 162 OutputUnit constantUnit = |
162 compiler.deferredLoadTask.outputUnitForConstant(constant); | 163 compiler.deferredLoadTask.outputUnitForConstant(constant); |
163 if (constantUnit == null) { | 164 if (constantUnit == null) { |
164 // The back-end introduces some constants, like "InterceptorConstant" or | 165 // The back-end introduces some constants, like "InterceptorConstant" or |
165 // some list constants. They are emitted in the main output-unit. | 166 // some list constants. They are emitted in the main output-unit. |
166 // TODO(sigurdm): We should track those constants. | 167 // TODO(sigurdm): We should track those constants. |
167 constantUnit = compiler.deferredLoadTask.mainOutputUnit; | 168 constantUnit = compiler.deferredLoadTask.mainOutputUnit; |
168 } | 169 } |
169 outputConstantLists | 170 outputConstantLists |
170 .putIfAbsent(constantUnit, () => new List<ConstantValue>()) | 171 .putIfAbsent(constantUnit, () => new List<ConstantValue>()) |
171 .add(constant); | 172 .add(constant); |
172 } | 173 } |
173 } | 174 } |
174 | 175 |
175 /// Compute all the classes and typedefs that must be emitted. | 176 /// Compute all the classes and typedefs that must be emitted. |
176 void computeNeededDeclarations() { | 177 void computeNeededDeclarations() { |
177 // Compute needed typedefs. | 178 // Compute needed typedefs. |
178 typedefsNeededForReflection = Elements.sortedByPosition(closedWorld | 179 typedefsNeededForReflection = Elements.sortedByPosition(closedWorld |
179 .allTypedefs | 180 .allTypedefs |
180 .where(backend.mirrorsData.isAccessibleByReflection) | 181 .where(backend.mirrorsData.isTypedefAccessibleByReflection) |
181 .toList()); | 182 .toList()); |
182 | 183 |
183 // Compute needed classes. | 184 // Compute needed classes. |
184 Set<ClassElement> instantiatedClasses = compiler | 185 Set<ClassElement> instantiatedClasses = compiler |
185 // TODO(johnniwinther): This should be accessed from a codegen closed | 186 // TODO(johnniwinther): This should be accessed from a codegen closed |
186 // world. | 187 // world. |
187 .codegenWorldBuilder | 188 .codegenWorldBuilder |
188 .directlyInstantiatedClasses | 189 .directlyInstantiatedClasses |
189 .where(computeClassFilter()) | 190 .where(computeClassFilter()) |
190 .toSet(); | 191 .toSet(); |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
263 outputClassLists | 264 outputClassLists |
264 .putIfAbsent( | 265 .putIfAbsent( |
265 compiler.deferredLoadTask.outputUnitForElement(element), | 266 compiler.deferredLoadTask.outputUnitForElement(element), |
266 () => new List<ClassElement>()) | 267 () => new List<ClassElement>()) |
267 .add(element); | 268 .add(element); |
268 } | 269 } |
269 } | 270 } |
270 } | 271 } |
271 | 272 |
272 void computeNeededStatics() { | 273 void computeNeededStatics() { |
273 bool isStaticFunction(Element element) => | 274 bool isStaticFunction(MemberElement element) => |
274 !element.isInstanceMember && !element.isField; | 275 !element.isInstanceMember && !element.isField; |
275 | 276 |
276 Iterable<Element> elements = | 277 Iterable<MemberElement> elements = |
277 backend.generatedCode.keys.where(isStaticFunction); | 278 backend.generatedCode.keys.where(isStaticFunction); |
278 | 279 |
279 for (Element element in Elements.sortedByPosition(elements)) { | 280 for (Element element in Elements.sortedByPosition(elements)) { |
280 List<Element> list = outputStaticLists.putIfAbsent( | 281 List<Element> list = outputStaticLists.putIfAbsent( |
281 compiler.deferredLoadTask.outputUnitForElement(element), | 282 compiler.deferredLoadTask.outputUnitForElement(element), |
282 () => new List<Element>()); | 283 () => new List<Element>()); |
283 list.add(element); | 284 list.add(element); |
284 } | 285 } |
285 } | 286 } |
286 | 287 |
287 void computeNeededStaticNonFinalFields() { | 288 void computeNeededStaticNonFinalFields() { |
288 addToOutputUnit(Element element) { | 289 addToOutputUnit(Element element) { |
289 List<VariableElement> list = outputStaticNonFinalFieldLists.putIfAbsent( | 290 List<VariableElement> list = outputStaticNonFinalFieldLists.putIfAbsent( |
290 compiler.deferredLoadTask.outputUnitForElement(element), | 291 compiler.deferredLoadTask.outputUnitForElement(element), |
291 () => new List<VariableElement>()); | 292 () => new List<VariableElement>()); |
292 list.add(element); | 293 list.add(element); |
293 } | 294 } |
294 | 295 |
295 Iterable<Element> fields = compiler | 296 Iterable<FieldElement> fields = compiler |
296 // TODO(johnniwinther): This should be accessed from a codegen closed | 297 // TODO(johnniwinther): This should be accessed from a codegen closed |
297 // world. | 298 // world. |
298 .codegenWorldBuilder | 299 .codegenWorldBuilder |
299 .allReferencedStaticFields | 300 .allReferencedStaticFields |
300 .where((FieldElement field) { | 301 .where((FieldElement field) { |
301 if (!field.isConst) { | 302 if (!field.isConst) { |
302 return field.isField && | 303 return field.isField && |
303 !field.isInstanceMember && | 304 !field.isInstanceMember && |
304 !field.isFinal && | 305 !field.isFinal && |
305 field.constant != null; | 306 field.constant != null; |
306 } else { | 307 } else { |
307 // We also need to emit static const fields if they are available for | 308 // We also need to emit static const fields if they are available for |
308 // reflection. | 309 // reflection. |
309 return backend.mirrorsData.isAccessibleByReflection(field); | 310 return backend.mirrorsData.isMemberAccessibleByReflection(field); |
310 } | 311 } |
311 }); | 312 }); |
312 | 313 |
313 Elements.sortedByPosition(fields).forEach(addToOutputUnit); | 314 Elements.sortedByPosition(fields).forEach(addToOutputUnit); |
314 } | 315 } |
315 | 316 |
316 void computeNeededLibraries() { | 317 void computeNeededLibraries() { |
317 void addSurroundingLibraryToSet(Element element) { | 318 void addSurroundingLibraryToSet(Element element) { |
318 OutputUnit unit = compiler.deferredLoadTask.outputUnitForElement(element); | 319 OutputUnit unit = compiler.deferredLoadTask.outputUnitForElement(element); |
319 LibraryElement library = element.library; | 320 LibraryElement library = element.library; |
320 outputLibraryLists | 321 outputLibraryLists |
321 .putIfAbsent(unit, () => new Set<LibraryElement>()) | 322 .putIfAbsent(unit, () => new Set<LibraryElement>()) |
322 .add(library); | 323 .add(library); |
323 } | 324 } |
324 | 325 |
325 backend.generatedCode.keys.forEach(addSurroundingLibraryToSet); | 326 backend.generatedCode.keys.forEach(addSurroundingLibraryToSet); |
326 neededClasses.forEach(addSurroundingLibraryToSet); | 327 neededClasses.forEach(addSurroundingLibraryToSet); |
327 } | 328 } |
328 | 329 |
329 void collect() { | 330 void collect() { |
330 computeNeededDeclarations(); | 331 computeNeededDeclarations(); |
331 computeNeededConstants(); | 332 computeNeededConstants(); |
332 computeNeededStatics(); | 333 computeNeededStatics(); |
333 computeNeededStaticNonFinalFields(); | 334 computeNeededStaticNonFinalFields(); |
334 computeNeededLibraries(); | 335 computeNeededLibraries(); |
335 } | 336 } |
336 } | 337 } |
OLD | NEW |