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

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

Issue 2035813002: [Interpreter] Move jump processing to bytecode array writer. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@int_fix_bytecode
Patch Set: Address comments Created 4 years, 6 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 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-peephole-optimizer.h" 9 #include "src/interpreter/bytecode-peephole-optimizer.h"
9 #include "src/interpreter/constant-array-builder.h" 10 #include "src/interpreter/constant-array-builder.h"
10 #include "src/objects-inl.h" 11 #include "src/objects-inl.h"
11 #include "src/objects.h" 12 #include "src/objects.h"
12 #include "test/unittests/test-utils.h" 13 #include "test/unittests/test-utils.h"
13 14
14 namespace v8 { 15 namespace v8 {
15 namespace internal { 16 namespace internal {
16 namespace interpreter { 17 namespace interpreter {
17 18
18 class BytecodePeepholeOptimizerTest : public BytecodePipelineStage, 19 class BytecodePeepholeOptimizerTest : public BytecodePipelineStage,
19 public TestWithIsolateAndZone { 20 public TestWithIsolateAndZone {
20 public: 21 public:
21 BytecodePeepholeOptimizerTest() 22 BytecodePeepholeOptimizerTest()
22 : constant_array_builder_(isolate(), zone()), 23 : constant_array_builder_(isolate(), zone()),
23 peephole_optimizer_(&constant_array_builder_, this) {} 24 peephole_optimizer_(&constant_array_builder_, this) {}
24 ~BytecodePeepholeOptimizerTest() override {} 25 ~BytecodePeepholeOptimizerTest() override {}
25 26
26 size_t FlushForOffset() override {
27 flush_for_offset_count_++;
28 return 0;
29 };
30
31 void FlushBasicBlock() override { flush_basic_block_count_++; }
32
33 void Write(BytecodeNode* node) override { 27 void Write(BytecodeNode* node) override {
34 write_count_++; 28 write_count_++;
35 last_written_.Clone(node); 29 last_written_.Clone(node);
36 } 30 }
37 31
32 void WriteJump(BytecodeNode* node, BytecodeLabel* label) override {
33 write_count_++;
34 last_written_.Clone(node);
35 }
36
37 void BindLabel(BytecodeLabel* label) override {}
38 void BindLabel(const BytecodeLabel& target, BytecodeLabel* label) override {}
39 Handle<BytecodeArray> ToBytecodeArray(
40 int fixed_register_count, int parameter_count,
41 Handle<FixedArray> handle_table) override {
42 return Handle<BytecodeArray>();
43 }
44
45 void Flush() {
46 optimizer()->ToBytecodeArray(0, 0, factory()->empty_fixed_array());
47 }
48
38 BytecodePeepholeOptimizer* optimizer() { return &peephole_optimizer_; } 49 BytecodePeepholeOptimizer* optimizer() { return &peephole_optimizer_; }
39 ConstantArrayBuilder* constant_array() { return &constant_array_builder_; } 50 ConstantArrayBuilder* constant_array() { return &constant_array_builder_; }
40 51
41 int flush_for_offset_count() const { return flush_for_offset_count_; }
42 int flush_basic_block_count() const { return flush_basic_block_count_; }
43 int write_count() const { return write_count_; } 52 int write_count() const { return write_count_; }
44 const BytecodeNode& last_written() const { return last_written_; } 53 const BytecodeNode& last_written() const { return last_written_; }
45 54
46 private: 55 private:
47 ConstantArrayBuilder constant_array_builder_; 56 ConstantArrayBuilder constant_array_builder_;
48 BytecodePeepholeOptimizer peephole_optimizer_; 57 BytecodePeepholeOptimizer peephole_optimizer_;
49 58
50 int flush_for_offset_count_ = 0;
51 int flush_basic_block_count_ = 0;
52 int write_count_ = 0; 59 int write_count_ = 0;
53 BytecodeNode last_written_; 60 BytecodeNode last_written_;
54 }; 61 };
55 62
56 // Sanity tests. 63 // Sanity tests.
57 64
58 TEST_F(BytecodePeepholeOptimizerTest, FlushForOffsetPassThrough) { 65 TEST_F(BytecodePeepholeOptimizerTest, FlushOnJump) {
59 CHECK_EQ(flush_for_offset_count(), 0); 66 CHECK_EQ(write_count(), 0);
60 CHECK_EQ(optimizer()->FlushForOffset(), 0); 67
61 CHECK_EQ(flush_for_offset_count(), 1); 68 BytecodeNode add(Bytecode::kAdd, Register(0).ToOperand(),
69 OperandScale::kSingle);
70 optimizer()->Write(&add);
71 CHECK_EQ(write_count(), 0);
72
73 BytecodeLabel target;
74 BytecodeNode jump(Bytecode::kJump, 0, OperandScale::kSingle);
75 optimizer()->WriteJump(&jump, &target);
76 CHECK_EQ(write_count(), 2);
77 CHECK_EQ(jump, last_written());
62 } 78 }
63 79
64 TEST_F(BytecodePeepholeOptimizerTest, FlushForOffsetRightSize) { 80 TEST_F(BytecodePeepholeOptimizerTest, FlushOnBind) {
65 BytecodeNode node(Bytecode::kAdd, Register(0).ToOperand(),
66 OperandScale::kQuadruple);
67 optimizer()->Write(&node);
68 CHECK_EQ(optimizer()->FlushForOffset(), node.Size());
69 CHECK_EQ(flush_for_offset_count(), 1);
70 CHECK_EQ(write_count(), 0); 81 CHECK_EQ(write_count(), 0);
82
83 BytecodeNode add(Bytecode::kAdd, Register(0).ToOperand(),
84 OperandScale::kSingle);
85 optimizer()->Write(&add);
86 CHECK_EQ(write_count(), 0);
87
88 BytecodeLabel target;
89 optimizer()->BindLabel(&target);
90 CHECK_EQ(write_count(), 1);
91 CHECK_EQ(add, last_written());
71 } 92 }
72 93
73 TEST_F(BytecodePeepholeOptimizerTest, FlushForOffsetNop) { 94 // Nop elimination tests.
74 BytecodeNode node(Bytecode::kNop); 95
75 optimizer()->Write(&node); 96 TEST_F(BytecodePeepholeOptimizerTest, ElideEmptyNop) {
76 CHECK_EQ(optimizer()->FlushForOffset(), 0); 97 BytecodeNode nop(Bytecode::kNop);
77 CHECK_EQ(flush_for_offset_count(), 1); 98 optimizer()->Write(&nop);
78 CHECK_EQ(write_count(), 0); 99 BytecodeNode add(Bytecode::kAdd, Register(0).ToOperand(),
100 OperandScale::kSingle);
101 optimizer()->Write(&add);
102 Flush();
103 CHECK_EQ(write_count(), 1);
104 CHECK_EQ(add, last_written());
79 } 105 }
80 106
81 TEST_F(BytecodePeepholeOptimizerTest, FlushForOffsetNopExpression) { 107 TEST_F(BytecodePeepholeOptimizerTest, ElideExpressionNop) {
82 BytecodeNode node(Bytecode::kNop); 108 BytecodeNode nop(Bytecode::kNop);
83 node.source_info().Update({3, false}); 109 nop.source_info().Update({3, false});
84 optimizer()->Write(&node); 110 optimizer()->Write(&nop);
85 CHECK_EQ(optimizer()->FlushForOffset(), 0); 111 BytecodeNode add(Bytecode::kAdd, Register(0).ToOperand(),
86 CHECK_EQ(flush_for_offset_count(), 1); 112 OperandScale::kSingle);
87 CHECK_EQ(write_count(), 0); 113 optimizer()->Write(&add);
114 Flush();
115 CHECK_EQ(write_count(), 1);
116 CHECK_EQ(add, last_written());
88 } 117 }
89 118
90 TEST_F(BytecodePeepholeOptimizerTest, FlushForOffsetNopStatement) { 119 TEST_F(BytecodePeepholeOptimizerTest, KeepStatementNop) {
91 BytecodeNode node(Bytecode::kNop); 120 BytecodeNode nop(Bytecode::kNop);
92 node.source_info().Update({3, true}); 121 nop.source_info().Update({3, true});
93 optimizer()->Write(&node); 122 optimizer()->Write(&nop);
94 CHECK_EQ(optimizer()->FlushForOffset(), node.Size()); 123 BytecodeNode add(Bytecode::kAdd, Register(0).ToOperand(),
95 CHECK_EQ(flush_for_offset_count(), 1); 124 OperandScale::kSingle);
96 CHECK_EQ(write_count(), 0); 125 add.source_info().Update({3, false});
97 } 126 optimizer()->Write(&add);
98 127 Flush();
99 TEST_F(BytecodePeepholeOptimizerTest, FlushBasicBlockPassThrough) { 128 CHECK_EQ(write_count(), 2);
100 CHECK_EQ(flush_basic_block_count(), 0); 129 CHECK_EQ(add, last_written());
101 optimizer()->FlushBasicBlock();
102 CHECK_EQ(flush_basic_block_count(), 1);
103 CHECK_EQ(write_count(), 0);
104 }
105
106 TEST_F(BytecodePeepholeOptimizerTest, WriteOneFlushBasicBlock) {
107 BytecodeNode node(Bytecode::kAdd, Register(0).ToOperand(),
108 OperandScale::kQuadruple);
109 optimizer()->Write(&node);
110 CHECK_EQ(write_count(), 0);
111 optimizer()->FlushBasicBlock();
112 CHECK_EQ(write_count(), 1);
113 CHECK_EQ(node, last_written());
114 } 130 }
115 131
116 // Tests covering BytecodePeepholeOptimizer::UpdateCurrentBytecode(). 132 // Tests covering BytecodePeepholeOptimizer::UpdateCurrentBytecode().
117 133
118 TEST_F(BytecodePeepholeOptimizerTest, KeepJumpIfToBooleanTrue) { 134 TEST_F(BytecodePeepholeOptimizerTest, KeepJumpIfToBooleanTrue) {
119 BytecodeNode first(Bytecode::kLdaNull); 135 BytecodeNode first(Bytecode::kLdaNull);
120 BytecodeNode second(Bytecode::kJumpIfToBooleanTrue, 3, OperandScale::kSingle); 136 BytecodeNode second(Bytecode::kJumpIfToBooleanTrue, 3, OperandScale::kSingle);
121 optimizer()->Write(&first); 137 optimizer()->Write(&first);
122 CHECK_EQ(write_count(), 0); 138 CHECK_EQ(write_count(), 0);
123 optimizer()->Write(&second); 139 optimizer()->Write(&second);
124 CHECK_EQ(write_count(), 1); 140 CHECK_EQ(write_count(), 1);
125 CHECK_EQ(last_written(), first); 141 CHECK_EQ(last_written(), first);
126 optimizer()->FlushBasicBlock(); 142 Flush();
127 CHECK_EQ(write_count(), 2); 143 CHECK_EQ(write_count(), 2);
128 CHECK_EQ(last_written(), second); 144 CHECK_EQ(last_written(), second);
129 } 145 }
130 146
131 TEST_F(BytecodePeepholeOptimizerTest, ElideJumpIfToBooleanTrue) { 147 TEST_F(BytecodePeepholeOptimizerTest, ElideJumpIfToBooleanTrue) {
132 BytecodeNode first(Bytecode::kLdaTrue); 148 BytecodeNode first(Bytecode::kLdaTrue);
133 BytecodeNode second(Bytecode::kJumpIfToBooleanTrue, 3, OperandScale::kSingle); 149 BytecodeNode second(Bytecode::kJumpIfToBooleanTrue, 3, OperandScale::kSingle);
134 optimizer()->Write(&first); 150 optimizer()->Write(&first);
135 CHECK_EQ(write_count(), 0); 151 CHECK_EQ(write_count(), 0);
136 optimizer()->Write(&second); 152 optimizer()->Write(&second);
137 CHECK_EQ(write_count(), 1); 153 CHECK_EQ(write_count(), 1);
138 CHECK_EQ(last_written(), first); 154 CHECK_EQ(last_written(), first);
139 optimizer()->FlushBasicBlock(); 155 Flush();
140 CHECK_EQ(write_count(), 2); 156 CHECK_EQ(write_count(), 2);
141 CHECK_EQ(last_written().bytecode(), Bytecode::kJumpIfTrue); 157 CHECK_EQ(last_written().bytecode(), Bytecode::kJumpIfTrue);
142 CHECK_EQ(last_written().operand(0), second.operand(0)); 158 CHECK_EQ(last_written().operand(0), second.operand(0));
143 } 159 }
144 160
145 TEST_F(BytecodePeepholeOptimizerTest, KeepToBooleanLogicalNot) { 161 TEST_F(BytecodePeepholeOptimizerTest, KeepToBooleanLogicalNot) {
146 BytecodeNode first(Bytecode::kLdaNull); 162 BytecodeNode first(Bytecode::kLdaNull);
147 BytecodeNode second(Bytecode::kToBooleanLogicalNot); 163 BytecodeNode second(Bytecode::kToBooleanLogicalNot);
148 optimizer()->Write(&first); 164 optimizer()->Write(&first);
149 CHECK_EQ(write_count(), 0); 165 CHECK_EQ(write_count(), 0);
150 optimizer()->Write(&second); 166 optimizer()->Write(&second);
151 CHECK_EQ(write_count(), 1); 167 CHECK_EQ(write_count(), 1);
152 CHECK_EQ(last_written(), first); 168 CHECK_EQ(last_written(), first);
153 optimizer()->FlushBasicBlock(); 169 Flush();
154 CHECK_EQ(write_count(), 2); 170 CHECK_EQ(write_count(), 2);
155 CHECK_EQ(last_written(), second); 171 CHECK_EQ(last_written(), second);
156 } 172 }
157 173
158 TEST_F(BytecodePeepholeOptimizerTest, ElideToBooleanLogicalNot) { 174 TEST_F(BytecodePeepholeOptimizerTest, ElideToBooleanLogicalNot) {
159 BytecodeNode first(Bytecode::kLdaTrue); 175 BytecodeNode first(Bytecode::kLdaTrue);
160 BytecodeNode second(Bytecode::kToBooleanLogicalNot); 176 BytecodeNode second(Bytecode::kToBooleanLogicalNot);
161 optimizer()->Write(&first); 177 optimizer()->Write(&first);
162 CHECK_EQ(write_count(), 0); 178 CHECK_EQ(write_count(), 0);
163 optimizer()->Write(&second); 179 optimizer()->Write(&second);
164 CHECK_EQ(write_count(), 1); 180 CHECK_EQ(write_count(), 1);
165 CHECK_EQ(last_written(), first); 181 CHECK_EQ(last_written(), first);
166 optimizer()->FlushBasicBlock(); 182 Flush();
167 CHECK_EQ(write_count(), 2); 183 CHECK_EQ(write_count(), 2);
168 CHECK_EQ(last_written().bytecode(), Bytecode::kLogicalNot); 184 CHECK_EQ(last_written().bytecode(), Bytecode::kLogicalNot);
169 } 185 }
170 186
171 // Tests covering BytecodePeepholeOptimizer::CanElideCurrent(). 187 // Tests covering BytecodePeepholeOptimizer::CanElideCurrent().
172 188
173 TEST_F(BytecodePeepholeOptimizerTest, LdarRxLdarRy) { 189 TEST_F(BytecodePeepholeOptimizerTest, StarRxLdarRy) {
174 BytecodeNode first(Bytecode::kLdar, Register(0).ToOperand(), 190 BytecodeNode first(Bytecode::kStar, Register(0).ToOperand(),
175 OperandScale::kSingle); 191 OperandScale::kSingle);
176 BytecodeNode second(Bytecode::kLdar, Register(1).ToOperand(), 192 BytecodeNode second(Bytecode::kLdar, Register(1).ToOperand(),
177 OperandScale::kSingle); 193 OperandScale::kSingle);
178 optimizer()->Write(&first); 194 optimizer()->Write(&first);
179 optimizer()->FlushForOffset(); // Prevent CanElideLast removing |first|.
180 CHECK_EQ(write_count(), 0); 195 CHECK_EQ(write_count(), 0);
181 optimizer()->Write(&second); 196 optimizer()->Write(&second);
182 CHECK_EQ(write_count(), 1); 197 CHECK_EQ(write_count(), 1);
183 CHECK_EQ(last_written(), first); 198 CHECK_EQ(last_written(), first);
184 optimizer()->FlushBasicBlock(); 199 Flush();
185 CHECK_EQ(write_count(), 2); 200 CHECK_EQ(write_count(), 2);
186 CHECK_EQ(last_written(), second); 201 CHECK_EQ(last_written(), second);
187 } 202 }
188 203
189 TEST_F(BytecodePeepholeOptimizerTest, LdarRxLdarRx) { 204 TEST_F(BytecodePeepholeOptimizerTest, StarRxLdarRx) {
190 BytecodeNode first(Bytecode::kLdar, Register(0).ToOperand(), 205 BytecodeLabel label;
206 BytecodeNode first(Bytecode::kStar, Register(0).ToOperand(),
191 OperandScale::kSingle); 207 OperandScale::kSingle);
192 BytecodeNode second(Bytecode::kLdar, Register(0).ToOperand(), 208 BytecodeNode second(Bytecode::kLdar, Register(0).ToOperand(),
193 OperandScale::kSingle); 209 OperandScale::kSingle);
194 optimizer()->Write(&first); 210 optimizer()->Write(&first);
195 CHECK_EQ(write_count(), 0); 211 CHECK_EQ(write_count(), 0);
196 optimizer()->FlushForOffset(); // Prevent CanElideLast removing |first|.
197 optimizer()->Write(&second); 212 optimizer()->Write(&second);
198 CHECK_EQ(write_count(), 1); 213 CHECK_EQ(write_count(), 1);
199 CHECK_EQ(last_written(), first); 214 CHECK_EQ(last_written(), first);
200 optimizer()->FlushBasicBlock(); 215 Flush();
201 CHECK_EQ(write_count(), 1); 216 CHECK_EQ(write_count(), 1);
202 } 217 }
203 218
204 TEST_F(BytecodePeepholeOptimizerTest, LdarRxLdarRxStatement) { 219 TEST_F(BytecodePeepholeOptimizerTest, StarRxLdarRxStatement) {
205 BytecodeNode first(Bytecode::kLdar, Register(0).ToOperand(), 220 BytecodeNode first(Bytecode::kStar, Register(0).ToOperand(),
206 OperandScale::kSingle); 221 OperandScale::kSingle);
207 BytecodeNode second(Bytecode::kLdar, Register(0).ToOperand(), 222 BytecodeNode second(Bytecode::kLdar, Register(0).ToOperand(),
208 OperandScale::kSingle); 223 OperandScale::kSingle);
209 second.source_info().Update({0, true}); 224 second.source_info().Update({0, true});
210 optimizer()->Write(&first); 225 optimizer()->Write(&first);
211 CHECK_EQ(write_count(), 0); 226 CHECK_EQ(write_count(), 0);
212 optimizer()->FlushForOffset(); // Prevent CanElideLast removing |first|.
213 optimizer()->Write(&second); 227 optimizer()->Write(&second);
214 CHECK_EQ(write_count(), 1); 228 CHECK_EQ(write_count(), 1);
215 CHECK_EQ(last_written(), first); 229 CHECK_EQ(last_written(), first);
216 optimizer()->FlushBasicBlock(); 230 Flush();
217 CHECK_EQ(write_count(), 2); 231 CHECK_EQ(write_count(), 2);
218 CHECK_EQ(last_written().bytecode(), Bytecode::kNop); 232 CHECK_EQ(last_written().bytecode(), Bytecode::kNop);
219 CHECK_EQ(last_written().source_info(), second.source_info()); 233 CHECK_EQ(last_written().source_info(), second.source_info());
220 } 234 }
221 235
222 TEST_F(BytecodePeepholeOptimizerTest, LdarRxLdarRxStatementStarRy) { 236 TEST_F(BytecodePeepholeOptimizerTest, StarRxLdarRxStatementStarRy) {
223 BytecodeNode first(Bytecode::kLdar, Register(0).ToOperand(), 237 BytecodeLabel label;
238 BytecodeNode first(Bytecode::kStar, Register(0).ToOperand(),
224 OperandScale::kSingle); 239 OperandScale::kSingle);
225 BytecodeNode second(Bytecode::kLdar, Register(0).ToOperand(), 240 BytecodeNode second(Bytecode::kLdar, Register(0).ToOperand(),
226 OperandScale::kSingle); 241 OperandScale::kSingle);
227 BytecodeNode third(Bytecode::kStar, Register(3).ToOperand(), 242 BytecodeNode third(Bytecode::kStar, Register(3).ToOperand(),
228 OperandScale::kSingle); 243 OperandScale::kSingle);
229 second.source_info().Update({0, true}); 244 second.source_info().Update({0, true});
230 optimizer()->Write(&first); 245 optimizer()->Write(&first);
231 CHECK_EQ(write_count(), 0); 246 CHECK_EQ(write_count(), 0);
232 optimizer()->FlushForOffset(); // Prevent CanElideLast removing |first|.
233 optimizer()->Write(&second); 247 optimizer()->Write(&second);
234 CHECK_EQ(write_count(), 1); 248 CHECK_EQ(write_count(), 1);
235 CHECK_EQ(last_written(), first); 249 CHECK_EQ(last_written(), first);
236 optimizer()->Write(&third); 250 optimizer()->Write(&third);
237 CHECK_EQ(write_count(), 1); 251 CHECK_EQ(write_count(), 1);
238 optimizer()->FlushBasicBlock(); 252 Flush();
239 CHECK_EQ(write_count(), 2); 253 CHECK_EQ(write_count(), 2);
240 // Source position should move |second| to |third| when |second| is elided. 254 // Source position should move |second| to |third| when |second| is elided.
241 third.source_info().Update(second.source_info()); 255 third.source_info().Update(second.source_info());
242 CHECK_EQ(last_written(), third); 256 CHECK_EQ(last_written(), third);
243 } 257 }
244 258
245 TEST_F(BytecodePeepholeOptimizerTest, LdarToName) { 259 TEST_F(BytecodePeepholeOptimizerTest, LdarToName) {
246 BytecodeNode first(Bytecode::kLdar, Register(0).ToOperand(), 260 BytecodeNode first(Bytecode::kLdar, Register(0).ToOperand(),
247 OperandScale::kSingle); 261 OperandScale::kSingle);
248 BytecodeNode second(Bytecode::kToName); 262 BytecodeNode second(Bytecode::kToName);
249 optimizer()->Write(&first); 263 optimizer()->Write(&first);
250 CHECK_EQ(write_count(), 0); 264 CHECK_EQ(write_count(), 0);
251 optimizer()->Write(&second); 265 optimizer()->Write(&second);
252 CHECK_EQ(write_count(), 1); 266 CHECK_EQ(write_count(), 1);
253 CHECK_EQ(last_written(), first); 267 CHECK_EQ(last_written(), first);
254 optimizer()->FlushBasicBlock(); 268 Flush();
255 CHECK_EQ(write_count(), 2); 269 CHECK_EQ(write_count(), 2);
256 CHECK_EQ(last_written(), second); 270 CHECK_EQ(last_written(), second);
257 } 271 }
258 272
259 TEST_F(BytecodePeepholeOptimizerTest, ToNameToName) { 273 TEST_F(BytecodePeepholeOptimizerTest, ToNameToName) {
260 BytecodeNode first(Bytecode::kToName); 274 BytecodeNode first(Bytecode::kToName);
261 BytecodeNode second(Bytecode::kToName); 275 BytecodeNode second(Bytecode::kToName);
262 optimizer()->Write(&first); 276 optimizer()->Write(&first);
263 CHECK_EQ(write_count(), 0); 277 CHECK_EQ(write_count(), 0);
264 optimizer()->Write(&second); 278 optimizer()->Write(&second);
265 CHECK_EQ(write_count(), 1); 279 CHECK_EQ(write_count(), 1);
266 CHECK_EQ(last_written(), first); 280 CHECK_EQ(last_written(), first);
267 optimizer()->FlushBasicBlock(); 281 Flush();
268 CHECK_EQ(write_count(), 1); 282 CHECK_EQ(write_count(), 1);
269 } 283 }
270 284
271 TEST_F(BytecodePeepholeOptimizerTest, TypeOfToName) { 285 TEST_F(BytecodePeepholeOptimizerTest, TypeOfToName) {
272 BytecodeNode first(Bytecode::kTypeOf); 286 BytecodeNode first(Bytecode::kTypeOf);
273 BytecodeNode second(Bytecode::kToName); 287 BytecodeNode second(Bytecode::kToName);
274 optimizer()->Write(&first); 288 optimizer()->Write(&first);
275 CHECK_EQ(write_count(), 0); 289 CHECK_EQ(write_count(), 0);
276 optimizer()->Write(&second); 290 optimizer()->Write(&second);
277 CHECK_EQ(write_count(), 1); 291 CHECK_EQ(write_count(), 1);
278 CHECK_EQ(last_written(), first); 292 CHECK_EQ(last_written(), first);
279 optimizer()->FlushBasicBlock(); 293 Flush();
280 CHECK_EQ(write_count(), 1); 294 CHECK_EQ(write_count(), 1);
281 } 295 }
282 296
283 TEST_F(BytecodePeepholeOptimizerTest, LdaConstantStringToName) { 297 TEST_F(BytecodePeepholeOptimizerTest, LdaConstantStringToName) {
284 Handle<Object> word = 298 Handle<Object> word =
285 isolate()->factory()->NewStringFromStaticChars("optimizing"); 299 isolate()->factory()->NewStringFromStaticChars("optimizing");
286 size_t index = constant_array()->Insert(word); 300 size_t index = constant_array()->Insert(word);
287 BytecodeNode first(Bytecode::kLdaConstant, static_cast<uint32_t>(index), 301 BytecodeNode first(Bytecode::kLdaConstant, static_cast<uint32_t>(index),
288 OperandScale::kSingle); 302 OperandScale::kSingle);
289 BytecodeNode second(Bytecode::kToName); 303 BytecodeNode second(Bytecode::kToName);
290 optimizer()->Write(&first); 304 optimizer()->Write(&first);
291 CHECK_EQ(write_count(), 0); 305 CHECK_EQ(write_count(), 0);
292 optimizer()->Write(&second); 306 optimizer()->Write(&second);
293 CHECK_EQ(write_count(), 1); 307 CHECK_EQ(write_count(), 1);
294 CHECK_EQ(last_written(), first); 308 CHECK_EQ(last_written(), first);
295 optimizer()->FlushBasicBlock(); 309 Flush();
296 CHECK_EQ(write_count(), 1); 310 CHECK_EQ(write_count(), 1);
297 } 311 }
298 312
299 TEST_F(BytecodePeepholeOptimizerTest, LdaConstantNumberToName) { 313 TEST_F(BytecodePeepholeOptimizerTest, LdaConstantNumberToName) {
300 Handle<Object> word = isolate()->factory()->NewNumber(0.380); 314 Handle<Object> word = isolate()->factory()->NewNumber(0.380);
301 size_t index = constant_array()->Insert(word); 315 size_t index = constant_array()->Insert(word);
302 BytecodeNode first(Bytecode::kLdaConstant, static_cast<uint32_t>(index), 316 BytecodeNode first(Bytecode::kLdaConstant, static_cast<uint32_t>(index),
303 OperandScale::kSingle); 317 OperandScale::kSingle);
304 BytecodeNode second(Bytecode::kToName); 318 BytecodeNode second(Bytecode::kToName);
305 optimizer()->Write(&first); 319 optimizer()->Write(&first);
306 CHECK_EQ(write_count(), 0); 320 CHECK_EQ(write_count(), 0);
307 optimizer()->Write(&second); 321 optimizer()->Write(&second);
308 CHECK_EQ(write_count(), 1); 322 CHECK_EQ(write_count(), 1);
309 CHECK_EQ(last_written(), first); 323 CHECK_EQ(last_written(), first);
310 optimizer()->FlushBasicBlock(); 324 Flush();
311 CHECK_EQ(write_count(), 2); 325 CHECK_EQ(write_count(), 2);
312 CHECK_EQ(last_written(), second); 326 CHECK_EQ(last_written(), second);
313 } 327 }
314 328
315 // Tests covering BytecodePeepholeOptimizer::CanElideLast(). 329 // Tests covering BytecodePeepholeOptimizer::CanElideLast().
316 330
317 TEST_F(BytecodePeepholeOptimizerTest, LdaTrueLdaFalseNotDiscardable) {
318 BytecodeNode first(Bytecode::kLdaTrue);
319 BytecodeNode second(Bytecode::kLdaFalse);
320 optimizer()->Write(&first);
321 optimizer()->FlushForOffset(); // Prevent discarding of |first|.
322 CHECK_EQ(write_count(), 0);
323 optimizer()->Write(&second);
324 CHECK_EQ(write_count(), 1);
325 CHECK_EQ(last_written(), first);
326 optimizer()->FlushBasicBlock();
327 CHECK_EQ(write_count(), 2);
328 CHECK_EQ(last_written(), second);
329 }
330
331 TEST_F(BytecodePeepholeOptimizerTest, LdaTrueLdaFalse) { 331 TEST_F(BytecodePeepholeOptimizerTest, LdaTrueLdaFalse) {
332 BytecodeNode first(Bytecode::kLdaTrue); 332 BytecodeNode first(Bytecode::kLdaTrue);
333 BytecodeNode second(Bytecode::kLdaFalse); 333 BytecodeNode second(Bytecode::kLdaFalse);
334 optimizer()->Write(&first); 334 optimizer()->Write(&first);
335 CHECK_EQ(write_count(), 0); 335 CHECK_EQ(write_count(), 0);
336 optimizer()->Write(&second); 336 optimizer()->Write(&second);
337 CHECK_EQ(write_count(), 0); 337 CHECK_EQ(write_count(), 0);
338 optimizer()->FlushBasicBlock(); 338 Flush();
339 CHECK_EQ(write_count(), 1); 339 CHECK_EQ(write_count(), 1);
340 CHECK_EQ(last_written(), second); 340 CHECK_EQ(last_written(), second);
341 } 341 }
342 342
343 TEST_F(BytecodePeepholeOptimizerTest, LdaTrueStatementLdaFalse) { 343 TEST_F(BytecodePeepholeOptimizerTest, LdaTrueStatementLdaFalse) {
344 BytecodeNode first(Bytecode::kLdaTrue); 344 BytecodeNode first(Bytecode::kLdaTrue);
345 first.source_info().Update({3, false}); 345 first.source_info().Update({3, false});
346 BytecodeNode second(Bytecode::kLdaFalse); 346 BytecodeNode second(Bytecode::kLdaFalse);
347 optimizer()->Write(&first); 347 optimizer()->Write(&first);
348 CHECK_EQ(write_count(), 0); 348 CHECK_EQ(write_count(), 0);
349 optimizer()->Write(&second); 349 optimizer()->Write(&second);
350 CHECK_EQ(write_count(), 0); 350 CHECK_EQ(write_count(), 0);
351 optimizer()->FlushBasicBlock(); 351 Flush();
352 CHECK_EQ(write_count(), 1); 352 CHECK_EQ(write_count(), 1);
353 second.source_info().Update(first.source_info()); 353 second.source_info().Update(first.source_info());
354 CHECK_EQ(last_written(), second); 354 CHECK_EQ(last_written(), second);
355 } 355 }
356 356
357 TEST_F(BytecodePeepholeOptimizerTest, NopStackCheck) { 357 TEST_F(BytecodePeepholeOptimizerTest, NopStackCheck) {
358 BytecodeNode first(Bytecode::kNop); 358 BytecodeNode first(Bytecode::kNop);
359 BytecodeNode second(Bytecode::kStackCheck); 359 BytecodeNode second(Bytecode::kStackCheck);
360 optimizer()->Write(&first); 360 optimizer()->Write(&first);
361 CHECK_EQ(write_count(), 0); 361 CHECK_EQ(write_count(), 0);
362 optimizer()->Write(&second); 362 optimizer()->Write(&second);
363 CHECK_EQ(write_count(), 0); 363 CHECK_EQ(write_count(), 0);
364 optimizer()->FlushBasicBlock(); 364 Flush();
365 CHECK_EQ(write_count(), 1); 365 CHECK_EQ(write_count(), 1);
366 CHECK_EQ(last_written(), second); 366 CHECK_EQ(last_written(), second);
367 } 367 }
368 368
369 TEST_F(BytecodePeepholeOptimizerTest, NopStatementStackCheck) { 369 TEST_F(BytecodePeepholeOptimizerTest, NopStatementStackCheck) {
370 BytecodeNode first(Bytecode::kNop); 370 BytecodeNode first(Bytecode::kNop);
371 first.source_info().Update({3, false}); 371 first.source_info().Update({3, false});
372 BytecodeNode second(Bytecode::kStackCheck); 372 BytecodeNode second(Bytecode::kStackCheck);
373 optimizer()->Write(&first); 373 optimizer()->Write(&first);
374 CHECK_EQ(write_count(), 0); 374 CHECK_EQ(write_count(), 0);
375 optimizer()->Write(&second); 375 optimizer()->Write(&second);
376 CHECK_EQ(write_count(), 0); 376 CHECK_EQ(write_count(), 0);
377 optimizer()->FlushBasicBlock(); 377 Flush();
378 CHECK_EQ(write_count(), 1); 378 CHECK_EQ(write_count(), 1);
379 second.source_info().Update(first.source_info()); 379 second.source_info().Update(first.source_info());
380 CHECK_EQ(last_written(), second); 380 CHECK_EQ(last_written(), second);
381 } 381 }
382 382
383 // Tests covering BytecodePeepholeOptimizer::UpdateLastAndCurrentBytecodes(). 383 // Tests covering BytecodePeepholeOptimizer::UpdateLastAndCurrentBytecodes().
384 384
385 TEST_F(BytecodePeepholeOptimizerTest, MergeLoadICStar) { 385 TEST_F(BytecodePeepholeOptimizerTest, MergeLoadICStar) {
386 const uint32_t operands[] = { 386 const uint32_t operands[] = {
387 static_cast<uint32_t>(Register(31).ToOperand()), 32, 33, 387 static_cast<uint32_t>(Register(31).ToOperand()), 32, 33,
(...skipping 11 matching lines...) Expand all
399 CHECK_EQ(last_written().operand_count(), expected_operand_count); 399 CHECK_EQ(last_written().operand_count(), expected_operand_count);
400 for (int i = 0; i < expected_operand_count; ++i) { 400 for (int i = 0; i < expected_operand_count; ++i) {
401 CHECK_EQ(last_written().operand(i), operands[i]); 401 CHECK_EQ(last_written().operand(i), operands[i]);
402 } 402 }
403 CHECK_EQ(last_written().operand_scale(), 403 CHECK_EQ(last_written().operand_scale(),
404 std::max(first.operand_scale(), second.operand_scale())); 404 std::max(first.operand_scale(), second.operand_scale()));
405 optimizer()->Write(&third); 405 optimizer()->Write(&third);
406 CHECK_EQ(write_count(), 2); 406 CHECK_EQ(write_count(), 2);
407 CHECK_EQ(last_written().bytecode(), Bytecode::kLdar); 407 CHECK_EQ(last_written().bytecode(), Bytecode::kLdar);
408 CHECK_EQ(last_written().operand(0), operands[expected_operand_count - 1]); 408 CHECK_EQ(last_written().operand(0), operands[expected_operand_count - 1]);
409 optimizer()->FlushBasicBlock(); 409 Flush();
410 CHECK_EQ(last_written().bytecode(), third.bytecode()); 410 CHECK_EQ(last_written().bytecode(), third.bytecode());
411 } 411 }
412 412
413 TEST_F(BytecodePeepholeOptimizerTest, MergeLdaKeyedPropertyStar) { 413 TEST_F(BytecodePeepholeOptimizerTest, MergeLdaKeyedPropertyStar) {
414 const uint32_t operands[] = {static_cast<uint32_t>(Register(31).ToOperand()), 414 const uint32_t operands[] = {static_cast<uint32_t>(Register(31).ToOperand()),
415 9999997, 415 9999997,
416 static_cast<uint32_t>(Register(1).ToOperand())}; 416 static_cast<uint32_t>(Register(1).ToOperand())};
417 const int expected_operand_count = static_cast<int>(arraysize(operands)); 417 const int expected_operand_count = static_cast<int>(arraysize(operands));
418 418
419 BytecodeNode first(Bytecode::kLdaKeyedProperty, operands[0], operands[1], 419 BytecodeNode first(Bytecode::kLdaKeyedProperty, operands[0], operands[1],
420 OperandScale::kQuadruple); 420 OperandScale::kQuadruple);
421 BytecodeNode second(Bytecode::kStar, operands[2], OperandScale::kSingle); 421 BytecodeNode second(Bytecode::kStar, operands[2], OperandScale::kSingle);
422 BytecodeNode third(Bytecode::kReturn); 422 BytecodeNode third(Bytecode::kReturn);
423 optimizer()->Write(&first); 423 optimizer()->Write(&first);
424 optimizer()->Write(&second); 424 optimizer()->Write(&second);
425 CHECK_EQ(write_count(), 1); 425 CHECK_EQ(write_count(), 1);
426 CHECK_EQ(last_written().bytecode(), Bytecode::kLdrKeyedProperty); 426 CHECK_EQ(last_written().bytecode(), Bytecode::kLdrKeyedProperty);
427 CHECK_EQ(last_written().operand_count(), expected_operand_count); 427 CHECK_EQ(last_written().operand_count(), expected_operand_count);
428 for (int i = 0; i < expected_operand_count; ++i) { 428 for (int i = 0; i < expected_operand_count; ++i) {
429 CHECK_EQ(last_written().operand(i), operands[i]); 429 CHECK_EQ(last_written().operand(i), operands[i]);
430 } 430 }
431 CHECK_EQ(last_written().operand_scale(), 431 CHECK_EQ(last_written().operand_scale(),
432 std::max(first.operand_scale(), second.operand_scale())); 432 std::max(first.operand_scale(), second.operand_scale()));
433 optimizer()->Write(&third); 433 optimizer()->Write(&third);
434 CHECK_EQ(write_count(), 2); 434 CHECK_EQ(write_count(), 2);
435 CHECK_EQ(last_written().bytecode(), Bytecode::kLdar); 435 CHECK_EQ(last_written().bytecode(), Bytecode::kLdar);
436 CHECK_EQ(last_written().operand(0), operands[expected_operand_count - 1]); 436 CHECK_EQ(last_written().operand(0), operands[expected_operand_count - 1]);
437 optimizer()->FlushBasicBlock(); 437 Flush();
438 CHECK_EQ(last_written().bytecode(), third.bytecode()); 438 CHECK_EQ(last_written().bytecode(), third.bytecode());
439 } 439 }
440 440
441 TEST_F(BytecodePeepholeOptimizerTest, MergeLdaGlobalStar) { 441 TEST_F(BytecodePeepholeOptimizerTest, MergeLdaGlobalStar) {
442 const uint32_t operands[] = {54321, 19191, 442 const uint32_t operands[] = {54321, 19191,
443 static_cast<uint32_t>(Register(1).ToOperand())}; 443 static_cast<uint32_t>(Register(1).ToOperand())};
444 const int expected_operand_count = static_cast<int>(arraysize(operands)); 444 const int expected_operand_count = static_cast<int>(arraysize(operands));
445 445
446 BytecodeNode first(Bytecode::kLdaGlobal, operands[0], operands[1], 446 BytecodeNode first(Bytecode::kLdaGlobal, operands[0], operands[1],
447 OperandScale::kDouble); 447 OperandScale::kDouble);
448 BytecodeNode second(Bytecode::kStar, operands[2], OperandScale::kSingle); 448 BytecodeNode second(Bytecode::kStar, operands[2], OperandScale::kSingle);
449 BytecodeNode third(Bytecode::kReturn); 449 BytecodeNode third(Bytecode::kReturn);
450 optimizer()->Write(&first); 450 optimizer()->Write(&first);
451 optimizer()->Write(&second); 451 optimizer()->Write(&second);
452 CHECK_EQ(write_count(), 1); 452 CHECK_EQ(write_count(), 1);
453 CHECK_EQ(last_written().bytecode(), Bytecode::kLdrGlobal); 453 CHECK_EQ(last_written().bytecode(), Bytecode::kLdrGlobal);
454 CHECK_EQ(last_written().operand_count(), expected_operand_count); 454 CHECK_EQ(last_written().operand_count(), expected_operand_count);
455 for (int i = 0; i < expected_operand_count; ++i) { 455 for (int i = 0; i < expected_operand_count; ++i) {
456 CHECK_EQ(last_written().operand(i), operands[i]); 456 CHECK_EQ(last_written().operand(i), operands[i]);
457 } 457 }
458 CHECK_EQ(last_written().operand_scale(), 458 CHECK_EQ(last_written().operand_scale(),
459 std::max(first.operand_scale(), second.operand_scale())); 459 std::max(first.operand_scale(), second.operand_scale()));
460 optimizer()->Write(&third); 460 optimizer()->Write(&third);
461 CHECK_EQ(write_count(), 2); 461 CHECK_EQ(write_count(), 2);
462 CHECK_EQ(last_written().bytecode(), Bytecode::kLdar); 462 CHECK_EQ(last_written().bytecode(), Bytecode::kLdar);
463 CHECK_EQ(last_written().operand(0), operands[expected_operand_count - 1]); 463 CHECK_EQ(last_written().operand(0), operands[expected_operand_count - 1]);
464 optimizer()->FlushBasicBlock(); 464 Flush();
465 CHECK_EQ(last_written().bytecode(), third.bytecode()); 465 CHECK_EQ(last_written().bytecode(), third.bytecode());
466 } 466 }
467 467
468 TEST_F(BytecodePeepholeOptimizerTest, MergeLdaContextSlotStar) { 468 TEST_F(BytecodePeepholeOptimizerTest, MergeLdaContextSlotStar) {
469 const uint32_t operands[] = { 469 const uint32_t operands[] = {
470 static_cast<uint32_t>(Register(200000).ToOperand()), 55005500, 470 static_cast<uint32_t>(Register(200000).ToOperand()), 55005500,
471 static_cast<uint32_t>(Register(1).ToOperand())}; 471 static_cast<uint32_t>(Register(1).ToOperand())};
472 const int expected_operand_count = static_cast<int>(arraysize(operands)); 472 const int expected_operand_count = static_cast<int>(arraysize(operands));
473 473
474 BytecodeNode first(Bytecode::kLdaContextSlot, operands[0], operands[1], 474 BytecodeNode first(Bytecode::kLdaContextSlot, operands[0], operands[1],
475 OperandScale::kQuadruple); 475 OperandScale::kQuadruple);
476 BytecodeNode second(Bytecode::kStar, operands[2], OperandScale::kSingle); 476 BytecodeNode second(Bytecode::kStar, operands[2], OperandScale::kSingle);
477 BytecodeNode third(Bytecode::kReturn); 477 BytecodeNode third(Bytecode::kReturn);
478 optimizer()->Write(&first); 478 optimizer()->Write(&first);
479 optimizer()->Write(&second); 479 optimizer()->Write(&second);
480 CHECK_EQ(write_count(), 1); 480 CHECK_EQ(write_count(), 1);
481 CHECK_EQ(last_written().bytecode(), Bytecode::kLdrContextSlot); 481 CHECK_EQ(last_written().bytecode(), Bytecode::kLdrContextSlot);
482 CHECK_EQ(last_written().operand_count(), expected_operand_count); 482 CHECK_EQ(last_written().operand_count(), expected_operand_count);
483 for (int i = 0; i < expected_operand_count; ++i) { 483 for (int i = 0; i < expected_operand_count; ++i) {
484 CHECK_EQ(last_written().operand(i), operands[i]); 484 CHECK_EQ(last_written().operand(i), operands[i]);
485 } 485 }
486 CHECK_EQ(last_written().operand_scale(), 486 CHECK_EQ(last_written().operand_scale(),
487 std::max(first.operand_scale(), second.operand_scale())); 487 std::max(first.operand_scale(), second.operand_scale()));
488 optimizer()->Write(&third); 488 optimizer()->Write(&third);
489 CHECK_EQ(write_count(), 2); 489 CHECK_EQ(write_count(), 2);
490 CHECK_EQ(last_written().bytecode(), Bytecode::kLdar); 490 CHECK_EQ(last_written().bytecode(), Bytecode::kLdar);
491 CHECK_EQ(last_written().operand(0), operands[expected_operand_count - 1]); 491 CHECK_EQ(last_written().operand(0), operands[expected_operand_count - 1]);
492 optimizer()->FlushBasicBlock(); 492 Flush();
493 CHECK_EQ(last_written().bytecode(), third.bytecode()); 493 CHECK_EQ(last_written().bytecode(), third.bytecode());
494 } 494 }
495 495
496 TEST_F(BytecodePeepholeOptimizerTest, MergeLdaUndefinedStar) { 496 TEST_F(BytecodePeepholeOptimizerTest, MergeLdaUndefinedStar) {
497 const uint32_t operands[] = { 497 const uint32_t operands[] = {
498 static_cast<uint32_t>(Register(100000).ToOperand())}; 498 static_cast<uint32_t>(Register(100000).ToOperand())};
499 const int expected_operand_count = static_cast<int>(arraysize(operands)); 499 const int expected_operand_count = static_cast<int>(arraysize(operands));
500 500
501 BytecodeNode first(Bytecode::kLdaUndefined); 501 BytecodeNode first(Bytecode::kLdaUndefined);
502 BytecodeNode second(Bytecode::kStar, operands[0], OperandScale::kQuadruple); 502 BytecodeNode second(Bytecode::kStar, operands[0], OperandScale::kQuadruple);
503 BytecodeNode third(Bytecode::kReturn); 503 BytecodeNode third(Bytecode::kReturn);
504 optimizer()->Write(&first); 504 optimizer()->Write(&first);
505 optimizer()->Write(&second); 505 optimizer()->Write(&second);
506 CHECK_EQ(write_count(), 1); 506 CHECK_EQ(write_count(), 1);
507 CHECK_EQ(last_written().bytecode(), Bytecode::kLdrUndefined); 507 CHECK_EQ(last_written().bytecode(), Bytecode::kLdrUndefined);
508 CHECK_EQ(last_written().operand_count(), expected_operand_count); 508 CHECK_EQ(last_written().operand_count(), expected_operand_count);
509 for (int i = 0; i < expected_operand_count; ++i) { 509 for (int i = 0; i < expected_operand_count; ++i) {
510 CHECK_EQ(last_written().operand(i), operands[i]); 510 CHECK_EQ(last_written().operand(i), operands[i]);
511 } 511 }
512 CHECK_EQ(last_written().operand_scale(), 512 CHECK_EQ(last_written().operand_scale(),
513 std::max(first.operand_scale(), second.operand_scale())); 513 std::max(first.operand_scale(), second.operand_scale()));
514 optimizer()->Write(&third); 514 optimizer()->Write(&third);
515 CHECK_EQ(write_count(), 2); 515 CHECK_EQ(write_count(), 2);
516 CHECK_EQ(last_written().bytecode(), Bytecode::kLdar); 516 CHECK_EQ(last_written().bytecode(), Bytecode::kLdar);
517 CHECK_EQ(last_written().operand(0), operands[expected_operand_count - 1]); 517 CHECK_EQ(last_written().operand(0), operands[expected_operand_count - 1]);
518 optimizer()->FlushBasicBlock(); 518 Flush();
519 CHECK_EQ(last_written().bytecode(), third.bytecode()); 519 CHECK_EQ(last_written().bytecode(), third.bytecode());
520 } 520 }
521 521
522 } // namespace interpreter 522 } // namespace interpreter
523 } // namespace internal 523 } // namespace internal
524 } // namespace v8 524 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698