| 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 |