OLD | NEW |
---|---|
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/compiler/linkage.h" | 5 #include "src/compiler/linkage.h" |
6 #include "src/compiler/register-allocator.h" | 6 #include "src/compiler/register-allocator.h" |
7 #include "src/string-stream.h" | 7 #include "src/string-stream.h" |
8 | 8 |
9 namespace v8 { | 9 namespace v8 { |
10 namespace internal { | 10 namespace internal { |
(...skipping 527 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
538 local_zone()), | 538 local_zone()), |
539 fixed_double_live_ranges_(this->config()->num_double_registers(), NULL, | 539 fixed_double_live_ranges_(this->config()->num_double_registers(), NULL, |
540 local_zone()), | 540 local_zone()), |
541 unhandled_live_ranges_(code->VirtualRegisterCount() * 2, local_zone()), | 541 unhandled_live_ranges_(code->VirtualRegisterCount() * 2, local_zone()), |
542 active_live_ranges_(8, local_zone()), | 542 active_live_ranges_(8, local_zone()), |
543 inactive_live_ranges_(8, local_zone()), | 543 inactive_live_ranges_(8, local_zone()), |
544 reusable_slots_(8, local_zone()), | 544 reusable_slots_(8, local_zone()), |
545 spill_ranges_(8, local_zone()), | 545 spill_ranges_(8, local_zone()), |
546 mode_(UNALLOCATED_REGISTERS), | 546 mode_(UNALLOCATED_REGISTERS), |
547 num_registers_(-1), | 547 num_registers_(-1), |
548 allocation_ok_(true) { | 548 allocation_ok_(true), |
549 use_spill_ranges_(FLAG_turbo_reuse_spill_slots) { | |
Jarin
2014/11/21 10:55:39
Why is there this extra indirection? Can't we use
dcarney
2014/11/21 11:03:55
ok
| |
549 DCHECK(this->config()->num_general_registers() <= | 550 DCHECK(this->config()->num_general_registers() <= |
550 RegisterConfiguration::kMaxGeneralRegisters); | 551 RegisterConfiguration::kMaxGeneralRegisters); |
551 DCHECK(this->config()->num_double_registers() <= | 552 DCHECK(this->config()->num_double_registers() <= |
552 RegisterConfiguration::kMaxDoubleRegisters); | 553 RegisterConfiguration::kMaxDoubleRegisters); |
553 // TryAllocateFreeReg and AllocateBlockedReg assume this | 554 // TryAllocateFreeReg and AllocateBlockedReg assume this |
554 // when allocating local arrays. | 555 // when allocating local arrays. |
555 DCHECK(this->config()->num_double_registers() >= | 556 DCHECK(this->config()->num_double_registers() >= |
556 this->config()->num_general_registers()); | 557 this->config()->num_general_registers()); |
557 assigned_registers_ = | 558 assigned_registers_ = |
558 new (code_zone()) BitVector(config->num_general_registers(), code_zone()); | 559 new (code_zone()) BitVector(config->num_general_registers(), code_zone()); |
(...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
874 tail->set_next(current); | 875 tail->set_next(current); |
875 } | 876 } |
876 tail = current; | 877 tail = current; |
877 current = current->next(); | 878 current = current->next(); |
878 } | 879 } |
879 // Other list is empty => we are done | 880 // Other list is empty => we are done |
880 } | 881 } |
881 | 882 |
882 | 883 |
883 void RegisterAllocator::ReuseSpillSlots() { | 884 void RegisterAllocator::ReuseSpillSlots() { |
885 DCHECK(use_spill_ranges_); | |
886 | |
884 // Merge disjoint spill ranges | 887 // Merge disjoint spill ranges |
885 for (int i = 0; i < spill_ranges_.length(); i++) { | 888 for (int i = 0; i < spill_ranges_.length(); i++) { |
886 SpillRange* range = spill_ranges_.at(i); | 889 SpillRange* range = spill_ranges_.at(i); |
887 if (!range->IsEmpty()) { | 890 if (!range->IsEmpty()) { |
888 for (int j = i + 1; j < spill_ranges_.length(); j++) { | 891 for (int j = i + 1; j < spill_ranges_.length(); j++) { |
889 SpillRange* other = spill_ranges_.at(j); | 892 SpillRange* other = spill_ranges_.at(j); |
890 if (!other->IsEmpty()) { | 893 if (!other->IsEmpty()) { |
891 range->TryMerge(spill_ranges_.at(j), local_zone()); | 894 range->TryMerge(spill_ranges_.at(j), local_zone()); |
892 } | 895 } |
893 } | 896 } |
(...skipping 14 matching lines...) Expand all Loading... | |
908 DCHECK(kind == GENERAL_REGISTERS); | 911 DCHECK(kind == GENERAL_REGISTERS); |
909 op = StackSlotOperand::Create(index, local_zone()); | 912 op = StackSlotOperand::Create(index, local_zone()); |
910 } | 913 } |
911 range->SetOperand(op); | 914 range->SetOperand(op); |
912 } | 915 } |
913 } | 916 } |
914 } | 917 } |
915 | 918 |
916 | 919 |
917 SpillRange* RegisterAllocator::AssignSpillRangeToLiveRange(LiveRange* range) { | 920 SpillRange* RegisterAllocator::AssignSpillRangeToLiveRange(LiveRange* range) { |
921 DCHECK(use_spill_ranges_); | |
918 int spill_id = spill_ranges_.length(); | 922 int spill_id = spill_ranges_.length(); |
919 SpillRange* spill_range = | 923 SpillRange* spill_range = |
920 new (local_zone()) SpillRange(range, spill_id, local_zone()); | 924 new (local_zone()) SpillRange(range, spill_id, local_zone()); |
921 spill_ranges_.Add(spill_range, local_zone()); | 925 spill_ranges_.Add(spill_range, local_zone()); |
922 return spill_range; | 926 return spill_range; |
923 } | 927 } |
924 | 928 |
925 | 929 |
926 void RegisterAllocator::MeetRegisterConstraints(const InstructionBlock* block) { | 930 void RegisterAllocator::MeetRegisterConstraints(const InstructionBlock* block) { |
927 int start = block->first_instruction_index(); | 931 int start = block->first_instruction_index(); |
(...skipping 997 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1925 int len = unhandled_live_ranges_.length(); | 1929 int len = unhandled_live_ranges_.length(); |
1926 for (int i = 1; i < len; i++) { | 1930 for (int i = 1; i < len; i++) { |
1927 LiveRange* a = unhandled_live_ranges_.at(i - 1); | 1931 LiveRange* a = unhandled_live_ranges_.at(i - 1); |
1928 LiveRange* b = unhandled_live_ranges_.at(i); | 1932 LiveRange* b = unhandled_live_ranges_.at(i); |
1929 if (a->Start().Value() < b->Start().Value()) return false; | 1933 if (a->Start().Value() < b->Start().Value()) return false; |
1930 } | 1934 } |
1931 return true; | 1935 return true; |
1932 } | 1936 } |
1933 | 1937 |
1934 | 1938 |
1939 void RegisterAllocator::FreeSpillSlot(LiveRange* range) { | |
1940 DCHECK(!use_spill_ranges_); | |
1941 // Check that we are the last range. | |
1942 if (range->next() != NULL) return; | |
1943 | |
1944 if (!range->TopLevel()->HasAllocatedSpillOperand()) return; | |
1945 | |
1946 InstructionOperand* spill_operand = range->TopLevel()->GetSpillOperand(); | |
1947 if (spill_operand->IsConstant()) return; | |
1948 if (spill_operand->index() >= 0) { | |
1949 reusable_slots_.Add(range, local_zone()); | |
1950 } | |
1951 } | |
1952 | |
1953 | |
1954 InstructionOperand* RegisterAllocator::TryReuseSpillSlot(LiveRange* range) { | |
1955 DCHECK(!use_spill_ranges_); | |
1956 if (reusable_slots_.is_empty()) return NULL; | |
1957 if (reusable_slots_.first()->End().Value() > | |
1958 range->TopLevel()->Start().Value()) { | |
1959 return NULL; | |
1960 } | |
1961 InstructionOperand* result = | |
1962 reusable_slots_.first()->TopLevel()->GetSpillOperand(); | |
1963 reusable_slots_.Remove(0); | |
1964 return result; | |
1965 } | |
1966 | |
1967 | |
1935 void RegisterAllocator::ActiveToHandled(LiveRange* range) { | 1968 void RegisterAllocator::ActiveToHandled(LiveRange* range) { |
1936 DCHECK(active_live_ranges_.Contains(range)); | 1969 DCHECK(active_live_ranges_.Contains(range)); |
1937 active_live_ranges_.RemoveElement(range); | 1970 active_live_ranges_.RemoveElement(range); |
1938 TraceAlloc("Moving live range %d from active to handled\n", range->id()); | 1971 TraceAlloc("Moving live range %d from active to handled\n", range->id()); |
1972 if (!use_spill_ranges_) FreeSpillSlot(range); | |
1939 } | 1973 } |
1940 | 1974 |
1941 | 1975 |
1942 void RegisterAllocator::ActiveToInactive(LiveRange* range) { | 1976 void RegisterAllocator::ActiveToInactive(LiveRange* range) { |
1943 DCHECK(active_live_ranges_.Contains(range)); | 1977 DCHECK(active_live_ranges_.Contains(range)); |
1944 active_live_ranges_.RemoveElement(range); | 1978 active_live_ranges_.RemoveElement(range); |
1945 inactive_live_ranges_.Add(range, local_zone()); | 1979 inactive_live_ranges_.Add(range, local_zone()); |
1946 TraceAlloc("Moving live range %d from active to inactive\n", range->id()); | 1980 TraceAlloc("Moving live range %d from active to inactive\n", range->id()); |
1947 } | 1981 } |
1948 | 1982 |
1949 | 1983 |
1950 void RegisterAllocator::InactiveToHandled(LiveRange* range) { | 1984 void RegisterAllocator::InactiveToHandled(LiveRange* range) { |
1951 DCHECK(inactive_live_ranges_.Contains(range)); | 1985 DCHECK(inactive_live_ranges_.Contains(range)); |
1952 inactive_live_ranges_.RemoveElement(range); | 1986 inactive_live_ranges_.RemoveElement(range); |
1953 TraceAlloc("Moving live range %d from inactive to handled\n", range->id()); | 1987 TraceAlloc("Moving live range %d from inactive to handled\n", range->id()); |
1988 if (!use_spill_ranges_) FreeSpillSlot(range); | |
1954 } | 1989 } |
1955 | 1990 |
1956 | 1991 |
1957 void RegisterAllocator::InactiveToActive(LiveRange* range) { | 1992 void RegisterAllocator::InactiveToActive(LiveRange* range) { |
1958 DCHECK(inactive_live_ranges_.Contains(range)); | 1993 DCHECK(inactive_live_ranges_.Contains(range)); |
1959 inactive_live_ranges_.RemoveElement(range); | 1994 inactive_live_ranges_.RemoveElement(range); |
1960 active_live_ranges_.Add(range, local_zone()); | 1995 active_live_ranges_.Add(range, local_zone()); |
1961 TraceAlloc("Moving live range %d from inactive to active\n", range->id()); | 1996 TraceAlloc("Moving live range %d from inactive to active\n", range->id()); |
1962 } | 1997 } |
1963 | 1998 |
(...skipping 364 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2328 } | 2363 } |
2329 } | 2364 } |
2330 | 2365 |
2331 | 2366 |
2332 void RegisterAllocator::Spill(LiveRange* range) { | 2367 void RegisterAllocator::Spill(LiveRange* range) { |
2333 DCHECK(!range->IsSpilled()); | 2368 DCHECK(!range->IsSpilled()); |
2334 TraceAlloc("Spilling live range %d\n", range->id()); | 2369 TraceAlloc("Spilling live range %d\n", range->id()); |
2335 LiveRange* first = range->TopLevel(); | 2370 LiveRange* first = range->TopLevel(); |
2336 | 2371 |
2337 if (!first->HasAllocatedSpillOperand()) { | 2372 if (!first->HasAllocatedSpillOperand()) { |
2338 AssignSpillRangeToLiveRange(first); | 2373 if (use_spill_ranges_) { |
2374 AssignSpillRangeToLiveRange(first); | |
2375 } else { | |
2376 InstructionOperand* op = TryReuseSpillSlot(range); | |
2377 if (op == NULL) { | |
2378 // Allocate a new operand referring to the spill slot. | |
2379 RegisterKind kind = range->Kind(); | |
2380 int index = frame()->AllocateSpillSlot(kind == DOUBLE_REGISTERS); | |
2381 if (kind == DOUBLE_REGISTERS) { | |
2382 op = DoubleStackSlotOperand::Create(index, local_zone()); | |
2383 } else { | |
2384 DCHECK(kind == GENERAL_REGISTERS); | |
2385 op = StackSlotOperand::Create(index, local_zone()); | |
2386 } | |
2387 } | |
2388 first->SetSpillOperand(op); | |
2389 } | |
2339 } | 2390 } |
2340 range->MakeSpilled(code_zone()); | 2391 range->MakeSpilled(code_zone()); |
2341 } | 2392 } |
2342 | 2393 |
2343 | 2394 |
2344 int RegisterAllocator::RegisterCount() const { return num_registers_; } | 2395 int RegisterAllocator::RegisterCount() const { return num_registers_; } |
2345 | 2396 |
2346 | 2397 |
2347 #ifdef DEBUG | 2398 #ifdef DEBUG |
2348 | 2399 |
(...skipping 15 matching lines...) Expand all Loading... | |
2364 } else { | 2415 } else { |
2365 DCHECK(range->Kind() == GENERAL_REGISTERS); | 2416 DCHECK(range->Kind() == GENERAL_REGISTERS); |
2366 assigned_registers_->Add(reg); | 2417 assigned_registers_->Add(reg); |
2367 } | 2418 } |
2368 range->set_assigned_register(reg, code_zone()); | 2419 range->set_assigned_register(reg, code_zone()); |
2369 } | 2420 } |
2370 | 2421 |
2371 } | 2422 } |
2372 } | 2423 } |
2373 } // namespace v8::internal::compiler | 2424 } // namespace v8::internal::compiler |
OLD | NEW |