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-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 Loading... |
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 |
OLD | NEW |