Chromium Code Reviews| 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/flow_graph_allocator.h" | 5 #include "vm/flow_graph_allocator.h" |
| 6 | 6 |
| 7 #include "vm/bit_vector.h" | 7 #include "vm/bit_vector.h" |
| 8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
| 9 #include "vm/il_printer.h" | 9 #include "vm/il_printer.h" |
| 10 #include "vm/flow_graph.h" | 10 #include "vm/flow_graph.h" |
| (...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 257 // Process initial definitions, ie, constants and incoming parameters. | 257 // Process initial definitions, ie, constants and incoming parameters. |
| 258 for (intptr_t i = 0; i < graph_entry_->initial_definitions()->length(); i++) { | 258 for (intptr_t i = 0; i < graph_entry_->initial_definitions()->length(); i++) { |
| 259 Definition* def = (*graph_entry_->initial_definitions())[i]; | 259 Definition* def = (*graph_entry_->initial_definitions())[i]; |
| 260 const intptr_t vreg = def->ssa_temp_index(); | 260 const intptr_t vreg = def->ssa_temp_index(); |
| 261 kill_[graph_entry_->postorder_number()]->Add(vreg); | 261 kill_[graph_entry_->postorder_number()]->Add(vreg); |
| 262 live_in_[graph_entry_->postorder_number()]->Remove(vreg); | 262 live_in_[graph_entry_->postorder_number()]->Remove(vreg); |
| 263 } | 263 } |
| 264 } | 264 } |
| 265 | 265 |
| 266 | 266 |
| 267 void LiveRange::AddUse(intptr_t pos, Location* location_slot) { | 267 UsePosition* LiveRange::AddUse(intptr_t pos, Location* location_slot) { |
|
srdjan
2014/09/25 16:32:43
Who is using result of LiveRange::AddUse?
| |
| 268 ASSERT(location_slot != NULL); | 268 ASSERT(location_slot != NULL); |
| 269 ASSERT((first_use_interval_->start_ <= pos) && | 269 ASSERT((first_use_interval_->start_ <= pos) && |
| 270 (pos <= first_use_interval_->end_)); | 270 (pos <= first_use_interval_->end_)); |
| 271 if ((uses_ != NULL) && | 271 if (uses_ != NULL) { |
| 272 (uses_->pos() == pos) && | 272 if ((uses_->pos() == pos) && |
| 273 (uses_->location_slot() == location_slot)) { | 273 (uses_->location_slot() == location_slot)) { |
| 274 return; | 274 return uses_; |
| 275 } else if (uses_->pos() < pos) { | |
| 276 // If an instruction at position P is using the same value both as | |
| 277 // a fixed register input and a non-fixed input (in this order) we will | |
| 278 // add uses both at position P-1 and *then* P which will make | |
| 279 // uses_ unsorted unless we account for it here. | |
| 280 UsePosition* insert_after = uses_; | |
| 281 while ((insert_after->next() != NULL) && | |
| 282 (insert_after->next()->pos() < pos)) { | |
| 283 insert_after = insert_after->next(); | |
| 284 } | |
| 285 | |
| 286 UsePosition* insert_before = insert_after->next(); | |
| 287 while (insert_before != NULL && (insert_before->pos() == pos)) { | |
| 288 if (insert_before->location_slot() == location_slot) { | |
| 289 return insert_before; | |
| 290 } | |
| 291 insert_before = insert_before->next(); | |
| 292 } | |
| 293 | |
| 294 insert_after->set_next( | |
| 295 new UsePosition(pos, insert_after->next(), location_slot)); | |
| 296 return insert_after->next(); | |
| 297 } | |
| 275 } | 298 } |
| 276 uses_ = new UsePosition(pos, uses_, location_slot); | 299 uses_ = new UsePosition(pos, uses_, location_slot); |
| 300 return uses_; | |
| 277 } | 301 } |
| 278 | 302 |
| 279 | 303 |
| 280 void LiveRange::AddSafepoint(intptr_t pos, LocationSummary* locs) { | 304 void LiveRange::AddSafepoint(intptr_t pos, LocationSummary* locs) { |
| 281 ASSERT(IsInstructionStartPosition(pos)); | 305 ASSERT(IsInstructionStartPosition(pos)); |
| 282 SafepointPosition* safepoint = | 306 SafepointPosition* safepoint = |
| 283 new SafepointPosition(ToInstructionEnd(pos), locs); | 307 new SafepointPosition(ToInstructionEnd(pos), locs); |
| 284 | 308 |
| 285 if (first_safepoint_ == NULL) { | 309 if (first_safepoint_ == NULL) { |
| 286 ASSERT(last_safepoint_ == NULL); | 310 ASSERT(last_safepoint_ == NULL); |
| 287 first_safepoint_ = last_safepoint_ = safepoint; | 311 first_safepoint_ = last_safepoint_ = safepoint; |
| 288 } else { | 312 } else { |
| 289 ASSERT(last_safepoint_ != NULL); | 313 ASSERT(last_safepoint_ != NULL); |
| 290 // We assume that safepoints list is sorted by position and that | 314 // We assume that safepoints list is sorted by position and that |
| 291 // safepoints are added in this order. | 315 // safepoints are added in this order. |
| 292 ASSERT(last_safepoint_->pos() < pos); | 316 ASSERT(last_safepoint_->pos() < pos); |
| 293 last_safepoint_->set_next(safepoint); | 317 last_safepoint_->set_next(safepoint); |
| 294 last_safepoint_ = safepoint; | 318 last_safepoint_ = safepoint; |
| 295 } | 319 } |
| 296 } | 320 } |
| 297 | 321 |
| 298 | 322 |
| 299 void LiveRange::AddHintedUse(intptr_t pos, | 323 void LiveRange::AddHintedUse(intptr_t pos, |
| 300 Location* location_slot, | 324 Location* location_slot, |
| 301 Location* hint) { | 325 Location* hint) { |
| 302 ASSERT(hint != NULL); | 326 ASSERT(hint != NULL); |
| 303 AddUse(pos, location_slot); | 327 AddUse(pos, location_slot)->set_hint(hint); |
| 304 uses_->set_hint(hint); | |
| 305 } | 328 } |
| 306 | 329 |
| 307 | 330 |
| 308 void LiveRange::AddUseInterval(intptr_t start, intptr_t end) { | 331 void LiveRange::AddUseInterval(intptr_t start, intptr_t end) { |
| 309 ASSERT(start < end); | 332 ASSERT(start < end); |
| 310 | 333 |
| 311 // Live ranges are being build by visiting instructions in post-order. | 334 // Live ranges are being build by visiting instructions in post-order. |
| 312 // This implies that use intervals will be prepended in a monotonically | 335 // This implies that use intervals will be prepended in a monotonically |
| 313 // decreasing order. | 336 // decreasing order. |
| 314 if (first_use_interval() != NULL) { | 337 if (first_use_interval() != NULL) { |
| (...skipping 777 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1092 ASSERT(input != NULL); | 1115 ASSERT(input != NULL); |
| 1093 // Output register will contain a value of the first input at instruction's | 1116 // Output register will contain a value of the first input at instruction's |
| 1094 // start. Expected shape of live ranges: | 1117 // start. Expected shape of live ranges: |
| 1095 // | 1118 // |
| 1096 // i i' | 1119 // i i' |
| 1097 // input #0 --* | 1120 // input #0 --* |
| 1098 // output [---- | 1121 // output [---- |
| 1099 // | 1122 // |
| 1100 ASSERT(in_ref->Equals(Location::RequiresRegister()) || | 1123 ASSERT(in_ref->Equals(Location::RequiresRegister()) || |
| 1101 in_ref->Equals(Location::RequiresFpuRegister())); | 1124 in_ref->Equals(Location::RequiresFpuRegister())); |
| 1102 | |
| 1103 // TODO(johnmccutchan): Without this I get allocated a register instead | |
| 1104 // of an FPU register. Figure out why. | |
| 1105 | |
| 1106 *out = *in_ref; | 1125 *out = *in_ref; |
| 1107 // Create move that will copy value between input and output. | 1126 // Create move that will copy value between input and output. |
| 1108 MoveOperands* move = AddMoveAt(pos, | 1127 MoveOperands* move = AddMoveAt(pos, |
| 1109 Location::RequiresRegister(), | 1128 Location::RequiresRegister(), |
| 1110 Location::Any()); | 1129 Location::Any()); |
| 1111 | 1130 |
| 1112 // Add uses to the live range of the input. | 1131 // Add uses to the live range of the input. |
| 1113 LiveRange* input_range = GetLiveRange(input_vreg); | 1132 LiveRange* input_range = GetLiveRange(input_vreg); |
| 1114 input_range->AddUseInterval(block->start_pos(), pos); | 1133 input_range->AddUseInterval(block->start_pos(), pos); |
| 1115 input_range->AddUse(pos, move->src_slot()); | 1134 input_range->AddUse(pos, move->src_slot()); |
| (...skipping 448 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1564 first_register_use_ = range->first_use(); | 1583 first_register_use_ = range->first_use(); |
| 1565 first_register_beneficial_use_ = range->first_use(); | 1584 first_register_beneficial_use_ = range->first_use(); |
| 1566 first_hinted_use_ = range->first_use(); | 1585 first_hinted_use_ = range->first_use(); |
| 1567 } | 1586 } |
| 1568 | 1587 |
| 1569 | 1588 |
| 1570 bool AllocationFinger::Advance(const intptr_t start) { | 1589 bool AllocationFinger::Advance(const intptr_t start) { |
| 1571 UseInterval* a = first_pending_use_interval_; | 1590 UseInterval* a = first_pending_use_interval_; |
| 1572 while (a != NULL && a->end() <= start) a = a->next(); | 1591 while (a != NULL && a->end() <= start) a = a->next(); |
| 1573 first_pending_use_interval_ = a; | 1592 first_pending_use_interval_ = a; |
| 1574 if (first_pending_use_interval_ == NULL) { | 1593 return (first_pending_use_interval_ == NULL); |
| 1575 return true; | |
| 1576 } | |
| 1577 return false; | |
| 1578 } | 1594 } |
| 1579 | 1595 |
| 1580 | 1596 |
| 1581 Location AllocationFinger::FirstHint() { | 1597 Location AllocationFinger::FirstHint() { |
| 1582 UsePosition* use = first_hinted_use_; | 1598 UsePosition* use = first_hinted_use_; |
| 1583 | 1599 |
| 1584 while (use != NULL) { | 1600 while (use != NULL) { |
| 1585 if (use->HasHint()) return use->hint(); | 1601 if (use->HasHint()) return use->hint(); |
| 1586 use = use->next(); | 1602 use = use->next(); |
| 1587 } | 1603 } |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1670 a = a->next(); | 1686 a = a->next(); |
| 1671 } else { | 1687 } else { |
| 1672 u = u->next(); | 1688 u = u->next(); |
| 1673 } | 1689 } |
| 1674 } | 1690 } |
| 1675 | 1691 |
| 1676 return kMaxPosition; | 1692 return kMaxPosition; |
| 1677 } | 1693 } |
| 1678 | 1694 |
| 1679 | 1695 |
| 1680 LiveRange* LiveRange::MakeTemp(intptr_t pos, Location* location_slot) { | |
| 1681 UNREACHABLE(); | |
| 1682 return NULL; | |
| 1683 } | |
| 1684 | |
| 1685 | |
| 1686 template<typename PositionType> | 1696 template<typename PositionType> |
| 1687 PositionType* SplitListOfPositions(PositionType** head, | 1697 PositionType* SplitListOfPositions(PositionType** head, |
| 1688 intptr_t split_pos, | 1698 intptr_t split_pos, |
| 1689 bool split_at_start) { | 1699 bool split_at_start) { |
| 1690 PositionType* last_before_split = NULL; | 1700 PositionType* last_before_split = NULL; |
| 1691 PositionType* pos = *head; | 1701 PositionType* pos = *head; |
| 1692 if (split_at_start) { | 1702 if (split_at_start) { |
| 1693 while ((pos != NULL) && (pos->pos() < split_pos)) { | 1703 while ((pos != NULL) && (pos->pos() < split_pos)) { |
| 1694 last_before_split = pos; | 1704 last_before_split = pos; |
| 1695 pos = pos->next(); | 1705 pos = pos->next(); |
| (...skipping 1249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2945 OS::Print("-- [after ssa allocator] ir [%s] -------------\n", | 2955 OS::Print("-- [after ssa allocator] ir [%s] -------------\n", |
| 2946 function.ToFullyQualifiedCString()); | 2956 function.ToFullyQualifiedCString()); |
| 2947 FlowGraphPrinter printer(flow_graph_, true); | 2957 FlowGraphPrinter printer(flow_graph_, true); |
| 2948 printer.PrintBlocks(); | 2958 printer.PrintBlocks(); |
| 2949 OS::Print("----------------------------------------------\n"); | 2959 OS::Print("----------------------------------------------\n"); |
| 2950 } | 2960 } |
| 2951 } | 2961 } |
| 2952 | 2962 |
| 2953 | 2963 |
| 2954 } // namespace dart | 2964 } // namespace dart |
| OLD | NEW |