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

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

Issue 2393683004: [Interpreter] Optimize the Register Optimizer. (Closed)
Patch Set: Rebase Created 4 years, 1 month 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 2016 the V8 project authors. All rights reserved. 1 // Copyright 2016 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/factory.h" 7 #include "src/factory.h"
8 #include "src/interpreter/bytecode-label.h" 8 #include "src/interpreter/bytecode-label.h"
9 #include "src/interpreter/bytecode-register-optimizer.h" 9 #include "src/interpreter/bytecode-register-optimizer.h"
10 #include "src/objects-inl.h" 10 #include "src/objects-inl.h"
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
55 55
56 private: 56 private:
57 BytecodeRegisterAllocator* register_allocator_; 57 BytecodeRegisterAllocator* register_allocator_;
58 BytecodeRegisterOptimizer* register_optimizer_; 58 BytecodeRegisterOptimizer* register_optimizer_;
59 59
60 std::vector<BytecodeNode> output_; 60 std::vector<BytecodeNode> output_;
61 }; 61 };
62 62
63 // Sanity tests. 63 // Sanity tests.
64 64
65 TEST_F(BytecodeRegisterOptimizerTest, WriteNop) { 65 TEST_F(BytecodeRegisterOptimizerTest, TemporaryMaterializedForFlush) {
66 Initialize(1, 1); 66 Initialize(1, 1);
67 BytecodeNode node(Bytecode::kNop); 67 Register temp = NewTemporary();
68 optimizer()->Write(&node); 68 optimizer()->DoStar(temp, BytecodeSourceInfo());
69 CHECK_EQ(write_count(), 0);
70 optimizer()->Flush();
69 CHECK_EQ(write_count(), 1); 71 CHECK_EQ(write_count(), 1);
70 CHECK_EQ(node, last_written()); 72 CHECK_EQ(output()->at(0).bytecode(), Bytecode::kStar);
71 } 73 CHECK_EQ(output()->at(0).operand(0), temp.ToOperand());
72
73 TEST_F(BytecodeRegisterOptimizerTest, WriteNopExpression) {
74 Initialize(1, 1);
75 BytecodeSourceInfo source_info(3, false);
76 BytecodeNode node(Bytecode::kNop, &source_info);
77 optimizer()->Write(&node);
78 CHECK_EQ(write_count(), 1);
79 CHECK_EQ(node, last_written());
80 }
81
82 TEST_F(BytecodeRegisterOptimizerTest, WriteNopStatement) {
83 Initialize(1, 1);
84 BytecodeSourceInfo source_info(3, true);
85 BytecodeNode node(Bytecode::kNop);
86 optimizer()->Write(&node);
87 CHECK_EQ(write_count(), 1);
88 CHECK_EQ(node, last_written());
89 } 74 }
90 75
91 TEST_F(BytecodeRegisterOptimizerTest, TemporaryMaterializedForJump) { 76 TEST_F(BytecodeRegisterOptimizerTest, TemporaryMaterializedForJump) {
92 Initialize(1, 1); 77 Initialize(1, 1);
93 Register temp = NewTemporary(); 78 Register temp = NewTemporary();
94 BytecodeNode node(Bytecode::kStar, temp.ToOperand()); 79 optimizer()->DoStar(temp, BytecodeSourceInfo());
95 optimizer()->Write(&node);
96 CHECK_EQ(write_count(), 0); 80 CHECK_EQ(write_count(), 0);
97 BytecodeLabel label; 81 optimizer()->PrepareForBytecode(Bytecode::kJump);
98 BytecodeNode jump(Bytecode::kJump, 0, nullptr);
99 optimizer()->WriteJump(&jump, &label);
100 CHECK_EQ(write_count(), 2);
101 CHECK_EQ(output()->at(0).bytecode(), Bytecode::kStar);
102 CHECK_EQ(output()->at(0).operand(0), temp.ToOperand());
103 CHECK_EQ(output()->at(1).bytecode(), Bytecode::kJump);
104 }
105
106 TEST_F(BytecodeRegisterOptimizerTest, TemporaryMaterializedForBind) {
107 Initialize(1, 1);
108 Register temp = NewTemporary();
109 BytecodeNode node(Bytecode::kStar, temp.ToOperand());
110 optimizer()->Write(&node);
111 CHECK_EQ(write_count(), 0);
112 BytecodeLabel label;
113 optimizer()->BindLabel(&label);
114 CHECK_EQ(write_count(), 1); 82 CHECK_EQ(write_count(), 1);
115 CHECK_EQ(output()->at(0).bytecode(), Bytecode::kStar); 83 CHECK_EQ(output()->at(0).bytecode(), Bytecode::kStar);
116 CHECK_EQ(output()->at(0).operand(0), temp.ToOperand()); 84 CHECK_EQ(output()->at(0).operand(0), temp.ToOperand());
117 } 85 }
118 86
119 // Basic Register Optimizations 87 // Basic Register Optimizations
120 88
121 TEST_F(BytecodeRegisterOptimizerTest, TemporaryNotEmitted) { 89 TEST_F(BytecodeRegisterOptimizerTest, TemporaryNotEmitted) {
122 Initialize(3, 1); 90 Initialize(3, 1);
123 Register parameter = Register::FromParameterIndex(1, 3); 91 Register parameter = Register::FromParameterIndex(1, 3);
124 BytecodeNode node0(Bytecode::kLdar, parameter.ToOperand()); 92 optimizer()->DoLdar(parameter, BytecodeSourceInfo());
125 optimizer()->Write(&node0);
126 CHECK_EQ(write_count(), 0); 93 CHECK_EQ(write_count(), 0);
127 Register temp = NewTemporary(); 94 Register temp = NewTemporary();
95 optimizer()->DoStar(temp, BytecodeSourceInfo());
128 BytecodeNode node1(Bytecode::kStar, NewTemporary().ToOperand()); 96 BytecodeNode node1(Bytecode::kStar, NewTemporary().ToOperand());
129 optimizer()->Write(&node1);
130 CHECK_EQ(write_count(), 0);
131 ReleaseTemporaries(temp); 97 ReleaseTemporaries(temp);
132 CHECK_EQ(write_count(), 0); 98 CHECK_EQ(write_count(), 0);
133 BytecodeNode node2(Bytecode::kReturn); 99 optimizer()->PrepareForBytecode(Bytecode::kReturn);
134 optimizer()->Write(&node2);
135 CHECK_EQ(write_count(), 2);
136 CHECK_EQ(output()->at(0).bytecode(), Bytecode::kLdar); 100 CHECK_EQ(output()->at(0).bytecode(), Bytecode::kLdar);
137 CHECK_EQ(output()->at(0).operand(0), parameter.ToOperand()); 101 CHECK_EQ(output()->at(0).operand(0), parameter.ToOperand());
138 CHECK_EQ(output()->at(1).bytecode(), Bytecode::kReturn);
139 } 102 }
140 103
141 TEST_F(BytecodeRegisterOptimizerTest, ReleasedRegisterUsed) { 104 TEST_F(BytecodeRegisterOptimizerTest, ReleasedRegisterUsed) {
142 Initialize(3, 1); 105 Initialize(3, 1);
143 BytecodeNode node0(Bytecode::kLdaSmi, 3); 106 optimizer()->PrepareForBytecode(Bytecode::kLdaSmi);
144 optimizer()->Write(&node0);
145 CHECK_EQ(write_count(), 1);
146 Register temp0 = NewTemporary(); 107 Register temp0 = NewTemporary();
147 Register temp1 = NewTemporary(); 108 Register temp1 = NewTemporary();
148 BytecodeNode node1(Bytecode::kStar, temp1.ToOperand()); 109 optimizer()->DoStar(temp1, BytecodeSourceInfo());
149 optimizer()->Write(&node1); 110 CHECK_EQ(write_count(), 0);
111 optimizer()->PrepareForBytecode(Bytecode::kLdaSmi);
150 CHECK_EQ(write_count(), 1); 112 CHECK_EQ(write_count(), 1);
151 BytecodeNode node2(Bytecode::kLdaSmi, 1); 113 CHECK_EQ(output()->at(0).bytecode(), Bytecode::kStar);
152 optimizer()->Write(&node2); 114 CHECK_EQ(output()->at(0).operand(0), temp1.ToOperand());
153 CHECK_EQ(write_count(), 3); 115 optimizer()->DoMov(temp1, temp0, BytecodeSourceInfo());
154 BytecodeNode node3(Bytecode::kMov, temp1.ToOperand(), temp0.ToOperand()); 116 CHECK_EQ(write_count(), 1);
155 optimizer()->Write(&node3);
156 CHECK_EQ(write_count(), 3);
157 ReleaseTemporaries(temp1); 117 ReleaseTemporaries(temp1);
158 CHECK_EQ(write_count(), 3); 118 CHECK_EQ(write_count(), 1);
159 BytecodeNode node4(Bytecode::kLdar, temp0.ToOperand()); 119 optimizer()->DoLdar(temp0, BytecodeSourceInfo());
160 optimizer()->Write(&node4); 120 CHECK_EQ(write_count(), 1);
161 CHECK_EQ(write_count(), 3); 121 optimizer()->PrepareForBytecode(Bytecode::kReturn);
162 BytecodeNode node5(Bytecode::kReturn); 122 CHECK_EQ(write_count(), 2);
163 optimizer()->Write(&node5); 123 CHECK_EQ(output()->at(1).bytecode(), Bytecode::kLdar);
164 CHECK_EQ(write_count(), 5); 124 CHECK_EQ(output()->at(1).operand(0), temp1.ToOperand());
165 CHECK_EQ(output()->at(3).bytecode(), Bytecode::kLdar);
166 CHECK_EQ(output()->at(3).operand(0), temp1.ToOperand());
167 CHECK_EQ(output()->at(4).bytecode(), Bytecode::kReturn);
168 } 125 }
169 126
170 TEST_F(BytecodeRegisterOptimizerTest, ReleasedRegisterNotFlushed) { 127 TEST_F(BytecodeRegisterOptimizerTest, ReleasedRegisterNotFlushed) {
171 Initialize(3, 1); 128 Initialize(3, 1);
172 BytecodeNode node0(Bytecode::kLdaSmi, 3); 129 optimizer()->PrepareForBytecode(Bytecode::kLdaSmi);
173 optimizer()->Write(&node0);
174 CHECK_EQ(write_count(), 1);
175 Register temp0 = NewTemporary(); 130 Register temp0 = NewTemporary();
176 Register temp1 = NewTemporary(); 131 Register temp1 = NewTemporary();
177 BytecodeNode node1(Bytecode::kStar, temp0.ToOperand()); 132 optimizer()->DoStar(temp0, BytecodeSourceInfo());
178 optimizer()->Write(&node1); 133 CHECK_EQ(write_count(), 0);
134 optimizer()->DoStar(temp1, BytecodeSourceInfo());
135 CHECK_EQ(write_count(), 0);
136 ReleaseTemporaries(temp1);
137 optimizer()->Flush();
179 CHECK_EQ(write_count(), 1); 138 CHECK_EQ(write_count(), 1);
180 BytecodeNode node2(Bytecode::kStar, temp1.ToOperand()); 139 CHECK_EQ(output()->at(0).bytecode(), Bytecode::kStar);
181 optimizer()->Write(&node2); 140 CHECK_EQ(output()->at(0).operand(0), temp0.ToOperand());
182 CHECK_EQ(write_count(), 1);
183 ReleaseTemporaries(temp1);
184 BytecodeLabel label;
185 BytecodeNode jump(Bytecode::kJump, 0, nullptr);
186 optimizer()->WriteJump(&jump, &label);
187 BytecodeNode node3(Bytecode::kReturn);
188 optimizer()->Write(&node3);
189 CHECK_EQ(write_count(), 4);
190 CHECK_EQ(output()->at(1).bytecode(), Bytecode::kStar);
191 CHECK_EQ(output()->at(1).operand(0), temp0.ToOperand());
192 CHECK_EQ(output()->at(2).bytecode(), Bytecode::kJump);
193 CHECK_EQ(output()->at(3).bytecode(), Bytecode::kReturn);
194 } 141 }
195 142
196 TEST_F(BytecodeRegisterOptimizerTest, StoresToLocalsImmediate) { 143 TEST_F(BytecodeRegisterOptimizerTest, StoresToLocalsImmediate) {
197 Initialize(3, 1); 144 Initialize(3, 1);
198 Register parameter = Register::FromParameterIndex(1, 3); 145 Register parameter = Register::FromParameterIndex(1, 3);
199 BytecodeNode node0(Bytecode::kLdar, parameter.ToOperand()); 146 optimizer()->DoLdar(parameter, BytecodeSourceInfo());
200 optimizer()->Write(&node0);
201 CHECK_EQ(write_count(), 0); 147 CHECK_EQ(write_count(), 0);
202 Register local = Register(0); 148 Register local = Register(0);
203 BytecodeNode node1(Bytecode::kStar, local.ToOperand()); 149 optimizer()->DoStar(local, BytecodeSourceInfo());
204 optimizer()->Write(&node1);
205 CHECK_EQ(write_count(), 1); 150 CHECK_EQ(write_count(), 1);
206 CHECK_EQ(output()->at(0).bytecode(), Bytecode::kMov); 151 CHECK_EQ(output()->at(0).bytecode(), Bytecode::kMov);
207 CHECK_EQ(output()->at(0).operand(0), parameter.ToOperand()); 152 CHECK_EQ(output()->at(0).operand(0), parameter.ToOperand());
208 CHECK_EQ(output()->at(0).operand(1), local.ToOperand()); 153 CHECK_EQ(output()->at(0).operand(1), local.ToOperand());
209 154
210 BytecodeNode node2(Bytecode::kReturn); 155 optimizer()->PrepareForBytecode(Bytecode::kReturn);
211 optimizer()->Write(&node2); 156 CHECK_EQ(write_count(), 2);
212 CHECK_EQ(write_count(), 3);
213 CHECK_EQ(output()->at(1).bytecode(), Bytecode::kLdar); 157 CHECK_EQ(output()->at(1).bytecode(), Bytecode::kLdar);
214 CHECK_EQ(output()->at(1).operand(0), local.ToOperand()); 158 CHECK_EQ(output()->at(1).operand(0), local.ToOperand());
215 CHECK_EQ(output()->at(2).bytecode(), Bytecode::kReturn);
216 } 159 }
217 160
218 TEST_F(BytecodeRegisterOptimizerTest, TemporaryNotMaterializedForInput) { 161 TEST_F(BytecodeRegisterOptimizerTest, SingleTemporaryNotMaterializedForInput) {
219 Initialize(3, 1); 162 Initialize(3, 1);
220 Register parameter = Register::FromParameterIndex(1, 3); 163 Register parameter = Register::FromParameterIndex(1, 3);
221 Register temp0 = NewTemporary(); 164 Register temp0 = NewTemporary();
222 Register temp1 = NewTemporary(); 165 Register temp1 = NewTemporary();
223 BytecodeNode node0(Bytecode::kMov, parameter.ToOperand(), temp0.ToOperand()); 166 optimizer()->DoMov(parameter, temp0, BytecodeSourceInfo());
224 optimizer()->Write(&node0); 167 optimizer()->DoMov(parameter, temp1, BytecodeSourceInfo());
225 BytecodeNode node1(Bytecode::kMov, parameter.ToOperand(), temp1.ToOperand());
226 optimizer()->Write(&node1);
227 CHECK_EQ(write_count(), 0); 168 CHECK_EQ(write_count(), 0);
228 BytecodeNode node2(Bytecode::kCallJSRuntime, 0, temp0.ToOperand(), 1); 169
229 optimizer()->Write(&node2); 170 Register reg = optimizer()->GetInputRegister(temp0);
230 CHECK_EQ(write_count(), 1); 171 RegisterList reg_list =
231 CHECK_EQ(output()->at(0).bytecode(), Bytecode::kCallJSRuntime); 172 optimizer()->GetInputRegisterList(RegisterList(temp0.index(), 1));
232 CHECK_EQ(output()->at(0).operand(0), 0); 173 CHECK_EQ(write_count(), 0);
233 CHECK_EQ(output()->at(0).operand(1), parameter.ToOperand()); 174 CHECK_EQ(parameter.index(), reg.index());
234 CHECK_EQ(output()->at(0).operand(2), 1); 175 CHECK_EQ(parameter.index(), reg_list.first_register().index());
176 CHECK_EQ(1, reg_list.register_count());
235 } 177 }
236 178
237 TEST_F(BytecodeRegisterOptimizerTest, RangeOfTemporariesMaterializedForInput) { 179 TEST_F(BytecodeRegisterOptimizerTest, RangeOfTemporariesMaterializedForInput) {
238 Initialize(3, 1); 180 Initialize(3, 1);
239 Register parameter = Register::FromParameterIndex(1, 3); 181 Register parameter = Register::FromParameterIndex(1, 3);
240 Register temp0 = NewTemporary(); 182 Register temp0 = NewTemporary();
241 Register temp1 = NewTemporary(); 183 Register temp1 = NewTemporary();
242 BytecodeNode node0(Bytecode::kLdaSmi, 3); 184 optimizer()->PrepareForBytecode(Bytecode::kLdaSmi);
243 optimizer()->Write(&node0); 185 optimizer()->DoStar(temp0, BytecodeSourceInfo());
244 CHECK_EQ(write_count(), 1); 186 optimizer()->DoMov(parameter, temp1, BytecodeSourceInfo());
245 BytecodeNode node1(Bytecode::kStar, temp0.ToOperand()); 187 CHECK_EQ(write_count(), 0);
246 optimizer()->Write(&node1);
247 BytecodeNode node2(Bytecode::kMov, parameter.ToOperand(), temp1.ToOperand());
248 optimizer()->Write(&node2);
249 CHECK_EQ(write_count(), 1);
250 BytecodeNode node3(Bytecode::kCallJSRuntime, 0, temp0.ToOperand(), 2);
251 optimizer()->Write(&node3);
252 CHECK_EQ(write_count(), 4);
253 188
254 CHECK_EQ(output()->at(0).bytecode(), Bytecode::kLdaSmi); 189 optimizer()->PrepareForBytecode(Bytecode::kCallJSRuntime);
255 CHECK_EQ(output()->at(0).operand(0), 3); 190 RegisterList reg_list =
256 191 optimizer()->GetInputRegisterList(RegisterList(temp0.index(), 2));
257 CHECK_EQ(output()->at(1).bytecode(), Bytecode::kStar); 192 CHECK_EQ(temp0.index(), reg_list.first_register().index());
258 CHECK_EQ(output()->at(1).operand(0), temp0.ToOperand()); 193 CHECK_EQ(2, reg_list.register_count());
259 194 CHECK_EQ(write_count(), 2);
260 CHECK_EQ(output()->at(2).bytecode(), Bytecode::kMov); 195 CHECK_EQ(output()->at(0).bytecode(), Bytecode::kStar);
261 CHECK_EQ(output()->at(2).operand(0), parameter.ToOperand()); 196 CHECK_EQ(output()->at(0).operand(0), temp0.ToOperand());
262 CHECK_EQ(output()->at(2).operand(1), temp1.ToOperand()); 197 CHECK_EQ(output()->at(1).bytecode(), Bytecode::kMov);
263 198 CHECK_EQ(output()->at(1).operand(0), parameter.ToOperand());
264 CHECK_EQ(output()->at(3).bytecode(), Bytecode::kCallJSRuntime); 199 CHECK_EQ(output()->at(1).operand(1), temp1.ToOperand());
265 CHECK_EQ(output()->at(3).operand(0), 0);
266 CHECK_EQ(output()->at(3).operand(1), temp0.ToOperand());
267 CHECK_EQ(output()->at(3).operand(2), 2);
268 } 200 }
269 201
270 } // namespace interpreter 202 } // namespace interpreter
271 } // namespace internal 203 } // namespace internal
272 } // namespace v8 204 } // namespace v8
OLDNEW
« no previous file with comments | « test/unittests/interpreter/bytecode-pipeline-unittest.cc ('k') | test/unittests/interpreter/bytecodes-unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698