Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(427)

Side by Side Diff: src/compiler/register-allocator.cc

Issue 748773002: [turbofan] put spill slot reuse behind a flag (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698