OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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.enqueue; | 5 part of dart2js; |
6 | |
7 import 'dart:collection' show | |
8 Queue; | |
9 import 'dart2jslib.dart' show | |
10 invariant, | |
11 CodegenWorkItem, | |
12 Compiler, | |
13 CompilerTask, | |
14 DeferredAction, | |
15 DeferredTask, | |
16 ItemCompilationContext, | |
17 Registry, | |
18 ResolutionWorkItem, | |
19 WorkItem; | |
20 import 'dart_types.dart' show | |
21 DartType, | |
22 InterfaceType; | |
23 import 'elements/elements.dart' show | |
24 AnalyzableElement, | |
25 AstElement, | |
26 ClassElement, | |
27 ConstructorElement, | |
28 Element, | |
29 Elements, | |
30 FunctionElement, | |
31 LibraryElement, | |
32 LocalFunctionElement, | |
33 Member, | |
34 MemberElement, | |
35 MethodElement, | |
36 TypedElement, | |
37 TypedefElement; | |
38 import 'js/js.dart' as js; | |
39 import 'native/native.dart' as native; | |
40 import 'resolution/resolution.dart' show | |
41 ResolverVisitor; | |
42 import 'tree/tree.dart' show | |
43 Send; | |
44 import 'universe/universe.dart'; | |
45 import 'util/util.dart' show | |
46 Link, | |
47 Setlet, | |
48 SpannableAssertionFailure; | |
49 | 6 |
50 typedef ItemCompilationContext ItemCompilationContextCreator(); | 7 typedef ItemCompilationContext ItemCompilationContextCreator(); |
51 | 8 |
52 class EnqueueTask extends CompilerTask { | 9 class EnqueueTask extends CompilerTask { |
53 final ResolutionEnqueuer resolution; | 10 final ResolutionEnqueuer resolution; |
54 final CodegenEnqueuer codegen; | 11 final CodegenEnqueuer codegen; |
55 | 12 |
56 String get name => 'Enqueue'; | 13 String get name => 'Enqueue'; |
57 | 14 |
58 EnqueueTask(Compiler compiler) | 15 EnqueueTask(Compiler compiler) |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
182 void processInstantiatedClassMembers(ClassElement cls) { | 139 void processInstantiatedClassMembers(ClassElement cls) { |
183 cls.implementation.forEachMember(processInstantiatedClassMember); | 140 cls.implementation.forEachMember(processInstantiatedClassMember); |
184 } | 141 } |
185 | 142 |
186 void processInstantiatedClassMember(ClassElement cls, Element member) { | 143 void processInstantiatedClassMember(ClassElement cls, Element member) { |
187 assert(invariant(member, member.isDeclaration)); | 144 assert(invariant(member, member.isDeclaration)); |
188 if (isProcessed(member)) return; | 145 if (isProcessed(member)) return; |
189 if (!member.isInstanceMember) return; | 146 if (!member.isInstanceMember) return; |
190 String memberName = member.name; | 147 String memberName = member.name; |
191 | 148 |
192 if (member.isField) { | 149 if (member.kind == ElementKind.FIELD) { |
193 // The obvious thing to test here would be "member.isNative", | 150 // The obvious thing to test here would be "member.isNative", |
194 // however, that only works after metadata has been parsed/analyzed, | 151 // however, that only works after metadata has been parsed/analyzed, |
195 // and that may not have happened yet. | 152 // and that may not have happened yet. |
196 // So instead we use the enclosing class, which we know have had | 153 // So instead we use the enclosing class, which we know have had |
197 // its metadata parsed and analyzed. | 154 // its metadata parsed and analyzed. |
198 // Note: this assumes that there are no non-native fields on native | 155 // Note: this assumes that there are no non-native fields on native |
199 // classes, which may not be the case when a native class is subclassed. | 156 // classes, which may not be the case when a native class is subclassed. |
200 if (cls.isNative) { | 157 if (cls.isNative) { |
201 compiler.world.registerUsedElement(member); | 158 compiler.world.registerUsedElement(member); |
202 nativeEnqueuer.handleFieldAnnotations(member); | 159 nativeEnqueuer.handleFieldAnnotations(member); |
(...skipping 20 matching lines...) Expand all Loading... |
223 } | 180 } |
224 // Native fields need to go into instanceMembersByName as they | 181 // Native fields need to go into instanceMembersByName as they |
225 // are virtual instantiation points and escape points. | 182 // are virtual instantiation points and escape points. |
226 } else { | 183 } else { |
227 // All field initializers must be resolved as they could | 184 // All field initializers must be resolved as they could |
228 // have an observable side-effect (and cannot be tree-shaken | 185 // have an observable side-effect (and cannot be tree-shaken |
229 // away). | 186 // away). |
230 addToWorkList(member); | 187 addToWorkList(member); |
231 return; | 188 return; |
232 } | 189 } |
233 } else if (member.isFunction) { | 190 } else if (member.kind == ElementKind.FUNCTION) { |
234 FunctionElement function = member; | 191 FunctionElement function = member; |
235 function.computeType(compiler); | 192 function.computeType(compiler); |
236 if (function.name == Compiler.NO_SUCH_METHOD) { | 193 if (function.name == Compiler.NO_SUCH_METHOD) { |
237 registerNoSuchMethod(function); | 194 registerNoSuchMethod(function); |
238 } | 195 } |
239 if (function.name == Compiler.CALL_OPERATOR_NAME && | 196 if (function.name == Compiler.CALL_OPERATOR_NAME && |
240 !cls.typeVariables.isEmpty) { | 197 !cls.typeVariables.isEmpty) { |
241 registerCallMethodWithFreeTypeVariables( | 198 registerCallMethodWithFreeTypeVariables( |
242 function, compiler.globalDependencies); | 199 function, compiler.globalDependencies); |
243 } | 200 } |
244 // If there is a property access with the same name as a method we | 201 // If there is a property access with the same name as a method we |
245 // need to emit the method. | 202 // need to emit the method. |
246 if (universe.hasInvokedGetter(function, compiler.world)) { | 203 if (universe.hasInvokedGetter(function, compiler.world)) { |
247 registerClosurizedMember(function, compiler.globalDependencies); | 204 registerClosurizedMember(function, compiler.globalDependencies); |
248 addToWorkList(function); | 205 addToWorkList(function); |
249 return; | 206 return; |
250 } | 207 } |
251 // Store the member in [instanceFunctionsByName] to catch | 208 // Store the member in [instanceFunctionsByName] to catch |
252 // getters on the function. | 209 // getters on the function. |
253 instanceFunctionsByName.putIfAbsent(memberName, () => new Set<Element>()) | 210 instanceFunctionsByName.putIfAbsent(memberName, () => new Set<Element>()) |
254 .add(member); | 211 .add(member); |
255 if (universe.hasInvocation(function, compiler.world)) { | 212 if (universe.hasInvocation(function, compiler.world)) { |
256 addToWorkList(function); | 213 addToWorkList(function); |
257 return; | 214 return; |
258 } | 215 } |
259 } else if (member.isGetter) { | 216 } else if (member.kind == ElementKind.GETTER) { |
260 FunctionElement getter = member; | 217 FunctionElement getter = member; |
261 getter.computeType(compiler); | 218 getter.computeType(compiler); |
262 if (universe.hasInvokedGetter(getter, compiler.world)) { | 219 if (universe.hasInvokedGetter(getter, compiler.world)) { |
263 addToWorkList(getter); | 220 addToWorkList(getter); |
264 return; | 221 return; |
265 } | 222 } |
266 // We don't know what selectors the returned closure accepts. If | 223 // We don't know what selectors the returned closure accepts. If |
267 // the set contains any selector we have to assume that it matches. | 224 // the set contains any selector we have to assume that it matches. |
268 if (universe.hasInvocation(getter, compiler.world)) { | 225 if (universe.hasInvocation(getter, compiler.world)) { |
269 addToWorkList(getter); | 226 addToWorkList(getter); |
270 return; | 227 return; |
271 } | 228 } |
272 } else if (member.isSetter) { | 229 } else if (member.kind == ElementKind.SETTER) { |
273 FunctionElement setter = member; | 230 FunctionElement setter = member; |
274 setter.computeType(compiler); | 231 setter.computeType(compiler); |
275 if (universe.hasInvokedSetter(setter, compiler.world)) { | 232 if (universe.hasInvokedSetter(setter, compiler.world)) { |
276 addToWorkList(setter); | 233 addToWorkList(setter); |
277 return; | 234 return; |
278 } | 235 } |
279 } | 236 } |
280 | 237 |
281 // The element is not yet used. Add it to the list of instance | 238 // The element is not yet used. Add it to the list of instance |
282 // members to still be processed. | 239 // members to still be processed. |
(...skipping 352 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
635 | 592 |
636 void registerFieldSetter(Element element) { | 593 void registerFieldSetter(Element element) { |
637 universe.fieldSetters.add(element); | 594 universe.fieldSetters.add(element); |
638 } | 595 } |
639 | 596 |
640 void registerIsCheck(DartType type) { | 597 void registerIsCheck(DartType type) { |
641 type = universe.registerIsCheck(type, compiler); | 598 type = universe.registerIsCheck(type, compiler); |
642 // Even in checked mode, type annotations for return type and argument | 599 // Even in checked mode, type annotations for return type and argument |
643 // types do not imply type checks, so there should never be a check | 600 // types do not imply type checks, so there should never be a check |
644 // against the type variable of a typedef. | 601 // against the type variable of a typedef. |
645 assert(!type.isTypeVariable || | 602 assert(type.kind != TypeKind.TYPE_VARIABLE || |
646 !type.element.enclosingElement.isTypedef); | 603 !type.element.enclosingElement.isTypedef); |
647 } | 604 } |
648 | 605 |
649 void registerCallMethodWithFreeTypeVariables( | 606 void registerCallMethodWithFreeTypeVariables( |
650 Element element, | 607 Element element, |
651 Registry registry) { | 608 Registry registry) { |
652 compiler.backend.registerCallMethodWithFreeTypeVariables( | 609 compiler.backend.registerCallMethodWithFreeTypeVariables( |
653 element, this, registry); | 610 element, this, registry); |
654 universe.callMethodsWithFreeTypeVariables.add(element); | 611 universe.callMethodsWithFreeTypeVariables.add(element); |
655 } | 612 } |
(...skipping 339 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
995 void processWorkItem(void f(WorkItem work), WorkItem work) { | 952 void processWorkItem(void f(WorkItem work), WorkItem work) { |
996 f(work); | 953 f(work); |
997 } | 954 } |
998 } | 955 } |
999 | 956 |
1000 void removeFromSet(Map<String, Set<Element>> map, Element element) { | 957 void removeFromSet(Map<String, Set<Element>> map, Element element) { |
1001 Set<Element> set = map[element.name]; | 958 Set<Element> set = map[element.name]; |
1002 if (set == null) return; | 959 if (set == null) return; |
1003 set.remove(element); | 960 set.remove(element); |
1004 } | 961 } |
OLD | NEW |