OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 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/interpreter/bytecodes.h" | 5 #include "src/interpreter/bytecodes.h" |
6 | 6 |
7 #include <iomanip> | 7 #include <iomanip> |
8 | 8 |
9 #include "src/frames.h" | 9 #include "src/frames.h" |
10 #include "src/interpreter/bytecode-traits.h" | 10 #include "src/interpreter/bytecode-traits.h" |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
67 OPERAND_TYPE_LIST(CASE) | 67 OPERAND_TYPE_LIST(CASE) |
68 #undef CASE | 68 #undef CASE |
69 } | 69 } |
70 UNREACHABLE(); | 70 UNREACHABLE(); |
71 return ""; | 71 return ""; |
72 } | 72 } |
73 | 73 |
74 // static | 74 // static |
75 const char* Bytecodes::OperandScaleToString(OperandScale operand_scale) { | 75 const char* Bytecodes::OperandScaleToString(OperandScale operand_scale) { |
76 switch (operand_scale) { | 76 switch (operand_scale) { |
77 case OperandScale::kSingle: | 77 #define CASE(Name, _) \ |
78 return "Single"; | 78 case OperandScale::k##Name: \ |
79 case OperandScale::kDouble: | 79 return #Name; |
80 return "Double"; | 80 OPERAND_SCALE_LIST(CASE) |
81 case OperandScale::kQuadruple: | 81 #undef CASE |
82 return "Quadruple"; | |
83 case OperandScale::kInvalid: | |
84 UNREACHABLE(); | |
85 } | 82 } |
| 83 UNREACHABLE(); |
86 return ""; | 84 return ""; |
87 } | 85 } |
88 | 86 |
89 // static | 87 // static |
90 const char* Bytecodes::OperandSizeToString(OperandSize operand_size) { | 88 const char* Bytecodes::OperandSizeToString(OperandSize operand_size) { |
91 switch (operand_size) { | 89 switch (operand_size) { |
92 case OperandSize::kNone: | 90 case OperandSize::kNone: |
93 return "None"; | 91 return "None"; |
94 case OperandSize::kByte: | 92 case OperandSize::kByte: |
95 return "Byte"; | 93 return "Byte"; |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
234 AccumulatorUse::kRead; | 232 AccumulatorUse::kRead; |
235 } | 233 } |
236 | 234 |
237 // static | 235 // static |
238 bool Bytecodes::WritesAccumulator(Bytecode bytecode) { | 236 bool Bytecodes::WritesAccumulator(Bytecode bytecode) { |
239 return (GetAccumulatorUse(bytecode) & AccumulatorUse::kWrite) == | 237 return (GetAccumulatorUse(bytecode) & AccumulatorUse::kWrite) == |
240 AccumulatorUse::kWrite; | 238 AccumulatorUse::kWrite; |
241 } | 239 } |
242 | 240 |
243 // static | 241 // static |
| 242 bool Bytecodes::WritesAccumulatorWithBoolean(Bytecode bytecode) { |
| 243 switch (bytecode) { |
| 244 case Bytecode::kLdaTrue: |
| 245 case Bytecode::kLdaFalse: |
| 246 case Bytecode::kLogicalNot: |
| 247 case Bytecode::kTestEqual: |
| 248 case Bytecode::kTestNotEqual: |
| 249 case Bytecode::kTestEqualStrict: |
| 250 case Bytecode::kTestLessThan: |
| 251 case Bytecode::kTestLessThanOrEqual: |
| 252 case Bytecode::kTestGreaterThan: |
| 253 case Bytecode::kTestGreaterThanOrEqual: |
| 254 case Bytecode::kTestInstanceOf: |
| 255 case Bytecode::kTestIn: |
| 256 case Bytecode::kForInDone: |
| 257 return true; |
| 258 default: |
| 259 return false; |
| 260 } |
| 261 } |
| 262 |
| 263 // static |
| 264 bool Bytecodes::IsAccumulatorLoadWithoutEffects(Bytecode bytecode) { |
| 265 switch (bytecode) { |
| 266 case Bytecode::kLdaZero: |
| 267 case Bytecode::kLdaSmi: |
| 268 case Bytecode::kLdaUndefined: |
| 269 case Bytecode::kLdaNull: |
| 270 case Bytecode::kLdaTheHole: |
| 271 case Bytecode::kLdaTrue: |
| 272 case Bytecode::kLdaFalse: |
| 273 case Bytecode::kLdaConstant: |
| 274 case Bytecode::kLdar: |
| 275 return true; |
| 276 default: |
| 277 return false; |
| 278 } |
| 279 } |
| 280 |
| 281 // static |
244 OperandType Bytecodes::GetOperandType(Bytecode bytecode, int i) { | 282 OperandType Bytecodes::GetOperandType(Bytecode bytecode, int i) { |
| 283 DCHECK_LE(bytecode, Bytecode::kLast); |
| 284 DCHECK_LT(i, NumberOfOperands(bytecode)); |
| 285 DCHECK_GE(i, 0); |
| 286 return GetOperandTypes(bytecode)[i]; |
| 287 } |
| 288 |
| 289 // static |
| 290 const OperandType* Bytecodes::GetOperandTypes(Bytecode bytecode) { |
245 DCHECK(bytecode <= Bytecode::kLast); | 291 DCHECK(bytecode <= Bytecode::kLast); |
246 switch (bytecode) { | 292 switch (bytecode) { |
247 #define CASE(Name, ...) \ | 293 #define CASE(Name, ...) \ |
248 case Bytecode::k##Name: \ | 294 case Bytecode::k##Name: \ |
249 return BytecodeTraits<__VA_ARGS__>::GetOperandType(i); | 295 return BytecodeTraits<__VA_ARGS__>::GetOperandTypes(); |
250 BYTECODE_LIST(CASE) | 296 BYTECODE_LIST(CASE) |
251 #undef CASE | 297 #undef CASE |
252 } | 298 } |
253 UNREACHABLE(); | 299 UNREACHABLE(); |
254 return OperandType::kNone; | 300 return nullptr; |
255 } | 301 } |
256 | 302 |
257 // static | 303 // static |
258 OperandSize Bytecodes::GetOperandSize(Bytecode bytecode, int i, | 304 OperandSize Bytecodes::GetOperandSize(Bytecode bytecode, int i, |
259 OperandScale operand_scale) { | 305 OperandScale operand_scale) { |
260 OperandType op_type = GetOperandType(bytecode, i); | 306 DCHECK(bytecode <= Bytecode::kLast); |
261 return ScaledOperandSize(op_type, operand_scale); | 307 switch (bytecode) { |
| 308 #define CASE(Name, ...) \ |
| 309 case Bytecode::k##Name: \ |
| 310 return BytecodeTraits<__VA_ARGS__>::GetOperandSize(i, operand_scale); |
| 311 BYTECODE_LIST(CASE) |
| 312 #undef CASE |
| 313 } |
| 314 UNREACHABLE(); |
| 315 return OperandSize::kNone; |
262 } | 316 } |
263 | 317 |
264 // static | 318 // static |
265 int Bytecodes::GetRegisterOperandBitmap(Bytecode bytecode) { | 319 int Bytecodes::GetRegisterOperandBitmap(Bytecode bytecode) { |
266 DCHECK(bytecode <= Bytecode::kLast); | 320 DCHECK(bytecode <= Bytecode::kLast); |
267 switch (bytecode) { | 321 switch (bytecode) { |
268 #define CASE(Name, ...) \ | 322 #define CASE(Name, ...) \ |
269 case Bytecode::k##Name: \ | 323 case Bytecode::k##Name: \ |
270 typedef BytecodeTraits<__VA_ARGS__> Name##Trait; \ | 324 typedef BytecodeTraits<__VA_ARGS__> Name##Trait; \ |
271 return Name##Trait::kRegisterOperandBitmap; | 325 return Name##Trait::kRegisterOperandBitmap; |
272 BYTECODE_LIST(CASE) | 326 BYTECODE_LIST(CASE) |
273 #undef CASE | 327 #undef CASE |
274 } | 328 } |
275 UNREACHABLE(); | 329 UNREACHABLE(); |
276 return false; | 330 return false; |
277 } | 331 } |
278 | 332 |
279 // static | 333 // static |
280 int Bytecodes::GetOperandOffset(Bytecode bytecode, int i, | 334 int Bytecodes::GetOperandOffset(Bytecode bytecode, int i, |
281 OperandScale operand_scale) { | 335 OperandScale operand_scale) { |
| 336 DCHECK_LT(i, Bytecodes::NumberOfOperands(bytecode)); |
282 // TODO(oth): restore this to a statically determined constant. | 337 // TODO(oth): restore this to a statically determined constant. |
283 int offset = 1; | 338 int offset = 1; |
284 for (int operand_index = 0; operand_index < i; ++operand_index) { | 339 for (int operand_index = 0; operand_index < i; ++operand_index) { |
285 OperandSize operand_size = | 340 OperandSize operand_size = |
286 GetOperandSize(bytecode, operand_index, operand_scale); | 341 GetOperandSize(bytecode, operand_index, operand_scale); |
287 offset += static_cast<int>(operand_size); | 342 offset += static_cast<int>(operand_size); |
288 } | 343 } |
289 return offset; | 344 return offset; |
290 } | 345 } |
291 | 346 |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
336 bool Bytecodes::IsJumpConstant(Bytecode bytecode) { | 391 bool Bytecodes::IsJumpConstant(Bytecode bytecode) { |
337 return bytecode == Bytecode::kJumpConstant || | 392 return bytecode == Bytecode::kJumpConstant || |
338 IsConditionalJumpConstant(bytecode); | 393 IsConditionalJumpConstant(bytecode); |
339 } | 394 } |
340 | 395 |
341 // static | 396 // static |
342 bool Bytecodes::IsJump(Bytecode bytecode) { | 397 bool Bytecodes::IsJump(Bytecode bytecode) { |
343 return IsJumpImmediate(bytecode) || IsJumpConstant(bytecode); | 398 return IsJumpImmediate(bytecode) || IsJumpConstant(bytecode); |
344 } | 399 } |
345 | 400 |
| 401 // static |
| 402 bool Bytecodes::IsJumpIfToBoolean(Bytecode bytecode) { |
| 403 return bytecode == Bytecode::kJumpIfToBooleanTrue || |
| 404 bytecode == Bytecode::kJumpIfToBooleanFalse || |
| 405 bytecode == Bytecode::kJumpIfToBooleanTrueConstant || |
| 406 bytecode == Bytecode::kJumpIfToBooleanFalseConstant; |
| 407 } |
| 408 |
| 409 // static |
| 410 Bytecode Bytecodes::GetJumpWithoutToBoolean(Bytecode bytecode) { |
| 411 switch (bytecode) { |
| 412 case Bytecode::kJumpIfToBooleanTrue: |
| 413 return Bytecode::kJumpIfTrue; |
| 414 case Bytecode::kJumpIfToBooleanFalse: |
| 415 return Bytecode::kJumpIfFalse; |
| 416 case Bytecode::kJumpIfToBooleanTrueConstant: |
| 417 return Bytecode::kJumpIfTrueConstant; |
| 418 case Bytecode::kJumpIfToBooleanFalseConstant: |
| 419 return Bytecode::kJumpIfFalseConstant; |
| 420 default: |
| 421 break; |
| 422 } |
| 423 UNREACHABLE(); |
| 424 return Bytecode::kIllegal; |
| 425 } |
346 | 426 |
347 // static | 427 // static |
348 bool Bytecodes::IsCallOrNew(Bytecode bytecode) { | 428 bool Bytecodes::IsCallOrNew(Bytecode bytecode) { |
349 return bytecode == Bytecode::kCall || bytecode == Bytecode::kTailCall || | 429 return bytecode == Bytecode::kCall || bytecode == Bytecode::kTailCall || |
350 bytecode == Bytecode::kNew; | 430 bytecode == Bytecode::kNew; |
351 } | 431 } |
352 | 432 |
353 // static | 433 // static |
354 bool Bytecodes::IsCallRuntime(Bytecode bytecode) { | 434 bool Bytecodes::IsCallRuntime(Bytecode bytecode) { |
355 return bytecode == Bytecode::kCallRuntime || | 435 return bytecode == Bytecode::kCallRuntime || |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
454 case OperandType::k##Name: \ | 534 case OperandType::k##Name: \ |
455 break; | 535 break; |
456 NON_REGISTER_OPERAND_TYPE_LIST(CASE) | 536 NON_REGISTER_OPERAND_TYPE_LIST(CASE) |
457 REGISTER_INPUT_OPERAND_TYPE_LIST(CASE) | 537 REGISTER_INPUT_OPERAND_TYPE_LIST(CASE) |
458 #undef CASE | 538 #undef CASE |
459 } | 539 } |
460 return false; | 540 return false; |
461 } | 541 } |
462 | 542 |
463 // static | 543 // static |
| 544 int Bytecodes::GetNumberOfRegistersRepresentedBy(OperandType operand_type) { |
| 545 switch (operand_type) { |
| 546 case OperandType::kMaybeReg: |
| 547 case OperandType::kReg: |
| 548 case OperandType::kRegOut: |
| 549 return 1; |
| 550 case OperandType::kRegPair: |
| 551 case OperandType::kRegOutPair: |
| 552 return 2; |
| 553 case OperandType::kRegOutTriple: |
| 554 return 3; |
| 555 default: |
| 556 UNREACHABLE(); |
| 557 } |
| 558 return 0; |
| 559 } |
| 560 |
| 561 // static |
464 bool Bytecodes::IsUnsignedOperandType(OperandType operand_type) { | 562 bool Bytecodes::IsUnsignedOperandType(OperandType operand_type) { |
465 switch (operand_type) { | 563 switch (operand_type) { |
466 #define CASE(Name, _) \ | 564 #define CASE(Name, _) \ |
467 case OperandType::k##Name: \ | 565 case OperandType::k##Name: \ |
468 return OperandTraits<OperandType::k##Name>::TypeInfo::kIsUnsigned; | 566 return OperandTraits<OperandType::k##Name>::TypeInfo::kIsUnsigned; |
469 OPERAND_TYPE_LIST(CASE) | 567 OPERAND_TYPE_LIST(CASE) |
470 #undef CASE | 568 #undef CASE |
471 } | 569 } |
472 UNREACHABLE(); | 570 UNREACHABLE(); |
473 return false; | 571 return false; |
474 } | 572 } |
475 | 573 |
476 // static | 574 // static |
477 OperandScale Bytecodes::NextOperandScale(OperandScale operand_scale) { | 575 OperandSize Bytecodes::SizeForSignedOperand(int value) { |
478 DCHECK(operand_scale >= OperandScale::kSingle && | 576 if (kMinInt8 <= value && value <= kMaxInt8) { |
479 operand_scale <= OperandScale::kMaxValid); | 577 return OperandSize::kByte; |
480 return static_cast<OperandScale>(2 * static_cast<int>(operand_scale)); | 578 } else if (kMinInt16 <= value && value <= kMaxInt16) { |
| 579 return OperandSize::kShort; |
| 580 } else { |
| 581 return OperandSize::kQuad; |
| 582 } |
481 } | 583 } |
482 | 584 |
483 // static | 585 // static |
| 586 OperandSize Bytecodes::SizeForUnsignedOperand(int value) { |
| 587 DCHECK_GE(value, 0); |
| 588 if (value <= kMaxUInt8) { |
| 589 return OperandSize::kByte; |
| 590 } else if (value <= kMaxUInt16) { |
| 591 return OperandSize::kShort; |
| 592 } else { |
| 593 return OperandSize::kQuad; |
| 594 } |
| 595 } |
| 596 |
| 597 OperandSize Bytecodes::SizeForUnsignedOperand(size_t value) { |
| 598 if (value <= static_cast<size_t>(kMaxUInt8)) { |
| 599 return OperandSize::kByte; |
| 600 } else if (value <= static_cast<size_t>(kMaxUInt16)) { |
| 601 return OperandSize::kShort; |
| 602 } else if (value <= kMaxUInt32) { |
| 603 return OperandSize::kQuad; |
| 604 } else { |
| 605 UNREACHABLE(); |
| 606 return OperandSize::kQuad; |
| 607 } |
| 608 } |
| 609 |
| 610 OperandScale Bytecodes::OperandSizesToScale(OperandSize size0, |
| 611 OperandSize size1, |
| 612 OperandSize size2, |
| 613 OperandSize size3) { |
| 614 OperandSize upper = std::max(size0, size1); |
| 615 OperandSize lower = std::max(size2, size3); |
| 616 OperandSize result = std::max(upper, lower); |
| 617 // Operand sizes have been scaled before calling this function. |
| 618 // Currently all scalable operands are byte sized at |
| 619 // OperandScale::kSingle. |
| 620 STATIC_ASSERT(static_cast<int>(OperandSize::kByte) == |
| 621 static_cast<int>(OperandScale::kSingle) && |
| 622 static_cast<int>(OperandSize::kShort) == |
| 623 static_cast<int>(OperandScale::kDouble) && |
| 624 static_cast<int>(OperandSize::kQuad) == |
| 625 static_cast<int>(OperandScale::kQuadruple)); |
| 626 OperandScale operand_scale = static_cast<OperandScale>(result); |
| 627 DCHECK(operand_scale == OperandScale::kSingle || |
| 628 operand_scale == OperandScale::kDouble || |
| 629 operand_scale == OperandScale::kQuadruple); |
| 630 return operand_scale; |
| 631 } |
| 632 |
| 633 // static |
484 Register Bytecodes::DecodeRegisterOperand(const uint8_t* operand_start, | 634 Register Bytecodes::DecodeRegisterOperand(const uint8_t* operand_start, |
485 OperandType operand_type, | 635 OperandType operand_type, |
486 OperandScale operand_scale) { | 636 OperandScale operand_scale) { |
487 DCHECK(Bytecodes::IsRegisterOperandType(operand_type)); | 637 DCHECK(Bytecodes::IsRegisterOperandType(operand_type)); |
488 int32_t operand = | 638 int32_t operand = |
489 DecodeSignedOperand(operand_start, operand_type, operand_scale); | 639 DecodeSignedOperand(operand_start, operand_type, operand_scale); |
490 return Register::FromOperand(operand); | 640 return Register::FromOperand(operand); |
491 } | 641 } |
492 | 642 |
493 // static | 643 // static |
(...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
767 } else { | 917 } else { |
768 std::ostringstream s; | 918 std::ostringstream s; |
769 s << "r" << index(); | 919 s << "r" << index(); |
770 return s.str(); | 920 return s.str(); |
771 } | 921 } |
772 } | 922 } |
773 | 923 |
774 } // namespace interpreter | 924 } // namespace interpreter |
775 } // namespace internal | 925 } // namespace internal |
776 } // namespace v8 | 926 } // namespace v8 |
OLD | NEW |