1 | // Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file |
2 | // for details. All rights reserved. Use of this source code is governed by a |
3 | // BSD-style license that can be found in the LICENSE file. |
4 | |
5 | #ifndef RUNTIME_VM_CONSTANTS_KBC_H_ |
6 | #define RUNTIME_VM_CONSTANTS_KBC_H_ |
7 | |
8 | #include "platform/assert.h" |
9 | #include "platform/globals.h" |
10 | #include "platform/utils.h" |
11 | |
12 | namespace dart { |
13 | |
14 | // clang-format off |
15 | // List of KernelBytecode instructions. |
16 | // |
17 | // INTERPRETER STATE |
18 | // |
19 | // current frame info (see stack_frame_kbc.h for layout) |
20 | // v-----^-----v |
21 | // ~----+----~ ~----+-------+-------+-~ ~-+-------+-------+-~ |
22 | // ~ | ~ ~ | FP[0] | FP[1] | ~ ~ | SP[-1]| SP[0] | |
23 | // ~----+----~ ~----+-------+-------+-~ ~-+-------+-------+-~ |
24 | // ^ ^ |
25 | // FP SP |
26 | // |
27 | // |
28 | // The state of execution is captured in few interpreter registers: |
29 | // |
30 | // FP - base of the current frame |
31 | // SP - top of the stack (TOS) for the current frame |
32 | // PP - object pool for the currently execution function |
33 | // |
34 | // Frame info stored below FP additionally contains pointers to the currently |
35 | // executing function and code. |
36 | // |
37 | // In the unoptimized code most of bytecodes take operands implicitly from |
38 | // stack and store results again on the stack. Constant operands are usually |
39 | // taken from the object pool by index. |
40 | // |
41 | // ENCODING |
42 | // |
43 | // Each instruction starts with opcode byte. Certain instructions have |
44 | // wide encoding variant. In such case, the least significant bit of opcode is |
45 | // not set for compact variant and set for wide variant. |
46 | // |
47 | // The following operand encodings are used: |
48 | // |
49 | // 0........8.......16.......24.......32.......40.......48 |
50 | // +--------+ |
51 | // | opcode | 0: no operands |
52 | // +--------+ |
53 | // |
54 | // +--------+--------+ |
55 | // | opcode | A | A: unsigned 8-bit operand |
56 | // +--------+--------+ |
57 | // |
58 | // +--------+--------+ |
59 | // | opcode | D | D: unsigned 8/32-bit operand |
60 | // +--------+--------+ |
61 | // |
62 | // +--------+----------------------------------+ |
63 | // | opcode | D | D (wide) |
64 | // +--------+----------------------------------+ |
65 | // |
66 | // +--------+--------+ |
67 | // | opcode | X | X: signed 8/32-bit operand |
68 | // +--------+--------+ |
69 | // |
70 | // +--------+----------------------------------+ |
71 | // | opcode | X | X (wide) |
72 | // +--------+----------------------------------+ |
73 | // |
74 | // +--------+--------+ |
75 | // | opcode | T | T: signed 8/24-bit operand |
76 | // +--------+--------+ |
77 | // |
78 | // +--------+--------------------------+ |
79 | // | opcode | T | T (wide) |
80 | // +--------+--------------------------+ |
81 | // |
82 | // +--------+--------+--------+ |
83 | // | opcode | A | E | A_E: unsigned 8-bit operand and |
84 | // +--------+--------+--------+ unsigned 8/32-bit operand |
85 | // |
86 | // +--------+--------+----------------------------------+ |
87 | // | opcode | A | E | A_E (wide) |
88 | // +--------+--------+----------------------------------+ |
89 | // |
90 | // +--------+--------+--------+ |
91 | // | opcode | A | Y | A_Y: unsigned 8-bit operand and |
92 | // +--------+--------+--------+ signed 8/32-bit operand |
93 | // |
94 | // +--------+--------+----------------------------------+ |
95 | // | opcode | A | Y | A_Y (wide) |
96 | // +--------+--------+----------------------------------+ |
97 | // |
98 | // +--------+--------+--------+ |
99 | // | opcode | D | F | D_F: unsigned 8/32-bit operand and |
100 | // +--------+--------+--------+ unsigned 8-bit operand |
101 | // |
102 | // +--------+----------------------------------+--------+ |
103 | // | opcode | D | F | D_F (wide) |
104 | // +--------+----------------------------------+--------+ |
105 | // |
106 | // +--------+--------+--------+--------+ |
107 | // | opcode | A | B | C | A_B_C: 3 unsigned 8-bit operands |
108 | // +--------+--------+--------+--------+ |
109 | // |
110 | // |
111 | // INSTRUCTIONS |
112 | // |
113 | // - Trap |
114 | // |
115 | // Unreachable instruction. |
116 | // |
117 | // - Entry rD |
118 | // |
119 | // Function prologue for the function |
120 | // rD - number of local slots to reserve; |
121 | // |
122 | // - EntryFixed A, D |
123 | // |
124 | // Function prologue for functions without optional arguments. |
125 | // Checks number of arguments. |
126 | // A - expected number of positional arguments; |
127 | // D - number of local slots to reserve; |
128 | // |
129 | // - EntryOptional A, B, C |
130 | // |
131 | // Function prologue for the function with optional or named arguments: |
132 | // A - expected number of positional arguments; |
133 | // B - number of optional arguments; |
134 | // C - number of named arguments; |
135 | // |
136 | // Only one of B and C can be not 0. |
137 | // |
138 | // If B is not 0 then EntryOptional bytecode is followed by B LoadConstant |
139 | // bytecodes specifying default values for optional arguments. |
140 | // |
141 | // If C is not 0 then EntryOptional is followed by 2 * C LoadConstant |
142 | // bytecodes. |
143 | // Bytecode at 2 * i specifies name of the i-th named argument and at |
144 | // 2 * i + 1 default value. rA part of the LoadConstant bytecode specifies |
145 | // the location of the parameter on the stack. Here named arguments are |
146 | // sorted alphabetically to enable linear matching similar to how function |
147 | // prologues are implemented on other architectures. |
148 | // |
149 | // Note: Unlike Entry bytecode EntryOptional does not setup the frame for |
150 | // local variables this is done by a separate bytecode Frame, which should |
151 | // follow EntryOptional and its LoadConstant instructions. |
152 | // |
153 | // - LoadConstant rA, D |
154 | // |
155 | // Used in conjunction with EntryOptional instruction to describe names and |
156 | // default values of optional parameters. |
157 | // |
158 | // - Frame D |
159 | // |
160 | // Reserve and initialize with null space for D local variables. |
161 | // |
162 | // - CheckFunctionTypeArgs A, D |
163 | // |
164 | // Check for a passed-in type argument vector of length A and |
165 | // store it at FP[D]. |
166 | // |
167 | // - CheckStack A |
168 | // |
169 | // Compare SP against isolate stack limit and call StackOverflow handler if |
170 | // necessary. Should be used in prologue (A = 0), or at the beginning of |
171 | // a loop with depth A. |
172 | // |
173 | // - Allocate D |
174 | // |
175 | // Allocate object of class PP[D] with no type arguments. |
176 | // |
177 | // - AllocateT |
178 | // |
179 | // Allocate object of class SP[0] with type arguments SP[-1]. |
180 | // |
181 | // - CreateArrayTOS |
182 | // |
183 | // Allocate array of length SP[0] with type arguments SP[-1]. |
184 | // |
185 | // - AllocateContext A, D |
186 | // |
187 | // Allocate Context object holding D context variables. |
188 | // A is a static ID of the context. Static ID of a context may be used to |
189 | // disambiguate accesses to different context objects. |
190 | // Context objects with the same ID should have the same number of |
191 | // context variables. |
192 | // |
193 | // - CloneContext A, D |
194 | // |
195 | // Clone Context object SP[0] holding D context variables. |
196 | // A is a static ID of the context. Cloned context has the same ID. |
197 | // |
198 | // - LoadContextParent |
199 | // |
200 | // Load parent from context SP[0]. |
201 | // |
202 | // - StoreContextParent |
203 | // |
204 | // Store context SP[0] into `parent` field of context SP[-1]. |
205 | // |
206 | // - LoadContextVar A, D |
207 | // |
208 | // Load value from context SP[0] at index D. |
209 | // A is a static ID of the context. |
210 | // |
211 | // - StoreContextVar A, D |
212 | // |
213 | // Store value SP[0] into context SP[-1] at index D. |
214 | // A is a static ID of the context. |
215 | // |
216 | // - PushConstant D |
217 | // |
218 | // Push value at index D from constant pool onto the stack. |
219 | // |
220 | // - PushNull |
221 | // |
222 | // Push `null` onto the stack. |
223 | // |
224 | // - PushTrue |
225 | // |
226 | // Push `true` onto the stack. |
227 | // |
228 | // - PushFalse |
229 | // |
230 | // Push `false` onto the stack. |
231 | // |
232 | // - PushInt rX |
233 | // |
234 | // Push int rX onto the stack. |
235 | // |
236 | // - Drop1 |
237 | // |
238 | // Drop 1 value from the stack |
239 | // |
240 | // - Push rX |
241 | // |
242 | // Push FP[rX] to the stack. |
243 | // |
244 | // - StoreLocal rX; PopLocal rX |
245 | // |
246 | // Store top of the stack into FP[rX] and pop it if needed. |
247 | // |
248 | // - LoadFieldTOS D |
249 | // |
250 | // Push value at offset (in words) PP[D] from object SP[0]. |
251 | // |
252 | // - StoreFieldTOS D |
253 | // |
254 | // Store value SP[0] into object SP[-1] at offset (in words) PP[D]. |
255 | // |
256 | // - StoreIndexedTOS |
257 | // |
258 | // Store SP[0] into array SP[-2] at index SP[-1]. No typechecking is done. |
259 | // SP[-2] is assumed to be a RawArray, SP[-1] to be a smi. |
260 | // |
261 | // - PushStatic D |
262 | // |
263 | // Pushes value of the static field PP[D] on to the stack. |
264 | // |
265 | // - StoreStaticTOS D |
266 | // |
267 | // Stores TOS into the static field PP[D]. |
268 | // |
269 | // - Jump target |
270 | // |
271 | // Jump to the given target. Target is specified as offset from the PC of the |
272 | // jump instruction. |
273 | // |
274 | // - JumpIfNoAsserts target |
275 | // |
276 | // Jump to the given target if assertions are not enabled. |
277 | // Target is specified as offset from the PC of the jump instruction. |
278 | // |
279 | // - JumpIfNotZeroTypeArgs target |
280 | // |
281 | // Jump to the given target if number of passed function type |
282 | // arguments is not zero. |
283 | // Target is specified as offset from the PC of the jump instruction. |
284 | // |
285 | // - JumpIfEqStrict target; JumpIfNeStrict target |
286 | // |
287 | // Jump to the given target if SP[-1] is the same (JumpIfEqStrict) / |
288 | // not the same (JumpIfNeStrict) object as SP[0]. |
289 | // |
290 | // - JumpIfTrue target; JumpIfFalse target |
291 | // - JumpIfNull target; JumpIfNotNull target |
292 | // |
293 | // Jump to the given target if SP[0] is true/false/null/not null. |
294 | // |
295 | // - IndirectStaticCall ArgC, D |
296 | // |
297 | // Invoke the function given by the ICData in SP[0] with arguments |
298 | // SP[-(1+ArgC)], ..., SP[-1] and argument descriptor PP[D], which |
299 | // indicates whether the first argument is a type argument vector. |
300 | // |
301 | // - DirectCall ArgC, D |
302 | // |
303 | // Invoke the function PP[D] with arguments |
304 | // SP[-(ArgC-1)], ..., SP[0] and argument descriptor PP[D+1]. |
305 | // |
306 | // - InterfaceCall ArgC, D |
307 | // |
308 | // Lookup and invoke method using ICData in PP[D] |
309 | // with arguments SP[-(1+ArgC)], ..., SP[-1]. |
310 | // Method has to be declared (explicitly or implicitly) in an interface |
311 | // implemented by a receiver, and passed arguments are valid for the |
312 | // interface method declaration. |
313 | // The ICData indicates whether the first argument is a type argument vector. |
314 | // |
315 | // - UncheckedInterfaceCall ArgC, D |
316 | // |
317 | // Same as InterfaceCall, but can omit type checks of generic-covariant |
318 | // parameters. |
319 | // |
320 | // - DynamicCall ArgC, D |
321 | // |
322 | // Lookup and invoke method using ICData in PP[D] |
323 | // with arguments SP[-(1+ArgC)], ..., SP[-1]. |
324 | // The ICData indicates whether the first argument is a type argument vector. |
325 | // |
326 | // - NativeCall D |
327 | // |
328 | // Invoke native function described by array at pool[D]. |
329 | // array[0] is wrapper, array[1] is function, array[2] is argc_tag. |
330 | // |
331 | // - ReturnTOS |
332 | // |
333 | // Return to the caller using a value from the top-of-stack as a result. |
334 | // |
335 | // Note: return instruction knows how many arguments to remove from the |
336 | // stack because it can look at the call instruction at caller's PC and |
337 | // take argument count from it. |
338 | // |
339 | // - AssertAssignable A, D |
340 | // |
341 | // Assert that instance SP[-4] is assignable to variable named SP[0] of |
342 | // type SP[-1] with instantiator type arguments SP[-3] and function type |
343 | // arguments SP[-2] using SubtypeTestCache PP[D]. |
344 | // If A is 1, then the instance may be a Smi. |
345 | // |
346 | // Instance remains on stack. Other arguments are consumed. |
347 | // |
348 | // - AssertBoolean A |
349 | // |
350 | // Assert that TOS is a boolean (A = 1) or that TOS is not null (A = 0). |
351 | // |
352 | // - AssertSubtype |
353 | // |
354 | // Assert that one type is a subtype of another. Throws a TypeError |
355 | // otherwise. The stack has the following arguments on it: |
356 | // |
357 | // SP[-4] instantiator type args |
358 | // SP[-3] function type args |
359 | // SP[-2] sub_type |
360 | // SP[-1] super_type |
361 | // SP[-0] dst_name |
362 | // |
363 | // All 5 arguments are consumed from the stack and no results is pushed. |
364 | // |
365 | // - LoadTypeArgumentsField D |
366 | // |
367 | // Load instantiator type arguments from an instance SP[0]. |
368 | // PP[D] = offset (in words) of type arguments field corresponding |
369 | // to an instance's class. |
370 | // |
371 | // - InstantiateType D |
372 | // |
373 | // Instantiate type PP[D] with instantiator type arguments SP[-1] and |
374 | // function type arguments SP[0]. |
375 | // |
376 | // - InstantiateTypeArgumentsTOS A, D |
377 | // |
378 | // Instantiate type arguments PP[D] with instantiator type arguments SP[-1] |
379 | // and function type arguments SP[0]. A != 0 indicates that resulting type |
380 | // arguments are all dynamic if both instantiator and function type |
381 | // arguments are all dynamic. |
382 | // |
383 | // - Throw A |
384 | // |
385 | // Throw (Rethrow if A != 0) exception. Exception object and stack object |
386 | // are taken from TOS. |
387 | // |
388 | // - MoveSpecial A, rX |
389 | // |
390 | // Copy value from special variable to FP[rX]. Currently only |
391 | // used to pass exception object (A = 0) and stack trace object (A = 1) to |
392 | // catch handler. |
393 | // |
394 | // - SetFrame A |
395 | // |
396 | // Reinitialize SP assuming that current frame has size A. |
397 | // Used to drop temporaries from the stack in the exception handler. |
398 | // |
399 | // - BooleanNegateTOS |
400 | // |
401 | // SP[0] = !SP[0] |
402 | // |
403 | // - EqualsNull |
404 | // |
405 | // SP[0] = (SP[0] == null) ? true : false |
406 | // |
407 | // - NegateInt |
408 | // |
409 | // Equivalent to invocation of unary int operator-. |
410 | // Receiver should have static type int. |
411 | // Check SP[0] for null; SP[0] = -SP[0]. |
412 | // |
413 | // - AddInt; SubInt; MulInt; TruncDivInt; ModInt; BitAndInt; BitOrInt; |
414 | // BitXorInt; ShlInt; ShrInt |
415 | // |
416 | // Equivalent to invocation of binary int operator +, -, *, ~/, %, &, |, |
417 | // ^, << or >>. Receiver and argument should have static type int. |
418 | // Check SP[-1] and SP[0] for null; push SP[-1] <op> SP[0]. |
419 | // |
420 | // - CompareIntEq; CompareIntGt; CompareIntLt; CompareIntGe; CompareIntLe |
421 | // |
422 | // Equivalent to invocation of binary int operator ==, >, <, >= or <=. |
423 | // Receiver and argument should have static type int. |
424 | // Check SP[-1] and SP[0] for null; push SP[-1] <op> SP[0] ? true : false. |
425 | // |
426 | // - NegateDouble |
427 | // |
428 | // Equivalent to invocation of unary double operator-. |
429 | // Receiver should have static type double. |
430 | // Check SP[0] for null; SP[0] = -SP[0]. |
431 | // |
432 | // - AddDouble; SubDouble; MulDouble; DivDouble |
433 | // |
434 | // Equivalent to invocation of binary int operator +, -, *, /. |
435 | // Receiver and argument should have static type double. |
436 | // Check SP[-1] and SP[0] for null; push SP[-1] <op> SP[0]. |
437 | // |
438 | // - CompareDoubleEq; CompareDoubleGt; CompareDoubleLt; CompareDoubleGe; |
439 | // CompareDoubleLe |
440 | // |
441 | // Equivalent to invocation of binary double operator ==, >, <, >= or <=. |
442 | // Receiver and argument should have static type double. |
443 | // Check SP[-1] and SP[0] for null; push SP[-1] <op> SP[0] ? true : false. |
444 | // |
445 | // - AllocateClosure D |
446 | // |
447 | // Allocate closure object for closure function ConstantPool[D]. |
448 | // |
449 | // BYTECODE LIST FORMAT |
450 | // |
451 | // KernelBytecode list below is specified using the following format: |
452 | // |
453 | // V(BytecodeName, OperandForm, BytecodeKind, Op1, Op2, Op3) |
454 | // |
455 | // - OperandForm specifies operand encoding and should be one of 0, A, D, X, T, |
456 | // A_E, A_Y, D_F or A_B_C (see ENCODING section above). |
457 | // |
458 | // - BytecodeKind is one of WIDE, RESV (reserved), ORDN (ordinary) |
459 | // |
460 | // - Op1, Op2, Op3 specify operand meaning. Possible values: |
461 | // |
462 | // ___ ignored / non-existent operand |
463 | // num immediate operand |
464 | // lit constant literal from object pool |
465 | // reg register (unsigned FP relative local) |
466 | // xeg x-register (signed FP relative local) |
467 | // tgt jump target relative to the PC of the current instruction |
468 | // |
469 | // TODO(vegorov) jump targets should be encoded relative to PC of the next |
470 | // instruction because PC is incremented immediately after fetch |
471 | // and before decoding. |
472 | // |
473 | #define PUBLIC_KERNEL_BYTECODES_LIST(V) \ |
474 | V(UnusedOpcode000, 0, RESV, ___, ___, ___) \ |
475 | V(UnusedOpcode001, 0, RESV, ___, ___, ___) \ |
476 | V(UnusedOpcode002, 0, RESV, ___, ___, ___) \ |
477 | V(UnusedOpcode003, 0, RESV, ___, ___, ___) \ |
478 | V(UnusedOpcode004, 0, RESV, ___, ___, ___) \ |
479 | V(UnusedOpcode005, 0, RESV, ___, ___, ___) \ |
480 | V(UnusedOpcode006, 0, RESV, ___, ___, ___) \ |
481 | V(UnusedOpcode007, 0, RESV, ___, ___, ___) \ |
482 | V(UnusedOpcode008, 0, RESV, ___, ___, ___) \ |
483 | V(UnusedOpcode009, 0, RESV, ___, ___, ___) \ |
484 | V(UnusedOpcode010, 0, RESV, ___, ___, ___) \ |
485 | V(UnusedOpcode011, 0, RESV, ___, ___, ___) \ |
486 | V(UnusedOpcode012, 0, RESV, ___, ___, ___) \ |
487 | V(UnusedOpcode013, 0, RESV, ___, ___, ___) \ |
488 | V(UnusedOpcode014, 0, RESV, ___, ___, ___) \ |
489 | V(UnusedOpcode015, 0, RESV, ___, ___, ___) \ |
490 | V(UnusedOpcode016, 0, RESV, ___, ___, ___) \ |
491 | V(UnusedOpcode017, 0, RESV, ___, ___, ___) \ |
492 | V(UnusedOpcode018, 0, RESV, ___, ___, ___) \ |
493 | V(UnusedOpcode019, 0, RESV, ___, ___, ___) \ |
494 | V(UnusedOpcode020, 0, RESV, ___, ___, ___) \ |
495 | V(UnusedOpcode021, 0, RESV, ___, ___, ___) \ |
496 | V(UnusedOpcode022, 0, RESV, ___, ___, ___) \ |
497 | V(UnusedOpcode023, 0, RESV, ___, ___, ___) \ |
498 | V(UnusedOpcode024, 0, RESV, ___, ___, ___) \ |
499 | V(UnusedOpcode025, 0, RESV, ___, ___, ___) \ |
500 | V(UnusedOpcode026, 0, RESV, ___, ___, ___) \ |
501 | V(UnusedOpcode027, 0, RESV, ___, ___, ___) \ |
502 | V(UnusedOpcode028, 0, RESV, ___, ___, ___) \ |
503 | V(UnusedOpcode029, 0, RESV, ___, ___, ___) \ |
504 | V(UnusedOpcode030, 0, RESV, ___, ___, ___) \ |
505 | V(UnusedOpcode031, 0, RESV, ___, ___, ___) \ |
506 | V(UnusedOpcode032, 0, RESV, ___, ___, ___) \ |
507 | V(UnusedOpcode033, 0, RESV, ___, ___, ___) \ |
508 | V(UnusedOpcode034, 0, RESV, ___, ___, ___) \ |
509 | V(UnusedOpcode035, 0, RESV, ___, ___, ___) \ |
510 | V(UnusedOpcode036, 0, RESV, ___, ___, ___) \ |
511 | V(UnusedOpcode037, 0, RESV, ___, ___, ___) \ |
512 | V(UnusedOpcode038, 0, RESV, ___, ___, ___) \ |
513 | V(UnusedOpcode039, 0, RESV, ___, ___, ___) \ |
514 | V(UnusedOpcode040, 0, RESV, ___, ___, ___) \ |
515 | V(UnusedOpcode041, 0, RESV, ___, ___, ___) \ |
516 | V(UnusedOpcode042, 0, RESV, ___, ___, ___) \ |
517 | V(UnusedOpcode043, 0, RESV, ___, ___, ___) \ |
518 | V(UnusedOpcode044, 0, RESV, ___, ___, ___) \ |
519 | V(UnusedOpcode045, 0, RESV, ___, ___, ___) \ |
520 | V(UnusedOpcode046, 0, RESV, ___, ___, ___) \ |
521 | V(UnusedOpcode047, 0, RESV, ___, ___, ___) \ |
522 | V(UnusedOpcode048, 0, RESV, ___, ___, ___) \ |
523 | V(UnusedOpcode049, 0, RESV, ___, ___, ___) \ |
524 | V(UnusedOpcode050, 0, RESV, ___, ___, ___) \ |
525 | V(UnusedOpcode051, 0, RESV, ___, ___, ___) \ |
526 | V(UnusedOpcode052, 0, RESV, ___, ___, ___) \ |
527 | V(UnusedOpcode053, 0, RESV, ___, ___, ___) \ |
528 | V(UnusedOpcode054, 0, RESV, ___, ___, ___) \ |
529 | V(UnusedOpcode055, 0, RESV, ___, ___, ___) \ |
530 | V(UnusedOpcode056, 0, RESV, ___, ___, ___) \ |
531 | V(UnusedOpcode057, 0, RESV, ___, ___, ___) \ |
532 | V(UnusedOpcode058, 0, RESV, ___, ___, ___) \ |
533 | V(UnusedOpcode059, 0, RESV, ___, ___, ___) \ |
534 | V(UnusedOpcode060, 0, RESV, ___, ___, ___) \ |
535 | V(UnusedOpcode061, 0, RESV, ___, ___, ___) \ |
536 | V(UnusedOpcode062, 0, RESV, ___, ___, ___) \ |
537 | V(UnusedOpcode063, 0, RESV, ___, ___, ___) \ |
538 | V(UnusedOpcode064, 0, RESV, ___, ___, ___) \ |
539 | V(UnusedOpcode065, 0, RESV, ___, ___, ___) \ |
540 | V(UnusedOpcode066, 0, RESV, ___, ___, ___) \ |
541 | V(UnusedOpcode067, 0, RESV, ___, ___, ___) \ |
542 | V(UnusedOpcode068, 0, RESV, ___, ___, ___) \ |
543 | V(UnusedOpcode069, 0, RESV, ___, ___, ___) \ |
544 | V(UnusedOpcode070, 0, RESV, ___, ___, ___) \ |
545 | V(UnusedOpcode071, 0, RESV, ___, ___, ___) \ |
546 | V(UnusedOpcode072, 0, RESV, ___, ___, ___) \ |
547 | V(UnusedOpcode073, 0, RESV, ___, ___, ___) \ |
548 | V(UnusedOpcode074, 0, RESV, ___, ___, ___) \ |
549 | V(UnusedOpcode075, 0, RESV, ___, ___, ___) \ |
550 | V(UnusedOpcode076, 0, RESV, ___, ___, ___) \ |
551 | V(UnusedOpcode077, 0, RESV, ___, ___, ___) \ |
552 | V(UnusedOpcode078, 0, RESV, ___, ___, ___) \ |
553 | V(UnusedOpcode079, 0, RESV, ___, ___, ___) \ |
554 | V(UnusedOpcode080, 0, RESV, ___, ___, ___) \ |
555 | V(UnusedOpcode081, 0, RESV, ___, ___, ___) \ |
556 | V(JumpIfInitialized, T, ORDN, tgt, ___, ___) \ |
557 | V(JumpIfInitialized_Wide, T, WIDE, tgt, ___, ___) \ |
558 | V(PushUninitializedSentinel, 0, ORDN, ___, ___, ___) \ |
559 | V(Trap, 0, ORDN, ___, ___, ___) \ |
560 | V(Entry, D, ORDN, num, ___, ___) \ |
561 | V(Entry_Wide, D, WIDE, num, ___, ___) \ |
562 | V(EntryFixed, A_E, ORDN, num, num, ___) \ |
563 | V(EntryFixed_Wide, A_E, WIDE, num, num, ___) \ |
564 | V(EntryOptional, A_B_C, ORDN, num, num, num) \ |
565 | V(Unused00, 0, RESV, ___, ___, ___) \ |
566 | V(LoadConstant, A_E, ORDN, reg, lit, ___) \ |
567 | V(LoadConstant_Wide, A_E, WIDE, reg, lit, ___) \ |
568 | V(Frame, D, ORDN, num, ___, ___) \ |
569 | V(Frame_Wide, D, WIDE, num, ___, ___) \ |
570 | V(CheckFunctionTypeArgs, A_E, ORDN, num, reg, ___) \ |
571 | V(CheckFunctionTypeArgs_Wide, A_E, WIDE, num, reg, ___) \ |
572 | V(CheckStack, A, ORDN, num, ___, ___) \ |
573 | V(DebugCheck, 0, ORDN, ___, ___, ___) \ |
574 | V(JumpIfUnchecked, T, ORDN, tgt, ___, ___) \ |
575 | V(JumpIfUnchecked_Wide, T, WIDE, tgt, ___, ___) \ |
576 | V(Allocate, D, ORDN, lit, ___, ___) \ |
577 | V(Allocate_Wide, D, WIDE, lit, ___, ___) \ |
578 | V(AllocateT, 0, ORDN, ___, ___, ___) \ |
579 | V(CreateArrayTOS, 0, ORDN, ___, ___, ___) \ |
580 | V(AllocateClosure, D, ORDN, lit, ___, ___) \ |
581 | V(AllocateClosure_Wide, D, WIDE, lit, ___, ___) \ |
582 | V(AllocateContext, A_E, ORDN, num, num, ___) \ |
583 | V(AllocateContext_Wide, A_E, WIDE, num, num, ___) \ |
584 | V(CloneContext, A_E, ORDN, num, num, ___) \ |
585 | V(CloneContext_Wide, A_E, WIDE, num, num, ___) \ |
586 | V(LoadContextParent, 0, ORDN, ___, ___, ___) \ |
587 | V(StoreContextParent, 0, ORDN, ___, ___, ___) \ |
588 | V(LoadContextVar, A_E, ORDN, num, num, ___) \ |
589 | V(LoadContextVar_Wide, A_E, WIDE, num, num, ___) \ |
590 | V(Unused04, 0, RESV, ___, ___, ___) \ |
591 | V(Unused05, 0, RESV, ___, ___, ___) \ |
592 | V(StoreContextVar, A_E, ORDN, num, num, ___) \ |
593 | V(StoreContextVar_Wide, A_E, WIDE, num, num, ___) \ |
594 | V(PushConstant, D, ORDN, lit, ___, ___) \ |
595 | V(PushConstant_Wide, D, WIDE, lit, ___, ___) \ |
596 | V(Unused06, 0, RESV, ___, ___, ___) \ |
597 | V(Unused07, 0, RESV, ___, ___, ___) \ |
598 | V(PushTrue, 0, ORDN, ___, ___, ___) \ |
599 | V(PushFalse, 0, ORDN, ___, ___, ___) \ |
600 | V(PushInt, X, ORDN, num, ___, ___) \ |
601 | V(PushInt_Wide, X, WIDE, num, ___, ___) \ |
602 | V(Unused08, 0, RESV, ___, ___, ___) \ |
603 | V(Unused09, 0, RESV, ___, ___, ___) \ |
604 | V(Unused10, 0, RESV, ___, ___, ___) \ |
605 | V(Unused11, 0, RESV, ___, ___, ___) \ |
606 | V(PushNull, 0, ORDN, ___, ___, ___) \ |
607 | V(Drop1, 0, ORDN, ___, ___, ___) \ |
608 | V(Push, X, ORDN, xeg, ___, ___) \ |
609 | V(Push_Wide, X, WIDE, xeg, ___, ___) \ |
610 | V(Unused12, 0, RESV, ___, ___, ___) \ |
611 | V(Unused13, 0, RESV, ___, ___, ___) \ |
612 | V(Unused14, 0, RESV, ___, ___, ___) \ |
613 | V(Unused15, 0, RESV, ___, ___, ___) \ |
614 | V(Unused16, 0, RESV, ___, ___, ___) \ |
615 | V(Unused17, 0, RESV, ___, ___, ___) \ |
616 | V(PopLocal, X, ORDN, xeg, ___, ___) \ |
617 | V(PopLocal_Wide, X, WIDE, xeg, ___, ___) \ |
618 | V(LoadStatic, D, ORDN, lit, ___, ___) \ |
619 | V(LoadStatic_Wide, D, WIDE, lit, ___, ___) \ |
620 | V(StoreLocal, X, ORDN, xeg, ___, ___) \ |
621 | V(StoreLocal_Wide, X, WIDE, xeg, ___, ___) \ |
622 | V(LoadFieldTOS, D, ORDN, lit, ___, ___) \ |
623 | V(LoadFieldTOS_Wide, D, WIDE, lit, ___, ___) \ |
624 | V(StoreFieldTOS, D, ORDN, lit, ___, ___) \ |
625 | V(StoreFieldTOS_Wide, D, WIDE, lit, ___, ___) \ |
626 | V(StoreIndexedTOS, 0, ORDN, ___, ___, ___) \ |
627 | V(Unused20, 0, RESV, ___, ___, ___) \ |
628 | V(InitLateField, D, ORDN, lit, ___, ___) \ |
629 | V(InitLateField_Wide, D, WIDE, lit, ___, ___) \ |
630 | V(StoreStaticTOS, D, ORDN, lit, ___, ___) \ |
631 | V(StoreStaticTOS_Wide, D, WIDE, lit, ___, ___) \ |
632 | V(Jump, T, ORDN, tgt, ___, ___) \ |
633 | V(Jump_Wide, T, WIDE, tgt, ___, ___) \ |
634 | V(JumpIfNoAsserts, T, ORDN, tgt, ___, ___) \ |
635 | V(JumpIfNoAsserts_Wide, T, WIDE, tgt, ___, ___) \ |
636 | V(JumpIfNotZeroTypeArgs, T, ORDN, tgt, ___, ___) \ |
637 | V(JumpIfNotZeroTypeArgs_Wide, T, WIDE, tgt, ___, ___) \ |
638 | V(JumpIfEqStrict, T, ORDN, tgt, ___, ___) \ |
639 | V(JumpIfEqStrict_Wide, T, WIDE, tgt, ___, ___) \ |
640 | V(JumpIfNeStrict, T, ORDN, tgt, ___, ___) \ |
641 | V(JumpIfNeStrict_Wide, T, WIDE, tgt, ___, ___) \ |
642 | V(JumpIfTrue, T, ORDN, tgt, ___, ___) \ |
643 | V(JumpIfTrue_Wide, T, WIDE, tgt, ___, ___) \ |
644 | V(JumpIfFalse, T, ORDN, tgt, ___, ___) \ |
645 | V(JumpIfFalse_Wide, T, WIDE, tgt, ___, ___) \ |
646 | V(JumpIfNull, T, ORDN, tgt, ___, ___) \ |
647 | V(JumpIfNull_Wide, T, WIDE, tgt, ___, ___) \ |
648 | V(JumpIfNotNull, T, ORDN, tgt, ___, ___) \ |
649 | V(JumpIfNotNull_Wide, T, WIDE, tgt, ___, ___) \ |
650 | V(DirectCall, D_F, ORDN, num, num, ___) \ |
651 | V(DirectCall_Wide, D_F, WIDE, num, num, ___) \ |
652 | V(UncheckedDirectCall, D_F, ORDN, num, num, ___) \ |
653 | V(UncheckedDirectCall_Wide, D_F, WIDE, num, num, ___) \ |
654 | V(InterfaceCall, D_F, ORDN, num, num, ___) \ |
655 | V(InterfaceCall_Wide, D_F, WIDE, num, num, ___) \ |
656 | V(Unused23, 0, RESV, ___, ___, ___) \ |
657 | V(Unused24, 0, RESV, ___, ___, ___) \ |
658 | V(InstantiatedInterfaceCall, D_F, ORDN, num, num, ___) \ |
659 | V(InstantiatedInterfaceCall_Wide, D_F, WIDE, num, num, ___) \ |
660 | V(UncheckedClosureCall, D_F, ORDN, num, num, ___) \ |
661 | V(UncheckedClosureCall_Wide, D_F, WIDE, num, num, ___) \ |
662 | V(UncheckedInterfaceCall, D_F, ORDN, num, num, ___) \ |
663 | V(UncheckedInterfaceCall_Wide, D_F, WIDE, num, num, ___) \ |
664 | V(DynamicCall, D_F, ORDN, num, num, ___) \ |
665 | V(DynamicCall_Wide, D_F, WIDE, num, num, ___) \ |
666 | V(NativeCall, D, ORDN, lit, ___, ___) \ |
667 | V(NativeCall_Wide, D, WIDE, lit, ___, ___) \ |
668 | V(ReturnTOS, 0, ORDN, ___, ___, ___) \ |
669 | V(Unused29, 0, RESV, ___, ___, ___) \ |
670 | V(AssertAssignable, A_E, ORDN, num, lit, ___) \ |
671 | V(AssertAssignable_Wide, A_E, WIDE, num, lit, ___) \ |
672 | V(Unused30, 0, RESV, ___, ___, ___) \ |
673 | V(Unused31, 0, RESV, ___, ___, ___) \ |
674 | V(AssertBoolean, A, ORDN, num, ___, ___) \ |
675 | V(AssertSubtype, 0, ORDN, ___, ___, ___) \ |
676 | V(LoadTypeArgumentsField, D, ORDN, lit, ___, ___) \ |
677 | V(LoadTypeArgumentsField_Wide, D, WIDE, lit, ___, ___) \ |
678 | V(InstantiateType, D, ORDN, lit, ___, ___) \ |
679 | V(InstantiateType_Wide, D, WIDE, lit, ___, ___) \ |
680 | V(InstantiateTypeArgumentsTOS, A_E, ORDN, num, lit, ___) \ |
681 | V(InstantiateTypeArgumentsTOS_Wide, A_E, WIDE, num, lit, ___) \ |
682 | V(Unused32, 0, RESV, ___, ___, ___) \ |
683 | V(Unused33, 0, RESV, ___, ___, ___) \ |
684 | V(Unused34, 0, RESV, ___, ___, ___) \ |
685 | V(Unused35, 0, RESV, ___, ___, ___) \ |
686 | V(Throw, A, ORDN, num, ___, ___) \ |
687 | V(SetFrame, A, ORDN, num, ___, num) \ |
688 | V(MoveSpecial, A_Y, ORDN, num, xeg, ___) \ |
689 | V(MoveSpecial_Wide, A_Y, WIDE, num, xeg, ___) \ |
690 | V(BooleanNegateTOS, 0, ORDN, ___, ___, ___) \ |
691 | V(EqualsNull, 0, ORDN, ___, ___, ___) \ |
692 | V(NullCheck, D, ORDN, lit, ___, ___) \ |
693 | V(NullCheck_Wide, D, WIDE, lit, ___, ___) \ |
694 | V(NegateInt, 0, ORDN, ___, ___, ___) \ |
695 | V(AddInt, 0, ORDN, ___, ___, ___) \ |
696 | V(SubInt, 0, ORDN, ___, ___, ___) \ |
697 | V(MulInt, 0, ORDN, ___, ___, ___) \ |
698 | V(TruncDivInt, 0, ORDN, ___, ___, ___) \ |
699 | V(ModInt, 0, ORDN, ___, ___, ___) \ |
700 | V(BitAndInt, 0, ORDN, ___, ___, ___) \ |
701 | V(BitOrInt, 0, ORDN, ___, ___, ___) \ |
702 | V(BitXorInt, 0, ORDN, ___, ___, ___) \ |
703 | V(ShlInt, 0, ORDN, ___, ___, ___) \ |
704 | V(ShrInt, 0, ORDN, ___, ___, ___) \ |
705 | V(CompareIntEq, 0, ORDN, ___, ___, ___) \ |
706 | V(CompareIntGt, 0, ORDN, ___, ___, ___) \ |
707 | V(CompareIntLt, 0, ORDN, ___, ___, ___) \ |
708 | V(CompareIntGe, 0, ORDN, ___, ___, ___) \ |
709 | V(CompareIntLe, 0, ORDN, ___, ___, ___) \ |
710 | V(NegateDouble, 0, ORDN, ___, ___, ___) \ |
711 | V(AddDouble, 0, ORDN, ___, ___, ___) \ |
712 | V(SubDouble, 0, ORDN, ___, ___, ___) \ |
713 | V(MulDouble, 0, ORDN, ___, ___, ___) \ |
714 | V(DivDouble, 0, ORDN, ___, ___, ___) \ |
715 | V(CompareDoubleEq, 0, ORDN, ___, ___, ___) \ |
716 | V(CompareDoubleGt, 0, ORDN, ___, ___, ___) \ |
717 | V(CompareDoubleLt, 0, ORDN, ___, ___, ___) \ |
718 | V(CompareDoubleGe, 0, ORDN, ___, ___, ___) \ |
719 | V(CompareDoubleLe, 0, ORDN, ___, ___, ___) \ |
720 | |
721 | // These bytecodes are only generated within the VM. Reassigning their |
722 | // opcodes is not a breaking change. |
723 | #define INTERNAL_KERNEL_BYTECODES_LIST(V) \ |
724 | V(VMInternal_ImplicitGetter, 0, ORDN, ___, ___, ___) \ |
725 | V(VMInternal_ImplicitSetter, 0, ORDN, ___, ___, ___) \ |
726 | V(VMInternal_ImplicitStaticGetter, 0, ORDN, ___, ___, ___) \ |
727 | V(VMInternal_MethodExtractor, 0, ORDN, ___, ___, ___) \ |
728 | V(VMInternal_InvokeClosure, 0, ORDN, ___, ___, ___) \ |
729 | V(VMInternal_InvokeField, 0, ORDN, ___, ___, ___) \ |
730 | V(VMInternal_ForwardDynamicInvocation, 0, ORDN, ___, ___, ___) \ |
731 | V(VMInternal_NoSuchMethodDispatcher, 0, ORDN, ___, ___, ___) \ |
732 | V(VMInternal_ImplicitStaticClosure, 0, ORDN, ___, ___, ___) \ |
733 | V(VMInternal_ImplicitInstanceClosure, 0, ORDN, ___, ___, ___) \ |
734 | |
735 | #define KERNEL_BYTECODES_LIST(V) \ |
736 | PUBLIC_KERNEL_BYTECODES_LIST(V) \ |
737 | INTERNAL_KERNEL_BYTECODES_LIST(V) |
738 | |
739 | // clang-format on |
740 | |
741 | typedef uint8_t KBCInstr; |
742 | |
743 | class KernelBytecode { |
744 | public: |
745 | // Magic value of bytecode files. |
746 | static const intptr_t kMagicValue = 0x44424332; // 'DBC2' |
747 | // Minimum bytecode format version supported by VM. |
748 | static const intptr_t kMinSupportedBytecodeFormatVersion = 28; |
749 | // Maximum bytecode format version supported by VM. |
750 | // The range of supported versions should include version produced by bytecode |
751 | // generator (currentBytecodeFormatVersion in pkg/vm/lib/bytecode/dbc.dart). |
752 | static const intptr_t kMaxSupportedBytecodeFormatVersion = 28; |
753 | |
754 | enum Opcode { |
755 | #define DECLARE_BYTECODE(name, encoding, kind, op1, op2, op3) k##name, |
756 | KERNEL_BYTECODES_LIST(DECLARE_BYTECODE) |
757 | #undef DECLARE_BYTECODE |
758 | }; |
759 | |
760 | static const char* NameOf(Opcode op) { |
761 | const char* names[] = { |
762 | #define NAME(name, encoding, kind, op1, op2, op3) #name, |
763 | KERNEL_BYTECODES_LIST(NAME) |
764 | #undef NAME |
765 | }; |
766 | return names[op]; |
767 | } |
768 | |
769 | static const intptr_t kInstructionSize[]; |
770 | |
771 | enum SpecialIndex { |
772 | kExceptionSpecialIndex, |
773 | kStackTraceSpecialIndex, |
774 | kSpecialIndexCount |
775 | }; |
776 | |
777 | private: |
778 | static const intptr_t kWideModifier = 1; |
779 | |
780 | // Should be used only on instructions with wide variants. |
781 | DART_FORCE_INLINE static bool IsWide(const KBCInstr* instr) { |
782 | return ((DecodeOpcode(instr) & kWideModifier) != 0); |
783 | } |
784 | |
785 | public: |
786 | DART_FORCE_INLINE static uint8_t DecodeA(const KBCInstr* bc) { return bc[1]; } |
787 | |
788 | DART_FORCE_INLINE static uint8_t DecodeB(const KBCInstr* bc) { return bc[2]; } |
789 | |
790 | DART_FORCE_INLINE static uint8_t DecodeC(const KBCInstr* bc) { return bc[3]; } |
791 | |
792 | DART_FORCE_INLINE static uint32_t DecodeD(const KBCInstr* bc) { |
793 | if (IsWide(bc)) { |
794 | return static_cast<uint32_t>(bc[1]) | |
795 | (static_cast<uint32_t>(bc[2]) << 8) | |
796 | (static_cast<uint32_t>(bc[3]) << 16) | |
797 | (static_cast<uint32_t>(bc[4]) << 24); |
798 | } else { |
799 | return bc[1]; |
800 | } |
801 | } |
802 | |
803 | DART_FORCE_INLINE static int32_t DecodeX(const KBCInstr* bc) { |
804 | if (IsWide(bc)) { |
805 | return static_cast<int32_t>(static_cast<uint32_t>(bc[1]) | |
806 | (static_cast<uint32_t>(bc[2]) << 8) | |
807 | (static_cast<uint32_t>(bc[3]) << 16) | |
808 | (static_cast<uint32_t>(bc[4]) << 24)); |
809 | } else { |
810 | return static_cast<int8_t>(bc[1]); |
811 | } |
812 | } |
813 | |
814 | DART_FORCE_INLINE static int32_t DecodeT(const KBCInstr* bc) { |
815 | if (IsWide(bc)) { |
816 | return static_cast<int32_t>((static_cast<uint32_t>(bc[1]) << 8) | |
817 | (static_cast<uint32_t>(bc[2]) << 16) | |
818 | (static_cast<uint32_t>(bc[3]) << 24)) >> |
819 | 8; |
820 | } else { |
821 | return static_cast<int8_t>(bc[1]); |
822 | } |
823 | } |
824 | |
825 | DART_FORCE_INLINE static uint32_t DecodeE(const KBCInstr* bc) { |
826 | if (IsWide(bc)) { |
827 | return static_cast<uint32_t>(bc[2]) | |
828 | (static_cast<uint32_t>(bc[3]) << 8) | |
829 | (static_cast<uint32_t>(bc[4]) << 16) | |
830 | (static_cast<uint32_t>(bc[5]) << 24); |
831 | } else { |
832 | return bc[2]; |
833 | } |
834 | } |
835 | |
836 | DART_FORCE_INLINE static int32_t DecodeY(const KBCInstr* bc) { |
837 | if (IsWide(bc)) { |
838 | return static_cast<int32_t>(static_cast<uint32_t>(bc[2]) | |
839 | (static_cast<uint32_t>(bc[3]) << 8) | |
840 | (static_cast<uint32_t>(bc[4]) << 16) | |
841 | (static_cast<uint32_t>(bc[5]) << 24)); |
842 | } else { |
843 | return static_cast<int8_t>(bc[2]); |
844 | } |
845 | } |
846 | |
847 | DART_FORCE_INLINE static uint8_t DecodeF(const KBCInstr* bc) { |
848 | if (IsWide(bc)) { |
849 | return bc[5]; |
850 | } else { |
851 | return bc[2]; |
852 | } |
853 | } |
854 | |
855 | DART_FORCE_INLINE static Opcode DecodeOpcode(const KBCInstr* bc) { |
856 | return static_cast<Opcode>(bc[0]); |
857 | } |
858 | |
859 | DART_FORCE_INLINE static const KBCInstr* Next(const KBCInstr* bc) { |
860 | return bc + kInstructionSize[DecodeOpcode(bc)]; |
861 | } |
862 | |
863 | DART_FORCE_INLINE static uword Next(uword pc) { |
864 | return pc + kInstructionSize[DecodeOpcode( |
865 | reinterpret_cast<const KBCInstr*>(pc))]; |
866 | } |
867 | |
868 | DART_FORCE_INLINE static bool IsJumpOpcode(const KBCInstr* instr) { |
869 | switch (DecodeOpcode(instr)) { |
870 | case KernelBytecode::kJump: |
871 | case KernelBytecode::kJump_Wide: |
872 | case KernelBytecode::kJumpIfNoAsserts: |
873 | case KernelBytecode::kJumpIfNoAsserts_Wide: |
874 | case KernelBytecode::kJumpIfNotZeroTypeArgs: |
875 | case KernelBytecode::kJumpIfNotZeroTypeArgs_Wide: |
876 | case KernelBytecode::kJumpIfEqStrict: |
877 | case KernelBytecode::kJumpIfEqStrict_Wide: |
878 | case KernelBytecode::kJumpIfNeStrict: |
879 | case KernelBytecode::kJumpIfNeStrict_Wide: |
880 | case KernelBytecode::kJumpIfTrue: |
881 | case KernelBytecode::kJumpIfTrue_Wide: |
882 | case KernelBytecode::kJumpIfFalse: |
883 | case KernelBytecode::kJumpIfFalse_Wide: |
884 | case KernelBytecode::kJumpIfNull: |
885 | case KernelBytecode::kJumpIfNull_Wide: |
886 | case KernelBytecode::kJumpIfNotNull: |
887 | case KernelBytecode::kJumpIfNotNull_Wide: |
888 | case KernelBytecode::kJumpIfUnchecked: |
889 | case KernelBytecode::kJumpIfUnchecked_Wide: |
890 | case KernelBytecode::kJumpIfInitialized: |
891 | case KernelBytecode::kJumpIfInitialized_Wide: |
892 | return true; |
893 | |
894 | default: |
895 | return false; |
896 | } |
897 | } |
898 | |
899 | DART_FORCE_INLINE static bool IsJumpIfUncheckedOpcode(const KBCInstr* instr) { |
900 | switch (DecodeOpcode(instr)) { |
901 | case KernelBytecode::kJumpIfUnchecked: |
902 | case KernelBytecode::kJumpIfUnchecked_Wide: |
903 | return true; |
904 | default: |
905 | return false; |
906 | } |
907 | } |
908 | |
909 | DART_FORCE_INLINE static bool IsLoadConstantOpcode(const KBCInstr* instr) { |
910 | switch (DecodeOpcode(instr)) { |
911 | case KernelBytecode::kLoadConstant: |
912 | case KernelBytecode::kLoadConstant_Wide: |
913 | return true; |
914 | default: |
915 | return false; |
916 | } |
917 | } |
918 | |
919 | DART_FORCE_INLINE static bool IsCheckStackOpcode(const KBCInstr* instr) { |
920 | return DecodeOpcode(instr) == KernelBytecode::kCheckStack; |
921 | } |
922 | |
923 | DART_FORCE_INLINE static bool IsCheckFunctionTypeArgs(const KBCInstr* instr) { |
924 | switch (DecodeOpcode(instr)) { |
925 | case KernelBytecode::kCheckFunctionTypeArgs: |
926 | case KernelBytecode::kCheckFunctionTypeArgs_Wide: |
927 | return true; |
928 | default: |
929 | return false; |
930 | } |
931 | } |
932 | |
933 | DART_FORCE_INLINE static bool IsEntryOpcode(const KBCInstr* instr) { |
934 | switch (DecodeOpcode(instr)) { |
935 | case KernelBytecode::kEntry: |
936 | case KernelBytecode::kEntry_Wide: |
937 | return true; |
938 | default: |
939 | return false; |
940 | } |
941 | } |
942 | |
943 | DART_FORCE_INLINE static bool IsEntryFixedOpcode(const KBCInstr* instr) { |
944 | switch (DecodeOpcode(instr)) { |
945 | case KernelBytecode::kEntryFixed: |
946 | case KernelBytecode::kEntryFixed_Wide: |
947 | return true; |
948 | default: |
949 | return false; |
950 | } |
951 | } |
952 | |
953 | DART_FORCE_INLINE static bool IsEntryOptionalOpcode(const KBCInstr* instr) { |
954 | return DecodeOpcode(instr) == KernelBytecode::kEntryOptional; |
955 | } |
956 | |
957 | DART_FORCE_INLINE static bool IsFrameOpcode(const KBCInstr* instr) { |
958 | switch (DecodeOpcode(instr)) { |
959 | case KernelBytecode::kFrame: |
960 | case KernelBytecode::kFrame_Wide: |
961 | return true; |
962 | default: |
963 | return false; |
964 | } |
965 | } |
966 | |
967 | DART_FORCE_INLINE static bool IsSetFrameOpcode(const KBCInstr* instr) { |
968 | return DecodeOpcode(instr) == KernelBytecode::kSetFrame; |
969 | } |
970 | |
971 | DART_FORCE_INLINE static bool IsNativeCallOpcode(const KBCInstr* instr) { |
972 | switch (DecodeOpcode(instr)) { |
973 | case KernelBytecode::kNativeCall: |
974 | case KernelBytecode::kNativeCall_Wide: |
975 | return true; |
976 | default: |
977 | return false; |
978 | } |
979 | } |
980 | |
981 | DART_FORCE_INLINE static bool IsDebugCheckOpcode(const KBCInstr* instr) { |
982 | return DecodeOpcode(instr) == KernelBytecode::kDebugCheck; |
983 | } |
984 | |
985 | // The interpreter, the bytecode generator, the bytecode compiler, and this |
986 | // function must agree on this list of opcodes. |
987 | // For each instruction with listed opcode: |
988 | // - The interpreter checks for a debug break. |
989 | // - The bytecode generator emits a source position. |
990 | // - The bytecode compiler may emit a DebugStepCheck call. |
991 | DART_FORCE_INLINE static bool IsDebugCheckedOpcode(const KBCInstr* instr) { |
992 | switch (DecodeOpcode(instr)) { |
993 | case KernelBytecode::kDebugCheck: |
994 | case KernelBytecode::kDirectCall: |
995 | case KernelBytecode::kDirectCall_Wide: |
996 | case KernelBytecode::kUncheckedDirectCall: |
997 | case KernelBytecode::kUncheckedDirectCall_Wide: |
998 | case KernelBytecode::kInterfaceCall: |
999 | case KernelBytecode::kInterfaceCall_Wide: |
1000 | case KernelBytecode::kInstantiatedInterfaceCall: |
1001 | case KernelBytecode::kInstantiatedInterfaceCall_Wide: |
1002 | case KernelBytecode::kUncheckedClosureCall: |
1003 | case KernelBytecode::kUncheckedClosureCall_Wide: |
1004 | case KernelBytecode::kUncheckedInterfaceCall: |
1005 | case KernelBytecode::kUncheckedInterfaceCall_Wide: |
1006 | case KernelBytecode::kDynamicCall: |
1007 | case KernelBytecode::kDynamicCall_Wide: |
1008 | case KernelBytecode::kReturnTOS: |
1009 | case KernelBytecode::kEqualsNull: |
1010 | case KernelBytecode::kNegateInt: |
1011 | case KernelBytecode::kNegateDouble: |
1012 | case KernelBytecode::kAddInt: |
1013 | case KernelBytecode::kSubInt: |
1014 | case KernelBytecode::kMulInt: |
1015 | case KernelBytecode::kTruncDivInt: |
1016 | case KernelBytecode::kModInt: |
1017 | case KernelBytecode::kBitAndInt: |
1018 | case KernelBytecode::kBitOrInt: |
1019 | case KernelBytecode::kBitXorInt: |
1020 | case KernelBytecode::kShlInt: |
1021 | case KernelBytecode::kShrInt: |
1022 | case KernelBytecode::kCompareIntEq: |
1023 | case KernelBytecode::kCompareIntGt: |
1024 | case KernelBytecode::kCompareIntLt: |
1025 | case KernelBytecode::kCompareIntGe: |
1026 | case KernelBytecode::kCompareIntLe: |
1027 | case KernelBytecode::kAddDouble: |
1028 | case KernelBytecode::kSubDouble: |
1029 | case KernelBytecode::kMulDouble: |
1030 | case KernelBytecode::kDivDouble: |
1031 | case KernelBytecode::kCompareDoubleEq: |
1032 | case KernelBytecode::kCompareDoubleGt: |
1033 | case KernelBytecode::kCompareDoubleLt: |
1034 | case KernelBytecode::kCompareDoubleGe: |
1035 | case KernelBytecode::kCompareDoubleLe: |
1036 | return true; |
1037 | default: |
1038 | return false; |
1039 | } |
1040 | } |
1041 | |
1042 | static const uint8_t kNativeCallToGrowableListArgc = 2; |
1043 | |
1044 | // Returns a fake return address which points after the 2-argument |
1045 | // bytecode call, followed by ReturnTOS instructions. |
1046 | static const KBCInstr* GetNativeCallToGrowableListReturnTrampoline(); |
1047 | |
1048 | DART_FORCE_INLINE static uint8_t DecodeArgc(const KBCInstr* ret_addr) { |
1049 | // All call instructions have DF encoding, with argc being the last byte |
1050 | // regardless of whether the wide variant is used or not. |
1051 | return ret_addr[-1]; |
1052 | } |
1053 | |
1054 | // Converts bytecode PC into an offset. |
1055 | // For return addresses used in PcDescriptors, PC is also augmented by 1. |
1056 | // TODO(regis): Eliminate this correction. |
1057 | static intptr_t BytecodePcToOffset(uint32_t pc, bool is_return_address) { |
1058 | return pc + (is_return_address ? 1 : 0); |
1059 | } |
1060 | |
1061 | static uint32_t OffsetToBytecodePc(intptr_t offset, bool is_return_address) { |
1062 | return offset - (is_return_address ? 1 : 0); |
1063 | } |
1064 | |
1065 | static void GetVMInternalBytecodeInstructions(Opcode opcode, |
1066 | const KBCInstr** instructions, |
1067 | intptr_t* instructions_size); |
1068 | |
1069 | private: |
1070 | DISALLOW_ALLOCATION(); |
1071 | DISALLOW_IMPLICIT_CONSTRUCTORS(KernelBytecode); |
1072 | }; |
1073 | |
1074 | } // namespace dart |
1075 | |
1076 | #endif // RUNTIME_VM_CONSTANTS_KBC_H_ |
1077 | |