V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
bytecodes.cc
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
3 // found in the LICENSE file.
4 
5 #include "src/interpreter/bytecodes.h"
6 
7 #include <iomanip>
8 
9 #include "src/base/bits.h"
10 #include "src/interpreter/bytecode-traits.h"
11 
12 namespace v8 {
13 namespace internal {
14 namespace interpreter {
15 
16 // clang-format off
17 const OperandType* const Bytecodes::kOperandTypes[] = {
18 #define ENTRY(Name, ...) BytecodeTraits<__VA_ARGS__>::kOperandTypes,
19  BYTECODE_LIST(ENTRY)
20 #undef ENTRY
21 };
22 
23 const OperandTypeInfo* const Bytecodes::kOperandTypeInfos[] = {
24 #define ENTRY(Name, ...) BytecodeTraits<__VA_ARGS__>::kOperandTypeInfos,
25  BYTECODE_LIST(ENTRY)
26 #undef ENTRY
27 };
28 
29 const int Bytecodes::kOperandCount[] = {
30 #define ENTRY(Name, ...) BytecodeTraits<__VA_ARGS__>::kOperandCount,
31  BYTECODE_LIST(ENTRY)
32 #undef ENTRY
33 };
34 
35 const AccumulatorUse Bytecodes::kAccumulatorUse[] = {
36 #define ENTRY(Name, ...) BytecodeTraits<__VA_ARGS__>::kAccumulatorUse,
37  BYTECODE_LIST(ENTRY)
38 #undef ENTRY
39 };
40 
41 const int Bytecodes::kBytecodeSizes[3][kBytecodeCount] = {
42  {
43 #define ENTRY(Name, ...) BytecodeTraits<__VA_ARGS__>::kSingleScaleSize,
44  BYTECODE_LIST(ENTRY)
45 #undef ENTRY
46  }, {
47 #define ENTRY(Name, ...) BytecodeTraits<__VA_ARGS__>::kDoubleScaleSize,
48  BYTECODE_LIST(ENTRY)
49 #undef ENTRY
50  }, {
51 #define ENTRY(Name, ...) BytecodeTraits<__VA_ARGS__>::kQuadrupleScaleSize,
52  BYTECODE_LIST(ENTRY)
53 #undef ENTRY
54  }
55 };
56 
57 const OperandSize* const Bytecodes::kOperandSizes[3][kBytecodeCount] = {
58  {
59 #define ENTRY(Name, ...) \
60  BytecodeTraits<__VA_ARGS__>::kSingleScaleOperandSizes,
61  BYTECODE_LIST(ENTRY)
62 #undef ENTRY
63  }, {
64 #define ENTRY(Name, ...) \
65  BytecodeTraits<__VA_ARGS__>::kDoubleScaleOperandSizes,
66  BYTECODE_LIST(ENTRY)
67 #undef ENTRY
68  }, {
69 #define ENTRY(Name, ...) \
70  BytecodeTraits<__VA_ARGS__>::kQuadrupleScaleOperandSizes,
71  BYTECODE_LIST(ENTRY)
72 #undef ENTRY
73  }
74 };
75 
76 const OperandSize
77 Bytecodes::kOperandKindSizes[3][BytecodeOperands::kOperandTypeCount] = {
78  {
79 #define ENTRY(Name, ...) \
80  OperandScaler<OperandType::k##Name, OperandScale::kSingle>::kOperandSize,
81  OPERAND_TYPE_LIST(ENTRY)
82 #undef ENTRY
83  }, {
84 #define ENTRY(Name, ...) \
85  OperandScaler<OperandType::k##Name, OperandScale::kDouble>::kOperandSize,
86  OPERAND_TYPE_LIST(ENTRY)
87 #undef ENTRY
88  }, {
89 #define ENTRY(Name, ...) \
90  OperandScaler<OperandType::k##Name, OperandScale::kQuadruple>::kOperandSize,
91  OPERAND_TYPE_LIST(ENTRY)
92 #undef ENTRY
93  }
94 };
95 // clang-format on
96 
97 // static
98 const char* Bytecodes::ToString(Bytecode bytecode) {
99  switch (bytecode) {
100 #define CASE(Name, ...) \
101  case Bytecode::k##Name: \
102  return #Name;
103  BYTECODE_LIST(CASE)
104 #undef CASE
105  }
106  UNREACHABLE();
107 }
108 
109 // static
110 std::string Bytecodes::ToString(Bytecode bytecode, OperandScale operand_scale,
111  const char* separator) {
112  std::string value(ToString(bytecode));
113  if (operand_scale > OperandScale::kSingle) {
114  Bytecode prefix_bytecode = OperandScaleToPrefixBytecode(operand_scale);
115  std::string suffix = ToString(prefix_bytecode);
116  return value.append(separator).append(suffix);
117  } else {
118  return value;
119  }
120 }
121 
122 // static
123 Bytecode Bytecodes::GetDebugBreak(Bytecode bytecode) {
124  DCHECK(!IsDebugBreak(bytecode));
125  if (bytecode == Bytecode::kWide) {
126  return Bytecode::kDebugBreakWide;
127  }
128  if (bytecode == Bytecode::kExtraWide) {
129  return Bytecode::kDebugBreakExtraWide;
130  }
131  int bytecode_size = Size(bytecode, OperandScale::kSingle);
132 #define RETURN_IF_DEBUG_BREAK_SIZE_MATCHES(Name) \
133  if (bytecode_size == Size(Bytecode::k##Name, OperandScale::kSingle)) { \
134  return Bytecode::k##Name; \
135  }
136  DEBUG_BREAK_PLAIN_BYTECODE_LIST(RETURN_IF_DEBUG_BREAK_SIZE_MATCHES)
137 #undef RETURN_IF_DEBUG_BREAK_SIZE_MATCHES
138  UNREACHABLE();
139 }
140 
141 // static
142 int Bytecodes::GetOperandOffset(Bytecode bytecode, int i,
143  OperandScale operand_scale) {
144  DCHECK_LT(i, Bytecodes::NumberOfOperands(bytecode));
145  // TODO(oth): restore this to a statically determined constant.
146  int offset = 1;
147  for (int operand_index = 0; operand_index < i; ++operand_index) {
148  OperandSize operand_size =
149  GetOperandSize(bytecode, operand_index, operand_scale);
150  offset += static_cast<int>(operand_size);
151  }
152  return offset;
153 }
154 
155 // static
156 Bytecode Bytecodes::GetJumpWithoutToBoolean(Bytecode bytecode) {
157  switch (bytecode) {
158  case Bytecode::kJumpIfToBooleanTrue:
159  return Bytecode::kJumpIfTrue;
160  case Bytecode::kJumpIfToBooleanFalse:
161  return Bytecode::kJumpIfFalse;
162  case Bytecode::kJumpIfToBooleanTrueConstant:
163  return Bytecode::kJumpIfTrueConstant;
164  case Bytecode::kJumpIfToBooleanFalseConstant:
165  return Bytecode::kJumpIfFalseConstant;
166  default:
167  break;
168  }
169  UNREACHABLE();
170 }
171 
172 // static
173 bool Bytecodes::IsDebugBreak(Bytecode bytecode) {
174  switch (bytecode) {
175 #define CASE(Name, ...) case Bytecode::k##Name:
176  DEBUG_BREAK_BYTECODE_LIST(CASE);
177 #undef CASE
178  return true;
179  default:
180  break;
181  }
182  return false;
183 }
184 
185 // static
186 bool Bytecodes::IsRegisterOperandType(OperandType operand_type) {
187  switch (operand_type) {
188 #define CASE(Name, _) \
189  case OperandType::k##Name: \
190  return true;
191  REGISTER_OPERAND_TYPE_LIST(CASE)
192 #undef CASE
193 #define CASE(Name, _) \
194  case OperandType::k##Name: \
195  break;
196  NON_REGISTER_OPERAND_TYPE_LIST(CASE)
197 #undef CASE
198  }
199  return false;
200 }
201 
202 // static
203 bool Bytecodes::IsRegisterListOperandType(OperandType operand_type) {
204  switch (operand_type) {
205  case OperandType::kRegList:
206  case OperandType::kRegOutList:
207  return true;
208  default:
209  return false;
210  }
211 }
212 
213 bool Bytecodes::MakesCallAlongCriticalPath(Bytecode bytecode) {
214  if (IsCallOrConstruct(bytecode) || IsCallRuntime(bytecode)) return true;
215  switch (bytecode) {
216  case Bytecode::kCreateWithContext:
217  case Bytecode::kCreateBlockContext:
218  case Bytecode::kCreateCatchContext:
219  case Bytecode::kCreateRegExpLiteral:
220  return true;
221  default:
222  return false;
223  }
224 }
225 
226 // static
227 bool Bytecodes::IsRegisterInputOperandType(OperandType operand_type) {
228  switch (operand_type) {
229 #define CASE(Name, _) \
230  case OperandType::k##Name: \
231  return true;
232  REGISTER_INPUT_OPERAND_TYPE_LIST(CASE)
233 #undef CASE
234 #define CASE(Name, _) \
235  case OperandType::k##Name: \
236  break;
237  NON_REGISTER_OPERAND_TYPE_LIST(CASE)
238  REGISTER_OUTPUT_OPERAND_TYPE_LIST(CASE)
239 #undef CASE
240  }
241  return false;
242 }
243 
244 // static
245 bool Bytecodes::IsRegisterOutputOperandType(OperandType operand_type) {
246  switch (operand_type) {
247 #define CASE(Name, _) \
248  case OperandType::k##Name: \
249  return true;
250  REGISTER_OUTPUT_OPERAND_TYPE_LIST(CASE)
251 #undef CASE
252 #define CASE(Name, _) \
253  case OperandType::k##Name: \
254  break;
255  NON_REGISTER_OPERAND_TYPE_LIST(CASE)
256  REGISTER_INPUT_OPERAND_TYPE_LIST(CASE)
257 #undef CASE
258  }
259  return false;
260 }
261 
262 // static
263 bool Bytecodes::IsStarLookahead(Bytecode bytecode, OperandScale operand_scale) {
264  if (operand_scale == OperandScale::kSingle) {
265  switch (bytecode) {
266  case Bytecode::kLdaZero:
267  case Bytecode::kLdaSmi:
268  case Bytecode::kLdaNull:
269  case Bytecode::kLdaTheHole:
270  case Bytecode::kLdaConstant:
271  case Bytecode::kLdaUndefined:
272  case Bytecode::kLdaGlobal:
273  case Bytecode::kLdaNamedProperty:
274  case Bytecode::kLdaKeyedProperty:
275  case Bytecode::kLdaContextSlot:
276  case Bytecode::kLdaCurrentContextSlot:
277  case Bytecode::kAdd:
278  case Bytecode::kSub:
279  case Bytecode::kMul:
280  case Bytecode::kAddSmi:
281  case Bytecode::kSubSmi:
282  case Bytecode::kInc:
283  case Bytecode::kDec:
284  case Bytecode::kTypeOf:
285  case Bytecode::kCallAnyReceiver:
286  case Bytecode::kCallNoFeedback:
287  case Bytecode::kCallProperty:
288  case Bytecode::kCallProperty0:
289  case Bytecode::kCallProperty1:
290  case Bytecode::kCallProperty2:
291  case Bytecode::kCallUndefinedReceiver:
292  case Bytecode::kCallUndefinedReceiver0:
293  case Bytecode::kCallUndefinedReceiver1:
294  case Bytecode::kCallUndefinedReceiver2:
295  case Bytecode::kConstruct:
296  case Bytecode::kConstructWithSpread:
297  return true;
298  default:
299  return false;
300  }
301  }
302  return false;
303 }
304 
305 // static
306 bool Bytecodes::IsBytecodeWithScalableOperands(Bytecode bytecode) {
307  for (int i = 0; i < NumberOfOperands(bytecode); i++) {
308  if (OperandIsScalable(bytecode, i)) return true;
309  }
310  return false;
311 }
312 
313 // static
314 bool Bytecodes::IsUnsignedOperandType(OperandType operand_type) {
315  switch (operand_type) {
316 #define CASE(Name, _) \
317  case OperandType::k##Name: \
318  return OperandTraits<OperandType::k##Name>::TypeInfoTraits::kIsUnsigned;
319  OPERAND_TYPE_LIST(CASE)
320 #undef CASE
321  }
322  UNREACHABLE();
323 }
324 
325 // static
326 bool Bytecodes::BytecodeHasHandler(Bytecode bytecode,
327  OperandScale operand_scale) {
328  return operand_scale == OperandScale::kSingle ||
329  Bytecodes::IsBytecodeWithScalableOperands(bytecode);
330 }
331 
332 std::ostream& operator<<(std::ostream& os, const Bytecode& bytecode) {
333  return os << Bytecodes::ToString(bytecode);
334 }
335 
336 } // namespace interpreter
337 } // namespace internal
338 } // namespace v8
Definition: libplatform.h:13