OLD | NEW |
---|---|
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 #include "vm/block_scheduler.h" | 5 #include "vm/block_scheduler.h" |
6 | 6 |
7 #include "vm/allocation.h" | 7 #include "vm/allocation.h" |
8 #include "vm/code_patcher.h" | 8 #include "vm/code_patcher.h" |
9 #include "vm/flow_graph.h" | 9 #include "vm/flow_graph.h" |
10 | 10 |
11 namespace dart { | 11 namespace dart { |
12 | 12 |
13 DEFINE_FLAG(bool, emit_edge_counters, true, "Emit edge counters at targets."); | 13 DEFINE_FLAG(bool, emit_edge_counters, true, "Emit edge counters at targets."); |
14 | 14 |
15 // Compute the edge count at the deopt id of a TargetEntry or Goto. | 15 // Compute the edge count at the deopt id of a TargetEntry or Goto. |
16 static intptr_t ComputeEdgeCount(const Code& unoptimized_code, | 16 static intptr_t ComputeEdgeCount( |
17 intptr_t deopt_id) { | 17 const Code& unoptimized_code, |
18 const ZoneGrowableArray<uword>& deopt_id_pc_pairs, | |
19 intptr_t deopt_id) { | |
18 ASSERT(deopt_id != Isolate::kNoDeoptId); | 20 ASSERT(deopt_id != Isolate::kNoDeoptId); |
19 | 21 |
20 if (!FLAG_emit_edge_counters) { | 22 if (!FLAG_emit_edge_counters) { |
21 // Assume everything was visited once. | 23 // Assume everything was visited once. |
22 return 1; | 24 return 1; |
23 } | 25 } |
24 const uword pc = | 26 |
25 unoptimized_code.GetPcForDeoptId(deopt_id, RawPcDescriptors::kDeopt); | 27 intptr_t n = deopt_id_pc_pairs.length(); |
26 Array& array = Array::Handle(); | 28 intptr_t i = 0; |
27 array ^= CodePatcher::GetEdgeCounterAt(pc, unoptimized_code); | 29 while (i < n) { |
Florian Schneider
2015/05/18 11:33:28
I'd turn this into a for-loop.
rmacnak
2015/05/18 18:03:54
Done.
| |
28 ASSERT(!array.IsNull()); | 30 intptr_t deopt_id_entry = static_cast<intptr_t>(deopt_id_pc_pairs[i++]); |
29 return Smi::Value(Smi::RawCast(array.At(0))); | 31 uword pc = deopt_id_pc_pairs[i++]; |
32 if (deopt_id_entry == deopt_id) { | |
33 Array& array = Array::Handle(); | |
34 array ^= CodePatcher::GetEdgeCounterAt(pc, unoptimized_code); | |
35 ASSERT(!array.IsNull()); | |
36 return Smi::Value(Smi::RawCast(array.At(0))); | |
37 } | |
38 } | |
39 | |
40 UNREACHABLE(); | |
41 return 1; | |
30 } | 42 } |
31 | 43 |
32 | 44 |
33 // There is an edge from instruction->successor. Set its weight (edge count | 45 // There is an edge from instruction->successor. Set its weight (edge count |
34 // per function entry). | 46 // per function entry). |
35 static void SetEdgeWeight(Instruction* instruction, | 47 static void SetEdgeWeight(Instruction* instruction, |
36 BlockEntryInstr* successor, | 48 BlockEntryInstr* successor, |
37 const Code& unoptimized_code, | 49 const Code& unoptimized_code, |
50 const ZoneGrowableArray<uword>& deopt_id_pc_pairs, | |
38 intptr_t entry_count) { | 51 intptr_t entry_count) { |
39 TargetEntryInstr* target = successor->AsTargetEntry(); | 52 TargetEntryInstr* target = successor->AsTargetEntry(); |
40 if (target != NULL) { | 53 if (target != NULL) { |
41 // If this block ends in a goto, the edge count of this edge is the same | 54 // If this block ends in a goto, the edge count of this edge is the same |
42 // as the count on the single outgoing edge. This is true as long as the | 55 // as the count on the single outgoing edge. This is true as long as the |
43 // block does not throw an exception. | 56 // block does not throw an exception. |
44 GotoInstr* jump = target->last_instruction()->AsGoto(); | 57 GotoInstr* jump = target->last_instruction()->AsGoto(); |
45 const intptr_t deopt_id = | 58 const intptr_t deopt_id = |
46 (jump != NULL) ? jump->deopt_id() : target->deopt_id(); | 59 (jump != NULL) ? jump->deopt_id() : target->deopt_id(); |
47 intptr_t count = ComputeEdgeCount(unoptimized_code, deopt_id); | 60 intptr_t count = ComputeEdgeCount(unoptimized_code, |
61 deopt_id_pc_pairs, | |
62 deopt_id); | |
48 if ((count >= 0) && (entry_count != 0)) { | 63 if ((count >= 0) && (entry_count != 0)) { |
49 double weight = | 64 double weight = |
50 static_cast<double>(count) / static_cast<double>(entry_count); | 65 static_cast<double>(count) / static_cast<double>(entry_count); |
51 target->set_edge_weight(weight); | 66 target->set_edge_weight(weight); |
52 } | 67 } |
53 } else { | 68 } else { |
54 GotoInstr* jump = instruction->AsGoto(); | 69 GotoInstr* jump = instruction->AsGoto(); |
55 if (jump != NULL) { | 70 if (jump != NULL) { |
56 intptr_t count = ComputeEdgeCount(unoptimized_code, jump->deopt_id()); | 71 intptr_t count = ComputeEdgeCount(unoptimized_code, |
72 deopt_id_pc_pairs, | |
73 jump->deopt_id()); | |
57 if ((count >= 0) && (entry_count != 0)) { | 74 if ((count >= 0) && (entry_count != 0)) { |
58 double weight = | 75 double weight = |
59 static_cast<double>(count) / static_cast<double>(entry_count); | 76 static_cast<double>(count) / static_cast<double>(entry_count); |
60 jump->set_edge_weight(weight); | 77 jump->set_edge_weight(weight); |
61 } | 78 } |
62 } | 79 } |
63 } | 80 } |
64 } | 81 } |
65 | 82 |
66 | 83 |
67 void BlockScheduler::AssignEdgeWeights() const { | 84 void BlockScheduler::AssignEdgeWeights() const { |
68 const Code& unoptimized_code = flow_graph()->parsed_function().code(); | 85 const Code& unoptimized_code = flow_graph()->parsed_function().code(); |
69 ASSERT(!unoptimized_code.IsNull()); | 86 ASSERT(!unoptimized_code.IsNull()); |
70 | 87 |
88 ZoneGrowableArray<uword>* deopt_id_pc_pairs = new ZoneGrowableArray<uword>(); | |
Florian Schneider
2015/05/18 11:33:28
I wonder if using DirectChainedHashMap from hash_m
rmacnak
2015/05/18 18:03:54
I'll take a look.
| |
89 const PcDescriptors& descriptors = | |
90 PcDescriptors::Handle(unoptimized_code.pc_descriptors()); | |
91 PcDescriptors::Iterator iter(descriptors, RawPcDescriptors::kDeopt); | |
92 uword entry = unoptimized_code.EntryPoint(); | |
93 while (iter.MoveNext()) { | |
94 intptr_t deopt_id = iter.DeoptId(); | |
95 ASSERT(deopt_id != Isolate::kNoDeoptId); | |
96 uint32_t pc_offset = iter.PcOffset(); | |
97 deopt_id_pc_pairs->Add(static_cast<uword>(deopt_id)); | |
98 deopt_id_pc_pairs->Add(entry + pc_offset); | |
99 } | |
100 | |
71 intptr_t entry_count = | 101 intptr_t entry_count = |
72 ComputeEdgeCount(unoptimized_code, | 102 ComputeEdgeCount(unoptimized_code, |
103 *deopt_id_pc_pairs, | |
73 flow_graph()->graph_entry()->normal_entry()->deopt_id()); | 104 flow_graph()->graph_entry()->normal_entry()->deopt_id()); |
74 flow_graph()->graph_entry()->set_entry_count(entry_count); | 105 flow_graph()->graph_entry()->set_entry_count(entry_count); |
75 | 106 |
76 for (BlockIterator it = flow_graph()->reverse_postorder_iterator(); | 107 for (BlockIterator it = flow_graph()->reverse_postorder_iterator(); |
77 !it.Done(); | 108 !it.Done(); |
78 it.Advance()) { | 109 it.Advance()) { |
79 BlockEntryInstr* block = it.Current(); | 110 BlockEntryInstr* block = it.Current(); |
80 Instruction* last = block->last_instruction(); | 111 Instruction* last = block->last_instruction(); |
81 for (intptr_t i = 0; i < last->SuccessorCount(); ++i) { | 112 for (intptr_t i = 0; i < last->SuccessorCount(); ++i) { |
82 BlockEntryInstr* succ = last->SuccessorAt(i); | 113 BlockEntryInstr* succ = last->SuccessorAt(i); |
83 SetEdgeWeight(last, succ, unoptimized_code, entry_count); | 114 SetEdgeWeight(last, succ, |
115 unoptimized_code, *deopt_id_pc_pairs, entry_count); | |
84 } | 116 } |
85 } | 117 } |
86 } | 118 } |
87 | 119 |
88 | 120 |
89 // A weighted control-flow graph edge. | 121 // A weighted control-flow graph edge. |
90 struct Edge { | 122 struct Edge { |
91 Edge(BlockEntryInstr* source, BlockEntryInstr* target, double weight) | 123 Edge(BlockEntryInstr* source, BlockEntryInstr* target, double weight) |
92 : source(source), target(target), weight(weight) { } | 124 : source(source), target(target), weight(weight) { } |
93 | 125 |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
209 for (intptr_t i = block_count - 1; i >= 0; --i) { | 241 for (intptr_t i = block_count - 1; i >= 0; --i) { |
210 if (chains[i]->first->block == flow_graph()->postorder()[i]) { | 242 if (chains[i]->first->block == flow_graph()->postorder()[i]) { |
211 for (Link* link = chains[i]->first; link != NULL; link = link->next) { | 243 for (Link* link = chains[i]->first; link != NULL; link = link->next) { |
212 flow_graph()->CodegenBlockOrder(true)->Add(link->block); | 244 flow_graph()->CodegenBlockOrder(true)->Add(link->block); |
213 } | 245 } |
214 } | 246 } |
215 } | 247 } |
216 } | 248 } |
217 | 249 |
218 } // namespace dart | 250 } // namespace dart |
OLD | NEW |