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