OLD | NEW |
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-peephole-optimizer.h" | 9 #include "src/interpreter/bytecode-peephole-optimizer.h" |
10 #include "src/interpreter/constant-array-builder.h" | 10 #include "src/interpreter/constant-array-builder.h" |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
58 | 58 |
59 int write_count_ = 0; | 59 int write_count_ = 0; |
60 BytecodeNode last_written_; | 60 BytecodeNode last_written_; |
61 }; | 61 }; |
62 | 62 |
63 // Sanity tests. | 63 // Sanity tests. |
64 | 64 |
65 TEST_F(BytecodePeepholeOptimizerTest, FlushOnJump) { | 65 TEST_F(BytecodePeepholeOptimizerTest, FlushOnJump) { |
66 CHECK_EQ(write_count(), 0); | 66 CHECK_EQ(write_count(), 0); |
67 | 67 |
68 BytecodeNode add(Bytecode::kAdd, Register(0).ToOperand(), | 68 BytecodeNode add(Bytecode::kAdd, Register(0).ToOperand()); |
69 OperandScale::kSingle); | |
70 optimizer()->Write(&add); | 69 optimizer()->Write(&add); |
71 CHECK_EQ(write_count(), 0); | 70 CHECK_EQ(write_count(), 0); |
72 | 71 |
73 BytecodeLabel target; | 72 BytecodeLabel target; |
74 BytecodeNode jump(Bytecode::kJump, 0, OperandScale::kSingle); | 73 BytecodeNode jump(Bytecode::kJump, 0); |
75 optimizer()->WriteJump(&jump, &target); | 74 optimizer()->WriteJump(&jump, &target); |
76 CHECK_EQ(write_count(), 2); | 75 CHECK_EQ(write_count(), 2); |
77 CHECK_EQ(jump, last_written()); | 76 CHECK_EQ(jump, last_written()); |
78 } | 77 } |
79 | 78 |
80 TEST_F(BytecodePeepholeOptimizerTest, FlushOnBind) { | 79 TEST_F(BytecodePeepholeOptimizerTest, FlushOnBind) { |
81 CHECK_EQ(write_count(), 0); | 80 CHECK_EQ(write_count(), 0); |
82 | 81 |
83 BytecodeNode add(Bytecode::kAdd, Register(0).ToOperand(), | 82 BytecodeNode add(Bytecode::kAdd, Register(0).ToOperand()); |
84 OperandScale::kSingle); | |
85 optimizer()->Write(&add); | 83 optimizer()->Write(&add); |
86 CHECK_EQ(write_count(), 0); | 84 CHECK_EQ(write_count(), 0); |
87 | 85 |
88 BytecodeLabel target; | 86 BytecodeLabel target; |
89 optimizer()->BindLabel(&target); | 87 optimizer()->BindLabel(&target); |
90 CHECK_EQ(write_count(), 1); | 88 CHECK_EQ(write_count(), 1); |
91 CHECK_EQ(add, last_written()); | 89 CHECK_EQ(add, last_written()); |
92 } | 90 } |
93 | 91 |
94 // Nop elimination tests. | 92 // Nop elimination tests. |
95 | 93 |
96 TEST_F(BytecodePeepholeOptimizerTest, ElideEmptyNop) { | 94 TEST_F(BytecodePeepholeOptimizerTest, ElideEmptyNop) { |
97 BytecodeNode nop(Bytecode::kNop); | 95 BytecodeNode nop(Bytecode::kNop); |
98 optimizer()->Write(&nop); | 96 optimizer()->Write(&nop); |
99 BytecodeNode add(Bytecode::kAdd, Register(0).ToOperand(), | 97 BytecodeNode add(Bytecode::kAdd, Register(0).ToOperand()); |
100 OperandScale::kSingle); | |
101 optimizer()->Write(&add); | 98 optimizer()->Write(&add); |
102 Flush(); | 99 Flush(); |
103 CHECK_EQ(write_count(), 1); | 100 CHECK_EQ(write_count(), 1); |
104 CHECK_EQ(add, last_written()); | 101 CHECK_EQ(add, last_written()); |
105 } | 102 } |
106 | 103 |
107 TEST_F(BytecodePeepholeOptimizerTest, ElideExpressionNop) { | 104 TEST_F(BytecodePeepholeOptimizerTest, ElideExpressionNop) { |
108 BytecodeNode nop(Bytecode::kNop); | 105 BytecodeNode nop(Bytecode::kNop); |
109 nop.source_info().Update({3, false}); | 106 nop.source_info().Update({3, false}); |
110 optimizer()->Write(&nop); | 107 optimizer()->Write(&nop); |
111 BytecodeNode add(Bytecode::kAdd, Register(0).ToOperand(), | 108 BytecodeNode add(Bytecode::kAdd, Register(0).ToOperand()); |
112 OperandScale::kSingle); | |
113 optimizer()->Write(&add); | 109 optimizer()->Write(&add); |
114 Flush(); | 110 Flush(); |
115 CHECK_EQ(write_count(), 1); | 111 CHECK_EQ(write_count(), 1); |
116 CHECK_EQ(add, last_written()); | 112 CHECK_EQ(add, last_written()); |
117 } | 113 } |
118 | 114 |
119 TEST_F(BytecodePeepholeOptimizerTest, KeepStatementNop) { | 115 TEST_F(BytecodePeepholeOptimizerTest, KeepStatementNop) { |
120 BytecodeNode nop(Bytecode::kNop); | 116 BytecodeNode nop(Bytecode::kNop); |
121 nop.source_info().Update({3, true}); | 117 nop.source_info().Update({3, true}); |
122 optimizer()->Write(&nop); | 118 optimizer()->Write(&nop); |
123 BytecodeNode add(Bytecode::kAdd, Register(0).ToOperand(), | 119 BytecodeNode add(Bytecode::kAdd, Register(0).ToOperand()); |
124 OperandScale::kSingle); | |
125 add.source_info().Update({3, false}); | 120 add.source_info().Update({3, false}); |
126 optimizer()->Write(&add); | 121 optimizer()->Write(&add); |
127 Flush(); | 122 Flush(); |
128 CHECK_EQ(write_count(), 2); | 123 CHECK_EQ(write_count(), 2); |
129 CHECK_EQ(add, last_written()); | 124 CHECK_EQ(add, last_written()); |
130 } | 125 } |
131 | 126 |
132 // Tests covering BytecodePeepholeOptimizer::UpdateCurrentBytecode(). | 127 // Tests covering BytecodePeepholeOptimizer::UpdateCurrentBytecode(). |
133 | 128 |
134 TEST_F(BytecodePeepholeOptimizerTest, KeepJumpIfToBooleanTrue) { | 129 TEST_F(BytecodePeepholeOptimizerTest, KeepJumpIfToBooleanTrue) { |
135 BytecodeNode first(Bytecode::kLdaNull); | 130 BytecodeNode first(Bytecode::kLdaNull); |
136 BytecodeNode second(Bytecode::kJumpIfToBooleanTrue, 3, OperandScale::kSingle); | 131 BytecodeNode second(Bytecode::kJumpIfToBooleanTrue, 3); |
137 optimizer()->Write(&first); | 132 optimizer()->Write(&first); |
138 CHECK_EQ(write_count(), 0); | 133 CHECK_EQ(write_count(), 0); |
139 optimizer()->Write(&second); | 134 optimizer()->Write(&second); |
140 CHECK_EQ(write_count(), 1); | 135 CHECK_EQ(write_count(), 1); |
141 CHECK_EQ(last_written(), first); | 136 CHECK_EQ(last_written(), first); |
142 Flush(); | 137 Flush(); |
143 CHECK_EQ(write_count(), 2); | 138 CHECK_EQ(write_count(), 2); |
144 CHECK_EQ(last_written(), second); | 139 CHECK_EQ(last_written(), second); |
145 } | 140 } |
146 | 141 |
147 TEST_F(BytecodePeepholeOptimizerTest, ElideJumpIfToBooleanTrue) { | 142 TEST_F(BytecodePeepholeOptimizerTest, ElideJumpIfToBooleanTrue) { |
148 BytecodeNode first(Bytecode::kLdaTrue); | 143 BytecodeNode first(Bytecode::kLdaTrue); |
149 BytecodeNode second(Bytecode::kJumpIfToBooleanTrue, 3, OperandScale::kSingle); | 144 BytecodeNode second(Bytecode::kJumpIfToBooleanTrue, 3); |
150 optimizer()->Write(&first); | 145 optimizer()->Write(&first); |
151 CHECK_EQ(write_count(), 0); | 146 CHECK_EQ(write_count(), 0); |
152 optimizer()->Write(&second); | 147 optimizer()->Write(&second); |
153 CHECK_EQ(write_count(), 1); | 148 CHECK_EQ(write_count(), 1); |
154 CHECK_EQ(last_written(), first); | 149 CHECK_EQ(last_written(), first); |
155 Flush(); | 150 Flush(); |
156 CHECK_EQ(write_count(), 2); | 151 CHECK_EQ(write_count(), 2); |
157 CHECK_EQ(last_written().bytecode(), Bytecode::kJumpIfTrue); | 152 CHECK_EQ(last_written().bytecode(), Bytecode::kJumpIfTrue); |
158 CHECK_EQ(last_written().operand(0), second.operand(0)); | 153 CHECK_EQ(last_written().operand(0), second.operand(0)); |
159 } | 154 } |
(...skipping 20 matching lines...) Expand all Loading... |
180 CHECK_EQ(write_count(), 1); | 175 CHECK_EQ(write_count(), 1); |
181 CHECK_EQ(last_written(), first); | 176 CHECK_EQ(last_written(), first); |
182 Flush(); | 177 Flush(); |
183 CHECK_EQ(write_count(), 2); | 178 CHECK_EQ(write_count(), 2); |
184 CHECK_EQ(last_written().bytecode(), Bytecode::kLogicalNot); | 179 CHECK_EQ(last_written().bytecode(), Bytecode::kLogicalNot); |
185 } | 180 } |
186 | 181 |
187 // Tests covering BytecodePeepholeOptimizer::CanElideCurrent(). | 182 // Tests covering BytecodePeepholeOptimizer::CanElideCurrent(). |
188 | 183 |
189 TEST_F(BytecodePeepholeOptimizerTest, StarRxLdarRy) { | 184 TEST_F(BytecodePeepholeOptimizerTest, StarRxLdarRy) { |
190 BytecodeNode first(Bytecode::kStar, Register(0).ToOperand(), | 185 BytecodeNode first(Bytecode::kStar, Register(0).ToOperand()); |
191 OperandScale::kSingle); | 186 BytecodeNode second(Bytecode::kLdar, Register(1).ToOperand()); |
192 BytecodeNode second(Bytecode::kLdar, Register(1).ToOperand(), | |
193 OperandScale::kSingle); | |
194 optimizer()->Write(&first); | 187 optimizer()->Write(&first); |
195 CHECK_EQ(write_count(), 0); | 188 CHECK_EQ(write_count(), 0); |
196 optimizer()->Write(&second); | 189 optimizer()->Write(&second); |
197 CHECK_EQ(write_count(), 1); | 190 CHECK_EQ(write_count(), 1); |
198 CHECK_EQ(last_written(), first); | 191 CHECK_EQ(last_written(), first); |
199 Flush(); | 192 Flush(); |
200 CHECK_EQ(write_count(), 2); | 193 CHECK_EQ(write_count(), 2); |
201 CHECK_EQ(last_written(), second); | 194 CHECK_EQ(last_written(), second); |
202 } | 195 } |
203 | 196 |
204 TEST_F(BytecodePeepholeOptimizerTest, StarRxLdarRx) { | 197 TEST_F(BytecodePeepholeOptimizerTest, StarRxLdarRx) { |
205 BytecodeLabel label; | 198 BytecodeLabel label; |
206 BytecodeNode first(Bytecode::kStar, Register(0).ToOperand(), | 199 BytecodeNode first(Bytecode::kStar, Register(0).ToOperand()); |
207 OperandScale::kSingle); | 200 BytecodeNode second(Bytecode::kLdar, Register(0).ToOperand()); |
208 BytecodeNode second(Bytecode::kLdar, Register(0).ToOperand(), | |
209 OperandScale::kSingle); | |
210 optimizer()->Write(&first); | 201 optimizer()->Write(&first); |
211 CHECK_EQ(write_count(), 0); | 202 CHECK_EQ(write_count(), 0); |
212 optimizer()->Write(&second); | 203 optimizer()->Write(&second); |
213 CHECK_EQ(write_count(), 1); | 204 CHECK_EQ(write_count(), 1); |
214 CHECK_EQ(last_written(), first); | 205 CHECK_EQ(last_written(), first); |
215 Flush(); | 206 Flush(); |
216 CHECK_EQ(write_count(), 1); | 207 CHECK_EQ(write_count(), 1); |
217 } | 208 } |
218 | 209 |
219 TEST_F(BytecodePeepholeOptimizerTest, StarRxLdarRxStatement) { | 210 TEST_F(BytecodePeepholeOptimizerTest, StarRxLdarRxStatement) { |
220 BytecodeNode first(Bytecode::kStar, Register(0).ToOperand(), | 211 BytecodeNode first(Bytecode::kStar, Register(0).ToOperand()); |
221 OperandScale::kSingle); | 212 BytecodeNode second(Bytecode::kLdar, Register(0).ToOperand()); |
222 BytecodeNode second(Bytecode::kLdar, Register(0).ToOperand(), | |
223 OperandScale::kSingle); | |
224 second.source_info().Update({0, true}); | 213 second.source_info().Update({0, true}); |
225 optimizer()->Write(&first); | 214 optimizer()->Write(&first); |
226 CHECK_EQ(write_count(), 0); | 215 CHECK_EQ(write_count(), 0); |
227 optimizer()->Write(&second); | 216 optimizer()->Write(&second); |
228 CHECK_EQ(write_count(), 1); | 217 CHECK_EQ(write_count(), 1); |
229 CHECK_EQ(last_written(), first); | 218 CHECK_EQ(last_written(), first); |
230 Flush(); | 219 Flush(); |
231 CHECK_EQ(write_count(), 2); | 220 CHECK_EQ(write_count(), 2); |
232 CHECK_EQ(last_written().bytecode(), Bytecode::kNop); | 221 CHECK_EQ(last_written().bytecode(), Bytecode::kNop); |
233 CHECK_EQ(last_written().source_info(), second.source_info()); | 222 CHECK_EQ(last_written().source_info(), second.source_info()); |
234 } | 223 } |
235 | 224 |
236 TEST_F(BytecodePeepholeOptimizerTest, StarRxLdarRxStatementStarRy) { | 225 TEST_F(BytecodePeepholeOptimizerTest, StarRxLdarRxStatementStarRy) { |
237 BytecodeLabel label; | 226 BytecodeLabel label; |
238 BytecodeNode first(Bytecode::kStar, Register(0).ToOperand(), | 227 BytecodeNode first(Bytecode::kStar, Register(0).ToOperand()); |
239 OperandScale::kSingle); | 228 BytecodeNode second(Bytecode::kLdar, Register(0).ToOperand()); |
240 BytecodeNode second(Bytecode::kLdar, Register(0).ToOperand(), | 229 BytecodeNode third(Bytecode::kStar, Register(3).ToOperand()); |
241 OperandScale::kSingle); | |
242 BytecodeNode third(Bytecode::kStar, Register(3).ToOperand(), | |
243 OperandScale::kSingle); | |
244 second.source_info().Update({0, true}); | 230 second.source_info().Update({0, true}); |
245 optimizer()->Write(&first); | 231 optimizer()->Write(&first); |
246 CHECK_EQ(write_count(), 0); | 232 CHECK_EQ(write_count(), 0); |
247 optimizer()->Write(&second); | 233 optimizer()->Write(&second); |
248 CHECK_EQ(write_count(), 1); | 234 CHECK_EQ(write_count(), 1); |
249 CHECK_EQ(last_written(), first); | 235 CHECK_EQ(last_written(), first); |
250 optimizer()->Write(&third); | 236 optimizer()->Write(&third); |
251 CHECK_EQ(write_count(), 1); | 237 CHECK_EQ(write_count(), 1); |
252 Flush(); | 238 Flush(); |
253 CHECK_EQ(write_count(), 2); | 239 CHECK_EQ(write_count(), 2); |
254 // Source position should move |second| to |third| when |second| is elided. | 240 // Source position should move |second| to |third| when |second| is elided. |
255 third.source_info().Update(second.source_info()); | 241 third.source_info().Update(second.source_info()); |
256 CHECK_EQ(last_written(), third); | 242 CHECK_EQ(last_written(), third); |
257 } | 243 } |
258 | 244 |
259 TEST_F(BytecodePeepholeOptimizerTest, LdarToName) { | 245 TEST_F(BytecodePeepholeOptimizerTest, LdarToName) { |
260 BytecodeNode first(Bytecode::kLdar, Register(0).ToOperand(), | 246 BytecodeNode first(Bytecode::kLdar, Register(0).ToOperand()); |
261 OperandScale::kSingle); | |
262 BytecodeNode second(Bytecode::kToName); | 247 BytecodeNode second(Bytecode::kToName); |
263 optimizer()->Write(&first); | 248 optimizer()->Write(&first); |
264 CHECK_EQ(write_count(), 0); | 249 CHECK_EQ(write_count(), 0); |
265 optimizer()->Write(&second); | 250 optimizer()->Write(&second); |
266 CHECK_EQ(write_count(), 1); | 251 CHECK_EQ(write_count(), 1); |
267 CHECK_EQ(last_written(), first); | 252 CHECK_EQ(last_written(), first); |
268 Flush(); | 253 Flush(); |
269 CHECK_EQ(write_count(), 2); | 254 CHECK_EQ(write_count(), 2); |
270 CHECK_EQ(last_written(), second); | 255 CHECK_EQ(last_written(), second); |
271 } | 256 } |
(...skipping 19 matching lines...) Expand all Loading... |
291 CHECK_EQ(write_count(), 1); | 276 CHECK_EQ(write_count(), 1); |
292 CHECK_EQ(last_written(), first); | 277 CHECK_EQ(last_written(), first); |
293 Flush(); | 278 Flush(); |
294 CHECK_EQ(write_count(), 1); | 279 CHECK_EQ(write_count(), 1); |
295 } | 280 } |
296 | 281 |
297 TEST_F(BytecodePeepholeOptimizerTest, LdaConstantStringToName) { | 282 TEST_F(BytecodePeepholeOptimizerTest, LdaConstantStringToName) { |
298 Handle<Object> word = | 283 Handle<Object> word = |
299 isolate()->factory()->NewStringFromStaticChars("optimizing"); | 284 isolate()->factory()->NewStringFromStaticChars("optimizing"); |
300 size_t index = constant_array()->Insert(word); | 285 size_t index = constant_array()->Insert(word); |
301 BytecodeNode first(Bytecode::kLdaConstant, static_cast<uint32_t>(index), | 286 BytecodeNode first(Bytecode::kLdaConstant, static_cast<uint32_t>(index)); |
302 OperandScale::kSingle); | |
303 BytecodeNode second(Bytecode::kToName); | 287 BytecodeNode second(Bytecode::kToName); |
304 optimizer()->Write(&first); | 288 optimizer()->Write(&first); |
305 CHECK_EQ(write_count(), 0); | 289 CHECK_EQ(write_count(), 0); |
306 optimizer()->Write(&second); | 290 optimizer()->Write(&second); |
307 CHECK_EQ(write_count(), 1); | 291 CHECK_EQ(write_count(), 1); |
308 CHECK_EQ(last_written(), first); | 292 CHECK_EQ(last_written(), first); |
309 Flush(); | 293 Flush(); |
310 CHECK_EQ(write_count(), 1); | 294 CHECK_EQ(write_count(), 1); |
311 } | 295 } |
312 | 296 |
313 TEST_F(BytecodePeepholeOptimizerTest, LdaConstantNumberToName) { | 297 TEST_F(BytecodePeepholeOptimizerTest, LdaConstantNumberToName) { |
314 Handle<Object> word = isolate()->factory()->NewNumber(0.380); | 298 Handle<Object> word = isolate()->factory()->NewNumber(0.380); |
315 size_t index = constant_array()->Insert(word); | 299 size_t index = constant_array()->Insert(word); |
316 BytecodeNode first(Bytecode::kLdaConstant, static_cast<uint32_t>(index), | 300 BytecodeNode first(Bytecode::kLdaConstant, static_cast<uint32_t>(index)); |
317 OperandScale::kSingle); | |
318 BytecodeNode second(Bytecode::kToName); | 301 BytecodeNode second(Bytecode::kToName); |
319 optimizer()->Write(&first); | 302 optimizer()->Write(&first); |
320 CHECK_EQ(write_count(), 0); | 303 CHECK_EQ(write_count(), 0); |
321 optimizer()->Write(&second); | 304 optimizer()->Write(&second); |
322 CHECK_EQ(write_count(), 1); | 305 CHECK_EQ(write_count(), 1); |
323 CHECK_EQ(last_written(), first); | 306 CHECK_EQ(last_written(), first); |
324 Flush(); | 307 Flush(); |
325 CHECK_EQ(write_count(), 2); | 308 CHECK_EQ(write_count(), 2); |
326 CHECK_EQ(last_written(), second); | 309 CHECK_EQ(last_written(), second); |
327 } | 310 } |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
382 | 365 |
383 // Tests covering BytecodePeepholeOptimizer::UpdateLastAndCurrentBytecodes(). | 366 // Tests covering BytecodePeepholeOptimizer::UpdateLastAndCurrentBytecodes(). |
384 | 367 |
385 TEST_F(BytecodePeepholeOptimizerTest, MergeLoadICStar) { | 368 TEST_F(BytecodePeepholeOptimizerTest, MergeLoadICStar) { |
386 const uint32_t operands[] = { | 369 const uint32_t operands[] = { |
387 static_cast<uint32_t>(Register(31).ToOperand()), 32, 33, | 370 static_cast<uint32_t>(Register(31).ToOperand()), 32, 33, |
388 static_cast<uint32_t>(Register(256).ToOperand())}; | 371 static_cast<uint32_t>(Register(256).ToOperand())}; |
389 const int expected_operand_count = static_cast<int>(arraysize(operands)); | 372 const int expected_operand_count = static_cast<int>(arraysize(operands)); |
390 | 373 |
391 BytecodeNode first(Bytecode::kLdaNamedProperty, operands[0], operands[1], | 374 BytecodeNode first(Bytecode::kLdaNamedProperty, operands[0], operands[1], |
392 operands[2], OperandScale::kSingle); | 375 operands[2]); |
393 BytecodeNode second(Bytecode::kStar, operands[3], OperandScale::kDouble); | 376 BytecodeNode second(Bytecode::kStar, operands[3]); |
394 BytecodeNode third(Bytecode::kReturn); | 377 BytecodeNode third(Bytecode::kReturn); |
395 optimizer()->Write(&first); | 378 optimizer()->Write(&first); |
396 optimizer()->Write(&second); | 379 optimizer()->Write(&second); |
397 CHECK_EQ(write_count(), 1); | 380 CHECK_EQ(write_count(), 1); |
398 CHECK_EQ(last_written().bytecode(), Bytecode::kLdrNamedProperty); | 381 CHECK_EQ(last_written().bytecode(), Bytecode::kLdrNamedProperty); |
399 CHECK_EQ(last_written().operand_count(), expected_operand_count); | 382 CHECK_EQ(last_written().operand_count(), expected_operand_count); |
400 for (int i = 0; i < expected_operand_count; ++i) { | 383 for (int i = 0; i < expected_operand_count; ++i) { |
401 CHECK_EQ(last_written().operand(i), operands[i]); | 384 CHECK_EQ(last_written().operand(i), operands[i]); |
402 } | 385 } |
403 CHECK_EQ(last_written().operand_scale(), | |
404 std::max(first.operand_scale(), second.operand_scale())); | |
405 optimizer()->Write(&third); | 386 optimizer()->Write(&third); |
406 CHECK_EQ(write_count(), 2); | 387 CHECK_EQ(write_count(), 2); |
407 CHECK_EQ(last_written().bytecode(), Bytecode::kLdar); | 388 CHECK_EQ(last_written().bytecode(), Bytecode::kLdar); |
408 CHECK_EQ(last_written().operand(0), operands[expected_operand_count - 1]); | 389 CHECK_EQ(last_written().operand(0), operands[expected_operand_count - 1]); |
409 Flush(); | 390 Flush(); |
410 CHECK_EQ(last_written().bytecode(), third.bytecode()); | 391 CHECK_EQ(last_written().bytecode(), third.bytecode()); |
411 } | 392 } |
412 | 393 |
413 TEST_F(BytecodePeepholeOptimizerTest, MergeLdaKeyedPropertyStar) { | 394 TEST_F(BytecodePeepholeOptimizerTest, MergeLdaKeyedPropertyStar) { |
414 const uint32_t operands[] = {static_cast<uint32_t>(Register(31).ToOperand()), | 395 const uint32_t operands[] = {static_cast<uint32_t>(Register(31).ToOperand()), |
415 9999997, | 396 9999997, |
416 static_cast<uint32_t>(Register(1).ToOperand())}; | 397 static_cast<uint32_t>(Register(1).ToOperand())}; |
417 const int expected_operand_count = static_cast<int>(arraysize(operands)); | 398 const int expected_operand_count = static_cast<int>(arraysize(operands)); |
418 | 399 |
419 BytecodeNode first(Bytecode::kLdaKeyedProperty, operands[0], operands[1], | 400 BytecodeNode first(Bytecode::kLdaKeyedProperty, operands[0], operands[1]); |
420 OperandScale::kQuadruple); | 401 BytecodeNode second(Bytecode::kStar, operands[2]); |
421 BytecodeNode second(Bytecode::kStar, operands[2], OperandScale::kSingle); | |
422 BytecodeNode third(Bytecode::kReturn); | 402 BytecodeNode third(Bytecode::kReturn); |
423 optimizer()->Write(&first); | 403 optimizer()->Write(&first); |
424 optimizer()->Write(&second); | 404 optimizer()->Write(&second); |
425 CHECK_EQ(write_count(), 1); | 405 CHECK_EQ(write_count(), 1); |
426 CHECK_EQ(last_written().bytecode(), Bytecode::kLdrKeyedProperty); | 406 CHECK_EQ(last_written().bytecode(), Bytecode::kLdrKeyedProperty); |
427 CHECK_EQ(last_written().operand_count(), expected_operand_count); | 407 CHECK_EQ(last_written().operand_count(), expected_operand_count); |
428 for (int i = 0; i < expected_operand_count; ++i) { | 408 for (int i = 0; i < expected_operand_count; ++i) { |
429 CHECK_EQ(last_written().operand(i), operands[i]); | 409 CHECK_EQ(last_written().operand(i), operands[i]); |
430 } | 410 } |
431 CHECK_EQ(last_written().operand_scale(), | |
432 std::max(first.operand_scale(), second.operand_scale())); | |
433 optimizer()->Write(&third); | 411 optimizer()->Write(&third); |
434 CHECK_EQ(write_count(), 2); | 412 CHECK_EQ(write_count(), 2); |
435 CHECK_EQ(last_written().bytecode(), Bytecode::kLdar); | 413 CHECK_EQ(last_written().bytecode(), Bytecode::kLdar); |
436 CHECK_EQ(last_written().operand(0), operands[expected_operand_count - 1]); | 414 CHECK_EQ(last_written().operand(0), operands[expected_operand_count - 1]); |
437 Flush(); | 415 Flush(); |
438 CHECK_EQ(last_written().bytecode(), third.bytecode()); | 416 CHECK_EQ(last_written().bytecode(), third.bytecode()); |
439 } | 417 } |
440 | 418 |
441 TEST_F(BytecodePeepholeOptimizerTest, MergeLdaGlobalStar) { | 419 TEST_F(BytecodePeepholeOptimizerTest, MergeLdaGlobalStar) { |
442 const uint32_t operands[] = {54321, 19191, | 420 const uint32_t operands[] = {54321, 19191, |
443 static_cast<uint32_t>(Register(1).ToOperand())}; | 421 static_cast<uint32_t>(Register(1).ToOperand())}; |
444 const int expected_operand_count = static_cast<int>(arraysize(operands)); | 422 const int expected_operand_count = static_cast<int>(arraysize(operands)); |
445 | 423 |
446 BytecodeNode first(Bytecode::kLdaGlobal, operands[0], operands[1], | 424 BytecodeNode first(Bytecode::kLdaGlobal, operands[0], operands[1]); |
447 OperandScale::kDouble); | 425 BytecodeNode second(Bytecode::kStar, operands[2]); |
448 BytecodeNode second(Bytecode::kStar, operands[2], OperandScale::kSingle); | |
449 BytecodeNode third(Bytecode::kReturn); | 426 BytecodeNode third(Bytecode::kReturn); |
450 optimizer()->Write(&first); | 427 optimizer()->Write(&first); |
451 optimizer()->Write(&second); | 428 optimizer()->Write(&second); |
452 CHECK_EQ(write_count(), 1); | 429 CHECK_EQ(write_count(), 1); |
453 CHECK_EQ(last_written().bytecode(), Bytecode::kLdrGlobal); | 430 CHECK_EQ(last_written().bytecode(), Bytecode::kLdrGlobal); |
454 CHECK_EQ(last_written().operand_count(), expected_operand_count); | 431 CHECK_EQ(last_written().operand_count(), expected_operand_count); |
455 for (int i = 0; i < expected_operand_count; ++i) { | 432 for (int i = 0; i < expected_operand_count; ++i) { |
456 CHECK_EQ(last_written().operand(i), operands[i]); | 433 CHECK_EQ(last_written().operand(i), operands[i]); |
457 } | 434 } |
458 CHECK_EQ(last_written().operand_scale(), | |
459 std::max(first.operand_scale(), second.operand_scale())); | |
460 optimizer()->Write(&third); | 435 optimizer()->Write(&third); |
461 CHECK_EQ(write_count(), 2); | 436 CHECK_EQ(write_count(), 2); |
462 CHECK_EQ(last_written().bytecode(), Bytecode::kLdar); | 437 CHECK_EQ(last_written().bytecode(), Bytecode::kLdar); |
463 CHECK_EQ(last_written().operand(0), operands[expected_operand_count - 1]); | 438 CHECK_EQ(last_written().operand(0), operands[expected_operand_count - 1]); |
464 Flush(); | 439 Flush(); |
465 CHECK_EQ(last_written().bytecode(), third.bytecode()); | 440 CHECK_EQ(last_written().bytecode(), third.bytecode()); |
466 } | 441 } |
467 | 442 |
468 TEST_F(BytecodePeepholeOptimizerTest, MergeLdaContextSlotStar) { | 443 TEST_F(BytecodePeepholeOptimizerTest, MergeLdaContextSlotStar) { |
469 const uint32_t operands[] = { | 444 const uint32_t operands[] = { |
470 static_cast<uint32_t>(Register(200000).ToOperand()), 55005500, | 445 static_cast<uint32_t>(Register(200000).ToOperand()), 55005500, |
471 static_cast<uint32_t>(Register(1).ToOperand())}; | 446 static_cast<uint32_t>(Register(1).ToOperand())}; |
472 const int expected_operand_count = static_cast<int>(arraysize(operands)); | 447 const int expected_operand_count = static_cast<int>(arraysize(operands)); |
473 | 448 |
474 BytecodeNode first(Bytecode::kLdaContextSlot, operands[0], operands[1], | 449 BytecodeNode first(Bytecode::kLdaContextSlot, operands[0], operands[1]); |
475 OperandScale::kQuadruple); | 450 BytecodeNode second(Bytecode::kStar, operands[2]); |
476 BytecodeNode second(Bytecode::kStar, operands[2], OperandScale::kSingle); | |
477 BytecodeNode third(Bytecode::kReturn); | 451 BytecodeNode third(Bytecode::kReturn); |
478 optimizer()->Write(&first); | 452 optimizer()->Write(&first); |
479 optimizer()->Write(&second); | 453 optimizer()->Write(&second); |
480 CHECK_EQ(write_count(), 1); | 454 CHECK_EQ(write_count(), 1); |
481 CHECK_EQ(last_written().bytecode(), Bytecode::kLdrContextSlot); | 455 CHECK_EQ(last_written().bytecode(), Bytecode::kLdrContextSlot); |
482 CHECK_EQ(last_written().operand_count(), expected_operand_count); | 456 CHECK_EQ(last_written().operand_count(), expected_operand_count); |
483 for (int i = 0; i < expected_operand_count; ++i) { | 457 for (int i = 0; i < expected_operand_count; ++i) { |
484 CHECK_EQ(last_written().operand(i), operands[i]); | 458 CHECK_EQ(last_written().operand(i), operands[i]); |
485 } | 459 } |
486 CHECK_EQ(last_written().operand_scale(), | |
487 std::max(first.operand_scale(), second.operand_scale())); | |
488 optimizer()->Write(&third); | 460 optimizer()->Write(&third); |
489 CHECK_EQ(write_count(), 2); | 461 CHECK_EQ(write_count(), 2); |
490 CHECK_EQ(last_written().bytecode(), Bytecode::kLdar); | 462 CHECK_EQ(last_written().bytecode(), Bytecode::kLdar); |
491 CHECK_EQ(last_written().operand(0), operands[expected_operand_count - 1]); | 463 CHECK_EQ(last_written().operand(0), operands[expected_operand_count - 1]); |
492 Flush(); | 464 Flush(); |
493 CHECK_EQ(last_written().bytecode(), third.bytecode()); | 465 CHECK_EQ(last_written().bytecode(), third.bytecode()); |
494 } | 466 } |
495 | 467 |
496 TEST_F(BytecodePeepholeOptimizerTest, MergeLdaUndefinedStar) { | 468 TEST_F(BytecodePeepholeOptimizerTest, MergeLdaUndefinedStar) { |
497 const uint32_t operands[] = { | 469 const uint32_t operands[] = { |
498 static_cast<uint32_t>(Register(100000).ToOperand())}; | 470 static_cast<uint32_t>(Register(100000).ToOperand())}; |
499 const int expected_operand_count = static_cast<int>(arraysize(operands)); | 471 const int expected_operand_count = static_cast<int>(arraysize(operands)); |
500 | 472 |
501 BytecodeNode first(Bytecode::kLdaUndefined); | 473 BytecodeNode first(Bytecode::kLdaUndefined); |
502 BytecodeNode second(Bytecode::kStar, operands[0], OperandScale::kQuadruple); | 474 BytecodeNode second(Bytecode::kStar, operands[0]); |
503 BytecodeNode third(Bytecode::kReturn); | 475 BytecodeNode third(Bytecode::kReturn); |
504 optimizer()->Write(&first); | 476 optimizer()->Write(&first); |
505 optimizer()->Write(&second); | 477 optimizer()->Write(&second); |
506 CHECK_EQ(write_count(), 1); | 478 CHECK_EQ(write_count(), 1); |
507 CHECK_EQ(last_written().bytecode(), Bytecode::kLdrUndefined); | 479 CHECK_EQ(last_written().bytecode(), Bytecode::kLdrUndefined); |
508 CHECK_EQ(last_written().operand_count(), expected_operand_count); | 480 CHECK_EQ(last_written().operand_count(), expected_operand_count); |
509 for (int i = 0; i < expected_operand_count; ++i) { | 481 for (int i = 0; i < expected_operand_count; ++i) { |
510 CHECK_EQ(last_written().operand(i), operands[i]); | 482 CHECK_EQ(last_written().operand(i), operands[i]); |
511 } | 483 } |
512 CHECK_EQ(last_written().operand_scale(), | |
513 std::max(first.operand_scale(), second.operand_scale())); | |
514 optimizer()->Write(&third); | 484 optimizer()->Write(&third); |
515 CHECK_EQ(write_count(), 2); | 485 CHECK_EQ(write_count(), 2); |
516 CHECK_EQ(last_written().bytecode(), Bytecode::kLdar); | 486 CHECK_EQ(last_written().bytecode(), Bytecode::kLdar); |
517 CHECK_EQ(last_written().operand(0), operands[expected_operand_count - 1]); | 487 CHECK_EQ(last_written().operand(0), operands[expected_operand_count - 1]); |
518 Flush(); | 488 Flush(); |
519 CHECK_EQ(last_written().bytecode(), third.bytecode()); | 489 CHECK_EQ(last_written().bytecode(), third.bytecode()); |
520 } | 490 } |
521 | 491 |
522 } // namespace interpreter | 492 } // namespace interpreter |
523 } // namespace internal | 493 } // namespace internal |
524 } // namespace v8 | 494 } // namespace v8 |
OLD | NEW |