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 #ifndef V8_INTERPRETER_BYTECODES_H_
6 #define V8_INTERPRETER_BYTECODES_H_
7 
8 #include <cstdint>
9 #include <iosfwd>
10 #include <string>
11 
12 #include "src/globals.h"
13 #include "src/interpreter/bytecode-operands.h"
14 
15 // This interface and it's implementation are independent of the
16 // libv8_base library as they are used by the interpreter and the
17 // standalone mkpeephole table generator program.
18 
19 namespace v8 {
20 namespace internal {
21 namespace interpreter {
22 
23 // The list of bytecodes which are interpreted by the interpreter.
24 // Format is V(<bytecode>, <accumulator_use>, <operands>).
25 #define BYTECODE_LIST(V)                                                       \
26   /* Extended width operands */                                                \
27   V(Wide, AccumulatorUse::kNone)                                               \
28   V(ExtraWide, AccumulatorUse::kNone)                                          \
29                                                                                \
30   /* Loading the accumulator */                                                \
31   V(LdaZero, AccumulatorUse::kWrite)                                           \
32   V(LdaSmi, AccumulatorUse::kWrite, OperandType::kImm)                         \
33   V(LdaUndefined, AccumulatorUse::kWrite)                                      \
34   V(LdaNull, AccumulatorUse::kWrite)                                           \
35   V(LdaTheHole, AccumulatorUse::kWrite)                                        \
36   V(LdaTrue, AccumulatorUse::kWrite)                                           \
37   V(LdaFalse, AccumulatorUse::kWrite)                                          \
38   V(LdaConstant, AccumulatorUse::kWrite, OperandType::kIdx)                    \
39                                                                                \
40   /* Globals */                                                                \
41   V(LdaGlobal, AccumulatorUse::kWrite, OperandType::kIdx)                      \
42   V(LdaGlobalInsideTypeof, AccumulatorUse::kWrite, OperandType::kIdx)          \
43   V(StaGlobalSloppy, AccumulatorUse::kRead, OperandType::kIdx,                 \
44     OperandType::kIdx)                                                         \
45   V(StaGlobalStrict, AccumulatorUse::kRead, OperandType::kIdx,                 \
46     OperandType::kIdx)                                                         \
47                                                                                \
48   /* Context operations */                                                     \
49   V(PushContext, AccumulatorUse::kRead, OperandType::kRegOut)                  \
50   V(PopContext, AccumulatorUse::kNone, OperandType::kReg)                      \
51   V(LdaContextSlot, AccumulatorUse::kWrite, OperandType::kReg,                 \
52     OperandType::kIdx, OperandType::kUImm)                                     \
53   V(LdaCurrentContextSlot, AccumulatorUse::kWrite, OperandType::kIdx)          \
54   V(StaContextSlot, AccumulatorUse::kRead, OperandType::kReg,                  \
55     OperandType::kIdx, OperandType::kUImm)                                     \
56   V(StaCurrentContextSlot, AccumulatorUse::kRead, OperandType::kIdx)           \
57                                                                                \
58   /* Load-Store lookup slots */                                                \
59   V(LdaLookupSlot, AccumulatorUse::kWrite, OperandType::kIdx)                  \
60   V(LdaLookupContextSlot, AccumulatorUse::kWrite, OperandType::kIdx,           \
61     OperandType::kIdx, OperandType::kUImm)                                     \
62   V(LdaLookupGlobalSlot, AccumulatorUse::kWrite, OperandType::kIdx,            \
63     OperandType::kIdx, OperandType::kUImm)                                     \
64   V(LdaLookupSlotInsideTypeof, AccumulatorUse::kWrite, OperandType::kIdx)      \
65   V(LdaLookupContextSlotInsideTypeof, AccumulatorUse::kWrite,                  \
66     OperandType::kIdx, OperandType::kIdx, OperandType::kUImm)                  \
67   V(LdaLookupGlobalSlotInsideTypeof, AccumulatorUse::kWrite,                   \
68     OperandType::kIdx, OperandType::kIdx, OperandType::kUImm)                  \
69   V(StaLookupSlotSloppy, AccumulatorUse::kReadWrite, OperandType::kIdx)        \
70   V(StaLookupSlotStrict, AccumulatorUse::kReadWrite, OperandType::kIdx)        \
71                                                                                \
72   /* Register-accumulator transfers */                                         \
73   V(Ldar, AccumulatorUse::kWrite, OperandType::kReg)                           \
74   V(Star, AccumulatorUse::kRead, OperandType::kRegOut)                         \
75                                                                                \
76   /* Register-register transfers */                                            \
77   V(Mov, AccumulatorUse::kNone, OperandType::kReg, OperandType::kRegOut)       \
78                                                                                \
79   /* Property loads (LoadIC) operations */                                     \
80   V(LdaNamedProperty, AccumulatorUse::kWrite, OperandType::kReg,               \
81     OperandType::kIdx, OperandType::kIdx)                                      \
82   V(LdaKeyedProperty, AccumulatorUse::kReadWrite, OperandType::kReg,           \
83     OperandType::kIdx)                                                         \
84                                                                                \
85   /* Operations on module variables */                                         \
86   V(LdaModuleVariable, AccumulatorUse::kWrite, OperandType::kImm,              \
87     OperandType::kUImm)                                                        \
88   V(StaModuleVariable, AccumulatorUse::kRead, OperandType::kImm,               \
89     OperandType::kUImm)                                                        \
90                                                                                \
91   /* Propery stores (StoreIC) operations */                                    \
92   V(StaNamedPropertySloppy, AccumulatorUse::kRead, OperandType::kReg,          \
93     OperandType::kIdx, OperandType::kIdx)                                      \
94   V(StaNamedPropertyStrict, AccumulatorUse::kRead, OperandType::kReg,          \
95     OperandType::kIdx, OperandType::kIdx)                                      \
96   V(StaKeyedPropertySloppy, AccumulatorUse::kRead, OperandType::kReg,          \
97     OperandType::kReg, OperandType::kIdx)                                      \
98   V(StaKeyedPropertyStrict, AccumulatorUse::kRead, OperandType::kReg,          \
99     OperandType::kReg, OperandType::kIdx)                                      \
100                                                                                \
101   /* Binary Operators */                                                       \
102   V(Add, AccumulatorUse::kReadWrite, OperandType::kReg, OperandType::kIdx)     \
103   V(Sub, AccumulatorUse::kReadWrite, OperandType::kReg, OperandType::kIdx)     \
104   V(Mul, AccumulatorUse::kReadWrite, OperandType::kReg, OperandType::kIdx)     \
105   V(Div, AccumulatorUse::kReadWrite, OperandType::kReg, OperandType::kIdx)     \
106   V(Mod, AccumulatorUse::kReadWrite, OperandType::kReg, OperandType::kIdx)     \
107   V(BitwiseOr, AccumulatorUse::kReadWrite, OperandType::kReg,                  \
108     OperandType::kIdx)                                                         \
109   V(BitwiseXor, AccumulatorUse::kReadWrite, OperandType::kReg,                 \
110     OperandType::kIdx)                                                         \
111   V(BitwiseAnd, AccumulatorUse::kReadWrite, OperandType::kReg,                 \
112     OperandType::kIdx)                                                         \
113   V(ShiftLeft, AccumulatorUse::kReadWrite, OperandType::kReg,                  \
114     OperandType::kIdx)                                                         \
115   V(ShiftRight, AccumulatorUse::kReadWrite, OperandType::kReg,                 \
116     OperandType::kIdx)                                                         \
117   V(ShiftRightLogical, AccumulatorUse::kReadWrite, OperandType::kReg,          \
118     OperandType::kIdx)                                                         \
119                                                                                \
120   /* Binary operators with immediate operands */                               \
121   V(AddSmi, AccumulatorUse::kWrite, OperandType::kImm, OperandType::kReg,      \
122     OperandType::kIdx)                                                         \
123   V(SubSmi, AccumulatorUse::kWrite, OperandType::kImm, OperandType::kReg,      \
124     OperandType::kIdx)                                                         \
125   V(BitwiseOrSmi, AccumulatorUse::kWrite, OperandType::kImm,                   \
126     OperandType::kReg, OperandType::kIdx)                                      \
127   V(BitwiseAndSmi, AccumulatorUse::kWrite, OperandType::kImm,                  \
128     OperandType::kReg, OperandType::kIdx)                                      \
129   V(ShiftLeftSmi, AccumulatorUse::kWrite, OperandType::kImm,                   \
130     OperandType::kReg, OperandType::kIdx)                                      \
131   V(ShiftRightSmi, AccumulatorUse::kWrite, OperandType::kImm,                  \
132     OperandType::kReg, OperandType::kIdx)                                      \
133                                                                                \
134   /* Unary Operators */                                                        \
135   V(Inc, AccumulatorUse::kReadWrite, OperandType::kIdx)                        \
136   V(Dec, AccumulatorUse::kReadWrite, OperandType::kIdx)                        \
137   V(ToBooleanLogicalNot, AccumulatorUse::kReadWrite)                           \
138   V(LogicalNot, AccumulatorUse::kReadWrite)                                    \
139   V(TypeOf, AccumulatorUse::kReadWrite)                                        \
140   V(DeletePropertyStrict, AccumulatorUse::kReadWrite, OperandType::kReg)       \
141   V(DeletePropertySloppy, AccumulatorUse::kReadWrite, OperandType::kReg)       \
142                                                                                \
143   /* Call operations */                                                        \
144   V(Call, AccumulatorUse::kWrite, OperandType::kReg, OperandType::kRegList,    \
145     OperandType::kRegCount, OperandType::kIdx)                                 \
146   V(CallProperty, AccumulatorUse::kWrite, OperandType::kReg,                   \
147     OperandType::kRegList, OperandType::kRegCount, OperandType::kIdx)          \
148   V(TailCall, AccumulatorUse::kWrite, OperandType::kReg,                       \
149     OperandType::kRegList, OperandType::kRegCount, OperandType::kIdx)          \
150   V(CallRuntime, AccumulatorUse::kWrite, OperandType::kRuntimeId,              \
151     OperandType::kRegList, OperandType::kRegCount)                             \
152   V(CallRuntimeForPair, AccumulatorUse::kNone, OperandType::kRuntimeId,        \
153     OperandType::kRegList, OperandType::kRegCount, OperandType::kRegOutPair)   \
154   V(CallJSRuntime, AccumulatorUse::kWrite, OperandType::kIdx,                  \
155     OperandType::kRegList, OperandType::kRegCount)                             \
156                                                                                \
157   /* Intrinsics */                                                             \
158   V(InvokeIntrinsic, AccumulatorUse::kWrite, OperandType::kIntrinsicId,        \
159     OperandType::kRegList, OperandType::kRegCount)                             \
160                                                                                \
161   /* New operator */                                                           \
162   V(New, AccumulatorUse::kReadWrite, OperandType::kReg, OperandType::kRegList, \
163     OperandType::kRegCount, OperandType::kIdx)                                 \
164                                                                                \
165   /* Test Operators */                                                         \
166   V(TestEqual, AccumulatorUse::kReadWrite, OperandType::kReg,                  \
167     OperandType::kIdx)                                                         \
168   V(TestNotEqual, AccumulatorUse::kReadWrite, OperandType::kReg,               \
169     OperandType::kIdx)                                                         \
170   V(TestEqualStrict, AccumulatorUse::kReadWrite, OperandType::kReg,            \
171     OperandType::kIdx)                                                         \
172   V(TestLessThan, AccumulatorUse::kReadWrite, OperandType::kReg,               \
173     OperandType::kIdx)                                                         \
174   V(TestGreaterThan, AccumulatorUse::kReadWrite, OperandType::kReg,            \
175     OperandType::kIdx)                                                         \
176   V(TestLessThanOrEqual, AccumulatorUse::kReadWrite, OperandType::kReg,        \
177     OperandType::kIdx)                                                         \
178   V(TestGreaterThanOrEqual, AccumulatorUse::kReadWrite, OperandType::kReg,     \
179     OperandType::kIdx)                                                         \
180   V(TestInstanceOf, AccumulatorUse::kReadWrite, OperandType::kReg)             \
181   V(TestIn, AccumulatorUse::kReadWrite, OperandType::kReg)                     \
182                                                                                \
183   /* Cast operators */                                                         \
184   V(ToName, AccumulatorUse::kRead, OperandType::kRegOut)                       \
185   V(ToNumber, AccumulatorUse::kRead, OperandType::kRegOut)                     \
186   V(ToObject, AccumulatorUse::kRead, OperandType::kRegOut)                     \
187                                                                                \
188   /* Literals */                                                               \
189   V(CreateRegExpLiteral, AccumulatorUse::kWrite, OperandType::kIdx,            \
190     OperandType::kIdx, OperandType::kFlag8)                                    \
191   V(CreateArrayLiteral, AccumulatorUse::kWrite, OperandType::kIdx,             \
192     OperandType::kIdx, OperandType::kFlag8)                                    \
193   V(CreateObjectLiteral, AccumulatorUse::kNone, OperandType::kIdx,             \
194     OperandType::kIdx, OperandType::kFlag8, OperandType::kRegOut)              \
195                                                                                \
196   /* Closure allocation */                                                     \
197   V(CreateClosure, AccumulatorUse::kWrite, OperandType::kIdx,                  \
198     OperandType::kFlag8)                                                       \
199                                                                                \
200   /* Context allocation */                                                     \
201   V(CreateBlockContext, AccumulatorUse::kReadWrite, OperandType::kIdx)         \
202   V(CreateCatchContext, AccumulatorUse::kReadWrite, OperandType::kReg,         \
203     OperandType::kIdx, OperandType::kIdx)                                      \
204   V(CreateFunctionContext, AccumulatorUse::kWrite, OperandType::kUImm)         \
205   V(CreateWithContext, AccumulatorUse::kReadWrite, OperandType::kReg,          \
206     OperandType::kIdx)                                                         \
207                                                                                \
208   /* Arguments allocation */                                                   \
209   V(CreateMappedArguments, AccumulatorUse::kWrite)                             \
210   V(CreateUnmappedArguments, AccumulatorUse::kWrite)                           \
211   V(CreateRestParameter, AccumulatorUse::kWrite)                               \
212                                                                                \
213   /* Control Flow */                                                           \
214   V(Jump, AccumulatorUse::kNone, OperandType::kImm)                            \
215   V(JumpConstant, AccumulatorUse::kNone, OperandType::kIdx)                    \
216   V(JumpIfTrue, AccumulatorUse::kRead, OperandType::kImm)                      \
217   V(JumpIfTrueConstant, AccumulatorUse::kRead, OperandType::kIdx)              \
218   V(JumpIfFalse, AccumulatorUse::kRead, OperandType::kImm)                     \
219   V(JumpIfFalseConstant, AccumulatorUse::kRead, OperandType::kIdx)             \
220   V(JumpIfToBooleanTrue, AccumulatorUse::kRead, OperandType::kImm)             \
221   V(JumpIfToBooleanTrueConstant, AccumulatorUse::kRead, OperandType::kIdx)     \
222   V(JumpIfToBooleanFalse, AccumulatorUse::kRead, OperandType::kImm)            \
223   V(JumpIfToBooleanFalseConstant, AccumulatorUse::kRead, OperandType::kIdx)    \
224   V(JumpIfNull, AccumulatorUse::kRead, OperandType::kImm)                      \
225   V(JumpIfNullConstant, AccumulatorUse::kRead, OperandType::kIdx)              \
226   V(JumpIfUndefined, AccumulatorUse::kRead, OperandType::kImm)                 \
227   V(JumpIfUndefinedConstant, AccumulatorUse::kRead, OperandType::kIdx)         \
228   V(JumpIfNotHole, AccumulatorUse::kRead, OperandType::kImm)                   \
229   V(JumpIfNotHoleConstant, AccumulatorUse::kRead, OperandType::kIdx)           \
230   V(JumpLoop, AccumulatorUse::kNone, OperandType::kImm, OperandType::kImm)     \
231                                                                                \
232   /* Complex flow control For..in */                                           \
233   V(ForInPrepare, AccumulatorUse::kNone, OperandType::kReg,                    \
234     OperandType::kRegOutTriple)                                                \
235   V(ForInContinue, AccumulatorUse::kWrite, OperandType::kReg,                  \
236     OperandType::kReg)                                                         \
237   V(ForInNext, AccumulatorUse::kWrite, OperandType::kReg, OperandType::kReg,   \
238     OperandType::kRegPair, OperandType::kIdx)                                  \
239   V(ForInStep, AccumulatorUse::kWrite, OperandType::kReg)                      \
240                                                                                \
241   /* Perform a stack guard check */                                            \
242   V(StackCheck, AccumulatorUse::kNone)                                         \
243                                                                                \
244   /* Non-local flow control */                                                 \
245   V(Throw, AccumulatorUse::kRead)                                              \
246   V(ReThrow, AccumulatorUse::kRead)                                            \
247   V(Return, AccumulatorUse::kRead)                                             \
248                                                                                \
249   /* Generators */                                                             \
250   V(SuspendGenerator, AccumulatorUse::kRead, OperandType::kReg)                \
251   V(ResumeGenerator, AccumulatorUse::kWrite, OperandType::kReg)                \
252                                                                                \
253   /* Debugger */                                                               \
254   V(Debugger, AccumulatorUse::kNone)                                           \
255                                                                                \
256   /* Debug Breakpoints - one for each possible size of unscaled bytecodes */   \
257   /* and one for each operand widening prefix bytecode                    */   \
258   V(DebugBreak0, AccumulatorUse::kRead)                                        \
259   V(DebugBreak1, AccumulatorUse::kRead, OperandType::kReg)                     \
260   V(DebugBreak2, AccumulatorUse::kRead, OperandType::kReg, OperandType::kReg)  \
261   V(DebugBreak3, AccumulatorUse::kRead, OperandType::kReg, OperandType::kReg,  \
262     OperandType::kReg)                                                         \
263   V(DebugBreak4, AccumulatorUse::kRead, OperandType::kReg, OperandType::kReg,  \
264     OperandType::kReg, OperandType::kReg)                                      \
265   V(DebugBreak5, AccumulatorUse::kRead, OperandType::kRuntimeId,               \
266     OperandType::kReg, OperandType::kReg)                                      \
267   V(DebugBreak6, AccumulatorUse::kRead, OperandType::kRuntimeId,               \
268     OperandType::kReg, OperandType::kReg, OperandType::kReg)                   \
269   V(DebugBreakWide, AccumulatorUse::kRead)                                     \
270   V(DebugBreakExtraWide, AccumulatorUse::kRead)                                \
271                                                                                \
272   /* Illegal bytecode (terminates execution) */                                \
273   V(Illegal, AccumulatorUse::kNone)                                            \
274                                                                                \
275   /* No operation (used to maintain source positions for peephole */           \
276   /* eliminated bytecodes). */                                                 \
277   V(Nop, AccumulatorUse::kNone)
278 
279 // List of debug break bytecodes.
280 #define DEBUG_BREAK_PLAIN_BYTECODE_LIST(V) \
281   V(DebugBreak0)                           \
282   V(DebugBreak1)                           \
283   V(DebugBreak2)                           \
284   V(DebugBreak3)                           \
285   V(DebugBreak4)                           \
286   V(DebugBreak5)                           \
287   V(DebugBreak6)
288 
289 #define DEBUG_BREAK_PREFIX_BYTECODE_LIST(V) \
290   V(DebugBreakWide)                         \
291   V(DebugBreakExtraWide)
292 
293 #define DEBUG_BREAK_BYTECODE_LIST(V) \
294   DEBUG_BREAK_PLAIN_BYTECODE_LIST(V) \
295   DEBUG_BREAK_PREFIX_BYTECODE_LIST(V)
296 
297 // Enumeration of interpreter bytecodes.
298 enum class Bytecode : uint8_t {
299 #define DECLARE_BYTECODE(Name, ...) k##Name,
300   BYTECODE_LIST(DECLARE_BYTECODE)
301 #undef DECLARE_BYTECODE
302 #define COUNT_BYTECODE(x, ...) +1
303   // The COUNT_BYTECODE macro will turn this into kLast = -1 +1 +1... which will
304   // evaluate to the same value as the last real bytecode.
305   kLast = -1 BYTECODE_LIST(COUNT_BYTECODE)
306 #undef COUNT_BYTECODE
307 };
308 
309 // TODO(rmcilroy): Remove once we switch to MSVC 2015 which supports constexpr.
310 // See crbug.com/603131.
311 #if V8_CC_MSVC
312 #define CONSTEXPR const
313 #else
314 #define CONSTEXPR constexpr
315 #endif
316 
317 class V8_EXPORT_PRIVATE Bytecodes final {
318  public:
319   //  The maximum number of operands a bytecode may have.
320   static const int kMaxOperands = 4;
321 
322   // Returns string representation of |bytecode|.
323   static const char* ToString(Bytecode bytecode);
324 
325   // Returns string representation of |bytecode|.
326   static std::string ToString(Bytecode bytecode, OperandScale operand_scale);
327 
328   // Returns byte value of bytecode.
ToByte(Bytecode bytecode)329   static uint8_t ToByte(Bytecode bytecode) {
330     DCHECK_LE(bytecode, Bytecode::kLast);
331     return static_cast<uint8_t>(bytecode);
332   }
333 
334   // Returns bytecode for |value|.
FromByte(uint8_t value)335   static Bytecode FromByte(uint8_t value) {
336     Bytecode bytecode = static_cast<Bytecode>(value);
337     DCHECK(bytecode <= Bytecode::kLast);
338     return bytecode;
339   }
340 
341   // Returns the prefix bytecode representing an operand scale to be
342   // applied to a a bytecode.
OperandScaleToPrefixBytecode(OperandScale operand_scale)343   static Bytecode OperandScaleToPrefixBytecode(OperandScale operand_scale) {
344     switch (operand_scale) {
345       case OperandScale::kQuadruple:
346         return Bytecode::kExtraWide;
347       case OperandScale::kDouble:
348         return Bytecode::kWide;
349       default:
350         UNREACHABLE();
351         return Bytecode::kIllegal;
352     }
353   }
354 
355   // Returns true if the operand scale requires a prefix bytecode.
OperandScaleRequiresPrefixBytecode(OperandScale operand_scale)356   static bool OperandScaleRequiresPrefixBytecode(OperandScale operand_scale) {
357     return operand_scale != OperandScale::kSingle;
358   }
359 
360   // Returns the scaling applied to scalable operands if bytecode is
361   // is a scaling prefix.
PrefixBytecodeToOperandScale(Bytecode bytecode)362   static OperandScale PrefixBytecodeToOperandScale(Bytecode bytecode) {
363     switch (bytecode) {
364       case Bytecode::kExtraWide:
365       case Bytecode::kDebugBreakExtraWide:
366         return OperandScale::kQuadruple;
367       case Bytecode::kWide:
368       case Bytecode::kDebugBreakWide:
369         return OperandScale::kDouble;
370       default:
371         UNREACHABLE();
372         return OperandScale::kSingle;
373     }
374   }
375 
376   // Returns how accumulator is used by |bytecode|.
GetAccumulatorUse(Bytecode bytecode)377   static AccumulatorUse GetAccumulatorUse(Bytecode bytecode) {
378     DCHECK(bytecode <= Bytecode::kLast);
379     return kAccumulatorUse[static_cast<size_t>(bytecode)];
380   }
381 
382   // Returns true if |bytecode| reads the accumulator.
ReadsAccumulator(Bytecode bytecode)383   static bool ReadsAccumulator(Bytecode bytecode) {
384     return (GetAccumulatorUse(bytecode) & AccumulatorUse::kRead) ==
385            AccumulatorUse::kRead;
386   }
387 
388   // Returns true if |bytecode| writes the accumulator.
WritesAccumulator(Bytecode bytecode)389   static bool WritesAccumulator(Bytecode bytecode) {
390     return (GetAccumulatorUse(bytecode) & AccumulatorUse::kWrite) ==
391            AccumulatorUse::kWrite;
392   }
393 
394   // Return true if |bytecode| writes the accumulator with a boolean value.
WritesBooleanToAccumulator(Bytecode bytecode)395   static bool WritesBooleanToAccumulator(Bytecode bytecode) {
396     switch (bytecode) {
397       case Bytecode::kLdaTrue:
398       case Bytecode::kLdaFalse:
399       case Bytecode::kToBooleanLogicalNot:
400       case Bytecode::kLogicalNot:
401       case Bytecode::kTestEqual:
402       case Bytecode::kTestNotEqual:
403       case Bytecode::kTestEqualStrict:
404       case Bytecode::kTestLessThan:
405       case Bytecode::kTestLessThanOrEqual:
406       case Bytecode::kTestGreaterThan:
407       case Bytecode::kTestGreaterThanOrEqual:
408       case Bytecode::kTestInstanceOf:
409       case Bytecode::kTestIn:
410       case Bytecode::kForInContinue:
411         return true;
412       default:
413         return false;
414     }
415   }
416 
417   // Return true if |bytecode| is an accumulator load without effects,
418   // e.g. LdaConstant, LdaTrue, Ldar.
IsAccumulatorLoadWithoutEffects(Bytecode bytecode)419   static CONSTEXPR bool IsAccumulatorLoadWithoutEffects(Bytecode bytecode) {
420     return bytecode == Bytecode::kLdar || bytecode == Bytecode::kLdaZero ||
421            bytecode == Bytecode::kLdaSmi || bytecode == Bytecode::kLdaNull ||
422            bytecode == Bytecode::kLdaTrue || bytecode == Bytecode::kLdaFalse ||
423            bytecode == Bytecode::kLdaUndefined ||
424            bytecode == Bytecode::kLdaTheHole ||
425            bytecode == Bytecode::kLdaConstant ||
426            bytecode == Bytecode::kLdaContextSlot ||
427            bytecode == Bytecode::kLdaCurrentContextSlot;
428   }
429 
430   // Return true if |bytecode| is a register load without effects,
431   // e.g. Mov, Star.
IsRegisterLoadWithoutEffects(Bytecode bytecode)432   static CONSTEXPR bool IsRegisterLoadWithoutEffects(Bytecode bytecode) {
433     return bytecode == Bytecode::kMov || bytecode == Bytecode::kPopContext ||
434            bytecode == Bytecode::kPushContext || bytecode == Bytecode::kStar;
435   }
436 
437   // Returns true if the bytecode is a conditional jump taking
438   // an immediate byte operand (OperandType::kImm).
IsConditionalJumpImmediate(Bytecode bytecode)439   static CONSTEXPR bool IsConditionalJumpImmediate(Bytecode bytecode) {
440     return bytecode == Bytecode::kJumpIfTrue ||
441            bytecode == Bytecode::kJumpIfFalse ||
442            bytecode == Bytecode::kJumpIfToBooleanTrue ||
443            bytecode == Bytecode::kJumpIfToBooleanFalse ||
444            bytecode == Bytecode::kJumpIfNotHole ||
445            bytecode == Bytecode::kJumpIfNull ||
446            bytecode == Bytecode::kJumpIfUndefined;
447   }
448 
449   // Returns true if the bytecode is a conditional jump taking
450   // a constant pool entry (OperandType::kIdx).
IsConditionalJumpConstant(Bytecode bytecode)451   static CONSTEXPR bool IsConditionalJumpConstant(Bytecode bytecode) {
452     return bytecode == Bytecode::kJumpIfTrueConstant ||
453            bytecode == Bytecode::kJumpIfFalseConstant ||
454            bytecode == Bytecode::kJumpIfToBooleanTrueConstant ||
455            bytecode == Bytecode::kJumpIfToBooleanFalseConstant ||
456            bytecode == Bytecode::kJumpIfNotHoleConstant ||
457            bytecode == Bytecode::kJumpIfNullConstant ||
458            bytecode == Bytecode::kJumpIfUndefinedConstant;
459   }
460 
461   // Returns true if the bytecode is a conditional jump taking
462   // any kind of operand.
IsConditionalJump(Bytecode bytecode)463   static CONSTEXPR bool IsConditionalJump(Bytecode bytecode) {
464     return IsConditionalJumpImmediate(bytecode) ||
465            IsConditionalJumpConstant(bytecode);
466   }
467 
468   // Returns true if the bytecode is a jump or a conditional jump taking
469   // an immediate byte operand (OperandType::kImm).
IsJumpImmediate(Bytecode bytecode)470   static CONSTEXPR bool IsJumpImmediate(Bytecode bytecode) {
471     return bytecode == Bytecode::kJump || bytecode == Bytecode::kJumpLoop ||
472            IsConditionalJumpImmediate(bytecode);
473   }
474 
475   // Returns true if the bytecode is a jump or conditional jump taking a
476   // constant pool entry (OperandType::kIdx).
IsJumpConstant(Bytecode bytecode)477   static CONSTEXPR bool IsJumpConstant(Bytecode bytecode) {
478     return bytecode == Bytecode::kJumpConstant ||
479            IsConditionalJumpConstant(bytecode);
480   }
481 
482   // Returns true if the bytecode is a jump that internally coerces the
483   // accumulator to a boolean.
IsJumpIfToBoolean(Bytecode bytecode)484   static CONSTEXPR bool IsJumpIfToBoolean(Bytecode bytecode) {
485     return bytecode == Bytecode::kJumpIfToBooleanTrue ||
486            bytecode == Bytecode::kJumpIfToBooleanFalse ||
487            bytecode == Bytecode::kJumpIfToBooleanTrueConstant ||
488            bytecode == Bytecode::kJumpIfToBooleanFalseConstant;
489   }
490 
491   // Returns true if the bytecode is a jump or conditional jump taking
492   // any kind of operand.
IsJump(Bytecode bytecode)493   static CONSTEXPR bool IsJump(Bytecode bytecode) {
494     return IsJumpImmediate(bytecode) || IsJumpConstant(bytecode);
495   }
496 
497   // Returns true if the bytecode is a conditional jump, a jump, or a return.
IsJumpOrReturn(Bytecode bytecode)498   static CONSTEXPR bool IsJumpOrReturn(Bytecode bytecode) {
499     return bytecode == Bytecode::kReturn || IsJump(bytecode);
500   }
501 
502   // Return true if |bytecode| is a jump without effects,
503   // e.g.  any jump excluding those that include type coercion like
504   // JumpIfTrueToBoolean.
IsJumpWithoutEffects(Bytecode bytecode)505   static CONSTEXPR bool IsJumpWithoutEffects(Bytecode bytecode) {
506     return IsJump(bytecode) && !IsJumpIfToBoolean(bytecode);
507   }
508 
509   // Returns true if |bytecode| has no effects. These bytecodes only manipulate
510   // interpreter frame state and will never throw.
IsWithoutExternalSideEffects(Bytecode bytecode)511   static CONSTEXPR bool IsWithoutExternalSideEffects(Bytecode bytecode) {
512     return (IsAccumulatorLoadWithoutEffects(bytecode) ||
513             IsRegisterLoadWithoutEffects(bytecode) ||
514             bytecode == Bytecode::kNop || IsJumpWithoutEffects(bytecode));
515   }
516 
517   // Returns true if the bytecode is Ldar or Star.
IsLdarOrStar(Bytecode bytecode)518   static CONSTEXPR bool IsLdarOrStar(Bytecode bytecode) {
519     return bytecode == Bytecode::kLdar || bytecode == Bytecode::kStar;
520   }
521 
522   // Returns true if |bytecode| puts a name in the accumulator.
PutsNameInAccumulator(Bytecode bytecode)523   static CONSTEXPR bool PutsNameInAccumulator(Bytecode bytecode) {
524     return bytecode == Bytecode::kTypeOf;
525   }
526 
527   // Returns true if the bytecode is a call or a constructor call.
IsCallOrNew(Bytecode bytecode)528   static CONSTEXPR bool IsCallOrNew(Bytecode bytecode) {
529     return bytecode == Bytecode::kCall || bytecode == Bytecode::kCallProperty ||
530            bytecode == Bytecode::kTailCall || bytecode == Bytecode::kNew;
531   }
532 
533   // Returns true if the bytecode is a call to the runtime.
IsCallRuntime(Bytecode bytecode)534   static CONSTEXPR bool IsCallRuntime(Bytecode bytecode) {
535     return bytecode == Bytecode::kCallRuntime ||
536            bytecode == Bytecode::kCallRuntimeForPair ||
537            bytecode == Bytecode::kInvokeIntrinsic;
538   }
539 
540   // Returns true if the bytecode is a scaling prefix bytecode.
IsPrefixScalingBytecode(Bytecode bytecode)541   static CONSTEXPR bool IsPrefixScalingBytecode(Bytecode bytecode) {
542     return bytecode == Bytecode::kExtraWide || bytecode == Bytecode::kWide ||
543            bytecode == Bytecode::kDebugBreakExtraWide ||
544            bytecode == Bytecode::kDebugBreakWide;
545   }
546 
547   // Returns the number of values which |bytecode| returns.
ReturnCount(Bytecode bytecode)548   static CONSTEXPR size_t ReturnCount(Bytecode bytecode) {
549     return bytecode == Bytecode::kReturn ? 1 : 0;
550   }
551 
552   // Returns the number of operands expected by |bytecode|.
NumberOfOperands(Bytecode bytecode)553   static int NumberOfOperands(Bytecode bytecode) {
554     DCHECK(bytecode <= Bytecode::kLast);
555     return kOperandCount[static_cast<size_t>(bytecode)];
556   }
557 
558   // Returns the i-th operand of |bytecode|.
GetOperandType(Bytecode bytecode,int i)559   static OperandType GetOperandType(Bytecode bytecode, int i) {
560     DCHECK_LE(bytecode, Bytecode::kLast);
561     DCHECK_LT(i, NumberOfOperands(bytecode));
562     DCHECK_GE(i, 0);
563     return GetOperandTypes(bytecode)[i];
564   }
565 
566   // Returns a pointer to an array of operand types terminated in
567   // OperandType::kNone.
GetOperandTypes(Bytecode bytecode)568   static const OperandType* GetOperandTypes(Bytecode bytecode) {
569     DCHECK(bytecode <= Bytecode::kLast);
570     return kOperandTypes[static_cast<size_t>(bytecode)];
571   }
572 
OperandIsScalableSignedByte(Bytecode bytecode,int operand_index)573   static bool OperandIsScalableSignedByte(Bytecode bytecode,
574                                           int operand_index) {
575     DCHECK(bytecode <= Bytecode::kLast);
576     return kOperandTypeInfos[static_cast<size_t>(bytecode)][operand_index] ==
577            OperandTypeInfo::kScalableSignedByte;
578   }
579 
OperandIsScalableUnsignedByte(Bytecode bytecode,int operand_index)580   static bool OperandIsScalableUnsignedByte(Bytecode bytecode,
581                                             int operand_index) {
582     DCHECK(bytecode <= Bytecode::kLast);
583     return kOperandTypeInfos[static_cast<size_t>(bytecode)][operand_index] ==
584            OperandTypeInfo::kScalableUnsignedByte;
585   }
586 
OperandIsScalable(Bytecode bytecode,int operand_index)587   static bool OperandIsScalable(Bytecode bytecode, int operand_index) {
588     return OperandIsScalableSignedByte(bytecode, operand_index) ||
589            OperandIsScalableUnsignedByte(bytecode, operand_index);
590   }
591 
592   // Returns true if the bytecode has wider operand forms.
593   static bool IsBytecodeWithScalableOperands(Bytecode bytecode);
594 
595   // Returns the size of the i-th operand of |bytecode|.
GetOperandSize(Bytecode bytecode,int i,OperandScale operand_scale)596   static OperandSize GetOperandSize(Bytecode bytecode, int i,
597                                     OperandScale operand_scale) {
598     CHECK_LT(i, NumberOfOperands(bytecode));
599     return GetOperandSizes(bytecode, operand_scale)[i];
600   }
601 
602   // Returns the operand sizes of |bytecode| with scale |operand_scale|.
GetOperandSizes(Bytecode bytecode,OperandScale operand_scale)603   static const OperandSize* GetOperandSizes(Bytecode bytecode,
604                                             OperandScale operand_scale) {
605     DCHECK(bytecode <= Bytecode::kLast);
606     DCHECK_GE(operand_scale, OperandScale::kSingle);
607     DCHECK_LE(operand_scale, OperandScale::kLast);
608     STATIC_ASSERT(static_cast<int>(OperandScale::kQuadruple) == 4 &&
609                   OperandScale::kLast == OperandScale::kQuadruple);
610     int scale_index = static_cast<int>(operand_scale) >> 1;
611     return kOperandSizes[static_cast<size_t>(bytecode)][scale_index];
612   }
613 
614   // Returns the offset of the i-th operand of |bytecode| relative to the start
615   // of the bytecode.
616   static int GetOperandOffset(Bytecode bytecode, int i,
617                               OperandScale operand_scale);
618 
619   // Returns the size of the bytecode including its operands for the
620   // given |operand_scale|.
Size(Bytecode bytecode,OperandScale operand_scale)621   static int Size(Bytecode bytecode, OperandScale operand_scale) {
622     DCHECK(bytecode <= Bytecode::kLast);
623     STATIC_ASSERT(static_cast<int>(OperandScale::kQuadruple) == 4 &&
624                   OperandScale::kLast == OperandScale::kQuadruple);
625     int scale_index = static_cast<int>(operand_scale) >> 1;
626     return kBytecodeSizes[static_cast<size_t>(bytecode)][scale_index];
627   }
628 
629   // Returns a debug break bytecode to replace |bytecode|.
630   static Bytecode GetDebugBreak(Bytecode bytecode);
631 
632   // Returns the equivalent jump bytecode without the accumulator coercion.
633   static Bytecode GetJumpWithoutToBoolean(Bytecode bytecode);
634 
635   // Returns true if the bytecode is a debug break.
636   static bool IsDebugBreak(Bytecode bytecode);
637 
638   // Returns true if |operand_type| is any type of register operand.
639   static bool IsRegisterOperandType(OperandType operand_type);
640 
641   // Returns true if |operand_type| represents a register used as an input.
642   static bool IsRegisterInputOperandType(OperandType operand_type);
643 
644   // Returns true if |operand_type| represents a register used as an output.
645   static bool IsRegisterOutputOperandType(OperandType operand_type);
646 
647   // Returns true if the handler for |bytecode| should look ahead and inline a
648   // dispatch to a Star bytecode.
649   static bool IsStarLookahead(Bytecode bytecode, OperandScale operand_scale);
650 
651   // Returns the number of registers represented by a register operand. For
652   // instance, a RegPair represents two registers. Should not be called for
653   // kRegList which has a variable number of registers based on the following
654   // kRegCount operand.
GetNumberOfRegistersRepresentedBy(OperandType operand_type)655   static int GetNumberOfRegistersRepresentedBy(OperandType operand_type) {
656     switch (operand_type) {
657       case OperandType::kReg:
658       case OperandType::kRegOut:
659         return 1;
660       case OperandType::kRegPair:
661       case OperandType::kRegOutPair:
662         return 2;
663       case OperandType::kRegOutTriple:
664         return 3;
665       case OperandType::kRegList:
666         UNREACHABLE();
667         return 0;
668       default:
669         return 0;
670     }
671     return 0;
672   }
673 
674   // Returns the size of |operand| for |operand_scale|.
675   static OperandSize SizeOfOperand(OperandType operand, OperandScale scale);
676 
677   // Returns true if |operand_type| is a runtime-id operand (kRuntimeId).
678   static bool IsRuntimeIdOperandType(OperandType operand_type);
679 
680   // Returns true if |operand_type| is unsigned, false if signed.
681   static bool IsUnsignedOperandType(OperandType operand_type);
682 
683   // Returns true if a handler is generated for a bytecode at a given
684   // operand scale. All bytecodes have handlers at OperandScale::kSingle,
685   // but only bytecodes with scalable operands have handlers with larger
686   // OperandScale values.
687   static bool BytecodeHasHandler(Bytecode bytecode, OperandScale operand_scale);
688 
689   // Return the operand scale required to hold a signed operand with |value|.
ScaleForSignedOperand(int32_t value)690   static OperandScale ScaleForSignedOperand(int32_t value) {
691     if (value >= kMinInt8 && value <= kMaxInt8) {
692       return OperandScale::kSingle;
693     } else if (value >= kMinInt16 && value <= kMaxInt16) {
694       return OperandScale::kDouble;
695     } else {
696       return OperandScale::kQuadruple;
697     }
698   }
699 
700   // Return the operand scale required to hold an unsigned operand with |value|.
ScaleForUnsignedOperand(uint32_t value)701   static OperandScale ScaleForUnsignedOperand(uint32_t value) {
702     if (value <= kMaxUInt8) {
703       return OperandScale::kSingle;
704     } else if (value <= kMaxUInt16) {
705       return OperandScale::kDouble;
706     } else {
707       return OperandScale::kQuadruple;
708     }
709   }
710 
711   // Return the operand size required to hold an unsigned operand with |value|.
SizeForUnsignedOperand(uint32_t value)712   static OperandSize SizeForUnsignedOperand(uint32_t value) {
713     if (value <= kMaxUInt8) {
714       return OperandSize::kByte;
715     } else if (value <= kMaxUInt16) {
716       return OperandSize::kShort;
717     } else {
718       return OperandSize::kQuad;
719     }
720   }
721 
722  private:
723   static const OperandType* const kOperandTypes[];
724   static const OperandTypeInfo* const kOperandTypeInfos[];
725   static const int kOperandCount[];
726   static const int kNumberOfRegisterOperands[];
727   static const AccumulatorUse kAccumulatorUse[];
728   static const bool kIsScalable[];
729   static const int kBytecodeSizes[][3];
730   static const OperandSize* const kOperandSizes[][3];
731 };
732 
733 // TODO(rmcilroy): Remove once we switch to MSVC 2015 which supports constexpr.
734 // See crbug.com/603131.
735 #undef CONSTEXPR
736 
737 V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
738                                            const Bytecode& bytecode);
739 
740 }  // namespace interpreter
741 }  // namespace internal
742 }  // namespace v8
743 
744 #endif  // V8_INTERPRETER_BYTECODES_H_
745