Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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 library analyzer.src.task.driver; | 5 library analyzer.src.task.driver; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 import 'dart:collection'; | 8 import 'dart:collection'; |
| 9 | 9 |
| 10 import 'package:analyzer/src/context/cache.dart'; | 10 import 'package:analyzer/src/context/cache.dart'; |
| 11 import 'package:analyzer/src/generated/engine.dart' | 11 import 'package:analyzer/src/generated/engine.dart' |
| 12 hide AnalysisTask, AnalysisContextImpl, WorkManager; | 12 hide AnalysisTask, AnalysisContextImpl, WorkManager; |
| 13 import 'package:analyzer/src/generated/java_engine.dart'; | 13 import 'package:analyzer/src/generated/java_engine.dart'; |
| 14 import 'package:analyzer/src/generated/resolver.dart'; | 14 import 'package:analyzer/src/generated/resolver.dart'; |
| 15 import 'package:analyzer/src/generated/utilities_general.dart'; | 15 import 'package:analyzer/src/generated/utilities_general.dart'; |
| 16 import 'package:analyzer/src/task/inputs.dart'; | 16 import 'package:analyzer/src/task/inputs.dart'; |
| 17 import 'package:analyzer/src/task/manager.dart'; | 17 import 'package:analyzer/src/task/manager.dart'; |
| 18 import 'package:analyzer/task/model.dart'; | 18 import 'package:analyzer/task/model.dart'; |
| 19 | 19 |
| 20 final PerformanceTag workOrderMoveNextPerfTag = | 20 final PerformanceTag workOrderMoveNextPerformanceTag = |
| 21 new PerformanceTag('WorkOrder.moveNext'); | 21 new PerformanceTag('WorkOrder.moveNext'); |
| 22 | 22 |
| 23 /** | 23 /** |
| 24 * An object that is used to cause analysis to be performed until all of the | 24 * An object that is used to cause analysis to be performed until all of the |
| 25 * required analysis information has been computed. | 25 * required analysis information has been computed. |
| 26 */ | 26 */ |
| 27 class AnalysisDriver { | 27 class AnalysisDriver { |
| 28 /** | 28 /** |
| 29 * The task manager used to figure out how to compute analysis results. | 29 * The task manager used to figure out how to compute analysis results. |
| 30 */ | 30 */ |
| (...skipping 482 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 513 * if [nodes] has multiple elements, this will always be `true`. However, if | 513 * if [nodes] has multiple elements, this will always be `true`. However, if |
| 514 * [nodes] has exactly one element, this may be either `true` or `false` | 514 * [nodes] has exactly one element, this may be either `true` or `false` |
| 515 * depending on whether the node has a dependency on itself. | 515 * depending on whether the node has a dependency on itself. |
| 516 */ | 516 */ |
| 517 final bool containsCycle; | 517 final bool containsCycle; |
| 518 | 518 |
| 519 StronglyConnectedComponent(this.nodes, this.containsCycle); | 519 StronglyConnectedComponent(this.nodes, this.containsCycle); |
| 520 } | 520 } |
| 521 | 521 |
| 522 /** | 522 /** |
| 523 * A description of a single anaysis task that can be performed to advance | 523 * A description of a single analysis task that can be performed to advance |
| 524 * analysis. | 524 * analysis. |
| 525 */ | 525 */ |
| 526 class WorkItem { | 526 class WorkItem { |
| 527 /** | 527 /** |
| 528 * A table mapping the names of analysis tasks to the number of times each | |
| 529 * kind of task has been performed. | |
| 530 */ | |
| 531 static final Map<String, int> countMap = new HashMap<String, int>(); | |
| 532 | |
| 533 /** | |
| 534 * A table mapping the names of analysis tasks to stopwatches used to compute | |
| 535 * how much time was spent between creating an item and creating (for | |
| 536 * performing) of each kind of task | |
| 537 */ | |
| 538 static final Map<String, Stopwatch> stopwatchMap = | |
| 539 new HashMap<String, Stopwatch>(); | |
| 540 | |
| 541 /** | |
| 528 * The context in which the task will be performed. | 542 * The context in which the task will be performed. |
| 529 */ | 543 */ |
| 530 final InternalAnalysisContext context; | 544 final InternalAnalysisContext context; |
| 531 | 545 |
| 532 /** | 546 /** |
| 533 * The target for which a task is to be performed. | 547 * The target for which a task is to be performed. |
| 534 */ | 548 */ |
| 535 final AnalysisTarget target; | 549 final AnalysisTarget target; |
| 536 | 550 |
| 537 /** | 551 /** |
| 538 * A description of the task to be performed. | 552 * A description of the task to be performed. |
| 539 */ | 553 */ |
| 540 final TaskDescriptor descriptor; | 554 final TaskDescriptor descriptor; |
| 541 | 555 |
| 542 /** | 556 /** |
| 543 * The [ResultDescriptor] which was led to this work item being spawned. | 557 * The [ResultDescriptor] which was led to this work item being spawned. |
| 544 */ | 558 */ |
| 545 final ResultDescriptor spawningResult; | 559 final ResultDescriptor spawningResult; |
| 546 | 560 |
| 547 /** | 561 /** |
| 562 * The current inputs computing stopwatch. | |
| 563 */ | |
| 564 Stopwatch stopwatch; | |
| 565 | |
| 566 /** | |
| 548 * An iterator used to iterate over the descriptors of the inputs to the task, | 567 * An iterator used to iterate over the descriptors of the inputs to the task, |
| 549 * or `null` if all of the inputs have been collected and the task can be | 568 * or `null` if all of the inputs have been collected and the task can be |
| 550 * created. | 569 * created. |
| 551 */ | 570 */ |
| 552 TaskInputBuilder builder; | 571 TaskInputBuilder builder; |
| 553 | 572 |
| 554 /** | 573 /** |
| 555 * The [TargetedResult]s outputs of this task depends on. | 574 * The [TargetedResult]s outputs of this task depends on. |
| 556 */ | 575 */ |
| 557 final HashSet<TargetedResult> inputTargetedResults = | 576 final HashSet<TargetedResult> inputTargetedResults = |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 587 identical(target, AnalysisContextTarget.request) | 606 identical(target, AnalysisContextTarget.request) |
| 588 ? new AnalysisContextTarget(context) | 607 ? new AnalysisContextTarget(context) |
| 589 : target; | 608 : target; |
| 590 Map<String, TaskInput> inputDescriptors = | 609 Map<String, TaskInput> inputDescriptors = |
| 591 descriptor.createTaskInputs(actualTarget); | 610 descriptor.createTaskInputs(actualTarget); |
| 592 builder = new TopLevelTaskInputBuilder(inputDescriptors); | 611 builder = new TopLevelTaskInputBuilder(inputDescriptors); |
| 593 if (!builder.moveNext()) { | 612 if (!builder.moveNext()) { |
| 594 builder = null; | 613 builder = null; |
| 595 } | 614 } |
| 596 inputs = new HashMap<String, dynamic>(); | 615 inputs = new HashMap<String, dynamic>(); |
| 616 // Update performance counters. | |
| 617 { | |
| 618 stopwatch = stopwatchMap[descriptor.name]; | |
|
Brian Wilkerson
2015/10/23 16:27:11
The descriptors are long-lived and unique, so you
| |
| 619 if (stopwatch == null) { | |
| 620 stopwatch = new Stopwatch(); | |
| 621 stopwatchMap[descriptor.name] = stopwatch; | |
| 622 } | |
| 623 stopwatch.start(); | |
| 624 } | |
| 625 { | |
| 626 int count = countMap[descriptor.name]; | |
| 627 countMap[descriptor.name] = count == null ? 1 : count + 1; | |
| 628 } | |
| 597 } | 629 } |
| 598 | 630 |
| 599 @override | 631 @override |
| 600 int get hashCode => | 632 int get hashCode => |
| 601 JenkinsSmiHash.hash2(descriptor.hashCode, target.hashCode); | 633 JenkinsSmiHash.hash2(descriptor.hashCode, target.hashCode); |
| 602 | 634 |
| 603 @override | 635 @override |
| 604 bool operator ==(other) { | 636 bool operator ==(other) { |
| 605 if (other is WorkItem) { | 637 if (other is WorkItem) { |
| 606 return this.descriptor == other.descriptor && this.target == other.target; | 638 return this.descriptor == other.descriptor && this.target == other.target; |
| 607 } else { | 639 } else { |
| 608 return false; | 640 return false; |
| 609 } | 641 } |
| 610 } | 642 } |
| 611 | 643 |
| 612 /** | 644 /** |
| 613 * Build the task represented by this work item. | 645 * Build the task represented by this work item. |
| 614 */ | 646 */ |
| 615 AnalysisTask buildTask() { | 647 AnalysisTask buildTask() { |
| 648 stopwatch.stop(); | |
| 616 if (builder != null) { | 649 if (builder != null) { |
| 617 throw new StateError("some inputs have not been computed"); | 650 throw new StateError("some inputs have not been computed"); |
| 618 } | 651 } |
| 619 AnalysisTask task = descriptor.createTask(context, target, inputs); | 652 AnalysisTask task = descriptor.createTask(context, target, inputs); |
| 620 task.dependencyCycle = dependencyCycle; | 653 task.dependencyCycle = dependencyCycle; |
| 621 return task; | 654 return task; |
| 622 } | 655 } |
| 623 | 656 |
| 624 /** | 657 /** |
| 625 * Gather all of the inputs needed to perform the task. | 658 * Gather all of the inputs needed to perform the task. |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 723 WorkItem get current { | 756 WorkItem get current { |
| 724 if (currentItems == null) { | 757 if (currentItems == null) { |
| 725 return null; | 758 return null; |
| 726 } else { | 759 } else { |
| 727 return currentItems.last; | 760 return currentItems.last; |
| 728 } | 761 } |
| 729 } | 762 } |
| 730 | 763 |
| 731 @override | 764 @override |
| 732 bool moveNext() { | 765 bool moveNext() { |
| 733 return workOrderMoveNextPerfTag.makeCurrentWhile(() { | 766 return workOrderMoveNextPerformanceTag.makeCurrentWhile(() { |
| 734 if (currentItems != null && currentItems.length > 1) { | 767 if (currentItems != null && currentItems.length > 1) { |
| 735 // Yield more items. | 768 // Yield more items. |
| 736 currentItems.removeLast(); | 769 currentItems.removeLast(); |
| 737 return true; | 770 return true; |
| 738 } else { | 771 } else { |
| 739 // Get a new strongly connected component. | 772 // Get a new strongly connected component. |
| 740 StronglyConnectedComponent<WorkItem> nextStronglyConnectedComponent = | 773 StronglyConnectedComponent<WorkItem> nextStronglyConnectedComponent = |
| 741 _dependencyWalker.getNextStronglyConnectedComponent(); | 774 _dependencyWalker.getNextStronglyConnectedComponent(); |
| 742 if (nextStronglyConnectedComponent == null) { | 775 if (nextStronglyConnectedComponent == null) { |
| 743 currentItems = null; | 776 currentItems = null; |
| 744 return false; | 777 return false; |
| 745 } | 778 } |
| 746 currentItems = nextStronglyConnectedComponent.nodes; | 779 currentItems = nextStronglyConnectedComponent.nodes; |
| 747 if (nextStronglyConnectedComponent.containsCycle) { | 780 if (nextStronglyConnectedComponent.containsCycle) { |
| 748 // A cycle has been found. | 781 // A cycle has been found. |
| 749 for (WorkItem item in currentItems) { | 782 for (WorkItem item in currentItems) { |
| 750 item.dependencyCycle = currentItems.toList(); | 783 item.dependencyCycle = currentItems.toList(); |
| 751 } | 784 } |
| 752 } else { | 785 } else { |
| 753 assert(currentItems.length == 1); | 786 assert(currentItems.length == 1); |
| 754 } | 787 } |
| 755 return true; | 788 return true; |
| 756 } | 789 } |
| 757 }); | 790 }); |
| 758 } | 791 } |
| 759 } | 792 } |
| 760 | 793 |
| 761 /** | 794 /** |
| 762 * Specilaization of [CycleAwareDependencyWalker] for use by [WorkOrder]. | 795 * Specialization of [CycleAwareDependencyWalker] for use by [WorkOrder]. |
| 763 */ | 796 */ |
| 764 class _WorkOrderDependencyWalker extends CycleAwareDependencyWalker<WorkItem> { | 797 class _WorkOrderDependencyWalker extends CycleAwareDependencyWalker<WorkItem> { |
| 765 /** | 798 /** |
| 766 * The task manager used to build work items. | 799 * The task manager used to build work items. |
| 767 */ | 800 */ |
| 768 final TaskManager taskManager; | 801 final TaskManager taskManager; |
| 769 | 802 |
| 770 _WorkOrderDependencyWalker(this.taskManager, WorkItem startingNode) | 803 _WorkOrderDependencyWalker(this.taskManager, WorkItem startingNode) |
| 771 : super(startingNode); | 804 : super(startingNode); |
| 772 | 805 |
| 773 @override | 806 @override |
| 774 WorkItem getNextInput(WorkItem node, List<WorkItem> skipInputs) { | 807 WorkItem getNextInput(WorkItem node, List<WorkItem> skipInputs) { |
| 775 return node.gatherInputs(taskManager, skipInputs); | 808 return node.gatherInputs(taskManager, skipInputs); |
| 776 } | 809 } |
| 777 } | 810 } |
| OLD | NEW |