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

Side by Side Diff: test/unittests/interpreter/bytecode-register-allocator-unittest.cc

Issue 2369873002: [Interpreter] Replace BytecodeRegisterAllocator with a simple bump pointer. (Closed)
Patch Set: Rebase Created 4 years, 2 months 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/v8.h" 5 #include "src/v8.h"
6 6
7 #include "src/interpreter/bytecode-array-builder.h" 7 #include "src/interpreter/bytecode-array-builder.h"
8 #include "src/interpreter/bytecode-register-allocator.h" 8 #include "src/interpreter/bytecode-register-allocator.h"
9 #include "test/unittests/test-utils.h" 9 #include "test/unittests/test-utils.h"
10 10
11 namespace v8 { 11 namespace v8 {
12 namespace internal { 12 namespace internal {
13 namespace interpreter { 13 namespace interpreter {
14 14
15 class TemporaryRegisterAllocatorTest : public TestWithIsolateAndZone { 15 class BytecodeRegisterAllocatorTest : public TestWithIsolateAndZone {
16 public: 16 public:
17 TemporaryRegisterAllocatorTest() : allocator_(zone(), 0) {} 17 BytecodeRegisterAllocatorTest() : allocator_(0) {}
18 ~TemporaryRegisterAllocatorTest() override {} 18 ~BytecodeRegisterAllocatorTest() override {}
19 TemporaryRegisterAllocator* allocator() { return &allocator_; } 19
20 BytecodeRegisterAllocator* allocator() { return &allocator_; }
20 21
21 private: 22 private:
22 TemporaryRegisterAllocator allocator_; 23 BytecodeRegisterAllocator allocator_;
23 }; 24 };
24 25
25 TEST_F(TemporaryRegisterAllocatorTest, FirstAllocation) { 26 TEST_F(BytecodeRegisterAllocatorTest, SimpleAllocations) {
26 CHECK_EQ(allocator()->allocation_count(), 0); 27 CHECK_EQ(allocator()->maximum_register_count(), 0);
27 int reg0_index = allocator()->BorrowTemporaryRegister(); 28 Register reg0 = allocator()->NewRegister();
28 CHECK_EQ(reg0_index, 0); 29 CHECK_EQ(reg0.index(), 0);
29 CHECK_EQ(allocator()->allocation_count(), 1); 30 CHECK_EQ(allocator()->maximum_register_count(), 1);
30 CHECK(allocator()->RegisterIsLive(Register(reg0_index))); 31 CHECK_EQ(allocator()->next_register_index(), 1);
31 allocator()->ReturnTemporaryRegister(reg0_index); 32 CHECK(allocator()->RegisterIsLive(reg0));
32 CHECK(!allocator()->RegisterIsLive(Register(reg0_index))); 33
33 CHECK_EQ(allocator()->allocation_count(), 1); 34 allocator()->ReleaseRegisters(0);
34 CHECK(allocator()->first_temporary_register() == Register(0)); 35 CHECK(!allocator()->RegisterIsLive(reg0));
35 CHECK(allocator()->last_temporary_register() == Register(0)); 36 CHECK_EQ(allocator()->maximum_register_count(), 1);
37 CHECK_EQ(allocator()->next_register_index(), 0);
38
39 reg0 = allocator()->NewRegister();
40 Register reg1 = allocator()->NewRegister();
41 CHECK_EQ(reg0.index(), 0);
42 CHECK_EQ(reg1.index(), 1);
43 CHECK(allocator()->RegisterIsLive(reg0));
44 CHECK(allocator()->RegisterIsLive(reg1));
45 CHECK_EQ(allocator()->maximum_register_count(), 2);
46 CHECK_EQ(allocator()->next_register_index(), 2);
47
48 allocator()->ReleaseRegisters(1);
49 CHECK(allocator()->RegisterIsLive(reg0));
50 CHECK(!allocator()->RegisterIsLive(reg1));
51 CHECK_EQ(allocator()->maximum_register_count(), 2);
52 CHECK_EQ(allocator()->next_register_index(), 1);
36 } 53 }
37 54
38 TEST_F(TemporaryRegisterAllocatorTest, SimpleAllocations) { 55 TEST_F(BytecodeRegisterAllocatorTest, RegisterListAllocations) {
39 for (int i = 0; i < 13; i++) { 56 CHECK_EQ(allocator()->maximum_register_count(), 0);
40 int reg_index = allocator()->BorrowTemporaryRegister(); 57 RegisterList reg_list = allocator()->NewRegisterList(3);
41 CHECK_EQ(reg_index, i); 58 CHECK_EQ(reg_list.first_register().index(), 0);
42 CHECK_EQ(allocator()->allocation_count(), i + 1); 59 CHECK_EQ(reg_list.register_count(), 3);
43 } 60 CHECK_EQ(reg_list[0].index(), 0);
44 for (int i = 0; i < 13; i++) { 61 CHECK_EQ(reg_list[1].index(), 1);
45 CHECK(allocator()->RegisterIsLive(Register(i))); 62 CHECK_EQ(reg_list[2].index(), 2);
46 allocator()->ReturnTemporaryRegister(i); 63 CHECK_EQ(allocator()->maximum_register_count(), 3);
47 CHECK(!allocator()->RegisterIsLive(Register(i))); 64 CHECK_EQ(allocator()->next_register_index(), 3);
48 int reg_index = allocator()->BorrowTemporaryRegister(); 65 CHECK(allocator()->RegisterIsLive(reg_list[2]));
49 CHECK_EQ(reg_index, i);
50 CHECK_EQ(allocator()->allocation_count(), 13);
51 }
52 for (int i = 0; i < 13; i++) {
53 CHECK(allocator()->RegisterIsLive(Register(i)));
54 allocator()->ReturnTemporaryRegister(i);
55 CHECK(!allocator()->RegisterIsLive(Register(i)));
56 }
57 }
58 66
59 TEST_F(TemporaryRegisterAllocatorTest, SimpleRangeAllocation) { 67 Register reg = allocator()->NewRegister();
60 static const int kRunLength = 7; 68 RegisterList reg_list_2 = allocator()->NewRegisterList(2);
61 int start = allocator()->PrepareForConsecutiveTemporaryRegisters(kRunLength); 69 CHECK_EQ(reg.index(), 3);
62 CHECK(!allocator()->RegisterIsLive(Register(start))); 70 CHECK_EQ(reg_list_2.first_register().index(), 4);
63 for (int i = 0; i < kRunLength; i++) { 71 CHECK_EQ(reg_list_2.register_count(), 2);
64 CHECK(!allocator()->RegisterIsLive(Register(start + i))); 72 CHECK_EQ(reg_list_2[0].index(), 4);
65 allocator()->BorrowConsecutiveTemporaryRegister(start + i); 73 CHECK_EQ(reg_list_2[1].index(), 5);
66 CHECK(allocator()->RegisterIsLive(Register(start + i))); 74 CHECK_EQ(allocator()->maximum_register_count(), 6);
67 } 75 CHECK_EQ(allocator()->next_register_index(), 6);
68 } 76 CHECK(allocator()->RegisterIsLive(reg));
77 CHECK(allocator()->RegisterIsLive(reg_list_2[1]));
69 78
70 TEST_F(TemporaryRegisterAllocatorTest, RangeAllocationAbuttingFree) { 79 allocator()->ReleaseRegisters(reg.index());
71 static const int kFreeCount = 3; 80 CHECK(!allocator()->RegisterIsLive(reg));
72 static const int kRunLength = 6; 81 CHECK(!allocator()->RegisterIsLive(reg_list_2[0]));
82 CHECK(!allocator()->RegisterIsLive(reg_list_2[1]));
83 CHECK(allocator()->RegisterIsLive(reg_list[2]));
84 CHECK_EQ(allocator()->maximum_register_count(), 6);
85 CHECK_EQ(allocator()->next_register_index(), 3);
73 86
74 for (int i = 0; i < kFreeCount; i++) { 87 RegisterList empty_reg_list = allocator()->NewRegisterList(0);
75 int to_free = allocator()->BorrowTemporaryRegister(); 88 CHECK_EQ(empty_reg_list.first_register().index(), 0);
76 CHECK_EQ(to_free, i); 89 CHECK_EQ(empty_reg_list.register_count(), 0);
77 } 90 CHECK_EQ(allocator()->maximum_register_count(), 6);
78 for (int i = 0; i < kFreeCount; i++) { 91 CHECK_EQ(allocator()->next_register_index(), 3);
79 allocator()->ReturnTemporaryRegister(i);
80 }
81
82 int start = allocator()->PrepareForConsecutiveTemporaryRegisters(kRunLength);
83 CHECK(!allocator()->RegisterIsLive(Register(start)));
84 for (int i = 0; i < kRunLength; i++) {
85 CHECK(!allocator()->RegisterIsLive(Register(start + i)));
86 allocator()->BorrowConsecutiveTemporaryRegister(start + i);
87 CHECK(allocator()->RegisterIsLive(Register(start + i)));
88 }
89 }
90
91 TEST_F(TemporaryRegisterAllocatorTest, RangeAllocationAbuttingHole) {
92 static const int kPreAllocatedCount = 7;
93 static const int kPreAllocatedFreeCount = 6;
94 static const int kRunLength = 8;
95
96 for (int i = 0; i < kPreAllocatedCount; i++) {
97 int to_free = allocator()->BorrowTemporaryRegister();
98 CHECK_EQ(to_free, i);
99 }
100 for (int i = 0; i < kPreAllocatedFreeCount; i++) {
101 allocator()->ReturnTemporaryRegister(i);
102 }
103 int start = allocator()->PrepareForConsecutiveTemporaryRegisters(kRunLength);
104 CHECK(!allocator()->RegisterIsLive(Register(start)));
105 CHECK_EQ(start, kPreAllocatedCount);
106 for (int i = 0; i < kRunLength; i++) {
107 CHECK(!allocator()->RegisterIsLive(Register(start + i)));
108 allocator()->BorrowConsecutiveTemporaryRegister(start + i);
109 CHECK(allocator()->RegisterIsLive(Register(start + i)));
110 }
111 }
112
113 TEST_F(TemporaryRegisterAllocatorTest, RangeAllocationAvailableInTemporaries) {
114 static const int kNotRunLength = 13;
115 static const int kRunLength = 8;
116
117 // Allocate big batch
118 for (int i = 0; i < kNotRunLength * 2 + kRunLength; i++) {
119 int allocated = allocator()->BorrowTemporaryRegister();
120 CHECK_EQ(allocated, i);
121 }
122 // Free every other register either side of target.
123 for (int i = 0; i < kNotRunLength; i++) {
124 if ((i & 2) == 1) {
125 allocator()->ReturnTemporaryRegister(i);
126 allocator()->ReturnTemporaryRegister(kNotRunLength + kRunLength + i);
127 }
128 }
129 // Free all registers for target.
130 for (int i = kNotRunLength; i < kNotRunLength + kRunLength; i++) {
131 allocator()->ReturnTemporaryRegister(i);
132 }
133
134 int start = allocator()->PrepareForConsecutiveTemporaryRegisters(kRunLength);
135 CHECK_EQ(start, kNotRunLength);
136 for (int i = 0; i < kRunLength; i++) {
137 CHECK(!allocator()->RegisterIsLive(Register(start + i)));
138 allocator()->BorrowConsecutiveTemporaryRegister(start + i);
139 CHECK(allocator()->RegisterIsLive(Register(start + i)));
140 }
141 }
142
143 TEST_F(TemporaryRegisterAllocatorTest, NotInRange) {
144 for (int i = 0; i < 10; i++) {
145 int reg = allocator()->BorrowTemporaryRegisterNotInRange(2, 5);
146 CHECK(reg == i || (reg > 2 && reg == i + 4));
147 }
148 for (int i = 0; i < 10; i++) {
149 if (i < 2) {
150 allocator()->ReturnTemporaryRegister(i);
151 } else {
152 allocator()->ReturnTemporaryRegister(i + 4);
153 }
154 }
155 int reg0 = allocator()->BorrowTemporaryRegisterNotInRange(0, 3);
156 CHECK_EQ(reg0, 4);
157 int reg1 = allocator()->BorrowTemporaryRegisterNotInRange(3, 10);
158 CHECK_EQ(reg1, 2);
159 int reg2 = allocator()->BorrowTemporaryRegisterNotInRange(2, 6);
160 CHECK_EQ(reg2, 1);
161 allocator()->ReturnTemporaryRegister(reg0);
162 allocator()->ReturnTemporaryRegister(reg1);
163 allocator()->ReturnTemporaryRegister(reg2);
164 }
165
166 class BytecodeRegisterAllocatorTest : public TestWithIsolateAndZone {
167 public:
168 BytecodeRegisterAllocatorTest() {}
169 ~BytecodeRegisterAllocatorTest() override {}
170 };
171
172 TEST_F(BytecodeRegisterAllocatorTest, TemporariesRecycled) {
173 BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 0);
174
175 int first;
176 {
177 BytecodeRegisterAllocator allocator(zone(),
178 builder.temporary_register_allocator());
179 first = allocator.NewRegister().index();
180 allocator.NewRegister();
181 allocator.NewRegister();
182 allocator.NewRegister();
183 }
184
185 int second;
186 {
187 BytecodeRegisterAllocator allocator(zone(),
188 builder.temporary_register_allocator());
189 second = allocator.NewRegister().index();
190 }
191
192 CHECK_EQ(first, second);
193 }
194
195 TEST_F(BytecodeRegisterAllocatorTest, ConsecutiveRegisters) {
196 BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 0);
197 BytecodeRegisterAllocator allocator(zone(),
198 builder.temporary_register_allocator());
199 allocator.PrepareForConsecutiveAllocations(4);
200 Register reg0 = allocator.NextConsecutiveRegister();
201 Register other = allocator.NewRegister();
202 Register reg1 = allocator.NextConsecutiveRegister();
203 Register reg2 = allocator.NextConsecutiveRegister();
204 Register reg3 = allocator.NextConsecutiveRegister();
205 USE(other);
206
207 CHECK(Register::AreContiguous(reg0, reg1, reg2, reg3));
208 } 92 }
209 93
210 } // namespace interpreter 94 } // namespace interpreter
211 } // namespace internal 95 } // namespace internal
212 } // namespace v8 96 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698