• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
3 // found in the LICENSE file.
4 
5 #ifndef V8_INTERPRETER_BYTECODE_OPERANDS_H_
6 #define V8_INTERPRETER_BYTECODE_OPERANDS_H_
7 
8 #include "src/base/bounds.h"
9 #include "src/common/globals.h"
10 
11 namespace v8 {
12 namespace internal {
13 namespace interpreter {
14 
15 #define INVALID_OPERAND_TYPE_LIST(V) V(None, OperandTypeInfo::kNone)
16 
17 #define REGISTER_INPUT_OPERAND_TYPE_LIST(V)        \
18   V(Reg, OperandTypeInfo::kScalableSignedByte)     \
19   V(RegList, OperandTypeInfo::kScalableSignedByte) \
20   V(RegPair, OperandTypeInfo::kScalableSignedByte)
21 
22 #define REGISTER_OUTPUT_OPERAND_TYPE_LIST(V)          \
23   V(RegOut, OperandTypeInfo::kScalableSignedByte)     \
24   V(RegOutList, OperandTypeInfo::kScalableSignedByte) \
25   V(RegOutPair, OperandTypeInfo::kScalableSignedByte) \
26   V(RegOutTriple, OperandTypeInfo::kScalableSignedByte)
27 
28 #define SIGNED_SCALABLE_SCALAR_OPERAND_TYPE_LIST(V) \
29   V(Imm, OperandTypeInfo::kScalableSignedByte)
30 
31 #define UNSIGNED_SCALABLE_SCALAR_OPERAND_TYPE_LIST(V) \
32   V(Idx, OperandTypeInfo::kScalableUnsignedByte)      \
33   V(UImm, OperandTypeInfo::kScalableUnsignedByte)     \
34   V(RegCount, OperandTypeInfo::kScalableUnsignedByte)
35 
36 #define UNSIGNED_FIXED_SCALAR_OPERAND_TYPE_LIST(V)    \
37   V(Flag8, OperandTypeInfo::kFixedUnsignedByte)       \
38   V(IntrinsicId, OperandTypeInfo::kFixedUnsignedByte) \
39   V(RuntimeId, OperandTypeInfo::kFixedUnsignedShort)  \
40   V(NativeContextIndex, OperandTypeInfo::kFixedUnsignedByte)
41 
42 // Carefully ordered for operand type range checks below.
43 #define NON_REGISTER_OPERAND_TYPE_LIST(V)       \
44   INVALID_OPERAND_TYPE_LIST(V)                  \
45   UNSIGNED_FIXED_SCALAR_OPERAND_TYPE_LIST(V)    \
46   UNSIGNED_SCALABLE_SCALAR_OPERAND_TYPE_LIST(V) \
47   SIGNED_SCALABLE_SCALAR_OPERAND_TYPE_LIST(V)
48 
49 // Carefully ordered for operand type range checks below.
50 #define REGISTER_OPERAND_TYPE_LIST(V) \
51   REGISTER_INPUT_OPERAND_TYPE_LIST(V) \
52   REGISTER_OUTPUT_OPERAND_TYPE_LIST(V)
53 
54 // The list of operand types used by bytecodes.
55 // Carefully ordered for operand type range checks below.
56 #define OPERAND_TYPE_LIST(V)        \
57   NON_REGISTER_OPERAND_TYPE_LIST(V) \
58   REGISTER_OPERAND_TYPE_LIST(V)
59 
60 // Enumeration of scaling factors applicable to scalable operands. Code
61 // relies on being able to cast values to integer scaling values.
62 #define OPERAND_SCALE_LIST(V) \
63   V(Single, 1)                \
64   V(Double, 2)                \
65   V(Quadruple, 4)
66 
67 enum class OperandScale : uint8_t {
68 #define DECLARE_OPERAND_SCALE(Name, Scale) k##Name = Scale,
69   OPERAND_SCALE_LIST(DECLARE_OPERAND_SCALE)
70 #undef DECLARE_OPERAND_SCALE
71       kLast = kQuadruple
72 };
73 
74 // Enumeration of the size classes of operand types used by
75 // bytecodes. Code relies on being able to cast values to integer
76 // types to get the size in bytes.
77 enum class OperandSize : uint8_t {
78   kNone = 0,
79   kByte = 1,
80   kShort = 2,
81   kQuad = 4,
82   kLast = kQuad
83 };
84 
85 // Primitive operand info used that summarize properties of operands.
86 // Columns are Name, IsScalable, IsUnsigned, UnscaledSize.
87 #define OPERAND_TYPE_INFO_LIST(V)                         \
88   V(None, false, false, OperandSize::kNone)               \
89   V(ScalableSignedByte, true, false, OperandSize::kByte)  \
90   V(ScalableUnsignedByte, true, true, OperandSize::kByte) \
91   V(FixedUnsignedByte, false, true, OperandSize::kByte)   \
92   V(FixedUnsignedShort, false, true, OperandSize::kShort)
93 
94 enum class OperandTypeInfo : uint8_t {
95 #define DECLARE_OPERAND_TYPE_INFO(Name, ...) k##Name,
96   OPERAND_TYPE_INFO_LIST(DECLARE_OPERAND_TYPE_INFO)
97 #undef DECLARE_OPERAND_TYPE_INFO
98 };
99 
100 // Enumeration of operand types used by bytecodes.
101 enum class OperandType : uint8_t {
102 #define DECLARE_OPERAND_TYPE(Name, _) k##Name,
103   OPERAND_TYPE_LIST(DECLARE_OPERAND_TYPE)
104 #undef DECLARE_OPERAND_TYPE
105 #define COUNT_OPERAND_TYPES(x, _) +1
106   // The COUNT_OPERAND macro will turn this into kLast = -1 +1 +1... which will
107   // evaluate to the same value as the last operand.
108   kLast = -1 OPERAND_TYPE_LIST(COUNT_OPERAND_TYPES)
109 #undef COUNT_OPERAND_TYPES
110 };
111 
112 enum class AccumulatorUse : uint8_t {
113   kNone = 0,
114   kRead = 1 << 0,
115   kWrite = 1 << 1,
116   kReadWrite = kRead | kWrite
117 };
118 
119 constexpr inline AccumulatorUse operator&(AccumulatorUse lhs,
120                                           AccumulatorUse rhs) {
121   return static_cast<AccumulatorUse>(static_cast<int>(lhs) &
122                                      static_cast<int>(rhs));
123 }
124 
125 constexpr inline AccumulatorUse operator|(AccumulatorUse lhs,
126                                           AccumulatorUse rhs) {
127   return static_cast<AccumulatorUse>(static_cast<int>(lhs) |
128                                      static_cast<int>(rhs));
129 }
130 
131 V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
132                                            const AccumulatorUse& use);
133 V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
134                                            const OperandScale& operand_scale);
135 V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
136                                            const OperandSize& operand_size);
137 V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
138                                            const OperandType& operand_type);
139 
140 class BytecodeOperands : public AllStatic {
141  public:
142   // The total number of bytecode operand types used.
143   static const int kOperandTypeCount = static_cast<int>(OperandType::kLast) + 1;
144 
145 // The total number of bytecode operand scales used.
146 #define OPERAND_SCALE_COUNT(...) +1
147   static const int kOperandScaleCount =
148       0 OPERAND_SCALE_LIST(OPERAND_SCALE_COUNT);
149 #undef OPERAND_SCALE_COUNT
150 
OperandScaleAsIndex(OperandScale operand_scale)151   static constexpr int OperandScaleAsIndex(OperandScale operand_scale) {
152 #if V8_HAS_CXX14_CONSTEXPR
153 #ifdef DEBUG
154     int result = static_cast<int>(operand_scale) >> 1;
155     switch (operand_scale) {
156       case OperandScale::kSingle:
157         DCHECK_EQ(0, result);
158         break;
159       case OperandScale::kDouble:
160         DCHECK_EQ(1, result);
161         break;
162       case OperandScale::kQuadruple:
163         DCHECK_EQ(2, result);
164         break;
165       default:
166         UNREACHABLE();
167     }
168 #endif
169 #endif
170     return static_cast<int>(operand_scale) >> 1;
171   }
172 
173   // Returns true if |accumulator_use| reads the accumulator.
ReadsAccumulator(AccumulatorUse accumulator_use)174   static constexpr bool ReadsAccumulator(AccumulatorUse accumulator_use) {
175     return (accumulator_use & AccumulatorUse::kRead) == AccumulatorUse::kRead;
176   }
177 
178   // Returns true if |accumulator_use| writes the accumulator.
WritesAccumulator(AccumulatorUse accumulator_use)179   static constexpr bool WritesAccumulator(AccumulatorUse accumulator_use) {
180     return (accumulator_use & AccumulatorUse::kWrite) == AccumulatorUse::kWrite;
181   }
182 
183   // Returns true if |operand_type| is a scalable signed byte.
IsScalableSignedByte(OperandType operand_type)184   static constexpr bool IsScalableSignedByte(OperandType operand_type) {
185     return base::IsInRange(operand_type, OperandType::kImm,
186                            OperandType::kRegOutTriple);
187   }
188 
189   // Returns true if |operand_type| is a scalable unsigned byte.
IsScalableUnsignedByte(OperandType operand_type)190   static constexpr bool IsScalableUnsignedByte(OperandType operand_type) {
191     return base::IsInRange(operand_type, OperandType::kIdx,
192                            OperandType::kRegCount);
193   }
194 };
195 
196 }  // namespace interpreter
197 }  // namespace internal
198 }  // namespace v8
199 
200 #endif  // V8_INTERPRETER_BYTECODE_OPERANDS_H_
201