| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 460 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 471 if (use_pos->HasOperand()) { | 471 if (use_pos->HasOperand()) { |
| 472 ASSERT(op->IsRegister() || op->IsDoubleRegister() || | 472 ASSERT(op->IsRegister() || op->IsDoubleRegister() || |
| 473 !use_pos->RequiresRegister()); | 473 !use_pos->RequiresRegister()); |
| 474 use_pos->operand()->ConvertTo(op->kind(), op->index()); | 474 use_pos->operand()->ConvertTo(op->kind(), op->index()); |
| 475 } | 475 } |
| 476 use_pos = use_pos->next(); | 476 use_pos = use_pos->next(); |
| 477 } | 477 } |
| 478 } | 478 } |
| 479 | 479 |
| 480 | 480 |
| 481 UsePosition* LiveRange::AddUsePosition(LifetimePosition pos) { | |
| 482 return AddUsePosition(pos, CreateAssignedOperand()); | |
| 483 } | |
| 484 | |
| 485 | |
| 486 bool LiveRange::CanCover(LifetimePosition position) const { | 481 bool LiveRange::CanCover(LifetimePosition position) const { |
| 487 if (IsEmpty()) return false; | 482 if (IsEmpty()) return false; |
| 488 return Start().Value() <= position.Value() && | 483 return Start().Value() <= position.Value() && |
| 489 position.Value() < End().Value(); | 484 position.Value() < End().Value(); |
| 490 } | 485 } |
| 491 | 486 |
| 492 | 487 |
| 493 bool LiveRange::Covers(LifetimePosition position) { | 488 bool LiveRange::Covers(LifetimePosition position) { |
| 494 if (!CanCover(position)) return false; | 489 if (!CanCover(position)) return false; |
| 495 UseInterval* start_search = FirstSearchIntervalForPosition(position); | 490 UseInterval* start_search = FirstSearchIntervalForPosition(position); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 523 if (a == NULL || a->start().Value() > other->End().Value()) break; | 518 if (a == NULL || a->start().Value() > other->End().Value()) break; |
| 524 AdvanceLastProcessedMarker(a, advance_last_processed_up_to); | 519 AdvanceLastProcessedMarker(a, advance_last_processed_up_to); |
| 525 } else { | 520 } else { |
| 526 b = b->next(); | 521 b = b->next(); |
| 527 } | 522 } |
| 528 } | 523 } |
| 529 return LifetimePosition::Invalid(); | 524 return LifetimePosition::Invalid(); |
| 530 } | 525 } |
| 531 | 526 |
| 532 | 527 |
| 528 LAllocator::LAllocator(int num_values, HGraph* graph) |
| 529 : chunk_(NULL), |
| 530 live_in_sets_(graph->blocks()->length()), |
| 531 live_ranges_(num_values * 2), |
| 532 fixed_live_ranges_(NULL), |
| 533 fixed_double_live_ranges_(NULL), |
| 534 unhandled_live_ranges_(num_values * 2), |
| 535 active_live_ranges_(8), |
| 536 inactive_live_ranges_(8), |
| 537 reusable_slots_(8), |
| 538 next_virtual_register_(num_values), |
| 539 first_artificial_register_(num_values), |
| 540 mode_(NONE), |
| 541 num_registers_(-1), |
| 542 graph_(graph), |
| 543 has_osr_entry_(false) {} |
| 544 |
| 545 |
| 533 void LAllocator::InitializeLivenessAnalysis() { | 546 void LAllocator::InitializeLivenessAnalysis() { |
| 534 // Initialize the live_in sets for each block to NULL. | 547 // Initialize the live_in sets for each block to NULL. |
| 535 int block_count = graph_->blocks()->length(); | 548 int block_count = graph_->blocks()->length(); |
| 536 live_in_sets_.Initialize(block_count); | 549 live_in_sets_.Initialize(block_count); |
| 537 live_in_sets_.AddBlock(NULL, block_count); | 550 live_in_sets_.AddBlock(NULL, block_count); |
| 538 } | 551 } |
| 539 | 552 |
| 540 | 553 |
| 541 BitVector* LAllocator::ComputeLiveOut(HBasicBlock* block) { | 554 BitVector* LAllocator::ComputeLiveOut(HBasicBlock* block) { |
| 542 // Compute live out for the given block, except not including backward | 555 // Compute live out for the given block, except not including backward |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 616 LInstruction* instr = InstructionAt(pos); | 629 LInstruction* instr = InstructionAt(pos); |
| 617 if (instr->HasPointerMap()) { | 630 if (instr->HasPointerMap()) { |
| 618 instr->pointer_map()->RecordPointer(operand); | 631 instr->pointer_map()->RecordPointer(operand); |
| 619 } | 632 } |
| 620 } | 633 } |
| 621 return operand; | 634 return operand; |
| 622 } | 635 } |
| 623 | 636 |
| 624 | 637 |
| 625 LiveRange* LAllocator::FixedLiveRangeFor(int index) { | 638 LiveRange* LAllocator::FixedLiveRangeFor(int index) { |
| 626 if (index >= fixed_live_ranges_.length()) { | 639 ASSERT(index < Register::kNumAllocatableRegisters); |
| 627 fixed_live_ranges_.AddBlock(NULL, | |
| 628 index - fixed_live_ranges_.length() + 1); | |
| 629 } | |
| 630 | |
| 631 LiveRange* result = fixed_live_ranges_[index]; | 640 LiveRange* result = fixed_live_ranges_[index]; |
| 632 if (result == NULL) { | 641 if (result == NULL) { |
| 633 result = new LiveRange(FixedLiveRangeID(index)); | 642 result = new LiveRange(FixedLiveRangeID(index)); |
| 634 ASSERT(result->IsFixed()); | 643 ASSERT(result->IsFixed()); |
| 635 result->set_assigned_register(index, GENERAL_REGISTERS); | 644 result->set_assigned_register(index, GENERAL_REGISTERS); |
| 636 fixed_live_ranges_[index] = result; | 645 fixed_live_ranges_[index] = result; |
| 637 } | 646 } |
| 638 return result; | 647 return result; |
| 639 } | 648 } |
| 640 | 649 |
| 641 | 650 |
| 642 LiveRange* LAllocator::FixedDoubleLiveRangeFor(int index) { | 651 LiveRange* LAllocator::FixedDoubleLiveRangeFor(int index) { |
| 643 if (index >= fixed_double_live_ranges_.length()) { | 652 ASSERT(index < DoubleRegister::kNumAllocatableRegisters); |
| 644 fixed_double_live_ranges_.AddBlock(NULL, | |
| 645 index - fixed_double_live_ranges_.length() + 1); | |
| 646 } | |
| 647 | |
| 648 LiveRange* result = fixed_double_live_ranges_[index]; | 653 LiveRange* result = fixed_double_live_ranges_[index]; |
| 649 if (result == NULL) { | 654 if (result == NULL) { |
| 650 result = new LiveRange(FixedDoubleLiveRangeID(index)); | 655 result = new LiveRange(FixedDoubleLiveRangeID(index)); |
| 651 ASSERT(result->IsFixed()); | 656 ASSERT(result->IsFixed()); |
| 652 result->set_assigned_register(index, DOUBLE_REGISTERS); | 657 result->set_assigned_register(index, DOUBLE_REGISTERS); |
| 653 fixed_double_live_ranges_[index] = result; | 658 fixed_double_live_ranges_[index] = result; |
| 654 } | 659 } |
| 655 return result; | 660 return result; |
| 656 } | 661 } |
| 657 | 662 |
| 663 |
| 658 LiveRange* LAllocator::LiveRangeFor(int index) { | 664 LiveRange* LAllocator::LiveRangeFor(int index) { |
| 659 if (index >= live_ranges_.length()) { | 665 if (index >= live_ranges_.length()) { |
| 660 live_ranges_.AddBlock(NULL, index - live_ranges_.length() + 1); | 666 live_ranges_.AddBlock(NULL, index - live_ranges_.length() + 1); |
| 661 } | 667 } |
| 662 LiveRange* result = live_ranges_[index]; | 668 LiveRange* result = live_ranges_[index]; |
| 663 if (result == NULL) { | 669 if (result == NULL) { |
| 664 result = new LiveRange(index); | 670 result = new LiveRange(index); |
| 665 live_ranges_[index] = result; | 671 live_ranges_[index] = result; |
| 666 } | 672 } |
| 667 return result; | 673 return result; |
| (...skipping 424 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1092 LOperand* pred_op = pred_cover->CreateAssignedOperand(); | 1098 LOperand* pred_op = pred_cover->CreateAssignedOperand(); |
| 1093 LOperand* cur_op = cur_cover->CreateAssignedOperand(); | 1099 LOperand* cur_op = cur_cover->CreateAssignedOperand(); |
| 1094 if (!pred_op->Equals(cur_op)) { | 1100 if (!pred_op->Equals(cur_op)) { |
| 1095 LGap* gap = NULL; | 1101 LGap* gap = NULL; |
| 1096 if (block->predecessors()->length() == 1) { | 1102 if (block->predecessors()->length() == 1) { |
| 1097 gap = GapAt(block->first_instruction_index()); | 1103 gap = GapAt(block->first_instruction_index()); |
| 1098 } else { | 1104 } else { |
| 1099 ASSERT(pred->end()->SecondSuccessor() == NULL); | 1105 ASSERT(pred->end()->SecondSuccessor() == NULL); |
| 1100 gap = GetLastGap(pred); | 1106 gap = GetLastGap(pred); |
| 1101 | 1107 |
| 1108 // We are going to insert a move before the branch instruction. |
| 1109 // Some branch instructions (e.g. loops' back edges) |
| 1110 // can potentially cause a GC so they have a pointer map. |
| 1111 // By insterting a move we essentially create a copy of a |
| 1112 // value which is invisible to PopulatePointerMaps(), because we store |
| 1113 // it into a location different from the operand of a live range |
| 1114 // covering a branch instruction. |
| 1115 // Thus we need to manually record a pointer. |
| 1102 if (HasTaggedValue(range->id())) { | 1116 if (HasTaggedValue(range->id())) { |
| 1103 LInstruction* branch = InstructionAt(pred->last_instruction_index()); | 1117 LInstruction* branch = InstructionAt(pred->last_instruction_index()); |
| 1104 if (branch->HasPointerMap()) { | 1118 if (branch->HasPointerMap()) { |
| 1105 branch->pointer_map()->RecordPointer(cur_op); | 1119 branch->pointer_map()->RecordPointer(cur_op); |
| 1106 } | 1120 } |
| 1107 } | 1121 } |
| 1108 } | 1122 } |
| 1109 gap->GetOrCreateParallelMove(LGap::START)->AddMove(pred_op, cur_op); | 1123 gap->GetOrCreateParallelMove(LGap::START)->AddMove(pred_op, cur_op); |
| 1110 } | 1124 } |
| 1111 } | 1125 } |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1264 } | 1278 } |
| 1265 | 1279 |
| 1266 #ifdef DEBUG | 1280 #ifdef DEBUG |
| 1267 if (block_id == 0) { | 1281 if (block_id == 0) { |
| 1268 BitVector::Iterator iterator(live); | 1282 BitVector::Iterator iterator(live); |
| 1269 bool found = false; | 1283 bool found = false; |
| 1270 while (!iterator.Done()) { | 1284 while (!iterator.Done()) { |
| 1271 found = true; | 1285 found = true; |
| 1272 int operand_index = iterator.Current(); | 1286 int operand_index = iterator.Current(); |
| 1273 PrintF("Function: %s\n", | 1287 PrintF("Function: %s\n", |
| 1274 *graph_->info()->function()->debug_name()->ToCString()); | 1288 *chunk_->info()->function()->debug_name()->ToCString()); |
| 1275 PrintF("Value %d used before first definition!\n", operand_index); | 1289 PrintF("Value %d used before first definition!\n", operand_index); |
| 1276 LiveRange* range = LiveRangeFor(operand_index); | 1290 LiveRange* range = LiveRangeFor(operand_index); |
| 1277 PrintF("First use is at %d\n", range->first_pos()->pos().Value()); | 1291 PrintF("First use is at %d\n", range->first_pos()->pos().Value()); |
| 1278 iterator.Advance(); | 1292 iterator.Advance(); |
| 1279 } | 1293 } |
| 1280 ASSERT(!found); | 1294 ASSERT(!found); |
| 1281 } | 1295 } |
| 1282 #endif | 1296 #endif |
| 1283 } | 1297 } |
| 1284 } | 1298 } |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1426 void LAllocator::AllocateDoubleRegisters() { | 1440 void LAllocator::AllocateDoubleRegisters() { |
| 1427 HPhase phase("Allocate double registers", this); | 1441 HPhase phase("Allocate double registers", this); |
| 1428 num_registers_ = DoubleRegister::kNumAllocatableRegisters; | 1442 num_registers_ = DoubleRegister::kNumAllocatableRegisters; |
| 1429 mode_ = DOUBLE_REGISTERS; | 1443 mode_ = DOUBLE_REGISTERS; |
| 1430 AllocateRegisters(); | 1444 AllocateRegisters(); |
| 1431 } | 1445 } |
| 1432 | 1446 |
| 1433 | 1447 |
| 1434 void LAllocator::AllocateRegisters() { | 1448 void LAllocator::AllocateRegisters() { |
| 1435 ASSERT(mode_ != NONE); | 1449 ASSERT(mode_ != NONE); |
| 1436 reusable_slots_.Clear(); | 1450 ASSERT(unhandled_live_ranges_.is_empty()); |
| 1437 | 1451 |
| 1438 for (int i = 0; i < live_ranges_.length(); ++i) { | 1452 for (int i = 0; i < live_ranges_.length(); ++i) { |
| 1439 if (live_ranges_[i] != NULL) { | 1453 if (live_ranges_[i] != NULL) { |
| 1440 if (RequiredRegisterKind(live_ranges_[i]->id()) == mode_) { | 1454 if (RequiredRegisterKind(live_ranges_[i]->id()) == mode_) { |
| 1441 AddToUnhandledUnsorted(live_ranges_[i]); | 1455 AddToUnhandledUnsorted(live_ranges_[i]); |
| 1442 } | 1456 } |
| 1443 } | 1457 } |
| 1444 } | 1458 } |
| 1445 SortUnhandled(); | 1459 SortUnhandled(); |
| 1446 ASSERT(UnhandledIsSorted()); | 1460 ASSERT(UnhandledIsSorted()); |
| 1447 | 1461 |
| 1462 ASSERT(reusable_slots_.is_empty()); |
| 1448 ASSERT(active_live_ranges_.is_empty()); | 1463 ASSERT(active_live_ranges_.is_empty()); |
| 1449 ASSERT(inactive_live_ranges_.is_empty()); | 1464 ASSERT(inactive_live_ranges_.is_empty()); |
| 1450 | 1465 |
| 1451 if (mode_ == DOUBLE_REGISTERS) { | 1466 if (mode_ == DOUBLE_REGISTERS) { |
| 1452 for (int i = 0; i < fixed_double_live_ranges_.length(); ++i) { | 1467 for (int i = 0; i < fixed_double_live_ranges_.length(); ++i) { |
| 1453 LiveRange* current = fixed_double_live_ranges_.at(i); | 1468 LiveRange* current = fixed_double_live_ranges_.at(i); |
| 1454 if (current != NULL) { | 1469 if (current != NULL) { |
| 1455 AddToInactive(current); | 1470 AddToInactive(current); |
| 1456 } | 1471 } |
| 1457 } | 1472 } |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1522 bool result = TryAllocateFreeReg(current); | 1537 bool result = TryAllocateFreeReg(current); |
| 1523 if (!result) { | 1538 if (!result) { |
| 1524 AllocateBlockedReg(current); | 1539 AllocateBlockedReg(current); |
| 1525 } | 1540 } |
| 1526 | 1541 |
| 1527 if (current->HasRegisterAssigned()) { | 1542 if (current->HasRegisterAssigned()) { |
| 1528 AddToActive(current); | 1543 AddToActive(current); |
| 1529 } | 1544 } |
| 1530 } | 1545 } |
| 1531 | 1546 |
| 1532 active_live_ranges_.Clear(); | 1547 reusable_slots_.Rewind(0); |
| 1533 inactive_live_ranges_.Clear(); | 1548 active_live_ranges_.Rewind(0); |
| 1549 inactive_live_ranges_.Rewind(0); |
| 1534 } | 1550 } |
| 1535 | 1551 |
| 1536 | 1552 |
| 1537 void LAllocator::Setup() { | 1553 void LAllocator::Setup() { |
| 1538 LConstantOperand::SetupCache(); | 1554 LConstantOperand::SetupCache(); |
| 1539 LStackSlot::SetupCache(); | 1555 LStackSlot::SetupCache(); |
| 1540 LDoubleStackSlot::SetupCache(); | 1556 LDoubleStackSlot::SetupCache(); |
| 1541 LRegister::SetupCache(); | 1557 LRegister::SetupCache(); |
| 1542 LDoubleRegister::SetupCache(); | 1558 LDoubleRegister::SetupCache(); |
| 1543 } | 1559 } |
| (...skipping 537 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2081 LiveRange* current = live_ranges()->at(i); | 2097 LiveRange* current = live_ranges()->at(i); |
| 2082 if (current != NULL) current->Verify(); | 2098 if (current != NULL) current->Verify(); |
| 2083 } | 2099 } |
| 2084 } | 2100 } |
| 2085 | 2101 |
| 2086 | 2102 |
| 2087 #endif | 2103 #endif |
| 2088 | 2104 |
| 2089 | 2105 |
| 2090 } } // namespace v8::internal | 2106 } } // namespace v8::internal |
| OLD | NEW |