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 #ifndef RUNTIME_VM_FLOW_GRAPH_H_ | 5 #ifndef RUNTIME_VM_FLOW_GRAPH_H_ |
6 #define RUNTIME_VM_FLOW_GRAPH_H_ | 6 #define RUNTIME_VM_FLOW_GRAPH_H_ |
7 | 7 |
8 #include "vm/bit_vector.h" | 8 #include "vm/bit_vector.h" |
9 #include "vm/growable_array.h" | 9 #include "vm/growable_array.h" |
10 #include "vm/hash_map.h" | 10 #include "vm/hash_map.h" |
11 #include "vm/intermediate_language.h" | 11 #include "vm/intermediate_language.h" |
12 #include "vm/parser.h" | 12 #include "vm/parser.h" |
13 #include "vm/thread.h" | 13 #include "vm/thread.h" |
14 | 14 |
15 namespace dart { | 15 namespace dart { |
16 | 16 |
17 class BlockEffects; | 17 class BlockEffects; |
18 class FlowGraphBuilder; | 18 class FlowGraphBuilder; |
19 class ValueInliningContext; | 19 class ValueInliningContext; |
20 class VariableLivenessAnalysis; | 20 class VariableLivenessAnalysis; |
21 | 21 |
22 class BlockIterator : public ValueObject { | 22 class BlockIterator : public ValueObject { |
23 public: | 23 public: |
24 explicit BlockIterator(const GrowableArray<BlockEntryInstr*>& block_order) | 24 explicit BlockIterator(const GrowableArray<BlockEntryInstr*>& block_order) |
25 : block_order_(block_order), current_(0) { } | 25 : block_order_(block_order), current_(0) {} |
26 | 26 |
27 BlockIterator(const BlockIterator& other) | 27 BlockIterator(const BlockIterator& other) |
28 : ValueObject(), | 28 : ValueObject(), |
29 block_order_(other.block_order_), | 29 block_order_(other.block_order_), |
30 current_(other.current_) { } | 30 current_(other.current_) {} |
31 | 31 |
32 void Advance() { | 32 void Advance() { |
33 ASSERT(!Done()); | 33 ASSERT(!Done()); |
34 current_++; | 34 current_++; |
35 } | 35 } |
36 | 36 |
37 bool Done() const { return current_ >= block_order_.length(); } | 37 bool Done() const { return current_ >= block_order_.length(); } |
38 | 38 |
39 BlockEntryInstr* Current() const { return block_order_[current_]; } | 39 BlockEntryInstr* Current() const { return block_order_[current_]; } |
40 | 40 |
41 private: | 41 private: |
42 const GrowableArray<BlockEntryInstr*>& block_order_; | 42 const GrowableArray<BlockEntryInstr*>& block_order_; |
43 intptr_t current_; | 43 intptr_t current_; |
44 }; | 44 }; |
45 | 45 |
46 | 46 |
47 struct ConstantPoolTrait { | 47 struct ConstantPoolTrait { |
48 typedef ConstantInstr* Value; | 48 typedef ConstantInstr* Value; |
49 typedef const Object& Key; | 49 typedef const Object& Key; |
50 typedef ConstantInstr* Pair; | 50 typedef ConstantInstr* Pair; |
51 | 51 |
52 static Key KeyOf(Pair kv) { | 52 static Key KeyOf(Pair kv) { return kv->value(); } |
53 return kv->value(); | |
54 } | |
55 | 53 |
56 static Value ValueOf(Pair kv) { | 54 static Value ValueOf(Pair kv) { return kv; } |
57 return kv; | |
58 } | |
59 | 55 |
60 static inline intptr_t Hashcode(Key key) { | 56 static inline intptr_t Hashcode(Key key) { |
61 if (key.IsSmi()) { | 57 if (key.IsSmi()) { |
62 return Smi::Cast(key).Value(); | 58 return Smi::Cast(key).Value(); |
63 } | 59 } |
64 if (key.IsDouble()) { | 60 if (key.IsDouble()) { |
65 return static_cast<intptr_t>( | 61 return static_cast<intptr_t>(bit_cast<int32_t, float>( |
66 bit_cast<int32_t, float>( | 62 static_cast<float>(Double::Cast(key).value()))); |
67 static_cast<float>(Double::Cast(key).value()))); | |
68 } | 63 } |
69 if (key.IsMint()) { | 64 if (key.IsMint()) { |
70 return static_cast<intptr_t>(Mint::Cast(key).value()); | 65 return static_cast<intptr_t>(Mint::Cast(key).value()); |
71 } | 66 } |
72 if (key.IsString()) { | 67 if (key.IsString()) { |
73 return String::Cast(key).Hash(); | 68 return String::Cast(key).Hash(); |
74 } | 69 } |
75 return key.GetClassId(); | 70 return key.GetClassId(); |
76 } | 71 } |
77 | 72 |
78 static inline bool IsKeyEqual(Pair kv, Key key) { | 73 static inline bool IsKeyEqual(Pair kv, Key key) { |
79 return kv->value().raw() == key.raw(); | 74 return kv->value().raw() == key.raw(); |
80 } | 75 } |
81 }; | 76 }; |
82 | 77 |
83 | 78 |
84 // Class to encapsulate the construction and manipulation of the flow graph. | 79 // Class to encapsulate the construction and manipulation of the flow graph. |
85 class FlowGraph : public ZoneAllocated { | 80 class FlowGraph : public ZoneAllocated { |
86 public: | 81 public: |
87 FlowGraph(const ParsedFunction& parsed_function, | 82 FlowGraph(const ParsedFunction& parsed_function, |
88 GraphEntryInstr* graph_entry, | 83 GraphEntryInstr* graph_entry, |
89 intptr_t max_block_id); | 84 intptr_t max_block_id); |
90 | 85 |
91 // Function properties. | 86 // Function properties. |
92 const ParsedFunction& parsed_function() const { | 87 const ParsedFunction& parsed_function() const { return parsed_function_; } |
93 return parsed_function_; | 88 const Function& function() const { return parsed_function_.function(); } |
94 } | |
95 const Function& function() const { | |
96 return parsed_function_.function(); | |
97 } | |
98 intptr_t parameter_count() const { | 89 intptr_t parameter_count() const { |
99 return num_copied_params_ + num_non_copied_params_; | 90 return num_copied_params_ + num_non_copied_params_; |
100 } | 91 } |
101 intptr_t variable_count() const { | 92 intptr_t variable_count() const { |
102 return parameter_count() + parsed_function_.num_stack_locals(); | 93 return parameter_count() + parsed_function_.num_stack_locals(); |
103 } | 94 } |
104 intptr_t num_stack_locals() const { | 95 intptr_t num_stack_locals() const { |
105 return parsed_function_.num_stack_locals(); | 96 return parsed_function_.num_stack_locals(); |
106 } | 97 } |
107 intptr_t num_copied_params() const { | 98 intptr_t num_copied_params() const { return num_copied_params_; } |
108 return num_copied_params_; | 99 intptr_t num_non_copied_params() const { return num_non_copied_params_; } |
109 } | 100 bool IsIrregexpFunction() const { return function().IsIrregexpFunction(); } |
110 intptr_t num_non_copied_params() const { | |
111 return num_non_copied_params_; | |
112 } | |
113 bool IsIrregexpFunction() const { | |
114 return function().IsIrregexpFunction(); | |
115 } | |
116 | 101 |
117 LocalVariable* CurrentContextVar() const { | 102 LocalVariable* CurrentContextVar() const { |
118 return parsed_function().current_context_var(); | 103 return parsed_function().current_context_var(); |
119 } | 104 } |
120 | 105 |
121 intptr_t CurrentContextEnvIndex() const { | 106 intptr_t CurrentContextEnvIndex() const { |
122 return parsed_function().current_context_var()->BitIndexIn( | 107 return parsed_function().current_context_var()->BitIndexIn( |
123 num_non_copied_params_); | 108 num_non_copied_params_); |
124 } | 109 } |
125 | 110 |
126 // Flow graph orders. | 111 // Flow graph orders. |
127 const GrowableArray<BlockEntryInstr*>& preorder() const { | 112 const GrowableArray<BlockEntryInstr*>& preorder() const { return preorder_; } |
128 return preorder_; | |
129 } | |
130 const GrowableArray<BlockEntryInstr*>& postorder() const { | 113 const GrowableArray<BlockEntryInstr*>& postorder() const { |
131 return postorder_; | 114 return postorder_; |
132 } | 115 } |
133 const GrowableArray<BlockEntryInstr*>& reverse_postorder() const { | 116 const GrowableArray<BlockEntryInstr*>& reverse_postorder() const { |
134 return reverse_postorder_; | 117 return reverse_postorder_; |
135 } | 118 } |
136 static bool ShouldReorderBlocks(const Function& function, bool is_optimized); | 119 static bool ShouldReorderBlocks(const Function& function, bool is_optimized); |
137 GrowableArray<BlockEntryInstr*>* CodegenBlockOrder(bool is_optimized); | 120 GrowableArray<BlockEntryInstr*>* CodegenBlockOrder(bool is_optimized); |
138 | 121 |
139 // Iterators. | 122 // Iterators. |
(...skipping 23 matching lines...) Expand all Loading... |
163 RawFunction::Kind kind) const; | 146 RawFunction::Kind kind) const; |
164 | 147 |
165 Thread* thread() const { return thread_; } | 148 Thread* thread() const { return thread_; } |
166 Zone* zone() const { return thread()->zone(); } | 149 Zone* zone() const { return thread()->zone(); } |
167 Isolate* isolate() const { return thread()->isolate(); } | 150 Isolate* isolate() const { return thread()->isolate(); } |
168 | 151 |
169 intptr_t max_block_id() const { return max_block_id_; } | 152 intptr_t max_block_id() const { return max_block_id_; } |
170 void set_max_block_id(intptr_t id) { max_block_id_ = id; } | 153 void set_max_block_id(intptr_t id) { max_block_id_ = id; } |
171 intptr_t allocate_block_id() { return ++max_block_id_; } | 154 intptr_t allocate_block_id() { return ++max_block_id_; } |
172 | 155 |
173 GraphEntryInstr* graph_entry() const { | 156 GraphEntryInstr* graph_entry() const { return graph_entry_; } |
174 return graph_entry_; | |
175 } | |
176 | 157 |
177 ConstantInstr* constant_null() const { | 158 ConstantInstr* constant_null() const { return constant_null_; } |
178 return constant_null_; | |
179 } | |
180 | 159 |
181 ConstantInstr* constant_dead() const { | 160 ConstantInstr* constant_dead() const { return constant_dead_; } |
182 return constant_dead_; | |
183 } | |
184 | 161 |
185 ConstantInstr* constant_empty_context() const { | 162 ConstantInstr* constant_empty_context() const { |
186 return constant_empty_context_; | 163 return constant_empty_context_; |
187 } | 164 } |
188 | 165 |
189 intptr_t alloc_ssa_temp_index() { return current_ssa_temp_index_++; } | 166 intptr_t alloc_ssa_temp_index() { return current_ssa_temp_index_++; } |
190 | 167 |
191 void AllocateSSAIndexes(Definition* def) { | 168 void AllocateSSAIndexes(Definition* def) { |
192 ASSERT(def); | 169 ASSERT(def); |
193 def->set_ssa_temp_index(alloc_ssa_temp_index()); | 170 def->set_ssa_temp_index(alloc_ssa_temp_index()); |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
279 } | 256 } |
280 | 257 |
281 bool IsCompiledForOsr() const { return graph_entry()->IsCompiledForOsr(); } | 258 bool IsCompiledForOsr() const { return graph_entry()->IsCompiledForOsr(); } |
282 | 259 |
283 void AddToDeferredPrefixes(ZoneGrowableArray<const LibraryPrefix*>* from); | 260 void AddToDeferredPrefixes(ZoneGrowableArray<const LibraryPrefix*>* from); |
284 | 261 |
285 ZoneGrowableArray<const LibraryPrefix*>* deferred_prefixes() const { | 262 ZoneGrowableArray<const LibraryPrefix*>* deferred_prefixes() const { |
286 return deferred_prefixes_; | 263 return deferred_prefixes_; |
287 } | 264 } |
288 | 265 |
289 BitVector* captured_parameters() const { | 266 BitVector* captured_parameters() const { return captured_parameters_; } |
290 return captured_parameters_; | |
291 } | |
292 | 267 |
293 intptr_t inlining_id() const { return inlining_id_; } | 268 intptr_t inlining_id() const { return inlining_id_; } |
294 void set_inlining_id(intptr_t value) { inlining_id_ = value; } | 269 void set_inlining_id(intptr_t value) { inlining_id_ = value; } |
295 | 270 |
296 // Returns true if any instructions were canonicalized away. | 271 // Returns true if any instructions were canonicalized away. |
297 bool Canonicalize(); | 272 bool Canonicalize(); |
298 | 273 |
299 void SelectRepresentations(); | 274 void SelectRepresentations(); |
300 | 275 |
301 void WidenSmiToInt32(); | 276 void WidenSmiToInt32(); |
(...skipping 10 matching lines...) Expand all Loading... |
312 | 287 |
313 private: | 288 private: |
314 friend class IfConverter; | 289 friend class IfConverter; |
315 friend class BranchSimplifier; | 290 friend class BranchSimplifier; |
316 friend class ConstantPropagator; | 291 friend class ConstantPropagator; |
317 friend class DeadCodeElimination; | 292 friend class DeadCodeElimination; |
318 | 293 |
319 // SSA transformation methods and fields. | 294 // SSA transformation methods and fields. |
320 void ComputeDominators(GrowableArray<BitVector*>* dominance_frontier); | 295 void ComputeDominators(GrowableArray<BitVector*>* dominance_frontier); |
321 | 296 |
322 void CompressPath( | 297 void CompressPath(intptr_t start_index, |
323 intptr_t start_index, | 298 intptr_t current_index, |
324 intptr_t current_index, | 299 GrowableArray<intptr_t>* parent, |
325 GrowableArray<intptr_t>* parent, | 300 GrowableArray<intptr_t>* label); |
326 GrowableArray<intptr_t>* label); | |
327 | 301 |
328 void Rename(GrowableArray<PhiInstr*>* live_phis, | 302 void Rename(GrowableArray<PhiInstr*>* live_phis, |
329 VariableLivenessAnalysis* variable_liveness, | 303 VariableLivenessAnalysis* variable_liveness, |
330 ZoneGrowableArray<Definition*>* inlining_parameters); | 304 ZoneGrowableArray<Definition*>* inlining_parameters); |
331 void RenameRecursive( | 305 void RenameRecursive(BlockEntryInstr* block_entry, |
332 BlockEntryInstr* block_entry, | 306 GrowableArray<Definition*>* env, |
333 GrowableArray<Definition*>* env, | 307 GrowableArray<PhiInstr*>* live_phis, |
334 GrowableArray<PhiInstr*>* live_phis, | 308 VariableLivenessAnalysis* variable_liveness); |
335 VariableLivenessAnalysis* variable_liveness); | |
336 | 309 |
337 void AttachEnvironment(Instruction* instr, GrowableArray<Definition*>* env); | 310 void AttachEnvironment(Instruction* instr, GrowableArray<Definition*>* env); |
338 | 311 |
339 void InsertPhis( | 312 void InsertPhis(const GrowableArray<BlockEntryInstr*>& preorder, |
340 const GrowableArray<BlockEntryInstr*>& preorder, | 313 const GrowableArray<BitVector*>& assigned_vars, |
341 const GrowableArray<BitVector*>& assigned_vars, | 314 const GrowableArray<BitVector*>& dom_frontier, |
342 const GrowableArray<BitVector*>& dom_frontier, | 315 GrowableArray<PhiInstr*>* live_phis); |
343 GrowableArray<PhiInstr*>* live_phis); | |
344 | 316 |
345 void RemoveDeadPhis(GrowableArray<PhiInstr*>* live_phis); | 317 void RemoveDeadPhis(GrowableArray<PhiInstr*>* live_phis); |
346 | 318 |
347 void ReplacePredecessor(BlockEntryInstr* old_block, | 319 void ReplacePredecessor(BlockEntryInstr* old_block, |
348 BlockEntryInstr* new_block); | 320 BlockEntryInstr* new_block); |
349 | 321 |
350 // Find the natural loop for the back edge m->n and attach loop | 322 // Find the natural loop for the back edge m->n and attach loop |
351 // information to block n (loop header). The algorithm is described in | 323 // information to block n (loop header). The algorithm is described in |
352 // "Advanced Compiler Design & Implementation" (Muchnick) p192. | 324 // "Advanced Compiler Design & Implementation" (Muchnick) p192. |
353 // Returns a BitVector indexed by block pre-order number where each bit | 325 // Returns a BitVector indexed by block pre-order number where each bit |
(...skipping 15 matching lines...) Expand all Loading... |
369 void OptimizeLeftShiftBitAndSmiOp( | 341 void OptimizeLeftShiftBitAndSmiOp( |
370 ForwardInstructionIterator* current_iterator, | 342 ForwardInstructionIterator* current_iterator, |
371 Definition* bit_and_instr, | 343 Definition* bit_and_instr, |
372 Definition* left_instr, | 344 Definition* left_instr, |
373 Definition* right_instr); | 345 Definition* right_instr); |
374 | 346 |
375 void TryMergeTruncDivMod(GrowableArray<BinarySmiOpInstr*>* merge_candidates); | 347 void TryMergeTruncDivMod(GrowableArray<BinarySmiOpInstr*>* merge_candidates); |
376 void TryMergeMathUnary( | 348 void TryMergeMathUnary( |
377 GrowableArray<InvokeMathCFunctionInstr*>* merge_candidates); | 349 GrowableArray<InvokeMathCFunctionInstr*>* merge_candidates); |
378 | 350 |
379 void AppendExtractNthOutputForMerged(Definition* instr, intptr_t ix, | 351 void AppendExtractNthOutputForMerged(Definition* instr, |
380 Representation rep, intptr_t cid); | 352 intptr_t ix, |
| 353 Representation rep, |
| 354 intptr_t cid); |
381 | 355 |
382 Thread* thread_; | 356 Thread* thread_; |
383 | 357 |
384 // DiscoverBlocks computes parent_ and assigned_vars_ which are then used | 358 // DiscoverBlocks computes parent_ and assigned_vars_ which are then used |
385 // if/when computing SSA. | 359 // if/when computing SSA. |
386 GrowableArray<intptr_t> parent_; | 360 GrowableArray<intptr_t> parent_; |
387 GrowableArray<BitVector*> assigned_vars_; | 361 GrowableArray<BitVector*> assigned_vars_; |
388 | 362 |
389 intptr_t current_ssa_temp_index_; | 363 intptr_t current_ssa_temp_index_; |
390 intptr_t max_block_id_; | 364 intptr_t max_block_id_; |
(...skipping 24 matching lines...) Expand all Loading... |
415 }; | 389 }; |
416 | 390 |
417 | 391 |
418 class LivenessAnalysis : public ValueObject { | 392 class LivenessAnalysis : public ValueObject { |
419 public: | 393 public: |
420 LivenessAnalysis(intptr_t variable_count, | 394 LivenessAnalysis(intptr_t variable_count, |
421 const GrowableArray<BlockEntryInstr*>& postorder); | 395 const GrowableArray<BlockEntryInstr*>& postorder); |
422 | 396 |
423 void Analyze(); | 397 void Analyze(); |
424 | 398 |
425 virtual ~LivenessAnalysis() { } | 399 virtual ~LivenessAnalysis() {} |
426 | 400 |
427 BitVector* GetLiveInSetAt(intptr_t postorder_number) const { | 401 BitVector* GetLiveInSetAt(intptr_t postorder_number) const { |
428 return live_in_[postorder_number]; | 402 return live_in_[postorder_number]; |
429 } | 403 } |
430 | 404 |
431 BitVector* GetLiveOutSetAt(intptr_t postorder_number) const { | 405 BitVector* GetLiveOutSetAt(intptr_t postorder_number) const { |
432 return live_out_[postorder_number]; | 406 return live_out_[postorder_number]; |
433 } | 407 } |
434 | 408 |
435 BitVector* GetLiveInSet(BlockEntryInstr* block) const { | 409 BitVector* GetLiveInSet(BlockEntryInstr* block) const { |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
513 | 487 |
514 // Per block sets of available blocks. Block A is available at the block B if | 488 // Per block sets of available blocks. Block A is available at the block B if |
515 // and only if A dominates B and all paths from A to B are free of side | 489 // and only if A dominates B and all paths from A to B are free of side |
516 // effects. | 490 // effects. |
517 GrowableArray<BitVector*> available_at_; | 491 GrowableArray<BitVector*> available_at_; |
518 }; | 492 }; |
519 | 493 |
520 | 494 |
521 class DefinitionWorklist : public ValueObject { | 495 class DefinitionWorklist : public ValueObject { |
522 public: | 496 public: |
523 DefinitionWorklist(FlowGraph* flow_graph, | 497 DefinitionWorklist(FlowGraph* flow_graph, intptr_t initial_capacity) |
524 intptr_t initial_capacity) | |
525 : defs_(initial_capacity), | 498 : defs_(initial_capacity), |
526 contains_vector_( | 499 contains_vector_(new BitVector(flow_graph->zone(), |
527 new BitVector(flow_graph->zone(), | 500 flow_graph->current_ssa_temp_index())) {} |
528 flow_graph->current_ssa_temp_index())) { | |
529 } | |
530 | 501 |
531 void Add(Definition* defn) { | 502 void Add(Definition* defn) { |
532 if (!Contains(defn)) { | 503 if (!Contains(defn)) { |
533 defs_.Add(defn); | 504 defs_.Add(defn); |
534 contains_vector_->Add(defn->ssa_temp_index()); | 505 contains_vector_->Add(defn->ssa_temp_index()); |
535 } | 506 } |
536 } | 507 } |
537 | 508 |
538 bool Contains(Definition* defn) const { | 509 bool Contains(Definition* defn) const { |
539 return (defn->ssa_temp_index() >= 0) && | 510 return (defn->ssa_temp_index() >= 0) && |
540 contains_vector_->Contains(defn->ssa_temp_index()); | 511 contains_vector_->Contains(defn->ssa_temp_index()); |
541 } | 512 } |
542 | 513 |
543 bool IsEmpty() const { | 514 bool IsEmpty() const { return defs_.is_empty(); } |
544 return defs_.is_empty(); | |
545 } | |
546 | 515 |
547 Definition* RemoveLast() { | 516 Definition* RemoveLast() { |
548 Definition* defn = defs_.RemoveLast(); | 517 Definition* defn = defs_.RemoveLast(); |
549 contains_vector_->Remove(defn->ssa_temp_index()); | 518 contains_vector_->Remove(defn->ssa_temp_index()); |
550 return defn; | 519 return defn; |
551 } | 520 } |
552 | 521 |
553 const GrowableArray<Definition*>& definitions() const { return defs_; } | 522 const GrowableArray<Definition*>& definitions() const { return defs_; } |
554 BitVector* contains_vector() const { return contains_vector_; } | 523 BitVector* contains_vector() const { return contains_vector_; } |
555 | 524 |
556 void Clear() { | 525 void Clear() { |
557 defs_.TruncateTo(0); | 526 defs_.TruncateTo(0); |
558 contains_vector_->Clear(); | 527 contains_vector_->Clear(); |
559 } | 528 } |
560 | 529 |
561 private: | 530 private: |
562 GrowableArray<Definition*> defs_; | 531 GrowableArray<Definition*> defs_; |
563 BitVector* contains_vector_; | 532 BitVector* contains_vector_; |
564 }; | 533 }; |
565 | 534 |
566 | 535 |
567 } // namespace dart | 536 } // namespace dart |
568 | 537 |
569 #endif // RUNTIME_VM_FLOW_GRAPH_H_ | 538 #endif // RUNTIME_VM_FLOW_GRAPH_H_ |
OLD | NEW |