| 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 dart2js; | 5 part of dart2js; |
| 6 | 6 |
| 7 class EnqueueTask extends CompilerTask { | 7 class EnqueueTask extends CompilerTask { |
| 8 final ResolutionEnqueuer resolution; | 8 final ResolutionEnqueuer resolution; |
| 9 final CodegenEnqueuer codegen; | 9 final CodegenEnqueuer codegen; |
| 10 | 10 |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 80 compiler.backend.nativeResolutionEnqueuer(resolution); | 80 compiler.backend.nativeResolutionEnqueuer(resolution); |
| 81 } | 81 } |
| 82 } | 82 } |
| 83 | 83 |
| 84 abstract class Enqueuer { | 84 abstract class Enqueuer { |
| 85 final String name; | 85 final String name; |
| 86 final Compiler compiler; // TODO(ahe): Remove this dependency. | 86 final Compiler compiler; // TODO(ahe): Remove this dependency. |
| 87 final Function itemCompilationContextCreator; | 87 final Function itemCompilationContextCreator; |
| 88 final Map<String, Link<Element>> instanceMembersByName | 88 final Map<String, Link<Element>> instanceMembersByName |
| 89 = new Map<String, Link<Element>>(); | 89 = new Map<String, Link<Element>>(); |
| 90 final Map<String, Link<Element>> instanceFunctionsByName | |
| 91 = new Map<String, Link<Element>>(); | |
| 92 final Set<ClassElement> seenClasses = new Set<ClassElement>(); | 90 final Set<ClassElement> seenClasses = new Set<ClassElement>(); |
| 93 final Universe universe = new Universe(); | 91 final Universe universe = new Universe(); |
| 94 | 92 |
| 95 bool queueIsClosed = false; | 93 bool queueIsClosed = false; |
| 96 EnqueueTask task; | 94 EnqueueTask task; |
| 97 native.NativeEnqueuer nativeEnqueuer; // Set by EnqueueTask | 95 native.NativeEnqueuer nativeEnqueuer; // Set by EnqueueTask |
| 98 | 96 |
| 99 Enqueuer(this.name, this.compiler, | 97 Enqueuer(this.name, this.compiler, |
| 100 ItemCompilationContext itemCompilationContextCreator()) | 98 ItemCompilationContext itemCompilationContextCreator()) |
| 101 : this.itemCompilationContextCreator = itemCompilationContextCreator; | 99 : this.itemCompilationContextCreator = itemCompilationContextCreator; |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 204 // enclosing class, since the metadata has not been parsed yet. | 202 // enclosing class, since the metadata has not been parsed yet. |
| 205 if (!member.enclosingElement.isNative()) return; | 203 if (!member.enclosingElement.isNative()) return; |
| 206 } | 204 } |
| 207 | 205 |
| 208 String memberName = member.name.slowToString(); | 206 String memberName = member.name.slowToString(); |
| 209 | 207 |
| 210 if (member.kind == ElementKind.FUNCTION) { | 208 if (member.kind == ElementKind.FUNCTION) { |
| 211 if (member.name == Compiler.NO_SUCH_METHOD) { | 209 if (member.name == Compiler.NO_SUCH_METHOD) { |
| 212 enableNoSuchMethod(member); | 210 enableNoSuchMethod(member); |
| 213 } | 211 } |
| 212 if (universe.hasInvocation(member, compiler)) { |
| 213 return addToWorkList(member); |
| 214 } |
| 214 // If there is a property access with the same name as a method we | 215 // If there is a property access with the same name as a method we |
| 215 // need to emit the method. | 216 // need to emit the method. |
| 216 if (universe.hasInvokedGetter(member, compiler)) { | 217 if (universe.hasInvokedGetter(member, compiler)) { |
| 217 // We will emit a closure, so make sure the bound closure class is | 218 // We will emit a closure, so make sure the closure class is |
| 218 // generated. | 219 // generated. |
| 219 registerInstantiatedClass(compiler.boundClosureClass, | 220 compiler.closureClass.ensureResolved(compiler); |
| 221 registerInstantiatedClass(compiler.closureClass, |
| 220 // Precise dependency is not important here. | 222 // Precise dependency is not important here. |
| 221 compiler.globalDependencies); | 223 compiler.globalDependencies); |
| 222 return addToWorkList(member); | 224 return addToWorkList(member); |
| 223 } | 225 } |
| 224 // Store the member in [instanceFunctionsByName] to catch | |
| 225 // getters on the function. | |
| 226 Link<Element> members = instanceFunctionsByName.putIfAbsent( | |
| 227 memberName, () => const Link<Element>()); | |
| 228 instanceFunctionsByName[memberName] = members.prepend(member); | |
| 229 if (universe.hasInvocation(member, compiler)) { | |
| 230 return addToWorkList(member); | |
| 231 } | |
| 232 } else if (member.kind == ElementKind.GETTER) { | 226 } else if (member.kind == ElementKind.GETTER) { |
| 233 if (universe.hasInvokedGetter(member, compiler)) { | 227 if (universe.hasInvokedGetter(member, compiler)) { |
| 234 return addToWorkList(member); | 228 return addToWorkList(member); |
| 235 } | 229 } |
| 236 // We don't know what selectors the returned closure accepts. If | 230 // We don't know what selectors the returned closure accepts. If |
| 237 // the set contains any selector we have to assume that it matches. | 231 // the set contains any selector we have to assume that it matches. |
| 238 if (universe.hasInvocation(member, compiler)) { | 232 if (universe.hasInvocation(member, compiler)) { |
| 239 return addToWorkList(member); | 233 return addToWorkList(member); |
| 240 } | 234 } |
| 241 } else if (member.kind == ElementKind.SETTER) { | 235 } else if (member.kind == ElementKind.SETTER) { |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 385 registerInvokedGetter(element.name, selector); | 379 registerInvokedGetter(element.name, selector); |
| 386 } | 380 } |
| 387 } | 381 } |
| 388 } | 382 } |
| 389 } | 383 } |
| 390 | 384 |
| 391 /// Called when [:new Symbol(...):] is seen. | 385 /// Called when [:new Symbol(...):] is seen. |
| 392 void registerNewSymbol(TreeElements elements) { | 386 void registerNewSymbol(TreeElements elements) { |
| 393 } | 387 } |
| 394 | 388 |
| 395 processLink(Map<String, Link<Element>> map, | 389 processInstanceMembers(SourceString n, bool f(Element e)) { |
| 396 SourceString n, | |
| 397 bool f(Element e)) { | |
| 398 String memberName = n.slowToString(); | 390 String memberName = n.slowToString(); |
| 399 Link<Element> members = map[memberName]; | 391 Link<Element> members = instanceMembersByName[memberName]; |
| 400 if (members != null) { | 392 if (members != null) { |
| 401 LinkBuilder<Element> remaining = new LinkBuilder<Element>(); | 393 LinkBuilder<Element> remaining = new LinkBuilder<Element>(); |
| 402 for (; !members.isEmpty; members = members.tail) { | 394 for (; !members.isEmpty; members = members.tail) { |
| 403 if (!f(members.head)) remaining.addLast(members.head); | 395 if (!f(members.head)) remaining.addLast(members.head); |
| 404 } | 396 } |
| 405 map[memberName] = remaining.toLink(); | 397 instanceMembersByName[memberName] = remaining.toLink(); |
| 406 } | 398 } |
| 407 } | 399 } |
| 408 | 400 |
| 409 processInstanceMembers(SourceString n, bool f(Element e)) { | |
| 410 processLink(instanceMembersByName, n, f); | |
| 411 } | |
| 412 | |
| 413 processInstanceFunctions(SourceString n, bool f(Element e)) { | |
| 414 processLink(instanceFunctionsByName, n, f); | |
| 415 } | |
| 416 | |
| 417 void handleUnseenSelector(SourceString methodName, Selector selector) { | 401 void handleUnseenSelector(SourceString methodName, Selector selector) { |
| 418 processInstanceMembers(methodName, (Element member) { | 402 processInstanceMembers(methodName, (Element member) { |
| 419 if (selector.appliesUnnamed(member, compiler)) { | 403 if (selector.appliesUnnamed(member, compiler)) { |
| 420 if (member.isField() && member.enclosingElement.isNative()) { | 404 if (member.isField() && member.enclosingElement.isNative()) { |
| 421 if (selector.isGetter() || selector.isCall()) { | 405 if (selector.isGetter() || selector.isCall()) { |
| 422 nativeEnqueuer.registerFieldLoad(member); | 406 nativeEnqueuer.registerFieldLoad(member); |
| 423 // We have to also handle storing to the field because we only get | 407 // We have to also handle storing to the field because we only get |
| 424 // one look at each member and there might be a store we have not | 408 // one look at each member and there might be a store we have not |
| 425 // seen yet. | 409 // seen yet. |
| 426 // TODO(sra): Process fields for storing separately. | 410 // TODO(sra): Process fields for storing separately. |
| 427 nativeEnqueuer.registerFieldStore(member); | 411 nativeEnqueuer.registerFieldStore(member); |
| 428 } else { | 412 } else { |
| 429 nativeEnqueuer.registerFieldStore(member); | 413 nativeEnqueuer.registerFieldStore(member); |
| 430 // We have to also handle loading from the field because we only get | 414 // We have to also handle loading from the field because we only get |
| 431 // one look at each member and there might be a load we have not | 415 // one look at each member and there might be a load we have not |
| 432 // seen yet. | 416 // seen yet. |
| 433 // TODO(sra): Process fields for storing separately. | 417 // TODO(sra): Process fields for storing separately. |
| 434 nativeEnqueuer.registerFieldLoad(member); | 418 nativeEnqueuer.registerFieldLoad(member); |
| 435 } | 419 } |
| 436 } else { | 420 } else { |
| 437 addToWorkList(member); | 421 addToWorkList(member); |
| 438 } | 422 } |
| 439 return true; | 423 return true; |
| 440 } | 424 } |
| 441 return false; | 425 return false; |
| 442 }); | 426 }); |
| 443 if (selector.isGetter()) { | |
| 444 processInstanceFunctions(methodName, (Element member) { | |
| 445 if (selector.appliesUnnamed(member, compiler)) { | |
| 446 // We will emit a closure, so make sure the bound closure class is | |
| 447 // generated. | |
| 448 registerInstantiatedClass(compiler.boundClosureClass, | |
| 449 // Precise dependency is not important here. | |
| 450 compiler.globalDependencies); | |
| 451 return true; | |
| 452 } | |
| 453 return false; | |
| 454 }); | |
| 455 } | |
| 456 } | 427 } |
| 457 | 428 |
| 458 /** | 429 /** |
| 459 * Documentation wanted -- johnniwinther | 430 * Documentation wanted -- johnniwinther |
| 460 * | 431 * |
| 461 * Invariant: [element] must be a declaration element. | 432 * Invariant: [element] must be a declaration element. |
| 462 */ | 433 */ |
| 463 void registerStaticUse(Element element) { | 434 void registerStaticUse(Element element) { |
| 464 if (element == null) return; | 435 if (element == null) return; |
| 465 assert(invariant(element, element.isDeclaration)); | 436 assert(invariant(element, element.isDeclaration)); |
| 466 addToWorkList(element); | 437 addToWorkList(element); |
| 467 } | 438 } |
| 468 | 439 |
| 469 void registerGetOfStaticFunction(FunctionElement element) { | 440 void registerGetOfStaticFunction(FunctionElement element) { |
| 470 registerStaticUse(element); | 441 registerStaticUse(element); |
| 471 registerInstantiatedClass(compiler.closureClass, | |
| 472 compiler.globalDependencies); | |
| 473 universe.staticFunctionsNeedingGetter.add(element); | 442 universe.staticFunctionsNeedingGetter.add(element); |
| 474 } | 443 } |
| 475 | 444 |
| 476 void registerDynamicInvocation(SourceString methodName, Selector selector) { | 445 void registerDynamicInvocation(SourceString methodName, Selector selector) { |
| 477 assert(selector != null); | 446 assert(selector != null); |
| 478 registerInvocation(methodName, selector); | 447 registerInvocation(methodName, selector); |
| 479 } | 448 } |
| 480 | 449 |
| 481 void registerDynamicInvocationOf(Element element, Selector selector) { | 450 void registerDynamicInvocationOf(Element element, Selector selector) { |
| 482 assert(selector.isCall() | 451 assert(selector.isCall() |
| (...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 752 while(!queue.isEmpty) { | 721 while(!queue.isEmpty) { |
| 753 // TODO(johnniwinther): Find an optimal process order for codegen. | 722 // TODO(johnniwinther): Find an optimal process order for codegen. |
| 754 f(queue.removeLast()); | 723 f(queue.removeLast()); |
| 755 } | 724 } |
| 756 } | 725 } |
| 757 | 726 |
| 758 void _logSpecificSummary(log(message)) { | 727 void _logSpecificSummary(log(message)) { |
| 759 log('Compiled ${generatedCode.length} methods.'); | 728 log('Compiled ${generatedCode.length} methods.'); |
| 760 } | 729 } |
| 761 } | 730 } |
| OLD | NEW |