v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
bytecodes.h
Go to the documentation of this file.
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/common/globals.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
19namespace v8 {
20namespace internal {
21namespace interpreter {
22
23// The list of single-byte Star variants, in the format of BYTECODE_LIST.
24#define SHORT_STAR_BYTECODE_LIST(V) \
25 V(Star15, ImplicitRegisterUse::kReadAccumulatorWriteShortStar) \
26 V(Star14, ImplicitRegisterUse::kReadAccumulatorWriteShortStar) \
27 V(Star13, ImplicitRegisterUse::kReadAccumulatorWriteShortStar) \
28 V(Star12, ImplicitRegisterUse::kReadAccumulatorWriteShortStar) \
29 V(Star11, ImplicitRegisterUse::kReadAccumulatorWriteShortStar) \
30 V(Star10, ImplicitRegisterUse::kReadAccumulatorWriteShortStar) \
31 V(Star9, ImplicitRegisterUse::kReadAccumulatorWriteShortStar) \
32 V(Star8, ImplicitRegisterUse::kReadAccumulatorWriteShortStar) \
33 V(Star7, ImplicitRegisterUse::kReadAccumulatorWriteShortStar) \
34 V(Star6, ImplicitRegisterUse::kReadAccumulatorWriteShortStar) \
35 V(Star5, ImplicitRegisterUse::kReadAccumulatorWriteShortStar) \
36 V(Star4, ImplicitRegisterUse::kReadAccumulatorWriteShortStar) \
37 V(Star3, ImplicitRegisterUse::kReadAccumulatorWriteShortStar) \
38 V(Star2, ImplicitRegisterUse::kReadAccumulatorWriteShortStar) \
39 V(Star1, ImplicitRegisterUse::kReadAccumulatorWriteShortStar) \
40 V(Star0, ImplicitRegisterUse::kReadAccumulatorWriteShortStar)
41
42// The list of bytecodes which have unique handlers (no other bytecode is
43// executed using identical code).
44// Format is V(<bytecode>, <implicit_register_use>, <operands>).
45// Use V_TSA for bytecode handlers for which a TSA-based (Turboshaft Assembler)
46// alternative implementation exists, which will be used when
47// V8_ENABLE_EXPERIMENTAL_TSA_BUILTINS is set. Otherwise V_TSA is identical to
48// V.
49#define BYTECODE_LIST_WITH_UNIQUE_HANDLERS_IMPL(V, V_TSA) \
50 /* Extended width operands */ \
51 V(Wide, ImplicitRegisterUse::kNone) \
52 V(ExtraWide, ImplicitRegisterUse::kNone) \
53 \
54 /* Debug Breakpoints - one for each possible size of unscaled bytecodes */ \
55 /* and one for each operand widening prefix bytecode */ \
56 V(DebugBreakWide, ImplicitRegisterUse::kReadWriteAccumulator) \
57 V(DebugBreakExtraWide, ImplicitRegisterUse::kReadWriteAccumulator) \
58 V(DebugBreak0, ImplicitRegisterUse::kReadWriteAccumulator) \
59 V(DebugBreak1, ImplicitRegisterUse::kReadWriteAccumulator, \
60 OperandType::kReg) \
61 V(DebugBreak2, ImplicitRegisterUse::kReadWriteAccumulator, \
62 OperandType::kReg, OperandType::kReg) \
63 V(DebugBreak3, ImplicitRegisterUse::kReadWriteAccumulator, \
64 OperandType::kReg, OperandType::kReg, OperandType::kReg) \
65 V(DebugBreak4, ImplicitRegisterUse::kReadWriteAccumulator, \
66 OperandType::kReg, OperandType::kReg, OperandType::kReg, \
67 OperandType::kReg) \
68 V(DebugBreak5, ImplicitRegisterUse::kReadWriteAccumulator, \
69 OperandType::kRuntimeId, OperandType::kReg, OperandType::kReg) \
70 V(DebugBreak6, ImplicitRegisterUse::kReadWriteAccumulator, \
71 OperandType::kRuntimeId, OperandType::kReg, OperandType::kReg, \
72 OperandType::kReg) \
73 \
74 /* Side-effect-free bytecodes -- carefully ordered for efficient checks */ \
75 /* - [Loading the accumulator] */ \
76 V(Ldar, ImplicitRegisterUse::kWriteAccumulator, OperandType::kReg) \
77 V(LdaZero, ImplicitRegisterUse::kWriteAccumulator) \
78 V(LdaSmi, ImplicitRegisterUse::kWriteAccumulator, OperandType::kImm) \
79 V(LdaUndefined, ImplicitRegisterUse::kWriteAccumulator) \
80 V(LdaNull, ImplicitRegisterUse::kWriteAccumulator) \
81 V(LdaTheHole, ImplicitRegisterUse::kWriteAccumulator) \
82 V(LdaTrue, ImplicitRegisterUse::kWriteAccumulator) \
83 V(LdaFalse, ImplicitRegisterUse::kWriteAccumulator) \
84 V(LdaConstant, ImplicitRegisterUse::kWriteAccumulator, OperandType::kIdx) \
85 V(LdaContextSlot, ImplicitRegisterUse::kWriteAccumulator, OperandType::kReg, \
86 OperandType::kIdx, OperandType::kUImm) \
87 V(LdaScriptContextSlot, ImplicitRegisterUse::kWriteAccumulator, \
88 OperandType::kReg, OperandType::kIdx, OperandType::kUImm) \
89 V(LdaImmutableContextSlot, ImplicitRegisterUse::kWriteAccumulator, \
90 OperandType::kReg, OperandType::kIdx, OperandType::kUImm) \
91 V(LdaCurrentContextSlot, ImplicitRegisterUse::kWriteAccumulator, \
92 OperandType::kIdx) \
93 V(LdaCurrentScriptContextSlot, ImplicitRegisterUse::kWriteAccumulator, \
94 OperandType::kIdx) \
95 V(LdaImmutableCurrentContextSlot, ImplicitRegisterUse::kWriteAccumulator, \
96 OperandType::kIdx) \
97 /* - [Register Loads ] */ \
98 V(Star, ImplicitRegisterUse::kReadAccumulator, OperandType::kRegOut) \
99 V(Mov, ImplicitRegisterUse::kNone, OperandType::kReg, OperandType::kRegOut) \
100 V(PushContext, ImplicitRegisterUse::kReadAccumulator, OperandType::kRegOut) \
101 V(PopContext, ImplicitRegisterUse::kNone, OperandType::kReg) \
102 /* - [Test Operations ] */ \
103 V(TestReferenceEqual, ImplicitRegisterUse::kReadWriteAccumulator, \
104 OperandType::kReg) \
105 V(TestUndetectable, ImplicitRegisterUse::kReadWriteAccumulator) \
106 V(TestNull, ImplicitRegisterUse::kReadWriteAccumulator) \
107 V(TestUndefined, ImplicitRegisterUse::kReadWriteAccumulator) \
108 V(TestTypeOf, ImplicitRegisterUse::kReadWriteAccumulator, \
109 OperandType::kFlag8) \
110 \
111 /* Globals */ \
112 V(LdaGlobal, ImplicitRegisterUse::kWriteAccumulator, OperandType::kIdx, \
113 OperandType::kIdx) \
114 V(LdaGlobalInsideTypeof, ImplicitRegisterUse::kWriteAccumulator, \
115 OperandType::kIdx, OperandType::kIdx) \
116 V(StaGlobal, ImplicitRegisterUse::kReadAndClobberAccumulator, \
117 OperandType::kIdx, OperandType::kIdx) \
118 \
119 /* Context operations */ \
120 V(StaContextSlot, ImplicitRegisterUse::kReadAccumulator, OperandType::kReg, \
121 OperandType::kIdx, OperandType::kUImm) \
122 V(StaCurrentContextSlot, ImplicitRegisterUse::kReadAccumulator, \
123 OperandType::kIdx) \
124 V(StaScriptContextSlot, ImplicitRegisterUse::kReadAccumulator, \
125 OperandType::kReg, OperandType::kIdx, OperandType::kUImm) \
126 V(StaCurrentScriptContextSlot, ImplicitRegisterUse::kReadAccumulator, \
127 OperandType::kIdx) \
128 \
129 /* Load-Store lookup slots */ \
130 V(LdaLookupSlot, ImplicitRegisterUse::kWriteAccumulator, OperandType::kIdx) \
131 V(LdaLookupContextSlot, ImplicitRegisterUse::kWriteAccumulator, \
132 OperandType::kIdx, OperandType::kIdx, OperandType::kUImm) \
133 V(LdaLookupScriptContextSlot, ImplicitRegisterUse::kWriteAccumulator, \
134 OperandType::kIdx, OperandType::kIdx, OperandType::kUImm) \
135 V(LdaLookupGlobalSlot, ImplicitRegisterUse::kWriteAccumulator, \
136 OperandType::kIdx, OperandType::kIdx, OperandType::kUImm) \
137 V(LdaLookupSlotInsideTypeof, ImplicitRegisterUse::kWriteAccumulator, \
138 OperandType::kIdx) \
139 V(LdaLookupContextSlotInsideTypeof, ImplicitRegisterUse::kWriteAccumulator, \
140 OperandType::kIdx, OperandType::kIdx, OperandType::kUImm) \
141 V(LdaLookupScriptContextSlotInsideTypeof, \
142 ImplicitRegisterUse::kWriteAccumulator, OperandType::kIdx, \
143 OperandType::kIdx, OperandType::kUImm) \
144 V(LdaLookupGlobalSlotInsideTypeof, ImplicitRegisterUse::kWriteAccumulator, \
145 OperandType::kIdx, OperandType::kIdx, OperandType::kUImm) \
146 V(StaLookupSlot, ImplicitRegisterUse::kReadWriteAccumulator, \
147 OperandType::kIdx, OperandType::kFlag8) \
148 \
149 /* Property loads (LoadIC) operations */ \
150 V(GetNamedProperty, ImplicitRegisterUse::kWriteAccumulator, \
151 OperandType::kReg, OperandType::kIdx, OperandType::kIdx) \
152 V(GetNamedPropertyFromSuper, ImplicitRegisterUse::kReadWriteAccumulator, \
153 OperandType::kReg, OperandType::kIdx, OperandType::kIdx) \
154 V(GetKeyedProperty, ImplicitRegisterUse::kReadWriteAccumulator, \
155 OperandType::kReg, OperandType::kIdx) \
156 V(GetEnumeratedKeyedProperty, ImplicitRegisterUse::kReadWriteAccumulator, \
157 OperandType::kReg, OperandType::kReg, OperandType::kReg, \
158 OperandType::kIdx) \
159 \
160 /* Operations on module variables */ \
161 V(LdaModuleVariable, ImplicitRegisterUse::kWriteAccumulator, \
162 OperandType::kImm, OperandType::kUImm) \
163 V(StaModuleVariable, ImplicitRegisterUse::kReadAccumulator, \
164 OperandType::kImm, OperandType::kUImm) \
165 \
166 /* Propery stores (StoreIC) operations */ \
167 V(SetNamedProperty, ImplicitRegisterUse::kReadAndClobberAccumulator, \
168 OperandType::kReg, OperandType::kIdx, OperandType::kIdx) \
169 V(DefineNamedOwnProperty, ImplicitRegisterUse::kReadAndClobberAccumulator, \
170 OperandType::kReg, OperandType::kIdx, OperandType::kIdx) \
171 V(SetKeyedProperty, ImplicitRegisterUse::kReadAndClobberAccumulator, \
172 OperandType::kReg, OperandType::kReg, OperandType::kIdx) \
173 V(DefineKeyedOwnProperty, ImplicitRegisterUse::kReadAndClobberAccumulator, \
174 OperandType::kReg, OperandType::kReg, OperandType::kFlag8, \
175 OperandType::kIdx) \
176 V(StaInArrayLiteral, ImplicitRegisterUse::kReadAndClobberAccumulator, \
177 OperandType::kReg, OperandType::kReg, OperandType::kIdx) \
178 V(DefineKeyedOwnPropertyInLiteral, ImplicitRegisterUse::kReadAccumulator, \
179 OperandType::kReg, OperandType::kReg, OperandType::kFlag8, \
180 OperandType::kIdx) \
181 \
182 /* Binary Operators */ \
183 V(Add, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kReg, \
184 OperandType::kIdx) \
185 V(Sub, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kReg, \
186 OperandType::kIdx) \
187 V(Mul, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kReg, \
188 OperandType::kIdx) \
189 V(Div, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kReg, \
190 OperandType::kIdx) \
191 V(Mod, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kReg, \
192 OperandType::kIdx) \
193 V(Exp, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kReg, \
194 OperandType::kIdx) \
195 V(BitwiseOr, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kReg, \
196 OperandType::kIdx) \
197 V(BitwiseXor, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kReg, \
198 OperandType::kIdx) \
199 V(BitwiseAnd, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kReg, \
200 OperandType::kIdx) \
201 V(ShiftLeft, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kReg, \
202 OperandType::kIdx) \
203 V(ShiftRight, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kReg, \
204 OperandType::kIdx) \
205 V(ShiftRightLogical, ImplicitRegisterUse::kReadWriteAccumulator, \
206 OperandType::kReg, OperandType::kIdx) \
207 \
208 /* Binary operators with immediate operands */ \
209 V(AddSmi, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kImm, \
210 OperandType::kIdx) \
211 V(SubSmi, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kImm, \
212 OperandType::kIdx) \
213 V(MulSmi, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kImm, \
214 OperandType::kIdx) \
215 V(DivSmi, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kImm, \
216 OperandType::kIdx) \
217 V(ModSmi, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kImm, \
218 OperandType::kIdx) \
219 V(ExpSmi, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kImm, \
220 OperandType::kIdx) \
221 V(BitwiseOrSmi, ImplicitRegisterUse::kReadWriteAccumulator, \
222 OperandType::kImm, OperandType::kIdx) \
223 V(BitwiseXorSmi, ImplicitRegisterUse::kReadWriteAccumulator, \
224 OperandType::kImm, OperandType::kIdx) \
225 V(BitwiseAndSmi, ImplicitRegisterUse::kReadWriteAccumulator, \
226 OperandType::kImm, OperandType::kIdx) \
227 V(ShiftLeftSmi, ImplicitRegisterUse::kReadWriteAccumulator, \
228 OperandType::kImm, OperandType::kIdx) \
229 V(ShiftRightSmi, ImplicitRegisterUse::kReadWriteAccumulator, \
230 OperandType::kImm, OperandType::kIdx) \
231 V(ShiftRightLogicalSmi, ImplicitRegisterUse::kReadWriteAccumulator, \
232 OperandType::kImm, OperandType::kIdx) \
233 \
234 /* Unary Operators */ \
235 V(Inc, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kIdx) \
236 V(Dec, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kIdx) \
237 V(Negate, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kIdx) \
238 V_TSA(BitwiseNot, ImplicitRegisterUse::kReadWriteAccumulator, \
239 OperandType::kIdx) \
240 V(ToBooleanLogicalNot, ImplicitRegisterUse::kReadWriteAccumulator) \
241 V(LogicalNot, ImplicitRegisterUse::kReadWriteAccumulator) \
242 V(TypeOf, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kIdx) \
243 V(DeletePropertyStrict, ImplicitRegisterUse::kReadWriteAccumulator, \
244 OperandType::kReg) \
245 V(DeletePropertySloppy, ImplicitRegisterUse::kReadWriteAccumulator, \
246 OperandType::kReg) \
247 \
248 /* GetSuperConstructor operator */ \
249 V(GetSuperConstructor, ImplicitRegisterUse::kReadAccumulator, \
250 OperandType::kRegOut) \
251 V(FindNonDefaultConstructorOrConstruct, ImplicitRegisterUse::kNone, \
252 OperandType::kReg, OperandType::kReg, OperandType::kRegOutPair) \
253 \
254 /* Call operations */ \
255 V(CallAnyReceiver, ImplicitRegisterUse::kWriteAccumulator, \
256 OperandType::kReg, OperandType::kRegList, OperandType::kRegCount, \
257 OperandType::kIdx) \
258 V(CallProperty, ImplicitRegisterUse::kWriteAccumulator, OperandType::kReg, \
259 OperandType::kRegList, OperandType::kRegCount, OperandType::kIdx) \
260 V(CallProperty0, ImplicitRegisterUse::kWriteAccumulator, OperandType::kReg, \
261 OperandType::kReg, OperandType::kIdx) \
262 V(CallProperty1, ImplicitRegisterUse::kWriteAccumulator, OperandType::kReg, \
263 OperandType::kReg, OperandType::kReg, OperandType::kIdx) \
264 V(CallProperty2, ImplicitRegisterUse::kWriteAccumulator, OperandType::kReg, \
265 OperandType::kReg, OperandType::kReg, OperandType::kReg, \
266 OperandType::kIdx) \
267 V(CallUndefinedReceiver, ImplicitRegisterUse::kWriteAccumulator, \
268 OperandType::kReg, OperandType::kRegList, OperandType::kRegCount, \
269 OperandType::kIdx) \
270 V(CallUndefinedReceiver0, ImplicitRegisterUse::kWriteAccumulator, \
271 OperandType::kReg, OperandType::kIdx) \
272 V(CallUndefinedReceiver1, ImplicitRegisterUse::kWriteAccumulator, \
273 OperandType::kReg, OperandType::kReg, OperandType::kIdx) \
274 V(CallUndefinedReceiver2, ImplicitRegisterUse::kWriteAccumulator, \
275 OperandType::kReg, OperandType::kReg, OperandType::kReg, \
276 OperandType::kIdx) \
277 V(CallWithSpread, ImplicitRegisterUse::kWriteAccumulator, OperandType::kReg, \
278 OperandType::kRegList, OperandType::kRegCount, OperandType::kIdx) \
279 V(CallRuntime, ImplicitRegisterUse::kWriteAccumulator, \
280 OperandType::kRuntimeId, OperandType::kRegList, OperandType::kRegCount) \
281 V(CallRuntimeForPair, ImplicitRegisterUse::kClobberAccumulator, \
282 OperandType::kRuntimeId, OperandType::kRegList, OperandType::kRegCount, \
283 OperandType::kRegOutPair) \
284 V(CallJSRuntime, ImplicitRegisterUse::kWriteAccumulator, \
285 OperandType::kNativeContextIndex, OperandType::kRegList, \
286 OperandType::kRegCount) \
287 \
288 /* Intrinsics */ \
289 V(InvokeIntrinsic, ImplicitRegisterUse::kWriteAccumulator, \
290 OperandType::kIntrinsicId, OperandType::kRegList, OperandType::kRegCount) \
291 \
292 /* Construct operators */ \
293 V(Construct, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kReg, \
294 OperandType::kRegList, OperandType::kRegCount, OperandType::kIdx) \
295 V(ConstructWithSpread, ImplicitRegisterUse::kReadWriteAccumulator, \
296 OperandType::kReg, OperandType::kRegList, OperandType::kRegCount, \
297 OperandType::kIdx) \
298 V(ConstructForwardAllArgs, ImplicitRegisterUse::kReadWriteAccumulator, \
299 OperandType::kReg, OperandType::kIdx) \
300 \
301 /* Effectful Test Operators */ \
302 V(TestEqual, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kReg, \
303 OperandType::kIdx) \
304 V(TestEqualStrict, ImplicitRegisterUse::kReadWriteAccumulator, \
305 OperandType::kReg, OperandType::kIdx) \
306 V(TestLessThan, ImplicitRegisterUse::kReadWriteAccumulator, \
307 OperandType::kReg, OperandType::kIdx) \
308 V(TestGreaterThan, ImplicitRegisterUse::kReadWriteAccumulator, \
309 OperandType::kReg, OperandType::kIdx) \
310 V(TestLessThanOrEqual, ImplicitRegisterUse::kReadWriteAccumulator, \
311 OperandType::kReg, OperandType::kIdx) \
312 V(TestGreaterThanOrEqual, ImplicitRegisterUse::kReadWriteAccumulator, \
313 OperandType::kReg, OperandType::kIdx) \
314 V(TestInstanceOf, ImplicitRegisterUse::kReadWriteAccumulator, \
315 OperandType::kReg, OperandType::kIdx) \
316 V(TestIn, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kReg, \
317 OperandType::kIdx) \
318 \
319 /* Cast operators */ \
320 V(ToName, ImplicitRegisterUse::kReadWriteAccumulator) \
321 V(ToNumber, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kIdx) \
322 V(ToNumeric, ImplicitRegisterUse::kReadWriteAccumulator, OperandType::kIdx) \
323 V(ToObject, ImplicitRegisterUse::kReadAccumulator, OperandType::kRegOut) \
324 V(ToString, ImplicitRegisterUse::kReadWriteAccumulator) \
325 V(ToBoolean, ImplicitRegisterUse::kReadWriteAccumulator) \
326 \
327 /* Literals */ \
328 V(CreateRegExpLiteral, ImplicitRegisterUse::kWriteAccumulator, \
329 OperandType::kIdx, OperandType::kIdx, OperandType::kFlag16) \
330 V(CreateArrayLiteral, ImplicitRegisterUse::kWriteAccumulator, \
331 OperandType::kIdx, OperandType::kIdx, OperandType::kFlag8) \
332 V(CreateArrayFromIterable, ImplicitRegisterUse::kReadWriteAccumulator) \
333 V(CreateEmptyArrayLiteral, ImplicitRegisterUse::kWriteAccumulator, \
334 OperandType::kIdx) \
335 V(CreateObjectLiteral, ImplicitRegisterUse::kWriteAccumulator, \
336 OperandType::kIdx, OperandType::kIdx, OperandType::kFlag8) \
337 V(CreateEmptyObjectLiteral, ImplicitRegisterUse::kWriteAccumulator) \
338 V(CloneObject, ImplicitRegisterUse::kWriteAccumulator, OperandType::kReg, \
339 OperandType::kFlag8, OperandType::kIdx) \
340 \
341 /* Tagged templates */ \
342 V(GetTemplateObject, ImplicitRegisterUse::kWriteAccumulator, \
343 OperandType::kIdx, OperandType::kIdx) \
344 \
345 /* Closure allocation */ \
346 V(CreateClosure, ImplicitRegisterUse::kWriteAccumulator, OperandType::kIdx, \
347 OperandType::kIdx, OperandType::kFlag8) \
348 \
349 /* Context allocation */ \
350 V(CreateBlockContext, ImplicitRegisterUse::kWriteAccumulator, \
351 OperandType::kIdx) \
352 V(CreateCatchContext, ImplicitRegisterUse::kWriteAccumulator, \
353 OperandType::kReg, OperandType::kIdx) \
354 V(CreateFunctionContext, ImplicitRegisterUse::kWriteAccumulator, \
355 OperandType::kIdx, OperandType::kUImm) \
356 V(CreateEvalContext, ImplicitRegisterUse::kWriteAccumulator, \
357 OperandType::kIdx, OperandType::kUImm) \
358 V(CreateWithContext, ImplicitRegisterUse::kWriteAccumulator, \
359 OperandType::kReg, OperandType::kIdx) \
360 \
361 /* Arguments allocation */ \
362 V(CreateMappedArguments, ImplicitRegisterUse::kWriteAccumulator) \
363 V(CreateUnmappedArguments, ImplicitRegisterUse::kWriteAccumulator) \
364 V(CreateRestParameter, ImplicitRegisterUse::kWriteAccumulator) \
365 \
366 /* Control Flow -- carefully ordered for efficient checks */ \
367 /* - [Unconditional jumps] */ \
368 V(JumpLoop, ImplicitRegisterUse::kClobberAccumulator, OperandType::kUImm, \
369 OperandType::kImm, OperandType::kIdx) \
370 /* - [Forward jumps] */ \
371 V(Jump, ImplicitRegisterUse::kNone, OperandType::kUImm) \
372 /* - [Start constant jumps] */ \
373 V(JumpConstant, ImplicitRegisterUse::kNone, OperandType::kIdx) \
374 /* - [Conditional jumps] */ \
375 /* - [Conditional constant jumps] */ \
376 V(JumpIfNullConstant, ImplicitRegisterUse::kReadAccumulator, \
377 OperandType::kIdx) \
378 V(JumpIfNotNullConstant, ImplicitRegisterUse::kReadAccumulator, \
379 OperandType::kIdx) \
380 V(JumpIfUndefinedConstant, ImplicitRegisterUse::kReadAccumulator, \
381 OperandType::kIdx) \
382 V(JumpIfNotUndefinedConstant, ImplicitRegisterUse::kReadAccumulator, \
383 OperandType::kIdx) \
384 V(JumpIfUndefinedOrNullConstant, ImplicitRegisterUse::kReadAccumulator, \
385 OperandType::kIdx) \
386 V(JumpIfTrueConstant, ImplicitRegisterUse::kReadAccumulator, \
387 OperandType::kIdx) \
388 V(JumpIfFalseConstant, ImplicitRegisterUse::kReadAccumulator, \
389 OperandType::kIdx) \
390 V(JumpIfJSReceiverConstant, ImplicitRegisterUse::kReadAccumulator, \
391 OperandType::kIdx) \
392 V(JumpIfForInDoneConstant, ImplicitRegisterUse::kNone, OperandType::kIdx, \
393 OperandType::kReg, OperandType::kReg) \
394 /* - [Start ToBoolean jumps] */ \
395 V(JumpIfToBooleanTrueConstant, ImplicitRegisterUse::kReadAccumulator, \
396 OperandType::kIdx) \
397 V(JumpIfToBooleanFalseConstant, ImplicitRegisterUse::kReadAccumulator, \
398 OperandType::kIdx) \
399 /* - [End constant jumps] */ \
400 /* - [Conditional immediate jumps] */ \
401 V(JumpIfToBooleanTrue, ImplicitRegisterUse::kReadAccumulator, \
402 OperandType::kUImm) \
403 V(JumpIfToBooleanFalse, ImplicitRegisterUse::kReadAccumulator, \
404 OperandType::kUImm) \
405 /* - [End ToBoolean jumps] */ \
406 V(JumpIfTrue, ImplicitRegisterUse::kReadAccumulator, OperandType::kUImm) \
407 V(JumpIfFalse, ImplicitRegisterUse::kReadAccumulator, OperandType::kUImm) \
408 V(JumpIfNull, ImplicitRegisterUse::kReadAccumulator, OperandType::kUImm) \
409 V(JumpIfNotNull, ImplicitRegisterUse::kReadAccumulator, OperandType::kUImm) \
410 V(JumpIfUndefined, ImplicitRegisterUse::kReadAccumulator, \
411 OperandType::kUImm) \
412 V(JumpIfNotUndefined, ImplicitRegisterUse::kReadAccumulator, \
413 OperandType::kUImm) \
414 V(JumpIfUndefinedOrNull, ImplicitRegisterUse::kReadAccumulator, \
415 OperandType::kUImm) \
416 V(JumpIfJSReceiver, ImplicitRegisterUse::kReadAccumulator, \
417 OperandType::kUImm) \
418 V(JumpIfForInDone, ImplicitRegisterUse::kNone, OperandType::kUImm, \
419 OperandType::kReg, OperandType::kReg) \
420 \
421 /* Smi-table lookup for switch statements */ \
422 V(SwitchOnSmiNoFeedback, ImplicitRegisterUse::kReadAccumulator, \
423 OperandType::kIdx, OperandType::kUImm, OperandType::kImm) \
424 \
425 /* Complex flow control For..in */ \
426 V(ForInEnumerate, ImplicitRegisterUse::kWriteAccumulator, OperandType::kReg) \
427 V(ForInPrepare, ImplicitRegisterUse::kReadAndClobberAccumulator, \
428 OperandType::kRegOutTriple, OperandType::kIdx) \
429 V(ForInNext, ImplicitRegisterUse::kWriteAccumulator, OperandType::kReg, \
430 OperandType::kReg, OperandType::kRegPair, OperandType::kIdx) \
431 V(ForInStep, ImplicitRegisterUse::kNone, OperandType::kRegInOut) \
432 \
433 /* Update the pending message */ \
434 V(SetPendingMessage, ImplicitRegisterUse::kReadWriteAccumulator) \
435 \
436 /* Non-local flow control */ \
437 V(Throw, ImplicitRegisterUse::kReadAccumulator) \
438 V(ReThrow, ImplicitRegisterUse::kReadAccumulator) \
439 V(Return, ImplicitRegisterUse::kReadAccumulator) \
440 V(ThrowReferenceErrorIfHole, ImplicitRegisterUse::kReadAccumulator, \
441 OperandType::kIdx) \
442 V(ThrowSuperNotCalledIfHole, ImplicitRegisterUse::kReadAccumulator) \
443 V(ThrowSuperAlreadyCalledIfNotHole, ImplicitRegisterUse::kReadAccumulator) \
444 V(ThrowIfNotSuperConstructor, ImplicitRegisterUse::kNone, OperandType::kReg) \
445 \
446 /* Generators */ \
447 V(SwitchOnGeneratorState, ImplicitRegisterUse::kNone, OperandType::kReg, \
448 OperandType::kIdx, OperandType::kUImm) \
449 V(SuspendGenerator, ImplicitRegisterUse::kReadAccumulator, \
450 OperandType::kReg, OperandType::kRegList, OperandType::kRegCount, \
451 OperandType::kUImm) \
452 V(ResumeGenerator, ImplicitRegisterUse::kWriteAccumulator, \
453 OperandType::kReg, OperandType::kRegOutList, OperandType::kRegCount) \
454 \
455 /* Iterator protocol operations */ \
456 V(GetIterator, ImplicitRegisterUse::kWriteAccumulator, OperandType::kReg, \
457 OperandType::kIdx, OperandType::kIdx) \
458 \
459 /* Debugger */ \
460 V(Debugger, ImplicitRegisterUse::kClobberAccumulator) \
461 \
462 /* Block Coverage */ \
463 V(IncBlockCounter, ImplicitRegisterUse::kNone, OperandType::kIdx) \
464 \
465 /* Execution Abort (internal error) */ \
466 V(Abort, ImplicitRegisterUse::kNone, OperandType::kIdx)
467
468#ifdef V8_ENABLE_EXPERIMENTAL_TSA_BUILTINS
469#define BYTECODE_LIST_WITH_UNIQUE_HANDLERS(V, V_TSA) \
470 BYTECODE_LIST_WITH_UNIQUE_HANDLERS_IMPL(V, V_TSA)
471#else
472#define BYTECODE_LIST_WITH_UNIQUE_HANDLERS(V, V_TSA) \
473 BYTECODE_LIST_WITH_UNIQUE_HANDLERS_IMPL(V, V)
474#endif
475
476// The list of bytecodes which are interpreted by the interpreter.
477// Format is V(<bytecode>, <implicit_register_use>, <operands>) and
478// V_TSA(<bytecode>, <implicit_register_use>, <operands>).
479#define BYTECODE_LIST(V, V_TSA) \
480 BYTECODE_LIST_WITH_UNIQUE_HANDLERS(V, V_TSA) \
481 \
482 /* Special-case Star for common register numbers, to save space */ \
483 SHORT_STAR_BYTECODE_LIST(V) \
484 \
485 /* Illegal bytecode */ \
486 V(Illegal, ImplicitRegisterUse::kNone)
487
488// List of debug break bytecodes.
489#define DEBUG_BREAK_PLAIN_BYTECODE_LIST(V) \
490 V(DebugBreak0) \
491 V(DebugBreak1) \
492 V(DebugBreak2) \
493 V(DebugBreak3) \
494 V(DebugBreak4) \
495 V(DebugBreak5) \
496 V(DebugBreak6)
497
498#define DEBUG_BREAK_PREFIX_BYTECODE_LIST(V) \
499 V(DebugBreakWide) \
500 V(DebugBreakExtraWide)
501
502#define DEBUG_BREAK_BYTECODE_LIST(V) \
503 DEBUG_BREAK_PLAIN_BYTECODE_LIST(V) \
504 DEBUG_BREAK_PREFIX_BYTECODE_LIST(V)
505
506// Lists of jump bytecodes.
507
508#define JUMP_UNCONDITIONAL_IMMEDIATE_BYTECODE_LIST(V) \
509 V(JumpLoop) \
510 V(Jump)
511
512#define JUMP_UNCONDITIONAL_CONSTANT_BYTECODE_LIST(V) V(JumpConstant)
513
514#define JUMP_TOBOOLEAN_CONDITIONAL_IMMEDIATE_BYTECODE_LIST(V) \
515 V(JumpIfToBooleanTrue) \
516 V(JumpIfToBooleanFalse)
517
518#define JUMP_TOBOOLEAN_CONDITIONAL_CONSTANT_BYTECODE_LIST(V) \
519 V(JumpIfToBooleanTrueConstant) \
520 V(JumpIfToBooleanFalseConstant)
521
522#define JUMP_CONDITIONAL_IMMEDIATE_BYTECODE_LIST(V) \
523 JUMP_TOBOOLEAN_CONDITIONAL_IMMEDIATE_BYTECODE_LIST(V) \
524 V(JumpIfTrue) \
525 V(JumpIfFalse) \
526 V(JumpIfNull) \
527 V(JumpIfNotNull) \
528 V(JumpIfUndefined) \
529 V(JumpIfNotUndefined) \
530 V(JumpIfUndefinedOrNull) \
531 V(JumpIfJSReceiver) \
532 V(JumpIfForInDone)
533
534#define JUMP_CONDITIONAL_CONSTANT_BYTECODE_LIST(V) \
535 JUMP_TOBOOLEAN_CONDITIONAL_CONSTANT_BYTECODE_LIST(V) \
536 V(JumpIfNullConstant) \
537 V(JumpIfNotNullConstant) \
538 V(JumpIfUndefinedConstant) \
539 V(JumpIfNotUndefinedConstant) \
540 V(JumpIfUndefinedOrNullConstant) \
541 V(JumpIfTrueConstant) \
542 V(JumpIfFalseConstant) \
543 V(JumpIfJSReceiverConstant) \
544 V(JumpIfForInDoneConstant)
545
546#define JUMP_CONSTANT_BYTECODE_LIST(V) \
547 JUMP_UNCONDITIONAL_CONSTANT_BYTECODE_LIST(V) \
548 JUMP_CONDITIONAL_CONSTANT_BYTECODE_LIST(V)
549
550#define JUMP_IMMEDIATE_BYTECODE_LIST(V) \
551 JUMP_UNCONDITIONAL_IMMEDIATE_BYTECODE_LIST(V) \
552 JUMP_CONDITIONAL_IMMEDIATE_BYTECODE_LIST(V)
553
554#define JUMP_TO_BOOLEAN_BYTECODE_LIST(V) \
555 JUMP_TOBOOLEAN_CONDITIONAL_IMMEDIATE_BYTECODE_LIST(V) \
556 JUMP_TOBOOLEAN_CONDITIONAL_CONSTANT_BYTECODE_LIST(V)
557
558#define JUMP_UNCONDITIONAL_BYTECODE_LIST(V) \
559 JUMP_UNCONDITIONAL_IMMEDIATE_BYTECODE_LIST(V) \
560 JUMP_UNCONDITIONAL_CONSTANT_BYTECODE_LIST(V)
561
562#define JUMP_CONDITIONAL_BYTECODE_LIST(V) \
563 JUMP_CONDITIONAL_IMMEDIATE_BYTECODE_LIST(V) \
564 JUMP_CONDITIONAL_CONSTANT_BYTECODE_LIST(V)
565
566#define JUMP_FORWARD_BYTECODE_LIST(V) \
567 V(Jump) \
568 V(JumpConstant) \
569 JUMP_CONDITIONAL_BYTECODE_LIST(V)
570
571#define JUMP_BYTECODE_LIST(V) \
572 JUMP_FORWARD_BYTECODE_LIST(V) \
573 V(JumpLoop)
574
575#define RETURN_BYTECODE_LIST(V) \
576 V(Return) \
577 V(SuspendGenerator)
578
579#define UNCONDITIONAL_THROW_BYTECODE_LIST(V) \
580 V(Throw) \
581 V(ReThrow)
582
583// Enumeration of interpreter bytecodes.
584enum class Bytecode : uint8_t {
585#define DECLARE_BYTECODE(Name, ...) k##Name,
587#undef DECLARE_BYTECODE
588#define COUNT_BYTECODE(x, ...) +1
589 // The COUNT_BYTECODE macro will turn this into kLast = -1 +1 +1... which will
590 // evaluate to the same value as the last real bytecode.
592 kFirstShortStar = kStar15,
593 kLastShortStar = kStar0
594#undef COUNT_BYTECODE
595};
596
598 public:
599 // The maximum number of operands a bytecode may have.
600 static const int kMaxOperands = 5;
601
602 // The total number of bytecodes used.
603 static const int kBytecodeCount = static_cast<int>(Bytecode::kLast) + 1;
604
605 static const int kShortStarCount =
606 static_cast<int>(Bytecode::kLastShortStar) -
607 static_cast<int>(Bytecode::kFirstShortStar) + 1;
608
609 // Returns string representation of |bytecode|.
610 static const char* ToString(Bytecode bytecode);
611
612 // Returns string representation of |bytecode| combined with |operand_scale|
613 // using the optionally provided |separator|.
614 static std::string ToString(Bytecode bytecode, OperandScale operand_scale,
615 const char* separator = ".");
616
617 // Returns byte value of bytecode.
618 static uint8_t ToByte(Bytecode bytecode) {
619 DCHECK_LE(bytecode, Bytecode::kLast);
620 return static_cast<uint8_t>(bytecode);
621 }
622
623 // Returns bytecode for |value|.
624 static Bytecode FromByte(uint8_t value) {
625 Bytecode bytecode = static_cast<Bytecode>(value);
626 DCHECK_LE(bytecode, Bytecode::kLast);
627 return bytecode;
628 }
629
630 // Returns the prefix bytecode representing an operand scale to be
631 // applied to a a bytecode.
633 switch (operand_scale) {
634 case OperandScale::kQuadruple:
635 return Bytecode::kExtraWide;
636 case OperandScale::kDouble:
637 return Bytecode::kWide;
638 default:
639 UNREACHABLE();
640 }
641 }
642
643 // Returns true if the operand scale requires a prefix bytecode.
645 return operand_scale != OperandScale::kSingle;
646 }
647
648 // Returns the scaling applied to scalable operands if bytecode is
649 // is a scaling prefix.
651#ifdef V8_TARGET_OS_ANDROID
652 // The compiler is very smart, turning the switch into branchless code.
653 // However this triggers a CPU bug on some android devices (see
654 // crbug.com/1379788). We therefore intentionally use code the compiler has
655 // a harder time optimizing on Android. At least until clang 15.0 the
656 // current workaround prevents hitting the CPU bug.
657 // TODO(chromium:1379788): Remove this hack if we get an external fix.
658 if (bytecode == Bytecode::kWide || bytecode == Bytecode::kDebugBreakWide) {
659 return OperandScale::kDouble;
660 } else if (bytecode == Bytecode::kExtraWide ||
661 bytecode == Bytecode::kDebugBreakExtraWide) {
662 return OperandScale::kQuadruple;
663 } else {
664 UNREACHABLE();
665 }
666#else
667 switch (bytecode) {
668 case Bytecode::kExtraWide:
669 case Bytecode::kDebugBreakExtraWide:
670 return OperandScale::kQuadruple;
671 case Bytecode::kWide:
672 case Bytecode::kDebugBreakWide:
673 return OperandScale::kDouble;
674 default:
675 UNREACHABLE();
676 }
677#endif
678 }
679
680 // Returns how accumulator is used by |bytecode|.
682 DCHECK_LE(bytecode, Bytecode::kLast);
683 return kImplicitRegisterUse[static_cast<size_t>(bytecode)];
684 }
685
686 // Returns true if |bytecode| reads the accumulator.
687 static bool ReadsAccumulator(Bytecode bytecode) {
688 return BytecodeOperands::ReadsAccumulator(GetImplicitRegisterUse(bytecode));
689 }
690
691 // Returns true if |bytecode| writes the accumulator.
692 static bool WritesAccumulator(Bytecode bytecode) {
693 return BytecodeOperands::WritesAccumulator(
694 GetImplicitRegisterUse(bytecode));
695 }
696
697 // Returns true if |bytecode| writes the accumulator.
698 static bool ClobbersAccumulator(Bytecode bytecode) {
699 return BytecodeOperands::ClobbersAccumulator(
700 GetImplicitRegisterUse(bytecode));
701 }
702
703 // Returns true if |bytecode| writes the accumulator.
704 static bool WritesOrClobbersAccumulator(Bytecode bytecode) {
705 return BytecodeOperands::WritesOrClobbersAccumulator(
706 GetImplicitRegisterUse(bytecode));
707 }
708
709 // Returns true if |bytecode| writes to a register not specified by an
710 // operand.
711 static bool WritesImplicitRegister(Bytecode bytecode) {
712 return BytecodeOperands::WritesImplicitRegister(
713 GetImplicitRegisterUse(bytecode));
714 }
715
716 // Return true if |bytecode| is an accumulator load without effects,
717 // e.g. LdaConstant, LdaTrue, Ldar.
718 static constexpr bool IsAccumulatorLoadWithoutEffects(Bytecode bytecode) {
719 static_assert(Bytecode::kLdar < Bytecode::kLdaImmutableCurrentContextSlot);
720 return bytecode >= Bytecode::kLdar &&
721 bytecode <= Bytecode::kLdaImmutableCurrentContextSlot;
722 }
723
724 // Returns true if |bytecode| is a compare operation without external effects
725 // (e.g., Type cooersion).
726 static constexpr bool IsCompareWithoutEffects(Bytecode bytecode) {
727 static_assert(Bytecode::kTestReferenceEqual < Bytecode::kTestTypeOf);
728 return bytecode >= Bytecode::kTestReferenceEqual &&
729 bytecode <= Bytecode::kTestTypeOf;
730 }
731
732 static constexpr bool IsShortStar(Bytecode bytecode) {
733 return bytecode >= Bytecode::kFirstShortStar &&
734 bytecode <= Bytecode::kLastShortStar;
735 }
736
737 static constexpr bool IsAnyStar(Bytecode bytecode) {
738 return bytecode == Bytecode::kStar || IsShortStar(bytecode);
739 }
740
741 // Return true if |bytecode| is a register load without effects,
742 // e.g. Mov, Star.
743 static constexpr bool IsRegisterLoadWithoutEffects(Bytecode bytecode) {
744 return IsShortStar(bytecode) ||
745 (bytecode >= Bytecode::kStar && bytecode <= Bytecode::kPopContext);
746 }
747
748 // Returns true if the bytecode is a conditional jump taking
749 // an immediate byte operand (OperandType::kImm).
750 static constexpr bool IsConditionalJumpImmediate(Bytecode bytecode) {
751 return bytecode >= Bytecode::kJumpIfToBooleanTrue &&
752 bytecode <= Bytecode::kJumpIfForInDone;
753 }
754
755 // Returns true if the bytecode is a conditional jump taking
756 // a constant pool entry (OperandType::kIdx).
757 static constexpr bool IsConditionalJumpConstant(Bytecode bytecode) {
758 return bytecode >= Bytecode::kJumpIfNullConstant &&
759 bytecode <= Bytecode::kJumpIfToBooleanFalseConstant;
760 }
761
762 // Returns true if the bytecode is a conditional jump taking
763 // any kind of operand.
764 static constexpr bool IsConditionalJump(Bytecode bytecode) {
765 return bytecode >= Bytecode::kJumpIfNullConstant &&
766 bytecode <= Bytecode::kJumpIfForInDone;
767 }
768
769 // Returns true if the bytecode is an unconditional jump.
770 static constexpr bool IsUnconditionalJump(Bytecode bytecode) {
771 return bytecode >= Bytecode::kJumpLoop &&
772 bytecode <= Bytecode::kJumpConstant;
773 }
774
775 // Returns true if the bytecode is a jump or a conditional jump taking
776 // an immediate byte operand (OperandType::kImm).
777 static constexpr bool IsJumpImmediate(Bytecode bytecode) {
778 return bytecode == Bytecode::kJump || bytecode == Bytecode::kJumpLoop ||
779 IsConditionalJumpImmediate(bytecode);
780 }
781
782 // Returns true if the bytecode is a jump or conditional jump taking a
783 // constant pool entry (OperandType::kIdx).
784 static constexpr bool IsJumpConstant(Bytecode bytecode) {
785 return bytecode >= Bytecode::kJumpConstant &&
786 bytecode <= Bytecode::kJumpIfToBooleanFalseConstant;
787 }
788
789 // Returns true if the bytecode is a jump that internally coerces the
790 // accumulator to a boolean.
791 static constexpr bool IsJumpIfToBoolean(Bytecode bytecode) {
792 return bytecode >= Bytecode::kJumpIfToBooleanTrueConstant &&
793 bytecode <= Bytecode::kJumpIfToBooleanFalse;
794 }
795
796 // Returns true if the bytecode is a jump or conditional jump taking
797 // any kind of operand.
798 static constexpr bool IsJump(Bytecode bytecode) {
799 return bytecode >= Bytecode::kJumpLoop &&
800 bytecode <= Bytecode::kJumpIfForInDone;
801 }
802
803 // Returns true if the bytecode is a forward jump or conditional jump taking
804 // any kind of operand.
805 static constexpr bool IsForwardJump(Bytecode bytecode) {
806 return bytecode >= Bytecode::kJump &&
807 bytecode <= Bytecode::kJumpIfForInDone;
808 }
809
810 // Return true if |bytecode| is a jump without effects,
811 // e.g. any jump excluding those that include type coercion like
812 // JumpIfTrueToBoolean, and JumpLoop due to having an implicit StackCheck.
813 static constexpr bool IsJumpWithoutEffects(Bytecode bytecode) {
814 return IsJump(bytecode) && !IsJumpIfToBoolean(bytecode) &&
815 bytecode != Bytecode::kJumpLoop;
816 }
817
818 // Returns true if the bytecode is a switch.
819 static constexpr bool IsSwitch(Bytecode bytecode) {
820 return bytecode == Bytecode::kSwitchOnSmiNoFeedback ||
821 bytecode == Bytecode::kSwitchOnGeneratorState;
822 }
823
824 // Returns true if |bytecode| has no effects. These bytecodes only manipulate
825 // interpreter frame state and will never throw.
826 static constexpr bool IsWithoutExternalSideEffects(Bytecode bytecode) {
827 return (IsAccumulatorLoadWithoutEffects(bytecode) ||
828 IsRegisterLoadWithoutEffects(bytecode) ||
829 IsCompareWithoutEffects(bytecode) ||
830 IsJumpWithoutEffects(bytecode) || IsSwitch(bytecode) ||
831 bytecode == Bytecode::kReturn);
832 }
833
834 // Returns true if the bytecode is Ldar or Star.
835 static constexpr bool IsLdarOrStar(Bytecode bytecode) {
836 return bytecode == Bytecode::kLdar || IsAnyStar(bytecode);
837 }
838
839 // Returns true if the bytecode is a call or a constructor call.
840 static constexpr bool IsCallOrConstruct(Bytecode bytecode) {
841 return bytecode == Bytecode::kCallAnyReceiver ||
842 bytecode == Bytecode::kCallProperty ||
843 bytecode == Bytecode::kCallProperty0 ||
844 bytecode == Bytecode::kCallProperty1 ||
845 bytecode == Bytecode::kCallProperty2 ||
846 bytecode == Bytecode::kCallUndefinedReceiver ||
847 bytecode == Bytecode::kCallUndefinedReceiver0 ||
848 bytecode == Bytecode::kCallUndefinedReceiver1 ||
849 bytecode == Bytecode::kCallUndefinedReceiver2 ||
850 bytecode == Bytecode::kConstruct ||
851 bytecode == Bytecode::kCallWithSpread ||
852 bytecode == Bytecode::kConstructWithSpread ||
853 bytecode == Bytecode::kConstructForwardAllArgs ||
854 bytecode == Bytecode::kCallJSRuntime;
855 }
856
857 // Returns true if the bytecode is a call to the runtime.
858 static constexpr bool IsCallRuntime(Bytecode bytecode) {
859 return bytecode == Bytecode::kCallRuntime ||
860 bytecode == Bytecode::kCallRuntimeForPair ||
861 bytecode == Bytecode::kInvokeIntrinsic;
862 }
863
864 // Returns true if the bytecode is a scaling prefix bytecode.
865 static constexpr bool IsPrefixScalingBytecode(Bytecode bytecode) {
866 return bytecode == Bytecode::kExtraWide || bytecode == Bytecode::kWide ||
867 bytecode == Bytecode::kDebugBreakExtraWide ||
868 bytecode == Bytecode::kDebugBreakWide;
869 }
870
871 // Returns true if the bytecode returns.
872 static constexpr bool Returns(Bytecode bytecode) {
873#define OR_BYTECODE(NAME) || bytecode == Bytecode::k##NAME
874 return false RETURN_BYTECODE_LIST(OR_BYTECODE);
875#undef OR_BYTECODE
876 }
877
878 // Returns true if the bytecode unconditionally throws.
879 static constexpr bool UnconditionallyThrows(Bytecode bytecode) {
880#define OR_BYTECODE(NAME) || bytecode == Bytecode::k##NAME
882#undef OR_BYTECODE
883 }
884
885 // Returns the number of operands expected by |bytecode|.
886 static int NumberOfOperands(Bytecode bytecode) {
887 // Using V8_ASSUME instead of DCHECK here works around a spurious GCC
888 // warning -- somehow GCC thinks that bytecode == kLast+1 can happen here.
889 V8_ASSUME(bytecode <= Bytecode::kLast);
890 return kOperandCount[static_cast<uint8_t>(bytecode)];
891 }
892
893 // Returns the i-th operand of |bytecode|.
894 static OperandType GetOperandType(Bytecode bytecode, int i) {
895 DCHECK_LE(bytecode, Bytecode::kLast);
896 DCHECK_LT(i, NumberOfOperands(bytecode));
897 DCHECK_GE(i, 0);
898 return GetOperandTypes(bytecode)[i];
899 }
900
901 // Returns a pointer to an array of operand types terminated in
902 // OperandType::kNone.
903 static const OperandType* GetOperandTypes(Bytecode bytecode) {
904 DCHECK_LE(bytecode, Bytecode::kLast);
905 return kOperandTypes[static_cast<size_t>(bytecode)];
906 }
907
909 int operand_index) {
910 DCHECK_LE(bytecode, Bytecode::kLast);
911 return kOperandTypeInfos[static_cast<size_t>(bytecode)][operand_index] ==
912 OperandTypeInfo::kScalableSignedByte;
913 }
914
916 int operand_index) {
917 DCHECK_LE(bytecode, Bytecode::kLast);
918 return kOperandTypeInfos[static_cast<size_t>(bytecode)][operand_index] ==
919 OperandTypeInfo::kScalableUnsignedByte;
920 }
921
922 static bool OperandIsScalable(Bytecode bytecode, int operand_index) {
923 return OperandIsScalableSignedByte(bytecode, operand_index) ||
924 OperandIsScalableUnsignedByte(bytecode, operand_index);
925 }
926
927 // Returns true if the bytecode has wider operand forms.
928 static bool IsBytecodeWithScalableOperands(Bytecode bytecode);
929
930 // Returns the size of the i-th operand of |bytecode|.
931 static OperandSize GetOperandSize(Bytecode bytecode, int i,
932 OperandScale operand_scale) {
933 CHECK_LT(i, NumberOfOperands(bytecode));
934 return GetOperandSizes(bytecode, operand_scale)[i];
935 }
936
937 // Returns the operand sizes of |bytecode| with scale |operand_scale|.
938 static const OperandSize* GetOperandSizes(Bytecode bytecode,
939 OperandScale operand_scale) {
940 DCHECK_LE(bytecode, Bytecode::kLast);
941 DCHECK_GE(operand_scale, OperandScale::kSingle);
942 DCHECK_LE(operand_scale, OperandScale::kLast);
943 static_assert(static_cast<int>(OperandScale::kQuadruple) == 4 &&
944 OperandScale::kLast == OperandScale::kQuadruple);
945 int scale_index = static_cast<int>(operand_scale) >> 1;
946 return kOperandSizes[scale_index][static_cast<size_t>(bytecode)];
947 }
948
949 // Returns the offset of the i-th operand of |bytecode| relative to the start
950 // of the bytecode.
951 static int GetOperandOffset(Bytecode bytecode, int i,
952 OperandScale operand_scale) {
953 DCHECK_LE(bytecode, Bytecode::kLast);
954 DCHECK_GE(operand_scale, OperandScale::kSingle);
955 DCHECK_LE(operand_scale, OperandScale::kLast);
956 static_assert(static_cast<int>(OperandScale::kQuadruple) == 4 &&
957 OperandScale::kLast == OperandScale::kQuadruple);
958 int scale_index = static_cast<int>(operand_scale) >> 1;
959 return kOperandOffsets[scale_index][static_cast<size_t>(bytecode)][i];
960 }
961
962 // Returns the size of the bytecode including its operands for the
963 // given |operand_scale|.
964 static int Size(Bytecode bytecode, OperandScale operand_scale) {
965 DCHECK_LE(bytecode, Bytecode::kLast);
966 static_assert(static_cast<int>(OperandScale::kQuadruple) == 4 &&
967 OperandScale::kLast == OperandScale::kQuadruple);
968 int scale_index = static_cast<int>(operand_scale) >> 1;
969 return kBytecodeSizes[scale_index][static_cast<size_t>(bytecode)];
970 }
971
972 // Returns a debug break bytecode to replace |bytecode|.
973 static Bytecode GetDebugBreak(Bytecode bytecode);
974
975 // Returns true if there is a call in the most-frequently executed path
976 // through the bytecode's handler.
977 static bool MakesCallAlongCriticalPath(Bytecode bytecode);
978
979 // Returns the receiver mode of the given call bytecode.
981 DCHECK(IsCallOrConstruct(bytecode) ||
982 bytecode == Bytecode::kInvokeIntrinsic);
983 switch (bytecode) {
984 case Bytecode::kCallProperty:
985 case Bytecode::kCallProperty0:
986 case Bytecode::kCallProperty1:
987 case Bytecode::kCallProperty2:
988 return ConvertReceiverMode::kNotNullOrUndefined;
989 case Bytecode::kCallUndefinedReceiver:
990 case Bytecode::kCallUndefinedReceiver0:
991 case Bytecode::kCallUndefinedReceiver1:
992 case Bytecode::kCallUndefinedReceiver2:
993 case Bytecode::kCallJSRuntime:
994 return ConvertReceiverMode::kNullOrUndefined;
995 case Bytecode::kCallAnyReceiver:
996 case Bytecode::kConstruct:
997 case Bytecode::kCallWithSpread:
998 case Bytecode::kConstructWithSpread:
999 case Bytecode::kInvokeIntrinsic:
1000 return ConvertReceiverMode::kAny;
1001 default:
1002 UNREACHABLE();
1003 }
1004 }
1005
1006 // Returns true if the bytecode is a debug break.
1007 static bool IsDebugBreak(Bytecode bytecode);
1008
1009 // Returns true if |operand_type| is any type of register operand.
1010 static bool IsRegisterOperandType(OperandType operand_type);
1011
1012 // Returns true if |operand_type| represents a register used as an input.
1013 static bool IsRegisterInputOperandType(OperandType operand_type);
1014
1015 // Returns true if |operand_type| represents a register used as an output.
1016 static bool IsRegisterOutputOperandType(OperandType operand_type);
1017
1018 // Returns true if |operand_type| represents a register list operand.
1019 static bool IsRegisterListOperandType(OperandType operand_type);
1020
1021 // Returns true if the handler for |bytecode| should look ahead and inline a
1022 // dispatch to a Star bytecode.
1023 static bool IsStarLookahead(Bytecode bytecode, OperandScale operand_scale);
1024
1025 // Returns the number of registers represented by a register operand. For
1026 // instance, a RegPair represents two registers. Should not be called for
1027 // kRegList which has a variable number of registers based on the following
1028 // kRegCount operand.
1030 switch (operand_type) {
1031 case OperandType::kReg:
1032 case OperandType::kRegOut:
1033 case OperandType::kRegInOut:
1034 return 1;
1035 case OperandType::kRegPair:
1036 case OperandType::kRegOutPair:
1037 return 2;
1038 case OperandType::kRegOutTriple:
1039 return 3;
1040 case OperandType::kRegList:
1041 case OperandType::kRegOutList:
1042 UNREACHABLE();
1043 default:
1044 return 0;
1045 }
1046 UNREACHABLE();
1047 }
1048
1049 // Returns the size of |operand_type| for |operand_scale|.
1051 OperandScale operand_scale) {
1052 DCHECK_LE(operand_type, OperandType::kLast);
1053 DCHECK_GE(operand_scale, OperandScale::kSingle);
1054 DCHECK_LE(operand_scale, OperandScale::kLast);
1055 static_assert(static_cast<int>(OperandScale::kQuadruple) == 4 &&
1056 OperandScale::kLast == OperandScale::kQuadruple);
1057 int scale_index = static_cast<int>(operand_scale) >> 1;
1058 return kOperandKindSizes[scale_index][static_cast<size_t>(operand_type)];
1059 }
1060
1061 // Returns true if |operand_type| is a runtime-id operand (kRuntimeId).
1062 static bool IsRuntimeIdOperandType(OperandType operand_type);
1063
1064 // Returns true if |operand_type| is unsigned, false if signed.
1065 static bool IsUnsignedOperandType(OperandType operand_type);
1066
1067 // Returns true if a handler is generated for a bytecode at a given
1068 // operand scale. All bytecodes have handlers at OperandScale::kSingle,
1069 // but only bytecodes with scalable operands have handlers with larger
1070 // OperandScale values.
1071 static bool BytecodeHasHandler(Bytecode bytecode, OperandScale operand_scale);
1072
1073 // Return the operand scale required to hold a signed operand with |value|.
1074 static OperandScale ScaleForSignedOperand(int32_t value) {
1075 if (value >= kMinInt8 && value <= kMaxInt8) {
1076 return OperandScale::kSingle;
1077 } else if (value >= kMinInt16 && value <= kMaxInt16) {
1078 return OperandScale::kDouble;
1079 } else {
1080 return OperandScale::kQuadruple;
1081 }
1082 }
1083
1084 // Return the operand scale required to hold an unsigned operand with |value|.
1085 static OperandScale ScaleForUnsignedOperand(uint32_t value) {
1086 if (value <= kMaxUInt8) {
1087 return OperandScale::kSingle;
1088 } else if (value <= kMaxUInt16) {
1089 return OperandScale::kDouble;
1090 } else {
1091 return OperandScale::kQuadruple;
1092 }
1093 }
1094
1095 // Return the operand size required to hold an unsigned operand with |value|.
1096 static OperandSize SizeForUnsignedOperand(uint32_t value) {
1097 if (value <= kMaxUInt8) {
1098 return OperandSize::kByte;
1099 } else if (value <= kMaxUInt16) {
1100 return OperandSize::kShort;
1101 } else {
1102 return OperandSize::kQuad;
1103 }
1104 }
1105
1107 return reinterpret_cast<Address>(
1108 const_cast<uint8_t*>(&kBytecodeSizes[0][0]));
1109 }
1110
1111 private:
1112 static const OperandType* const kOperandTypes[];
1113 static const OperandTypeInfo* const kOperandTypeInfos[];
1114 static const int kOperandCount[];
1115 static const int kNumberOfRegisterOperands[];
1116 static const ImplicitRegisterUse kImplicitRegisterUse[];
1117 static const bool kIsScalable[];
1118 static const uint8_t kBytecodeSizes[3][kBytecodeCount];
1119 static const OperandSize* const kOperandSizes[3][kBytecodeCount];
1120 static const int* const kOperandOffsets[3][kBytecodeCount];
1121 static OperandSize const
1122 kOperandKindSizes[3][BytecodeOperands::kOperandTypeCount];
1123};
1124
1125V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
1126 const Bytecode& bytecode);
1127
1128} // namespace interpreter
1129} // namespace internal
1130} // namespace v8
1131
1132#endif // V8_INTERPRETER_BYTECODES_H_
interpreter::Bytecode bytecode
Definition builtins.cc:43
#define OR_BYTECODE(NAME)
#define BYTECODE_LIST(V, V_TSA)
Definition bytecodes.h:479
#define RETURN_BYTECODE_LIST(V)
Definition bytecodes.h:575
#define UNCONDITIONAL_THROW_BYTECODE_LIST(V)
Definition bytecodes.h:579
static bool ClobbersAccumulator(Bytecode bytecode)
Definition bytecodes.h:698
static ImplicitRegisterUse GetImplicitRegisterUse(Bytecode bytecode)
Definition bytecodes.h:681
static constexpr bool UnconditionallyThrows(Bytecode bytecode)
Definition bytecodes.h:879
static constexpr bool IsJumpIfToBoolean(Bytecode bytecode)
Definition bytecodes.h:791
static constexpr bool IsCompareWithoutEffects(Bytecode bytecode)
Definition bytecodes.h:726
static constexpr bool Returns(Bytecode bytecode)
Definition bytecodes.h:872
static const OperandType * GetOperandTypes(Bytecode bytecode)
Definition bytecodes.h:903
static OperandScale ScaleForUnsignedOperand(uint32_t value)
Definition bytecodes.h:1085
static OperandSize GetOperandSize(Bytecode bytecode, int i, OperandScale operand_scale)
Definition bytecodes.h:931
static constexpr bool IsConditionalJumpConstant(Bytecode bytecode)
Definition bytecodes.h:757
static Bytecode FromByte(uint8_t value)
Definition bytecodes.h:624
static OperandScale PrefixBytecodeToOperandScale(Bytecode bytecode)
Definition bytecodes.h:650
static bool WritesAccumulator(Bytecode bytecode)
Definition bytecodes.h:692
static constexpr bool IsAnyStar(Bytecode bytecode)
Definition bytecodes.h:737
static constexpr bool IsConditionalJumpImmediate(Bytecode bytecode)
Definition bytecodes.h:750
static int GetNumberOfRegistersRepresentedBy(OperandType operand_type)
Definition bytecodes.h:1029
static constexpr bool IsJumpImmediate(Bytecode bytecode)
Definition bytecodes.h:777
static constexpr bool IsWithoutExternalSideEffects(Bytecode bytecode)
Definition bytecodes.h:826
static constexpr bool IsForwardJump(Bytecode bytecode)
Definition bytecodes.h:805
static constexpr bool IsCallRuntime(Bytecode bytecode)
Definition bytecodes.h:858
static bool OperandIsScalableUnsignedByte(Bytecode bytecode, int operand_index)
Definition bytecodes.h:915
static int GetOperandOffset(Bytecode bytecode, int i, OperandScale operand_scale)
Definition bytecodes.h:951
static constexpr bool IsSwitch(Bytecode bytecode)
Definition bytecodes.h:819
static constexpr bool IsJumpWithoutEffects(Bytecode bytecode)
Definition bytecodes.h:813
static Bytecode OperandScaleToPrefixBytecode(OperandScale operand_scale)
Definition bytecodes.h:632
static constexpr bool IsAccumulatorLoadWithoutEffects(Bytecode bytecode)
Definition bytecodes.h:718
static Address bytecode_size_table_address()
Definition bytecodes.h:1106
static bool ReadsAccumulator(Bytecode bytecode)
Definition bytecodes.h:687
static bool OperandIsScalable(Bytecode bytecode, int operand_index)
Definition bytecodes.h:922
static OperandSize SizeOfOperand(OperandType operand_type, OperandScale operand_scale)
Definition bytecodes.h:1050
static constexpr bool IsCallOrConstruct(Bytecode bytecode)
Definition bytecodes.h:840
static bool WritesImplicitRegister(Bytecode bytecode)
Definition bytecodes.h:711
static uint8_t ToByte(Bytecode bytecode)
Definition bytecodes.h:618
static OperandType GetOperandType(Bytecode bytecode, int i)
Definition bytecodes.h:894
static constexpr bool IsJumpConstant(Bytecode bytecode)
Definition bytecodes.h:784
static bool OperandIsScalableSignedByte(Bytecode bytecode, int operand_index)
Definition bytecodes.h:908
static int Size(Bytecode bytecode, OperandScale operand_scale)
Definition bytecodes.h:964
static constexpr bool IsPrefixScalingBytecode(Bytecode bytecode)
Definition bytecodes.h:865
static OperandSize SizeForUnsignedOperand(uint32_t value)
Definition bytecodes.h:1096
static OperandScale ScaleForSignedOperand(int32_t value)
Definition bytecodes.h:1074
static constexpr bool IsRegisterLoadWithoutEffects(Bytecode bytecode)
Definition bytecodes.h:743
static bool OperandScaleRequiresPrefixBytecode(OperandScale operand_scale)
Definition bytecodes.h:644
static int NumberOfOperands(Bytecode bytecode)
Definition bytecodes.h:886
static bool IsRuntimeIdOperandType(OperandType operand_type)
static constexpr bool IsConditionalJump(Bytecode bytecode)
Definition bytecodes.h:764
static constexpr bool IsShortStar(Bytecode bytecode)
Definition bytecodes.h:732
static constexpr bool IsLdarOrStar(Bytecode bytecode)
Definition bytecodes.h:835
static ConvertReceiverMode GetReceiverMode(Bytecode bytecode)
Definition bytecodes.h:980
static constexpr bool IsJump(Bytecode bytecode)
Definition bytecodes.h:798
static bool WritesOrClobbersAccumulator(Bytecode bytecode)
Definition bytecodes.h:704
static constexpr bool IsUnconditionalJump(Bytecode bytecode)
Definition bytecodes.h:770
static const OperandSize * GetOperandSizes(Bytecode bytecode, OperandScale operand_scale)
Definition bytecodes.h:938
constexpr const char * ToString(DataViewOp op)
std::ostream & operator<<(std::ostream &os, PaddingSpace padding)
constexpr int kMaxInt8
Definition globals.h:376
constexpr int kMaxUInt8
Definition globals.h:378
constexpr int kMaxUInt16
Definition globals.h:382
constexpr int kMinInt16
Definition globals.h:381
constexpr int kMinInt8
Definition globals.h:377
constexpr int kMaxInt16
Definition globals.h:380
#define UNREACHABLE()
Definition logging.h:67
#define DCHECK_LE(v1, v2)
Definition logging.h:490
#define CHECK_LT(lhs, rhs)
#define DCHECK_GE(v1, v2)
Definition logging.h:488
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_LT(v1, v2)
Definition logging.h:489
#define V8_EXPORT_PRIVATE
Definition macros.h:460
#define V8_ASSUME
Definition v8config.h:533
std::unique_ptr< ValueMirror > value