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