| 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 | 5 |
| 6 /** | 6 /** |
| 7 * If true, print a warning for each method that was resolved, but not | 7 * If true, print a warning for each method that was resolved, but not |
| 8 * compiled. | 8 * compiled. |
| 9 */ | 9 */ |
| 10 final bool REPORT_EXCESS_RESOLUTION = false; | 10 final bool REPORT_EXCESS_RESOLUTION = false; |
| 11 | 11 |
| 12 /** |
| 13 * If true, trace information on pass2 optimizations. |
| 14 */ |
| 15 final bool REPORT_PASS2_OPTIMIZATIONS = false; |
| 16 |
| 12 class WorkItem { | 17 class WorkItem { |
| 13 final Element element; | 18 final Element element; |
| 14 TreeElements resolutionTree; | 19 TreeElements resolutionTree; |
| 15 bool allowSpeculativeOptimization = true; | 20 bool allowSpeculativeOptimization = true; |
| 16 List<HTypeGuard> guards = const <HTypeGuard>[]; | 21 List<HTypeGuard> guards = const <HTypeGuard>[]; |
| 17 | 22 |
| 18 WorkItem(this.element, this.resolutionTree); | 23 WorkItem(this.element, this.resolutionTree); |
| 19 | 24 |
| 20 bool isAnalyzed() => resolutionTree !== null; | 25 bool isAnalyzed() => resolutionTree !== null; |
| 21 | 26 |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 150 ScannerTask scanner; | 155 ScannerTask scanner; |
| 151 DietParserTask dietParser; | 156 DietParserTask dietParser; |
| 152 ParserTask parser; | 157 ParserTask parser; |
| 153 TreeValidatorTask validator; | 158 TreeValidatorTask validator; |
| 154 UnparseValidator unparseValidator; | 159 UnparseValidator unparseValidator; |
| 155 ResolverTask resolver; | 160 ResolverTask resolver; |
| 156 TypeCheckerTask checker; | 161 TypeCheckerTask checker; |
| 157 Backend backend; | 162 Backend backend; |
| 158 ConstantHandler constantHandler; | 163 ConstantHandler constantHandler; |
| 159 EnqueueTask enqueuer; | 164 EnqueueTask enqueuer; |
| 165 int pass = 1; |
| 160 | 166 |
| 161 static final SourceString MAIN = const SourceString('main'); | 167 static final SourceString MAIN = const SourceString('main'); |
| 162 static final SourceString NO_SUCH_METHOD = const SourceString('noSuchMethod'); | 168 static final SourceString NO_SUCH_METHOD = const SourceString('noSuchMethod'); |
| 163 static final SourceString NO_SUCH_METHOD_EXCEPTION = | 169 static final SourceString NO_SUCH_METHOD_EXCEPTION = |
| 164 const SourceString('NoSuchMethodException'); | 170 const SourceString('NoSuchMethodException'); |
| 165 static final SourceString START_ROOT_ISOLATE = | 171 static final SourceString START_ROOT_ISOLATE = |
| 166 const SourceString('startRootIsolate'); | 172 const SourceString('startRootIsolate'); |
| 167 bool enabledNoSuchMethod = false; | 173 bool enabledNoSuchMethod = false; |
| 168 | 174 |
| 169 Stopwatch codegenProgress; | 175 Stopwatch codegenProgress; |
| (...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 403 // should know this. | 409 // should know this. |
| 404 world.populate(this, libraries.getValues()); | 410 world.populate(this, libraries.getValues()); |
| 405 | 411 |
| 406 log('Resolving...'); | 412 log('Resolving...'); |
| 407 backend.enqueueHelpers(enqueuer.resolution); | 413 backend.enqueueHelpers(enqueuer.resolution); |
| 408 processQueue(enqueuer.resolution, main); | 414 processQueue(enqueuer.resolution, main); |
| 409 log('Resolved ${enqueuer.resolution.resolvedElements.length} elements.'); | 415 log('Resolved ${enqueuer.resolution.resolvedElements.length} elements.'); |
| 410 | 416 |
| 411 log('Compiling...'); | 417 log('Compiling...'); |
| 412 processQueue(enqueuer.codegen, main); | 418 processQueue(enqueuer.codegen, main); |
| 419 log("Recompiling ${enqueuer.codegen.recompilationCandidates.length} " |
| 420 "methods..."); |
| 421 processRecompilationQueue(enqueuer.codegen); |
| 413 log('Compiled ${codegenWorld.generatedCode.length} methods.'); | 422 log('Compiled ${codegenWorld.generatedCode.length} methods.'); |
| 414 | 423 |
| 415 backend.assembleProgram(); | 424 backend.assembleProgram(); |
| 416 | 425 |
| 417 checkQueues(); | 426 checkQueues(); |
| 418 } | 427 } |
| 419 | 428 |
| 420 processQueue(Enqueuer world, Element main) { | 429 processQueue(Enqueuer world, Element main) { |
| 421 backend.processNativeClasses(world, libraries.getValues()); | 430 backend.processNativeClasses(world, libraries.getValues()); |
| 422 world.addToWorkList(main); | 431 world.addToWorkList(main); |
| 423 codegenProgress.reset(); | 432 codegenProgress.reset(); |
| 424 world.forEach((WorkItem work) { | 433 world.forEach((WorkItem work) { |
| 425 withCurrentElement(work.element, () => work.run(this, world)); | 434 withCurrentElement(work.element, () => work.run(this, world)); |
| 426 }); | 435 }); |
| 427 world.queueIsClosed = true; | 436 world.queueIsClosed = true; |
| 428 assert(world.checkNoEnqueuedInvokedInstanceMethods()); | 437 assert(world.checkNoEnqueuedInvokedInstanceMethods()); |
| 429 world.registerFieldClosureInvocations(); | 438 world.registerFieldClosureInvocations(); |
| 430 } | 439 } |
| 431 | 440 |
| 441 processRecompilationQueue(Enqueuer world) { |
| 442 pass = 2; |
| 443 while (!world.recompilationCandidates.isEmpty()) { |
| 444 WorkItem work = world.recompilationCandidates.next(); |
| 445 var oldCode = world.universe.generatedCode[work.element]; |
| 446 world.universe.generatedCode.remove(work.element); |
| 447 withCurrentElement(work.element, () => work.run(this, world)); |
| 448 var newCode = world.universe.generatedCode[work.element]; |
| 449 if (REPORT_PASS2_OPTIMIZATIONS && newCode != oldCode) { |
| 450 log("Pass 2 optimization:"); |
| 451 log("Before:\n$oldCode"); |
| 452 log("After:\n$newCode"); |
| 453 } |
| 454 } |
| 455 } |
| 456 |
| 432 /** | 457 /** |
| 433 * Perform various checks of the queues. This includes checking that | 458 * Perform various checks of the queues. This includes checking that |
| 434 * the queues are empty (nothing was added after we stopped | 459 * the queues are empty (nothing was added after we stopped |
| 435 * processing the quese). Also compute the number of methods that | 460 * processing the quese). Also compute the number of methods that |
| 436 * were resolved, but not compiled (aka excess resolution). | 461 * were resolved, but not compiled (aka excess resolution). |
| 437 */ | 462 */ |
| 438 checkQueues() { | 463 checkQueues() { |
| 439 for (var world in [enqueuer.resolution, enqueuer.codegen]) { | 464 for (var world in [enqueuer.resolution, enqueuer.codegen]) { |
| 440 world.forEach((WorkItem work) { | 465 world.forEach((WorkItem work) { |
| 441 internalErrorOnElement(work.element, "Work list is not empty."); | 466 internalErrorOnElement(work.element, "Work list is not empty."); |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 566 if (message is TypeWarning) { | 591 if (message is TypeWarning) { |
| 567 // TODO(ahe): Don't supress these warning when the type checker | 592 // TODO(ahe): Don't supress these warning when the type checker |
| 568 // is more complete. | 593 // is more complete. |
| 569 if (message.message.kind === MessageKind.NOT_ASSIGNABLE) return; | 594 if (message.message.kind === MessageKind.NOT_ASSIGNABLE) return; |
| 570 if (message.message.kind === MessageKind.MISSING_RETURN) return; | 595 if (message.message.kind === MessageKind.MISSING_RETURN) return; |
| 571 if (message.message.kind === MessageKind.MAYBE_MISSING_RETURN) return; | 596 if (message.message.kind === MessageKind.MAYBE_MISSING_RETURN) return; |
| 572 if (message.message.kind === MessageKind.ADDITIONAL_ARGUMENT) return; | 597 if (message.message.kind === MessageKind.ADDITIONAL_ARGUMENT) return; |
| 573 if (message.message.kind === MessageKind.METHOD_NOT_FOUND) return; | 598 if (message.message.kind === MessageKind.METHOD_NOT_FOUND) return; |
| 574 } | 599 } |
| 575 SourceSpan span = spanFromNode(node); | 600 SourceSpan span = spanFromNode(node); |
| 601 |
| 576 reportDiagnostic(span, "${magenta('warning:')} $message", false); | 602 reportDiagnostic(span, "${magenta('warning:')} $message", false); |
| 577 } | 603 } |
| 578 | 604 |
| 579 reportError(Node node, var message) { | 605 reportError(Node node, var message) { |
| 580 SourceSpan span = spanFromNode(node); | 606 SourceSpan span = spanFromNode(node); |
| 581 reportDiagnostic(span, "${red('error:')} $message", true); | 607 reportDiagnostic(span, "${red('error:')} $message", true); |
| 582 throw new CompilerCancelledException(message.toString()); | 608 throw new CompilerCancelledException(message.toString()); |
| 583 } | 609 } |
| 584 | 610 |
| 585 abstract void reportDiagnostic(SourceSpan span, String message, bool fatal); | 611 abstract void reportDiagnostic(SourceSpan span, String message, bool fatal); |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 701 // invariant that endOffset > beginOffset, but for EOF the | 727 // invariant that endOffset > beginOffset, but for EOF the |
| 702 // charoffset of the next token may be [beginOffset]. This can | 728 // charoffset of the next token may be [beginOffset]. This can |
| 703 // also happen for synthetized tokens that are produced during | 729 // also happen for synthetized tokens that are produced during |
| 704 // error handling. | 730 // error handling. |
| 705 final endOffset = | 731 final endOffset = |
| 706 Math.max((end.next !== null) ? end.next.charOffset : 0, beginOffset + 1); | 732 Math.max((end.next !== null) ? end.next.charOffset : 0, beginOffset + 1); |
| 707 assert(endOffset > beginOffset); | 733 assert(endOffset > beginOffset); |
| 708 return f(beginOffset, endOffset); | 734 return f(beginOffset, endOffset); |
| 709 } | 735 } |
| 710 } | 736 } |
| OLD | NEW |