| 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 |