| 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 class EnqueueTask extends CompilerTask { | 5 class EnqueueTask extends CompilerTask { |
| 6 final Map<String, Link<Element>> instanceMembersByName; | 6 final Enqueuer codegen; |
| 7 final Set<ClassElement> seenClasses; | 7 final Enqueuer resolution; |
| 8 | 8 |
| 9 String get name() => 'Enqueue'; | 9 String get name() => 'Enqueue'; |
| 10 | 10 |
| 11 EnqueueTask(Compiler compiler) | 11 EnqueueTask(Compiler compiler) |
| 12 : codegen = new Enqueuer(compiler), |
| 13 resolution = new Enqueuer(compiler), |
| 14 super(compiler) { |
| 15 codegen.task = this; |
| 16 resolution.task = this; |
| 17 } |
| 18 } |
| 19 |
| 20 class Enqueuer { |
| 21 final Compiler compiler; // TODO(ahe): Remove this dependency. |
| 22 final Map<String, Link<Element>> instanceMembersByName; |
| 23 final Set<ClassElement> seenClasses; |
| 24 final Universe universe; |
| 25 final Queue<WorkItem> queue; |
| 26 bool queueIsClosed = false; |
| 27 EnqueueTask task; |
| 28 |
| 29 Enqueuer(this.compiler) |
| 12 : instanceMembersByName = new Map<String, Link<Element>>(), | 30 : instanceMembersByName = new Map<String, Link<Element>>(), |
| 13 seenClasses = new Set<ClassElement>(), | 31 seenClasses = new Set<ClassElement>(), |
| 14 super(compiler); | 32 universe = new Universe(), |
| 33 queue = new Queue<WorkItem>(); |
| 34 |
| 35 void addToWorkList(Element element, [TreeElements elements]) { |
| 36 if (queueIsClosed) { |
| 37 compiler.internalErrorOnElement(element, "Work list is closed."); |
| 38 } |
| 39 if (element.kind === ElementKind.GENERATIVE_CONSTRUCTOR) { |
| 40 compiler.registerInstantiatedClass(element.enclosingElement); |
| 41 } |
| 42 queue.add(new WorkItem(element, elements)); |
| 43 } |
| 44 |
| 45 void registerInstantiatedClass(ClassElement cls) { |
| 46 universe.instantiatedClasses.add(cls); |
| 47 onRegisterInstantiatedClass(cls); |
| 48 } |
| 15 | 49 |
| 16 bool checkNoEnqueuedInvokedInstanceMethods() { | 50 bool checkNoEnqueuedInvokedInstanceMethods() { |
| 17 measure(() { | 51 task.measure(() { |
| 18 // Run through the classes and see if we need to compile methods. | 52 // Run through the classes and see if we need to compile methods. |
| 19 for (ClassElement classElement in compiler.universe.instantiatedClasses) { | 53 for (ClassElement classElement in universe.instantiatedClasses) { |
| 20 for (ClassElement currentClass = classElement; | 54 for (ClassElement currentClass = classElement; |
| 21 currentClass !== null; | 55 currentClass !== null; |
| 22 currentClass = currentClass.superclass) { | 56 currentClass = currentClass.superclass) { |
| 23 processInstantiatedClass(currentClass); | 57 processInstantiatedClass(currentClass); |
| 24 } | 58 } |
| 25 } | 59 } |
| 26 }); | 60 }); |
| 27 return true; | 61 return true; |
| 28 } | 62 } |
| 29 | 63 |
| 30 void processInstantiatedClass(ClassElement cls) { | 64 void processInstantiatedClass(ClassElement cls) { |
| 31 cls.members.forEach(processInstantiatedClassMember); | 65 cls.members.forEach(processInstantiatedClassMember); |
| 32 } | 66 } |
| 33 | 67 |
| 34 void registerFieldClosureInvocations() { | 68 void registerFieldClosureInvocations() { |
| 35 measure(() { | 69 task.measure(() { |
| 36 // Make sure that the closure understands a call with the given | 70 // Make sure that the closure understands a call with the given |
| 37 // selector. For a method-invocation of the form o.foo(a: 499), we | 71 // selector. For a method-invocation of the form o.foo(a: 499), we |
| 38 // need to make sure that closures can handle the optional argument if | 72 // need to make sure that closures can handle the optional argument if |
| 39 // there exists a field or getter 'foo'. | 73 // there exists a field or getter 'foo'. |
| 40 var names = compiler.universe.instantiatedClassInstanceFields; | 74 var names = universe.instantiatedClassInstanceFields; |
| 41 // TODO(ahe): Might be enough to use invokedGetters. | 75 // TODO(ahe): Might be enough to use invokedGetters. |
| 42 for (SourceString name in names) { | 76 for (SourceString name in names) { |
| 43 Set<Selector> invokedSelectors = compiler.universe.invokedNames[name]; | 77 Set<Selector> invokedSelectors = universe.invokedNames[name]; |
| 44 if (invokedSelectors != null) { | 78 if (invokedSelectors != null) { |
| 45 for (Selector selector in invokedSelectors) { | 79 for (Selector selector in invokedSelectors) { |
| 46 compiler.registerDynamicInvocation(Namer.CLOSURE_INVOCATION_NAME, | 80 compiler.registerDynamicInvocation(Namer.CLOSURE_INVOCATION_NAME, |
| 47 selector); | 81 selector); |
| 48 } | 82 } |
| 49 } | 83 } |
| 50 } | 84 } |
| 51 }); | 85 }); |
| 52 } | 86 } |
| 53 | 87 |
| 54 void processInstantiatedClassMember(Element member) { | 88 void processInstantiatedClassMember(Element member) { |
| 55 Universe universe = compiler.universe; | |
| 56 if (universe.generatedCode.containsKey(member)) return; | 89 if (universe.generatedCode.containsKey(member)) return; |
| 57 | 90 |
| 58 if (!member.isInstanceMember()) return; | 91 if (!member.isInstanceMember()) return; |
| 59 if (member.isField()) return; | 92 if (member.isField()) return; |
| 60 | 93 |
| 61 String memberName = member.name.slowToString(); | 94 String memberName = member.name.slowToString(); |
| 62 Link<Element> members = instanceMembersByName.putIfAbsent( | 95 Link<Element> members = instanceMembersByName.putIfAbsent( |
| 63 memberName, () => const EmptyLink<Element>()); | 96 memberName, () => const EmptyLink<Element>()); |
| 64 instanceMembersByName[memberName] = members.prepend(member); | 97 instanceMembersByName[memberName] = members.prepend(member); |
| 65 | 98 |
| 66 if (member.kind === ElementKind.GETTER || | 99 if (member.kind === ElementKind.GETTER || |
| 67 member.kind === ElementKind.FIELD) { | 100 member.kind === ElementKind.FIELD) { |
| 68 universe.instantiatedClassInstanceFields.add(member.name); | 101 universe.instantiatedClassInstanceFields.add(member.name); |
| 69 } | 102 } |
| 70 | 103 |
| 71 if (member.kind == ElementKind.FUNCTION) { | 104 if (member.kind == ElementKind.FUNCTION) { |
| 72 if (member.name == Compiler.NO_SUCH_METHOD) { | 105 if (member.name == Compiler.NO_SUCH_METHOD) { |
| 73 compiler.enableNoSuchMethod(member); | 106 compiler.enableNoSuchMethod(member); |
| 74 } | 107 } |
| 75 if (universe.hasInvocation(member, compiler)) { | 108 if (universe.hasInvocation(member, compiler)) { |
| 76 return compiler.addToWorkList(member); | 109 return addToWorkList(member); |
| 77 } | 110 } |
| 78 // If there is a property access with the same name as a method we | 111 // If there is a property access with the same name as a method we |
| 79 // need to emit the method. | 112 // need to emit the method. |
| 80 if (universe.hasGetter(member, compiler)) { | 113 if (universe.hasGetter(member, compiler)) { |
| 81 // We will emit a closure, so make sure the closure class is | 114 // We will emit a closure, so make sure the closure class is |
| 82 // generated. | 115 // generated. |
| 83 compiler.closureClass.ensureResolved(compiler); | 116 compiler.closureClass.ensureResolved(compiler); |
| 84 compiler.registerInstantiatedClass(compiler.closureClass); | 117 compiler.registerInstantiatedClass(compiler.closureClass); |
| 85 return compiler.addToWorkList(member); | 118 return addToWorkList(member); |
| 86 } | 119 } |
| 87 } else if (member.kind == ElementKind.GETTER) { | 120 } else if (member.kind == ElementKind.GETTER) { |
| 88 if (universe.hasGetter(member, compiler)) { | 121 if (universe.hasGetter(member, compiler)) { |
| 89 return compiler.addToWorkList(member); | 122 return addToWorkList(member); |
| 90 } | 123 } |
| 91 // We don't know what selectors the returned closure accepts. If | 124 // We don't know what selectors the returned closure accepts. If |
| 92 // the set contains any selector we have to assume that it matches. | 125 // the set contains any selector we have to assume that it matches. |
| 93 if (universe.hasInvocation(member, compiler)) { | 126 if (universe.hasInvocation(member, compiler)) { |
| 94 return compiler.addToWorkList(member); | 127 return addToWorkList(member); |
| 95 } | 128 } |
| 96 } else if (member.kind === ElementKind.SETTER) { | 129 } else if (member.kind === ElementKind.SETTER) { |
| 97 if (universe.hasSetter(member, compiler)) { | 130 if (universe.hasSetter(member, compiler)) { |
| 98 return compiler.addToWorkList(member); | 131 return addToWorkList(member); |
| 99 } | 132 } |
| 100 } | 133 } |
| 101 } | 134 } |
| 102 | 135 |
| 103 void onRegisterInstantiatedClass(ClassElement cls) { | 136 void onRegisterInstantiatedClass(ClassElement cls) { |
| 104 measure(() { | 137 task.measure(() { |
| 105 while (cls !== null) { | 138 while (cls !== null) { |
| 106 if (seenClasses.contains(cls)) return; | 139 if (seenClasses.contains(cls)) return; |
| 107 seenClasses.add(cls); | 140 seenClasses.add(cls); |
| 108 // TODO(ahe): Don't call resolveType, instead, call this method | 141 // TODO(ahe): Don't call resolveType, instead, call this method |
| 109 // when resolveType is called. | 142 // when resolveType is called. |
| 110 compiler.resolveClass(cls); | 143 compiler.resolveClass(cls); |
| 111 cls.members.forEach(processInstantiatedClassMember); | 144 cls.members.forEach(processInstantiatedClassMember); |
| 112 cls = cls.superclass; | 145 cls = cls.superclass; |
| 113 } | 146 } |
| 114 }); | 147 }); |
| 115 } | 148 } |
| 116 | 149 |
| 117 void registerNewSelector(SourceString name, | 150 void registerNewSelector(SourceString name, |
| 118 Selector selector, | 151 Selector selector, |
| 119 Map<SourceString, Set<Selector>> selectorsMap) { | 152 Map<SourceString, Set<Selector>> selectorsMap) { |
| 120 Set<Selector> selectors = | 153 Set<Selector> selectors = |
| 121 selectorsMap.putIfAbsent(name, () => new Set<Selector>()); | 154 selectorsMap.putIfAbsent(name, () => new Set<Selector>()); |
| 122 if (!selectors.contains(selector)) { | 155 if (!selectors.contains(selector)) { |
| 123 selectors.add(selector); | 156 selectors.add(selector); |
| 124 handleUnseenSelector(name, selector); | 157 handleUnseenSelector(name, selector); |
| 125 } | 158 } |
| 126 } | 159 } |
| 127 | 160 |
| 128 void registerInvocation(SourceString methodName, Selector selector) { | 161 void registerInvocation(SourceString methodName, Selector selector) { |
| 129 measure(() { | 162 task.measure(() { |
| 130 registerNewSelector(methodName, selector, compiler.universe.invokedNames); | 163 registerNewSelector(methodName, selector, universe.invokedNames); |
| 131 }); | 164 }); |
| 132 } | 165 } |
| 133 | 166 |
| 134 void registerGetter(SourceString getterName, Selector selector) { | 167 void registerGetter(SourceString getterName, Selector selector) { |
| 135 measure(() { | 168 task.measure(() { |
| 136 registerNewSelector( | 169 registerNewSelector(getterName, selector, universe.invokedGetters); |
| 137 getterName, selector, compiler.universe.invokedGetters); | |
| 138 }); | 170 }); |
| 139 } | 171 } |
| 140 | 172 |
| 141 void registerSetter(SourceString setterName, Selector selector) { | 173 void registerSetter(SourceString setterName, Selector selector) { |
| 142 measure(() { | 174 task.measure(() { |
| 143 registerNewSelector( | 175 registerNewSelector(setterName, selector, universe.invokedSetters); |
| 144 setterName, selector, compiler.universe.invokedSetters); | |
| 145 }); | 176 }); |
| 146 } | 177 } |
| 147 | 178 |
| 148 processInstanceMembers(SourceString n, bool f(Element e)) { | 179 processInstanceMembers(SourceString n, bool f(Element e)) { |
| 149 String memberName = n.slowToString(); | 180 String memberName = n.slowToString(); |
| 150 Link<Element> members = instanceMembersByName[memberName]; | 181 Link<Element> members = instanceMembersByName[memberName]; |
| 151 if (members !== null) { | 182 if (members !== null) { |
| 152 LinkBuilder<Element> remaining = new LinkBuilder<Element>(); | 183 LinkBuilder<Element> remaining = new LinkBuilder<Element>(); |
| 153 for (; !members.isEmpty(); members = members.tail) { | 184 for (; !members.isEmpty(); members = members.tail) { |
| 154 if (!f(members.head)) remaining.addLast(members.head); | 185 if (!f(members.head)) remaining.addLast(members.head); |
| 155 } | 186 } |
| 156 instanceMembersByName[memberName] = remaining.toLink(); | 187 instanceMembersByName[memberName] = remaining.toLink(); |
| 157 } | 188 } |
| 158 } | 189 } |
| 159 | 190 |
| 160 void handleUnseenSelector(SourceString methodName, Selector selector) { | 191 void handleUnseenSelector(SourceString methodName, Selector selector) { |
| 161 processInstanceMembers(methodName, (Element member) { | 192 processInstanceMembers(methodName, (Element member) { |
| 162 if (selector.applies(member, compiler)) { | 193 if (selector.applies(member, compiler)) { |
| 163 compiler.addToWorkList(member); | 194 addToWorkList(member); |
| 164 return true; | 195 return true; |
| 165 } | 196 } |
| 166 return false; | 197 return false; |
| 167 }); | 198 }); |
| 168 } | 199 } |
| 169 } | 200 } |
| OLD | NEW |