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
12namespace 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
741typedef uint8_t KBCInstr;
742
743class 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