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 #ifndef V8_INTERPRETER_BYTECODES_H_ | 5 #ifndef V8_INTERPRETER_BYTECODES_H_ |
6 #define V8_INTERPRETER_BYTECODES_H_ | 6 #define V8_INTERPRETER_BYTECODES_H_ |
7 | 7 |
8 #include <iosfwd> | 8 #include <iosfwd> |
9 | 9 |
10 // Clients of this interface shouldn't depend on lots of interpreter internals. | 10 // Clients of this interface shouldn't depend on lots of interpreter internals. |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
91 /* Globals */ \ | 91 /* Globals */ \ |
92 V(LdaGlobal, AccumulatorUse::kWrite, OperandType::kIdx, OperandType::kIdx) \ | 92 V(LdaGlobal, AccumulatorUse::kWrite, OperandType::kIdx, OperandType::kIdx) \ |
93 V(LdaGlobalInsideTypeof, AccumulatorUse::kWrite, OperandType::kIdx, \ | 93 V(LdaGlobalInsideTypeof, AccumulatorUse::kWrite, OperandType::kIdx, \ |
94 OperandType::kIdx) \ | 94 OperandType::kIdx) \ |
95 V(StaGlobalSloppy, AccumulatorUse::kRead, OperandType::kIdx, \ | 95 V(StaGlobalSloppy, AccumulatorUse::kRead, OperandType::kIdx, \ |
96 OperandType::kIdx) \ | 96 OperandType::kIdx) \ |
97 V(StaGlobalStrict, AccumulatorUse::kRead, OperandType::kIdx, \ | 97 V(StaGlobalStrict, AccumulatorUse::kRead, OperandType::kIdx, \ |
98 OperandType::kIdx) \ | 98 OperandType::kIdx) \ |
99 \ | 99 \ |
100 /* Context operations */ \ | 100 /* Context operations */ \ |
101 V(PushContext, AccumulatorUse::kRead, OperandType::kReg) \ | 101 V(PushContext, AccumulatorUse::kRead, OperandType::kRegOut) \ |
102 V(PopContext, AccumulatorUse::kNone, OperandType::kReg) \ | 102 V(PopContext, AccumulatorUse::kNone, OperandType::kReg) \ |
103 V(LdaContextSlot, AccumulatorUse::kWrite, OperandType::kReg, \ | 103 V(LdaContextSlot, AccumulatorUse::kWrite, OperandType::kReg, \ |
104 OperandType::kIdx) \ | 104 OperandType::kIdx) \ |
105 V(StaContextSlot, AccumulatorUse::kRead, OperandType::kReg, \ | 105 V(StaContextSlot, AccumulatorUse::kRead, OperandType::kReg, \ |
106 OperandType::kIdx) \ | 106 OperandType::kIdx) \ |
107 \ | 107 \ |
108 /* Load-Store lookup slots */ \ | 108 /* Load-Store lookup slots */ \ |
109 V(LdaLookupSlot, AccumulatorUse::kWrite, OperandType::kIdx) \ | 109 V(LdaLookupSlot, AccumulatorUse::kWrite, OperandType::kIdx) \ |
110 V(LdaLookupSlotInsideTypeof, AccumulatorUse::kWrite, OperandType::kIdx) \ | 110 V(LdaLookupSlotInsideTypeof, AccumulatorUse::kWrite, OperandType::kIdx) \ |
111 V(StaLookupSlotSloppy, AccumulatorUse::kReadWrite, OperandType::kIdx) \ | 111 V(StaLookupSlotSloppy, AccumulatorUse::kReadWrite, OperandType::kIdx) \ |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
243 \ | 243 \ |
244 /* Generators */ \ | 244 /* Generators */ \ |
245 V(SuspendGenerator, AccumulatorUse::kRead, OperandType::kReg) \ | 245 V(SuspendGenerator, AccumulatorUse::kRead, OperandType::kReg) \ |
246 V(ResumeGenerator, AccumulatorUse::kWrite, OperandType::kReg) \ | 246 V(ResumeGenerator, AccumulatorUse::kWrite, OperandType::kReg) \ |
247 \ | 247 \ |
248 /* Debugger */ \ | 248 /* Debugger */ \ |
249 V(Debugger, AccumulatorUse::kNone) \ | 249 V(Debugger, AccumulatorUse::kNone) \ |
250 DEBUG_BREAK_BYTECODE_LIST(V) \ | 250 DEBUG_BREAK_BYTECODE_LIST(V) \ |
251 \ | 251 \ |
252 /* Illegal bytecode (terminates execution) */ \ | 252 /* Illegal bytecode (terminates execution) */ \ |
253 V(Illegal, AccumulatorUse::kNone) | 253 V(Illegal, AccumulatorUse::kNone) \ |
| 254 \ |
| 255 /* No operation (used to maintain source positions for peephole */ \ |
| 256 /* eliminated bytecodes). */ \ |
| 257 V(Nop, AccumulatorUse::kNone) |
254 | 258 |
255 enum class AccumulatorUse : uint8_t { | 259 enum class AccumulatorUse : uint8_t { |
256 kNone = 0, | 260 kNone = 0, |
257 kRead = 1 << 0, | 261 kRead = 1 << 0, |
258 kWrite = 1 << 1, | 262 kWrite = 1 << 1, |
259 kReadWrite = kRead | kWrite | 263 kReadWrite = kRead | kWrite |
260 }; | 264 }; |
261 | 265 |
262 V8_INLINE AccumulatorUse operator&(AccumulatorUse lhs, AccumulatorUse rhs) { | 266 V8_INLINE AccumulatorUse operator&(AccumulatorUse lhs, AccumulatorUse rhs) { |
263 int result = static_cast<int>(lhs) & static_cast<int>(rhs); | 267 int result = static_cast<int>(lhs) & static_cast<int>(rhs); |
264 return static_cast<AccumulatorUse>(result); | 268 return static_cast<AccumulatorUse>(result); |
265 } | 269 } |
266 | 270 |
267 V8_INLINE AccumulatorUse operator|(AccumulatorUse lhs, AccumulatorUse rhs) { | 271 V8_INLINE AccumulatorUse operator|(AccumulatorUse lhs, AccumulatorUse rhs) { |
268 int result = static_cast<int>(lhs) | static_cast<int>(rhs); | 272 int result = static_cast<int>(lhs) | static_cast<int>(rhs); |
269 return static_cast<AccumulatorUse>(result); | 273 return static_cast<AccumulatorUse>(result); |
270 } | 274 } |
271 | 275 |
272 // Enumeration of scaling factors applicable to scalable operands. Code | 276 // Enumeration of scaling factors applicable to scalable operands. Code |
273 // relies on being able to cast values to integer scaling values. | 277 // relies on being able to cast values to integer scaling values. |
| 278 #define OPERAND_SCALE_LIST(V) \ |
| 279 V(Single, 1) \ |
| 280 V(Double, 2) \ |
| 281 V(Quadruple, 4) |
| 282 |
274 enum class OperandScale : uint8_t { | 283 enum class OperandScale : uint8_t { |
275 kSingle = 1, | 284 #define DECLARE_OPERAND_SCALE(Name, Scale) k##Name = Scale, |
276 kDouble = 2, | 285 OPERAND_SCALE_LIST(DECLARE_OPERAND_SCALE) |
277 kQuadruple = 4, | 286 #undef DECLARE_OPERAND_SCALE |
278 kMaxValid = kQuadruple, | 287 #define COUNT_OPERAND_SCALES(x, _) *2 |
279 kInvalid = 8, | 288 // The COUNT_OPERAND macro will turn this into kLast = 2^N / 2... which will |
| 289 // evaluate to the same value as the last operand. |
| 290 kLast = (1 OPERAND_SCALE_LIST(COUNT_OPERAND_SCALES)) / 2 |
| 291 #undef COUNT_OPERAND_SCALES |
280 }; | 292 }; |
| 293 STATIC_ASSERT(OperandScale::kLast == OperandScale::kQuadruple); |
281 | 294 |
282 // Enumeration of the size classes of operand types used by | 295 // Enumeration of the size classes of operand types used by |
283 // bytecodes. Code relies on being able to cast values to integer | 296 // bytecodes. Code relies on being able to cast values to integer |
284 // types to get the size in bytes. | 297 // types to get the size in bytes. |
285 enum class OperandSize : uint8_t { | 298 enum class OperandSize : uint8_t { |
286 kNone = 0, | 299 kNone = 0, |
287 kByte = 1, | 300 kByte = 1, |
288 kShort = 2, | 301 kShort = 2, |
289 kQuad = 4, | 302 kQuad = 4, |
290 kLast = kQuad | 303 kLast = kQuad |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
326 #define COUNT_BYTECODE(x, ...) +1 | 339 #define COUNT_BYTECODE(x, ...) +1 |
327 // The COUNT_BYTECODE macro will turn this into kLast = -1 +1 +1... which will | 340 // The COUNT_BYTECODE macro will turn this into kLast = -1 +1 +1... which will |
328 // evaluate to the same value as the last real bytecode. | 341 // evaluate to the same value as the last real bytecode. |
329 kLast = -1 BYTECODE_LIST(COUNT_BYTECODE) | 342 kLast = -1 BYTECODE_LIST(COUNT_BYTECODE) |
330 #undef COUNT_BYTECODE | 343 #undef COUNT_BYTECODE |
331 }; | 344 }; |
332 | 345 |
333 | 346 |
334 // An interpreter Register which is located in the function's Register file | 347 // An interpreter Register which is located in the function's Register file |
335 // in its stack-frame. Register hold parameters, this, and expression values. | 348 // in its stack-frame. Register hold parameters, this, and expression values. |
336 class Register { | 349 class Register final { |
337 public: | 350 public: |
338 explicit Register(int index = kInvalidIndex) : index_(index) {} | 351 explicit Register(int index = kInvalidIndex) : index_(index) {} |
339 | 352 |
340 int index() const { return index_; } | 353 int index() const { return index_; } |
341 bool is_parameter() const { return index() < 0; } | 354 bool is_parameter() const { return index() < 0; } |
342 bool is_valid() const { return index_ != kInvalidIndex; } | 355 bool is_valid() const { return index_ != kInvalidIndex; } |
343 | 356 |
344 static Register FromParameterIndex(int index, int parameter_count); | 357 static Register FromParameterIndex(int index, int parameter_count); |
345 int ToParameterIndex(int parameter_count) const; | 358 int ToParameterIndex(int parameter_count) const; |
346 | 359 |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
457 | 470 |
458 // Returns how accumulator is used by |bytecode|. | 471 // Returns how accumulator is used by |bytecode|. |
459 static AccumulatorUse GetAccumulatorUse(Bytecode bytecode); | 472 static AccumulatorUse GetAccumulatorUse(Bytecode bytecode); |
460 | 473 |
461 // Returns true if |bytecode| reads the accumulator. | 474 // Returns true if |bytecode| reads the accumulator. |
462 static bool ReadsAccumulator(Bytecode bytecode); | 475 static bool ReadsAccumulator(Bytecode bytecode); |
463 | 476 |
464 // Returns true if |bytecode| writes the accumulator. | 477 // Returns true if |bytecode| writes the accumulator. |
465 static bool WritesAccumulator(Bytecode bytecode); | 478 static bool WritesAccumulator(Bytecode bytecode); |
466 | 479 |
| 480 // Return true if |bytecode| writes the accumulator with a boolean value. |
| 481 static bool WritesAccumulatorWithBoolean(Bytecode bytecode); |
| 482 |
| 483 // Return true if |bytecode| is an accumulator load bytecode, |
| 484 // e.g. LdaConstant, LdaTrue, Ldar. |
| 485 static bool IsAccumulatorLoadWithoutEffects(Bytecode bytecode); |
| 486 |
467 // Returns the i-th operand of |bytecode|. | 487 // Returns the i-th operand of |bytecode|. |
468 static OperandType GetOperandType(Bytecode bytecode, int i); | 488 static OperandType GetOperandType(Bytecode bytecode, int i); |
469 | 489 |
| 490 // Returns a pointer to an array of operand types terminated in |
| 491 // OperandType::kNone. |
| 492 static const OperandType* GetOperandTypes(Bytecode bytecode); |
| 493 |
470 // Returns the size of the i-th operand of |bytecode|. | 494 // Returns the size of the i-th operand of |bytecode|. |
471 static OperandSize GetOperandSize(Bytecode bytecode, int i, | 495 static OperandSize GetOperandSize(Bytecode bytecode, int i, |
472 OperandScale operand_scale); | 496 OperandScale operand_scale); |
473 | 497 |
474 // Returns the offset of the i-th operand of |bytecode| relative to the start | 498 // Returns the offset of the i-th operand of |bytecode| relative to the start |
475 // of the bytecode. | 499 // of the bytecode. |
476 static int GetOperandOffset(Bytecode bytecode, int i, | 500 static int GetOperandOffset(Bytecode bytecode, int i, |
477 OperandScale operand_scale); | 501 OperandScale operand_scale); |
478 | 502 |
479 // Returns a zero-based bitmap of the register operand positions of | 503 // Returns a zero-based bitmap of the register operand positions of |
(...skipping 27 matching lines...) Expand all Loading... |
507 static bool IsJumpImmediate(Bytecode bytecode); | 531 static bool IsJumpImmediate(Bytecode bytecode); |
508 | 532 |
509 // Returns true if the bytecode is a jump or conditional jump taking a | 533 // Returns true if the bytecode is a jump or conditional jump taking a |
510 // constant pool entry (OperandType::kIdx). | 534 // constant pool entry (OperandType::kIdx). |
511 static bool IsJumpConstant(Bytecode bytecode); | 535 static bool IsJumpConstant(Bytecode bytecode); |
512 | 536 |
513 // Returns true if the bytecode is a jump or conditional jump taking | 537 // Returns true if the bytecode is a jump or conditional jump taking |
514 // any kind of operand. | 538 // any kind of operand. |
515 static bool IsJump(Bytecode bytecode); | 539 static bool IsJump(Bytecode bytecode); |
516 | 540 |
| 541 // Returns true if the bytecode is a jump that internally coerces the |
| 542 // accumulator to a boolean. |
| 543 static bool IsJumpIfToBoolean(Bytecode bytecode); |
| 544 |
| 545 // Returns the equivalent jump bytecode without the accumulator coercion. |
| 546 static Bytecode GetJumpWithoutToBoolean(Bytecode bytecode); |
| 547 |
517 // Returns true if the bytecode is a conditional jump, a jump, or a return. | 548 // Returns true if the bytecode is a conditional jump, a jump, or a return. |
518 static bool IsJumpOrReturn(Bytecode bytecode); | 549 static bool IsJumpOrReturn(Bytecode bytecode); |
519 | 550 |
520 // Returns true if the bytecode is a call or a constructor call. | 551 // Returns true if the bytecode is a call or a constructor call. |
521 static bool IsCallOrNew(Bytecode bytecode); | 552 static bool IsCallOrNew(Bytecode bytecode); |
522 | 553 |
523 // Returns true if the bytecode is a call to the runtime. | 554 // Returns true if the bytecode is a call to the runtime. |
524 static bool IsCallRuntime(Bytecode bytecode); | 555 static bool IsCallRuntime(Bytecode bytecode); |
525 | 556 |
526 // Returns true if the bytecode is a debug break. | 557 // Returns true if the bytecode is a debug break. |
527 static bool IsDebugBreak(Bytecode bytecode); | 558 static bool IsDebugBreak(Bytecode bytecode); |
528 | 559 |
529 // Returns true if the bytecode has wider operand forms. | 560 // Returns true if the bytecode has wider operand forms. |
530 static bool IsBytecodeWithScalableOperands(Bytecode bytecode); | 561 static bool IsBytecodeWithScalableOperands(Bytecode bytecode); |
531 | 562 |
532 // Returns true if the bytecode is a scaling prefix bytecode. | 563 // Returns true if the bytecode is a scaling prefix bytecode. |
533 static bool IsPrefixScalingBytecode(Bytecode bytecode); | 564 static bool IsPrefixScalingBytecode(Bytecode bytecode); |
534 | 565 |
535 // Returns true if |operand_type| is any type of register operand. | 566 // Returns true if |operand_type| is any type of register operand. |
536 static bool IsRegisterOperandType(OperandType operand_type); | 567 static bool IsRegisterOperandType(OperandType operand_type); |
537 | 568 |
538 // Returns true if |operand_type| represents a register used as an input. | 569 // Returns true if |operand_type| represents a register used as an input. |
539 static bool IsRegisterInputOperandType(OperandType operand_type); | 570 static bool IsRegisterInputOperandType(OperandType operand_type); |
540 | 571 |
541 // Returns true if |operand_type| represents a register used as an output. | 572 // Returns true if |operand_type| represents a register used as an output. |
542 static bool IsRegisterOutputOperandType(OperandType operand_type); | 573 static bool IsRegisterOutputOperandType(OperandType operand_type); |
543 | 574 |
| 575 // Returns the number of registers represented by a register operand. For |
| 576 // instance, a RegPair represents two registers. |
| 577 static int GetNumberOfRegistersRepresentedBy(OperandType operand_type); |
| 578 |
544 // Returns true if |operand_type| is a maybe register operand | 579 // Returns true if |operand_type| is a maybe register operand |
545 // (kMaybeReg). | 580 // (kMaybeReg). |
546 static bool IsMaybeRegisterOperandType(OperandType operand_type); | 581 static bool IsMaybeRegisterOperandType(OperandType operand_type); |
547 | 582 |
548 // Returns true if |operand_type| is a runtime-id operand (kRuntimeId). | 583 // Returns true if |operand_type| is a runtime-id operand (kRuntimeId). |
549 static bool IsRuntimeIdOperandType(OperandType operand_type); | 584 static bool IsRuntimeIdOperandType(OperandType operand_type); |
550 | 585 |
551 // Returns true if |operand_type| is unsigned, false if signed. | 586 // Returns true if |operand_type| is unsigned, false if signed. |
552 static bool IsUnsignedOperandType(OperandType operand_type); | 587 static bool IsUnsignedOperandType(OperandType operand_type); |
553 | 588 |
(...skipping 15 matching lines...) Expand all Loading... |
569 // Decode a single bytecode and operands to |os|. | 604 // Decode a single bytecode and operands to |os|. |
570 static std::ostream& Decode(std::ostream& os, const uint8_t* bytecode_start, | 605 static std::ostream& Decode(std::ostream& os, const uint8_t* bytecode_start, |
571 int number_of_parameters); | 606 int number_of_parameters); |
572 | 607 |
573 // Returns true if a handler is generated for a bytecode at a given | 608 // Returns true if a handler is generated for a bytecode at a given |
574 // operand scale. All bytecodes have handlers at OperandScale::kSingle, | 609 // operand scale. All bytecodes have handlers at OperandScale::kSingle, |
575 // but only bytecodes with scalable operands have handlers with larger | 610 // but only bytecodes with scalable operands have handlers with larger |
576 // OperandScale values. | 611 // OperandScale values. |
577 static bool BytecodeHasHandler(Bytecode bytecode, OperandScale operand_scale); | 612 static bool BytecodeHasHandler(Bytecode bytecode, OperandScale operand_scale); |
578 | 613 |
579 // Return the next larger operand scale. | 614 // Return the operand size required to hold a signed operand. |
580 static OperandScale NextOperandScale(OperandScale operand_scale); | 615 static OperandSize SizeForSignedOperand(int value); |
| 616 |
| 617 // Return the operand size required to hold an unsigned operand. |
| 618 static OperandSize SizeForUnsignedOperand(int value); |
| 619 |
| 620 // Return the operand size required to hold an unsigned operand. |
| 621 static OperandSize SizeForUnsignedOperand(size_t value); |
| 622 |
| 623 // Return the OperandScale required for bytecode emission of |
| 624 // operand sizes. |
| 625 static OperandScale OperandSizesToScale( |
| 626 OperandSize size0, OperandSize size1 = OperandSize::kByte, |
| 627 OperandSize size2 = OperandSize::kByte, |
| 628 OperandSize size3 = OperandSize::kByte); |
581 | 629 |
582 private: | 630 private: |
583 DISALLOW_IMPLICIT_CONSTRUCTORS(Bytecodes); | 631 DISALLOW_IMPLICIT_CONSTRUCTORS(Bytecodes); |
584 }; | 632 }; |
585 | 633 |
586 class CreateObjectLiteralFlags { | 634 class CreateObjectLiteralFlags { |
587 public: | 635 public: |
588 class FlagsBits : public BitField8<int, 0, 3> {}; | 636 class FlagsBits : public BitField8<int, 0, 3> {}; |
589 class FastClonePropertiesCountBits | 637 class FastClonePropertiesCountBits |
590 : public BitField8<int, FlagsBits::kNext, 3> {}; | 638 : public BitField8<int, FlagsBits::kNext, 3> {}; |
591 STATIC_ASSERT((FlagsBits::kMask & FastClonePropertiesCountBits::kMask) == 0); | 639 STATIC_ASSERT((FlagsBits::kMask & FastClonePropertiesCountBits::kMask) == 0); |
592 }; | 640 }; |
593 | 641 |
594 std::ostream& operator<<(std::ostream& os, const Bytecode& bytecode); | 642 std::ostream& operator<<(std::ostream& os, const Bytecode& bytecode); |
595 std::ostream& operator<<(std::ostream& os, const AccumulatorUse& use); | 643 std::ostream& operator<<(std::ostream& os, const AccumulatorUse& use); |
596 std::ostream& operator<<(std::ostream& os, const OperandScale& operand_scale); | 644 std::ostream& operator<<(std::ostream& os, const OperandScale& operand_scale); |
597 std::ostream& operator<<(std::ostream& os, const OperandSize& operand_size); | 645 std::ostream& operator<<(std::ostream& os, const OperandSize& operand_size); |
598 std::ostream& operator<<(std::ostream& os, const OperandType& operand_type); | 646 std::ostream& operator<<(std::ostream& os, const OperandType& operand_type); |
599 | 647 |
600 } // namespace interpreter | 648 } // namespace interpreter |
601 } // namespace internal | 649 } // namespace internal |
602 } // namespace v8 | 650 } // namespace v8 |
603 | 651 |
604 #endif // V8_INTERPRETER_BYTECODES_H_ | 652 #endif // V8_INTERPRETER_BYTECODES_H_ |
OLD | NEW |