Chromium Code Reviews| 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 |