v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
bytecode-operands.h
Go to the documentation of this file.
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"
10
11namespace v8 {
12namespace internal {
13namespace 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(Flag16, OperandTypeInfo::kFixedUnsignedShort) \
39 V(IntrinsicId, OperandTypeInfo::kFixedUnsignedByte) \
40 V(RuntimeId, OperandTypeInfo::kFixedUnsignedShort) \
41 V(NativeContextIndex, OperandTypeInfo::kFixedUnsignedByte)
42
43// Carefully ordered for operand type range checks below.
44#define NON_REGISTER_OPERAND_TYPE_LIST(V) \
45 INVALID_OPERAND_TYPE_LIST(V) \
46 UNSIGNED_FIXED_SCALAR_OPERAND_TYPE_LIST(V) \
47 UNSIGNED_SCALABLE_SCALAR_OPERAND_TYPE_LIST(V) \
48 SIGNED_SCALABLE_SCALAR_OPERAND_TYPE_LIST(V)
49
50// Carefully ordered for operand type range checks below.
51#define REGISTER_OPERAND_TYPE_LIST(V) \
52 REGISTER_INPUT_OPERAND_TYPE_LIST(V) \
53 REGISTER_OUTPUT_OPERAND_TYPE_LIST(V) \
54 V(RegInOut, OperandTypeInfo::kScalableSignedByte)
55
56// The list of operand types used by bytecodes.
57// Carefully ordered for operand type range checks below.
58#define OPERAND_TYPE_LIST(V) \
59 NON_REGISTER_OPERAND_TYPE_LIST(V) \
60 REGISTER_OPERAND_TYPE_LIST(V)
61
62// Enumeration of scaling factors applicable to scalable operands. Code
63// relies on being able to cast values to integer scaling values.
64#define OPERAND_SCALE_LIST(V) \
65 V(Single, 1) \
66 V(Double, 2) \
67 V(Quadruple, 4)
68
69enum class OperandScale : uint8_t {
70#define DECLARE_OPERAND_SCALE(Name, Scale) k##Name = Scale,
72#undef DECLARE_OPERAND_SCALE
73 kLast = kQuadruple
74};
75
76// Enumeration of the size classes of operand types used by
77// bytecodes. Code relies on being able to cast values to integer
78// types to get the size in bytes.
79enum class OperandSize : uint8_t {
80 kNone = 0,
81 kByte = 1,
82 kShort = 2,
83 kQuad = 4,
84 kLast = kQuad
85};
86
87// Primitive operand info used that summarize properties of operands.
88// Columns are Name, IsScalable, IsUnsigned, UnscaledSize.
89#define OPERAND_TYPE_INFO_LIST(V) \
90 V(None, false, false, OperandSize::kNone) \
91 V(ScalableSignedByte, true, false, OperandSize::kByte) \
92 V(ScalableUnsignedByte, true, true, OperandSize::kByte) \
93 V(FixedUnsignedByte, false, true, OperandSize::kByte) \
94 V(FixedUnsignedShort, false, true, OperandSize::kShort)
95
96enum class OperandTypeInfo : uint8_t {
97#define DECLARE_OPERAND_TYPE_INFO(Name, ...) k##Name,
99#undef DECLARE_OPERAND_TYPE_INFO
100};
101
102// Enumeration of operand types used by bytecodes.
103enum class OperandType : uint8_t {
104#define DECLARE_OPERAND_TYPE(Name, _) k##Name,
106#undef DECLARE_OPERAND_TYPE
107#define COUNT_OPERAND_TYPES(x, _) +1
108 // The COUNT_OPERAND macro will turn this into kLast = -1 +1 +1... which will
109 // evaluate to the same value as the last operand.
111#undef COUNT_OPERAND_TYPES
112};
113
124
127 return static_cast<ImplicitRegisterUse>(static_cast<int>(lhs) &
128 static_cast<int>(rhs));
129}
130
133 return static_cast<ImplicitRegisterUse>(static_cast<int>(lhs) |
134 static_cast<int>(rhs));
135}
136
137V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
138 const ImplicitRegisterUse& use);
139V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
140 const OperandScale& operand_scale);
141V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
142 const OperandSize& operand_size);
143V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
144 const OperandType& operand_type);
145
147 public:
148 // The total number of bytecode operand types used.
149 static const int kOperandTypeCount = static_cast<int>(OperandType::kLast) + 1;
150
151// The total number of bytecode operand scales used.
152#define OPERAND_SCALE_COUNT(...) +1
153 static const int kOperandScaleCount =
155#undef OPERAND_SCALE_COUNT
156
157 static constexpr int OperandScaleAsIndex(OperandScale operand_scale) {
158#ifdef DEBUG
159 int result = static_cast<int>(operand_scale) >> 1;
160 switch (operand_scale) {
161 case OperandScale::kSingle:
162 DCHECK_EQ(0, result);
163 break;
164 case OperandScale::kDouble:
165 DCHECK_EQ(1, result);
166 break;
167 case OperandScale::kQuadruple:
168 DCHECK_EQ(2, result);
169 break;
170 default:
171 UNREACHABLE();
172 }
173#endif
174 return static_cast<int>(operand_scale) >> 1;
175 }
176
177 // Returns true if |implicit_register_use| reads the
178 // accumulator.
179 static constexpr bool ReadsAccumulator(
180 ImplicitRegisterUse implicit_register_use) {
181 return (implicit_register_use & ImplicitRegisterUse::kReadAccumulator) ==
183 }
184
185 // Returns true if |implicit_register_use| writes the
186 // accumulator.
187 static constexpr bool WritesAccumulator(
188 ImplicitRegisterUse implicit_register_use) {
189 return (implicit_register_use & ImplicitRegisterUse::kWriteAccumulator) ==
191 }
192
193 // Returns true if |implicit_register_use| clobbers the
194 // accumulator.
195 static constexpr bool ClobbersAccumulator(
196 ImplicitRegisterUse implicit_register_use) {
197 return (implicit_register_use & ImplicitRegisterUse::kClobberAccumulator) ==
199 }
200
201 // Returns true if |implicit_register_use| writes or clobbers the
202 // accumulator.
203 static constexpr bool WritesOrClobbersAccumulator(
204 ImplicitRegisterUse implicit_register_use) {
205 return (implicit_register_use &
209 }
210
211 // Returns true if |implicit_register_use| writes to a
212 // register not specified by an operand.
213 static constexpr bool WritesImplicitRegister(
214 ImplicitRegisterUse implicit_register_use) {
215 return (implicit_register_use & ImplicitRegisterUse::kWriteShortStar) ==
217 }
218
219 // Returns true if |operand_type| is a scalable signed byte.
220 static constexpr bool IsScalableSignedByte(OperandType operand_type) {
221 return base::IsInRange(operand_type, OperandType::kImm,
222 OperandType::kRegInOut);
223 }
224
225 // Returns true if |operand_type| is a scalable unsigned byte.
226 static constexpr bool IsScalableUnsignedByte(OperandType operand_type) {
227 return base::IsInRange(operand_type, OperandType::kIdx,
228 OperandType::kRegCount);
229 }
230};
231
232} // namespace interpreter
233} // namespace internal
234} // namespace v8
235
236#endif // V8_INTERPRETER_BYTECODE_OPERANDS_H_
#define OPERAND_TYPE_LIST(V)
#define OPERAND_SCALE_LIST(V)
#define OPERAND_TYPE_INFO_LIST(V)
#define OPERAND_SCALE_COUNT(...)
static constexpr bool IsScalableSignedByte(OperandType operand_type)
static constexpr bool WritesImplicitRegister(ImplicitRegisterUse implicit_register_use)
static constexpr bool ReadsAccumulator(ImplicitRegisterUse implicit_register_use)
static constexpr bool ClobbersAccumulator(ImplicitRegisterUse implicit_register_use)
static constexpr bool IsScalableUnsignedByte(OperandType operand_type)
static constexpr bool WritesAccumulator(ImplicitRegisterUse implicit_register_use)
static constexpr bool WritesOrClobbersAccumulator(ImplicitRegisterUse implicit_register_use)
static constexpr int OperandScaleAsIndex(OperandScale operand_scale)
ZoneVector< RpoNumber > & result
constexpr bool IsInRange(T value, U lower_limit, U higher_limit)
Definition bounds.h:20
std::ostream & operator<<(std::ostream &os, PaddingSpace padding)
constexpr ImplicitRegisterUse operator|(ImplicitRegisterUse lhs, ImplicitRegisterUse rhs)
constexpr ImplicitRegisterUse operator&(ImplicitRegisterUse lhs, ImplicitRegisterUse rhs)
#define DCHECK_EQ(v1, v2)
Definition logging.h:485
#define V8_EXPORT_PRIVATE
Definition macros.h:460