Chromium Code Reviews| 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 part of js_backend; | 5 part of js_backend; |
| 6 | 6 |
| 7 /** | 7 /** |
| 8 * A function element that represents a closure call. The signature is copied | 8 * A function element that represents a closure call. The signature is copied |
| 9 * from the given element. | 9 * from the given element. |
| 10 */ | 10 */ |
| (...skipping 2149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2160 | 2160 |
| 2161 Element createInvocationMirrorElement = | 2161 Element createInvocationMirrorElement = |
| 2162 compiler.findHelper(const SourceString("createInvocationMirror")); | 2162 compiler.findHelper(const SourceString("createInvocationMirror")); |
| 2163 String createInvocationMirrorName = | 2163 String createInvocationMirrorName = |
| 2164 namer.getName(createInvocationMirrorElement); | 2164 namer.getName(createInvocationMirrorElement); |
| 2165 | 2165 |
| 2166 // Keep track of the JavaScript names we've already added so we | 2166 // Keep track of the JavaScript names we've already added so we |
| 2167 // do not introduce duplicates (bad for code size). | 2167 // do not introduce duplicates (bad for code size). |
| 2168 Set<String> addedJsNames = new Set<String>(); | 2168 Set<String> addedJsNames = new Set<String>(); |
| 2169 | 2169 |
| 2170 // Keep track of the noSuchMethod holders for each possible | |
| 2171 // receiver type. | |
| 2172 Map<ClassElement, Set<ClassElement>> noSuchMethodHolders = | |
| 2173 new Map<ClassElement, Set<ClassElement>>(); | |
| 2174 Set<ClassElement> noSuchMethodHoldersFor(DartType type) { | |
| 2175 ClassElement element = type.element; | |
| 2176 Set<ClassElement> result = noSuchMethodHolders[element]; | |
| 2177 if (result == null) { | |
| 2178 // For now, we check the entire world to see if an object of | |
| 2179 // the given type may have a user-defined noSuchMethod | |
| 2180 // implementation. We could do better by only looking at | |
| 2181 // instantiated (or otherwise needed) classes. | |
| 2182 result = compiler.world.findNoSuchMethodHolders(type); | |
| 2183 noSuchMethodHolders[element] = result; | |
| 2184 } | |
| 2185 return result; | |
| 2186 } | |
| 2187 | |
| 2188 jsAst.Expression generateMethod(String jsName, Selector selector) { | 2170 jsAst.Expression generateMethod(String jsName, Selector selector) { |
| 2189 // Values match JSInvocationMirror in js-helper library. | 2171 // Values match JSInvocationMirror in js-helper library. |
| 2190 int type = selector.invocationMirrorKind; | 2172 int type = selector.invocationMirrorKind; |
| 2191 String methodName = selector.invocationMirrorMemberName; | 2173 String methodName = selector.invocationMirrorMemberName; |
| 2192 List<jsAst.Parameter> parameters = <jsAst.Parameter>[]; | 2174 List<jsAst.Parameter> parameters = <jsAst.Parameter>[]; |
| 2193 CodeBuffer args = new CodeBuffer(); | 2175 CodeBuffer args = new CodeBuffer(); |
| 2194 for (int i = 0; i < selector.argumentCount; i++) { | 2176 for (int i = 0; i < selector.argumentCount; i++) { |
| 2195 parameters.add(new jsAst.Parameter('\$$i')); | 2177 parameters.add(new jsAst.Parameter('\$$i')); |
| 2196 } | 2178 } |
| 2197 | 2179 |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2243 if (selector.isSetter() && element.modifiers.isFinalOrConst()) { | 2225 if (selector.isSetter() && element.modifiers.isFinalOrConst()) { |
| 2244 return false; | 2226 return false; |
| 2245 } | 2227 } |
| 2246 } | 2228 } |
| 2247 return selector.applies(element, compiler); | 2229 return selector.applies(element, compiler); |
| 2248 } | 2230 } |
| 2249 | 2231 |
| 2250 // If the selector is typed, we check to see if that type may | 2232 // If the selector is typed, we check to see if that type may |
| 2251 // have a user-defined noSuchMethod implementation. If not, we | 2233 // have a user-defined noSuchMethod implementation. If not, we |
| 2252 // skip the selector altogether. | 2234 // skip the selector altogether. |
| 2253 DartType receiverType = objectType; | |
| 2254 ClassElement receiverClass = objectClass; | 2235 ClassElement receiverClass = objectClass; |
| 2255 if (selector is TypedSelector) { | 2236 if (selector is TypedSelector) { |
|
ngeoffray
2013/02/18 08:35:34
Maybe we can put all of this logic in the selector
| |
| 2256 TypedSelector typedSelector = selector; | 2237 TypedSelector typedSelector = selector; |
| 2257 receiverType = typedSelector.receiverType; | 2238 DartType receiverType = typedSelector.receiverType; |
| 2258 receiverClass = receiverType.element; | 2239 receiverClass = receiverType.element; |
| 2259 } | 2240 } |
| 2260 | 2241 |
| 2261 // If the receiver class is guaranteed to have a member that | 2242 // If the receiver class is guaranteed to have a member that |
| 2262 // matches what we're looking for, there's no need to | 2243 // matches what we're looking for, there's no need to |
| 2263 // introduce a noSuchMethod handler. It will never be called. | 2244 // introduce a noSuchMethod handler. It will never be called. |
| 2264 // | 2245 // |
| 2265 // As an example, consider this class hierarchy: | 2246 // As an example, consider this class hierarchy: |
| 2266 // | 2247 // |
| 2267 // A <-- noSuchMethod | 2248 // A <-- noSuchMethod |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 2293 // that also (indirectly) implement foo, so we do not need a | 2274 // that also (indirectly) implement foo, so we do not need a |
| 2294 // handler for it. | 2275 // handler for it. |
| 2295 // | 2276 // |
| 2296 // If we're calling bar on an object of type D, we don't need | 2277 // If we're calling bar on an object of type D, we don't need |
| 2297 // the handler either because all objects of type D implement | 2278 // the handler either because all objects of type D implement |
| 2298 // bar through inheritance. | 2279 // bar through inheritance. |
| 2299 // | 2280 // |
| 2300 // If we're calling bar on an object of type A we do need the | 2281 // If we're calling bar on an object of type A we do need the |
| 2301 // handler because we may have to call B.noSuchMethod since B | 2282 // handler because we may have to call B.noSuchMethod since B |
| 2302 // does not implement bar. | 2283 // does not implement bar. |
| 2303 Set<ClassElement> holders = noSuchMethodHoldersFor(receiverType); | 2284 Iterable<ClassElement> holders = |
| 2285 compiler.world.locateNoSuchMethodHolders(selector); | |
| 2304 if (holders.every(hasMatchingMember)) continue; | 2286 if (holders.every(hasMatchingMember)) continue; |
| 2305 String jsName = namer.invocationMirrorInternalName(selector); | 2287 String jsName = namer.invocationMirrorInternalName(selector); |
| 2306 if (!addedJsNames.contains(jsName)) { | 2288 if (!addedJsNames.contains(jsName)) { |
| 2307 jsAst.Expression method = generateMethod(jsName, selector); | 2289 jsAst.Expression method = generateMethod(jsName, selector); |
| 2308 defineStub(jsName, method); | 2290 defineStub(jsName, method); |
| 2309 addedJsNames.add(jsName); | 2291 addedJsNames.add(jsName); |
| 2310 } | 2292 } |
| 2311 } | 2293 } |
| 2312 } | 2294 } |
| 2313 | 2295 |
| (...skipping 358 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2672 """; | 2654 """; |
| 2673 const String HOOKS_API_USAGE = """ | 2655 const String HOOKS_API_USAGE = """ |
| 2674 // The code supports the following hooks: | 2656 // The code supports the following hooks: |
| 2675 // dartPrint(message) - if this function is defined it is called | 2657 // dartPrint(message) - if this function is defined it is called |
| 2676 // instead of the Dart [print] method. | 2658 // instead of the Dart [print] method. |
| 2677 // dartMainRunner(main) - if this function is defined, the Dart [main] | 2659 // dartMainRunner(main) - if this function is defined, the Dart [main] |
| 2678 // method will not be invoked directly. | 2660 // method will not be invoked directly. |
| 2679 // Instead, a closure that will invoke [main] is | 2661 // Instead, a closure that will invoke [main] is |
| 2680 // passed to [dartMainRunner]. | 2662 // passed to [dartMainRunner]. |
| 2681 """; | 2663 """; |
| OLD | NEW |