| OLD | NEW | 
|---|
| 1 // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 562 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 573   UsePosition* use = | 573   UsePosition* use = | 
| 574       range->finger()->FirstRegisterBeneficialUse(graph_entry->start_pos()); | 574       range->finger()->FirstRegisterBeneficialUse(graph_entry->start_pos()); | 
| 575   if (use != NULL) { | 575   if (use != NULL) { | 
| 576     LiveRange* tail = SplitBetween(range, graph_entry->start_pos(), use->pos()); | 576     LiveRange* tail = SplitBetween(range, graph_entry->start_pos(), use->pos()); | 
| 577     CompleteRange(tail, Location::kRegister); | 577     CompleteRange(tail, Location::kRegister); | 
| 578   } | 578   } | 
| 579   ConvertAllUses(range); | 579   ConvertAllUses(range); | 
| 580 } | 580 } | 
| 581 | 581 | 
| 582 | 582 | 
|  | 583 static Location::Kind RegisterKindFromPolicy(Location loc) { | 
|  | 584   if (loc.policy() == Location::kRequiresXmmRegister) { | 
|  | 585     return Location::kXmmRegister; | 
|  | 586   } else { | 
|  | 587     return Location::kRegister; | 
|  | 588   } | 
|  | 589 } | 
|  | 590 | 
|  | 591 | 
|  | 592 static Location::Kind RegisterKindForResult(Instruction* instr) { | 
|  | 593   if (instr->representation() == kUnboxedDouble) { | 
|  | 594     return Location::kXmmRegister; | 
|  | 595   } else { | 
|  | 596     return Location::kRegister; | 
|  | 597   } | 
|  | 598 } | 
|  | 599 | 
|  | 600 | 
| 583 // | 601 // | 
| 584 // When describing shape of live ranges in comments below we are going to use | 602 // When describing shape of live ranges in comments below we are going to use | 
| 585 // the following notation: | 603 // the following notation: | 
| 586 // | 604 // | 
| 587 //    B    block entry | 605 //    B    block entry | 
| 588 //    g g' start and end of goto instruction | 606 //    g g' start and end of goto instruction | 
| 589 //    i i' start and end of any other instruction | 607 //    i i' start and end of any other instruction | 
| 590 //    j j' start and end of any other instruction | 608 //    j j' start and end of any other instruction | 
| 591 | 609 | 
| 592 //    -  body of a use interval | 610 //    -  body of a use interval | 
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 693         MoveOperands* move = | 711         MoveOperands* move = | 
| 694             goto_instr->parallel_move()->MoveOperandsAt(move_idx); | 712             goto_instr->parallel_move()->MoveOperandsAt(move_idx); | 
| 695         move->set_dest(Location::PrefersRegister()); | 713         move->set_dest(Location::PrefersRegister()); | 
| 696         range->AddUse(pos, move->dest_slot()); | 714         range->AddUse(pos, move->dest_slot()); | 
| 697       } | 715       } | 
| 698 | 716 | 
| 699       // All phi resolution moves are connected. Phi's live range is | 717       // All phi resolution moves are connected. Phi's live range is | 
| 700       // complete. | 718       // complete. | 
| 701       AssignSafepoints(range); | 719       AssignSafepoints(range); | 
| 702 | 720 | 
| 703       // TODO(vegorov): unboxed double phis. | 721       CompleteRange(range, RegisterKindForResult(phi)); | 
| 704       CompleteRange(range, Location::kRegister); |  | 
| 705 | 722 | 
| 706       move_idx++; | 723       move_idx++; | 
| 707     } | 724     } | 
| 708   } | 725   } | 
| 709 } | 726 } | 
| 710 | 727 | 
| 711 | 728 | 
| 712 void FlowGraphAllocator::ProcessEnvironmentUses(BlockEntryInstr* block, | 729 void FlowGraphAllocator::ProcessEnvironmentUses(BlockEntryInstr* block, | 
| 713                                                 Instruction* current) { | 730                                                 Instruction* current) { | 
| 714   ASSERT(current->env() != NULL); | 731   ASSERT(current->env() != NULL); | 
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 746     const intptr_t vreg = def->ssa_temp_index(); | 763     const intptr_t vreg = def->ssa_temp_index(); | 
| 747     LiveRange* range = GetLiveRange(vreg); | 764     LiveRange* range = GetLiveRange(vreg); | 
| 748     range->AddUseInterval(block_start_pos, use_pos); | 765     range->AddUseInterval(block_start_pos, use_pos); | 
| 749     range->AddUse(use_pos, &locations[i]); | 766     range->AddUse(use_pos, &locations[i]); | 
| 750   } | 767   } | 
| 751 | 768 | 
| 752   env->set_locations(locations); | 769   env->set_locations(locations); | 
| 753 } | 770 } | 
| 754 | 771 | 
| 755 | 772 | 
| 756 static Location::Kind RegisterKindFromPolicy(Location loc) { |  | 
| 757   if (loc.policy() == Location::kRequiresXmmRegister) { |  | 
| 758     return Location::kXmmRegister; |  | 
| 759   } else { |  | 
| 760     return Location::kRegister; |  | 
| 761   } |  | 
| 762 } |  | 
| 763 |  | 
| 764 |  | 
| 765 static Location::Kind RegisterKindForResult(Instruction* instr) { |  | 
| 766   if (instr->representation() == kUnboxedDouble) { |  | 
| 767     return Location::kXmmRegister; |  | 
| 768   } else { |  | 
| 769     return Location::kRegister; |  | 
| 770   } |  | 
| 771 } |  | 
| 772 |  | 
| 773 |  | 
| 774 // Create and update live ranges corresponding to instruction's inputs, | 773 // Create and update live ranges corresponding to instruction's inputs, | 
| 775 // temporaries and output. | 774 // temporaries and output. | 
| 776 void FlowGraphAllocator::ProcessOneInstruction(BlockEntryInstr* block, | 775 void FlowGraphAllocator::ProcessOneInstruction(BlockEntryInstr* block, | 
| 777                                                Instruction* current) { | 776                                                Instruction* current) { | 
| 778   const intptr_t pos = current->lifetime_position(); | 777   const intptr_t pos = current->lifetime_position(); | 
| 779   ASSERT(IsInstructionStartPosition(pos)); | 778   ASSERT(IsInstructionStartPosition(pos)); | 
| 780 | 779 | 
| 781   LocationSummary* locs = current->locs(); | 780   LocationSummary* locs = current->locs(); | 
| 782 | 781 | 
| 783   // Number of input locations and number of input operands have to agree. | 782   // Number of input locations and number of input operands have to agree. | 
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 864     //              i  i' | 863     //              i  i' | 
| 865     //              [--) | 864     //              [--) | 
| 866     // | 865     // | 
| 867     // The stack bitmap describes the position i. | 866     // The stack bitmap describes the position i. | 
| 868     for (intptr_t reg = 0; reg < kNumberOfCpuRegisters; reg++) { | 867     for (intptr_t reg = 0; reg < kNumberOfCpuRegisters; reg++) { | 
| 869       BlockLocation(Location::RegisterLocation(static_cast<Register>(reg)), | 868       BlockLocation(Location::RegisterLocation(static_cast<Register>(reg)), | 
| 870                     pos, | 869                     pos, | 
| 871                     pos + 1); | 870                     pos + 1); | 
| 872     } | 871     } | 
| 873 | 872 | 
|  | 873     for (intptr_t reg = 0; reg < kNumberOfXmmRegisters; reg++) { | 
|  | 874       BlockLocation( | 
|  | 875           Location::XmmRegisterLocation(static_cast<XmmRegister>(reg)), | 
|  | 876           pos, | 
|  | 877           pos + 1); | 
|  | 878     } | 
|  | 879 | 
|  | 880 | 
| 874 #if defined(DEBUG) | 881 #if defined(DEBUG) | 
| 875     // Verify that temps, inputs and output were specified as fixed | 882     // Verify that temps, inputs and output were specified as fixed | 
| 876     // locations.  Every register is blocked now so attempt to | 883     // locations.  Every register is blocked now so attempt to | 
| 877     // allocate will not succeed. | 884     // allocate will not succeed. | 
| 878     for (intptr_t j = 0; j < locs->temp_count(); j++) { | 885     for (intptr_t j = 0; j < locs->temp_count(); j++) { | 
| 879       ASSERT(!locs->temp(j).IsUnallocated()); | 886       ASSERT(!locs->temp(j).IsUnallocated()); | 
| 880     } | 887     } | 
| 881 | 888 | 
| 882     for (intptr_t j = 0; j < locs->input_count(); j++) { | 889     for (intptr_t j = 0; j < locs->input_count(); j++) { | 
| 883       ASSERT(!locs->in(j).IsUnallocated()); | 890       ASSERT(!locs->in(j).IsUnallocated()); | 
| (...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1181   return use; | 1188   return use; | 
| 1182 } | 1189 } | 
| 1183 | 1190 | 
| 1184 | 1191 | 
| 1185 UsePosition* AllocationFinger::FirstRegisterUse(intptr_t after) { | 1192 UsePosition* AllocationFinger::FirstRegisterUse(intptr_t after) { | 
| 1186   for (UsePosition* use = FirstUseAfter(first_register_use_, after); | 1193   for (UsePosition* use = FirstUseAfter(first_register_use_, after); | 
| 1187        use != NULL; | 1194        use != NULL; | 
| 1188        use = use->next()) { | 1195        use = use->next()) { | 
| 1189     Location* loc = use->location_slot(); | 1196     Location* loc = use->location_slot(); | 
| 1190     if (loc->IsUnallocated() && | 1197     if (loc->IsUnallocated() && | 
| 1191         (loc->policy() == Location::kRequiresRegister)) { | 1198         ((loc->policy() == Location::kRequiresRegister) || | 
|  | 1199         (loc->policy() == Location::kRequiresXmmRegister))) { | 
| 1192       first_register_use_ = use; | 1200       first_register_use_ = use; | 
| 1193       return use; | 1201       return use; | 
| 1194     } | 1202     } | 
| 1195   } | 1203   } | 
| 1196   return NULL; | 1204   return NULL; | 
| 1197 } | 1205 } | 
| 1198 | 1206 | 
| 1199 | 1207 | 
| 1200 UsePosition* AllocationFinger::FirstRegisterBeneficialUse(intptr_t after) { | 1208 UsePosition* AllocationFinger::FirstRegisterBeneficialUse(intptr_t after) { | 
| 1201   for (UsePosition* use = FirstUseAfter(first_register_beneficial_use_, after); | 1209   for (UsePosition* use = FirstUseAfter(first_register_beneficial_use_, after); | 
| (...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1427   LiveRange* last_sibling = range; | 1435   LiveRange* last_sibling = range; | 
| 1428   while (last_sibling->next_sibling() != NULL) { | 1436   while (last_sibling->next_sibling() != NULL) { | 
| 1429     last_sibling = last_sibling->next_sibling(); | 1437     last_sibling = last_sibling->next_sibling(); | 
| 1430   } | 1438   } | 
| 1431 | 1439 | 
| 1432   spill_slots_[idx] = last_sibling->End(); | 1440   spill_slots_[idx] = last_sibling->End(); | 
| 1433 | 1441 | 
| 1434   if (register_kind_ == Location::kRegister) { | 1442   if (register_kind_ == Location::kRegister) { | 
| 1435     range->set_spill_slot(Location::StackSlot(idx)); | 1443     range->set_spill_slot(Location::StackSlot(idx)); | 
| 1436   } else { | 1444   } else { | 
|  | 1445     // Double spill slots are essentially one (x64) or two (ia32) normal | 
|  | 1446     // word size spill slots.  We use the index of the slot with the lowest | 
|  | 1447     // address as an index for the double spill slot. In terms of indexes | 
|  | 1448     // this relation is inverted: so we have to take the highest index. | 
|  | 1449     const intptr_t slot_idx = | 
|  | 1450         idx * kDoubleSpillSlotFactor + (kDoubleSpillSlotFactor - 1); | 
| 1437     range->set_spill_slot( | 1451     range->set_spill_slot( | 
| 1438         Location::DoubleStackSlot( | 1452         Location::DoubleStackSlot( | 
| 1439             cpu_spill_slot_count_ + idx * kDoubleSpillSlotFactor)); | 1453             cpu_spill_slot_count_ + slot_idx)); | 
| 1440   } | 1454   } | 
| 1441 | 1455 | 
| 1442   spilled_.Add(range); | 1456   spilled_.Add(range); | 
| 1443 } | 1457 } | 
| 1444 | 1458 | 
| 1445 | 1459 | 
| 1446 void FlowGraphAllocator::MarkAsObjectAtSafepoints(LiveRange* range) { | 1460 void FlowGraphAllocator::MarkAsObjectAtSafepoints(LiveRange* range) { | 
| 1447   intptr_t stack_index = range->spill_slot().stack_index(); | 1461   intptr_t stack_index = range->spill_slot().stack_index(); | 
| 1448   ASSERT(stack_index >= 0); | 1462   ASSERT(stack_index >= 0); | 
| 1449 | 1463 | 
| (...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1667 | 1681 | 
| 1668 | 1682 | 
| 1669 void FlowGraphAllocator::AssignNonFreeRegister(LiveRange* unallocated, | 1683 void FlowGraphAllocator::AssignNonFreeRegister(LiveRange* unallocated, | 
| 1670                                                intptr_t reg) { | 1684                                                intptr_t reg) { | 
| 1671   intptr_t first_evicted = -1; | 1685   intptr_t first_evicted = -1; | 
| 1672   for (intptr_t i = registers_[reg].length() - 1; i >= 0; i--) { | 1686   for (intptr_t i = registers_[reg].length() - 1; i >= 0; i--) { | 
| 1673     LiveRange* allocated = registers_[reg][i]; | 1687     LiveRange* allocated = registers_[reg][i]; | 
| 1674     if (allocated->vreg() < 0) continue;  // Can't be evicted. | 1688     if (allocated->vreg() < 0) continue;  // Can't be evicted. | 
| 1675     if (EvictIntersection(allocated, unallocated)) { | 1689     if (EvictIntersection(allocated, unallocated)) { | 
| 1676       // If allocated was not spilled convert all pending uses. | 1690       // If allocated was not spilled convert all pending uses. | 
| 1677       if (allocated->assigned_location().IsRegister()) { | 1691       if (allocated->assigned_location().IsMachineRegister()) { | 
| 1678         ASSERT(allocated->End() <= unallocated->Start()); | 1692         ASSERT(allocated->End() <= unallocated->Start()); | 
| 1679         ConvertAllUses(allocated); | 1693         ConvertAllUses(allocated); | 
| 1680       } | 1694       } | 
| 1681       registers_[reg][i] = NULL; | 1695       registers_[reg][i] = NULL; | 
| 1682       first_evicted = i; | 1696       first_evicted = i; | 
| 1683     } | 1697     } | 
| 1684   } | 1698   } | 
| 1685 | 1699 | 
| 1686   // Remove evicted ranges from the array. | 1700   // Remove evicted ranges from the array. | 
| 1687   if (first_evicted != -1) RemoveEvicted(reg, first_evicted); | 1701   if (first_evicted != -1) RemoveEvicted(reg, first_evicted); | 
| (...skipping 443 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 2131     OS::Print("-- [after ssa allocator] ir [%s] -------------\n", | 2145     OS::Print("-- [after ssa allocator] ir [%s] -------------\n", | 
| 2132               function.ToFullyQualifiedCString()); | 2146               function.ToFullyQualifiedCString()); | 
| 2133     FlowGraphPrinter printer(flow_graph_, true); | 2147     FlowGraphPrinter printer(flow_graph_, true); | 
| 2134     printer.PrintBlocks(); | 2148     printer.PrintBlocks(); | 
| 2135     OS::Print("----------------------------------------------\n"); | 2149     OS::Print("----------------------------------------------\n"); | 
| 2136   } | 2150   } | 
| 2137 } | 2151 } | 
| 2138 | 2152 | 
| 2139 | 2153 | 
| 2140 }  // namespace dart | 2154 }  // namespace dart | 
| OLD | NEW | 
|---|