blob: 39ae12adf6164a1b37f564bc1e2bd3b24bc64e85 [file] [log] [blame]
// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
/// Dart kernel bytecode instructions (described in runtime/vm/constants_kbc.h).
library vm.bytecode.dbc;
/// Version of bytecode format, produced by default.
/// Before bumping current bytecode version format, make sure that
/// all users have switched to a VM which is able to consume new
/// version of bytecode.
const int currentBytecodeFormatVersion = 28;
enum Opcode {
kUnusedOpcode000,
kUnusedOpcode001,
kUnusedOpcode002,
kUnusedOpcode003,
kUnusedOpcode004,
kUnusedOpcode005,
kUnusedOpcode006,
kUnusedOpcode007,
kUnusedOpcode008,
kUnusedOpcode009,
kUnusedOpcode010,
kUnusedOpcode011,
kUnusedOpcode012,
kUnusedOpcode013,
kUnusedOpcode014,
kUnusedOpcode015,
kUnusedOpcode016,
kUnusedOpcode017,
kUnusedOpcode018,
kUnusedOpcode019,
kUnusedOpcode020,
kUnusedOpcode021,
kUnusedOpcode022,
kUnusedOpcode023,
kUnusedOpcode024,
kUnusedOpcode025,
kUnusedOpcode026,
kUnusedOpcode027,
kUnusedOpcode028,
kUnusedOpcode029,
kUnusedOpcode030,
kUnusedOpcode031,
kUnusedOpcode032,
kUnusedOpcode033,
kUnusedOpcode034,
kUnusedOpcode035,
kUnusedOpcode036,
kUnusedOpcode037,
kUnusedOpcode038,
kUnusedOpcode039,
kUnusedOpcode040,
kUnusedOpcode041,
kUnusedOpcode042,
kUnusedOpcode043,
kUnusedOpcode044,
kUnusedOpcode045,
kUnusedOpcode046,
kUnusedOpcode047,
kUnusedOpcode048,
kUnusedOpcode049,
kUnusedOpcode050,
kUnusedOpcode051,
kUnusedOpcode052,
kUnusedOpcode053,
kUnusedOpcode054,
kUnusedOpcode055,
kUnusedOpcode056,
kUnusedOpcode057,
kUnusedOpcode058,
kUnusedOpcode059,
kUnusedOpcode060,
kUnusedOpcode061,
kUnusedOpcode062,
kUnusedOpcode063,
kUnusedOpcode064,
kUnusedOpcode065,
kUnusedOpcode066,
kUnusedOpcode067,
kUnusedOpcode068,
kUnusedOpcode069,
kUnusedOpcode070,
kUnusedOpcode071,
kUnusedOpcode072,
kUnusedOpcode073,
kUnusedOpcode074,
kUnusedOpcode075,
kUnusedOpcode076,
kUnusedOpcode077,
kUnusedOpcode078,
kUnusedOpcode079,
kUnusedOpcode080,
kUnusedOpcode081,
// Late variables.
kJumpIfInitialized,
kJumpIfInitialized_Wide,
kPushUninitializedSentinel,
kTrap,
// Prologue and stack management.
kEntry,
kEntry_Wide,
// TODO(alexmarkov): cleanup now unused EntryFixed instruction.
kEntryFixed,
kEntryFixed_Wide,
kEntryOptional,
kUnused00, // Reserved for EntryNoLocals.
kLoadConstant,
kLoadConstant_Wide,
kFrame,
kFrame_Wide,
kCheckFunctionTypeArgs,
kCheckFunctionTypeArgs_Wide,
kCheckStack,
kDebugCheck,
kJumpIfUnchecked,
kJumpIfUnchecked_Wide,
// Object allocation.
kAllocate,
kAllocate_Wide,
kAllocateT,
kCreateArrayTOS,
kAllocateClosure,
kAllocateClosure_Wide,
// Context allocation and access.
kAllocateContext,
kAllocateContext_Wide,
kCloneContext,
kCloneContext_Wide,
kLoadContextParent,
kStoreContextParent,
kLoadContextVar,
kLoadContextVar_Wide,
kUnused04, // Reserved for LoadContextVar0
kUnused05,
kStoreContextVar,
kStoreContextVar_Wide,
// Constants.
kPushConstant,
kPushConstant_Wide,
kUnused06, // Reserved for PushConstant0
kUnused07,
kPushTrue,
kPushFalse,
kPushInt,
kPushInt_Wide,
kUnused08, // Reserved for PushInt0
kUnused09, // Reserved for PushInt1
kUnused10, // Reserved for PushInt2
kUnused11,
kPushNull,
// Locals and expression stack.
kDrop1,
kPush,
kPush_Wide,
kUnused12, // Reserved for PushLocal0
kUnused13, // Reserved for PushLocal1
kUnused14, // Reserved for PushLocal2
kUnused15, // Reserved for PushLocal3
kUnused16, // Reserved for PushParamLast0
kUnused17, // Reserved for PushParamLast1
kPopLocal,
kPopLocal_Wide,
kLoadStatic,
kLoadStatic_Wide,
kStoreLocal,
kStoreLocal_Wide,
// Instance fields and arrays.
kLoadFieldTOS,
kLoadFieldTOS_Wide,
kStoreFieldTOS,
kStoreFieldTOS_Wide,
kStoreIndexedTOS,
kUnused20,
// Late fields.
kInitLateField,
kInitLateField_Wide,
// Static fields.
kStoreStaticTOS,
kStoreStaticTOS_Wide,
// Jumps.
kJump,
kJump_Wide,
kJumpIfNoAsserts,
kJumpIfNoAsserts_Wide,
kJumpIfNotZeroTypeArgs,
kJumpIfNotZeroTypeArgs_Wide,
kJumpIfEqStrict,
kJumpIfEqStrict_Wide,
kJumpIfNeStrict,
kJumpIfNeStrict_Wide,
kJumpIfTrue,
kJumpIfTrue_Wide,
kJumpIfFalse,
kJumpIfFalse_Wide,
kJumpIfNull,
kJumpIfNull_Wide,
kJumpIfNotNull,
kJumpIfNotNull_Wide,
// Calls.
kDirectCall,
kDirectCall_Wide,
kUncheckedDirectCall,
kUncheckedDirectCall_Wide,
kInterfaceCall,
kInterfaceCall_Wide,
kUnused23, // Reserved for InterfaceCall1
kUnused24, // Reserved for InterfaceCall1_Wide
kInstantiatedInterfaceCall,
kInstantiatedInterfaceCall_Wide,
kUncheckedClosureCall,
kUncheckedClosureCall_Wide,
kUncheckedInterfaceCall,
kUncheckedInterfaceCall_Wide,
kDynamicCall,
kDynamicCall_Wide,
kNativeCall,
kNativeCall_Wide,
kReturnTOS,
kUnused29,
// Types and type checks.
kAssertAssignable,
kAssertAssignable_Wide,
kUnused30, // Reserved for AsSimpleType
kUnused31, // Reserved for AsSimpleType_Wide
kAssertBoolean,
kAssertSubtype,
kLoadTypeArgumentsField,
kLoadTypeArgumentsField_Wide,
kInstantiateType,
kInstantiateType_Wide,
kInstantiateTypeArgumentsTOS,
kInstantiateTypeArgumentsTOS_Wide,
kUnused32, // Reserved for IsType
kUnused33, // Reserved for IsType_Wide
kUnused34, // Reserved for IsSimpleType
kUnused35, // Reserved for IsSimpleType_Wide
// Exception handling.
kThrow,
kSetFrame,
kMoveSpecial,
kMoveSpecial_Wide,
// Bool operations.
kBooleanNegateTOS,
// Null operations.
kEqualsNull,
kNullCheck,
kNullCheck_Wide,
// Int operations.
kNegateInt,
kAddInt,
kSubInt,
kMulInt,
kTruncDivInt,
kModInt,
kBitAndInt,
kBitOrInt,
kBitXorInt,
kShlInt,
kShrInt,
kCompareIntEq,
kCompareIntGt,
kCompareIntLt,
kCompareIntGe,
kCompareIntLe,
// Double operations.
kNegateDouble,
kAddDouble,
kSubDouble,
kMulDouble,
kDivDouble,
kCompareDoubleEq,
kCompareDoubleGt,
kCompareDoubleLt,
kCompareDoubleGe,
kCompareDoubleLe,
}
/// Compact variants of opcodes are always even.
/// Wide variant = opcode + kWideModifier.
const int kWideModifier = 1;
/// Opcode should fit into 1 byte.
const int kMaxOpcodes = 256;
enum Encoding {
k0, // No operands.
kA, // 1 operand: A = 8-bit unsigned.
kD, // 1 operand: D = 8/32-bit unsigned.
kX, // 1 operand: X = 8/32-bit signed.
kT, // 1 operand: T = 8/24-bit signed.
kAE, // 2 operands: A = 8-bit unsigned, E = 8/32-bit unsigned
kAY, // 2 operands: A = 8-bit unsigned, Y = 8/32-bit signed
kDF, // 2 operands: D = 8/32-bit unsigned, F = 8-bit unsigned
kABC, // 3 operands: A, B, C - 8-bit unsigned.
}
int instructionSize(Encoding encoding, bool isWide) {
switch (encoding) {
case Encoding.k0:
return 1;
case Encoding.kA:
return 2;
case Encoding.kD:
return isWide ? 5 : 2;
case Encoding.kX:
return isWide ? 5 : 2;
case Encoding.kT:
return isWide ? 4 : 2;
case Encoding.kAE:
return isWide ? 6 : 3;
case Encoding.kAY:
return isWide ? 6 : 3;
case Encoding.kDF:
return isWide ? 6 : 3;
case Encoding.kABC:
return 4;
}
throw 'Unexpected instruction encoding $encoding';
}
enum Operand {
none, // ignored / non-existent operand
imm, // immediate operand
lit, // constant literal from object pool
reg, // register (unsigned FP relative local)
xeg, // x-register (signed FP relative local)
tgt, // jump target relative to the PC of the current instruction
spe, // SpecialIndex
}
class Format {
final Encoding encoding;
final List<Operand> operands;
const Format(this.encoding, this.operands);
}
const Map<Opcode, Format> BytecodeFormats = const {
Opcode.kTrap: const Format(
Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
Opcode.kEntry: const Format(
Encoding.kD, const [Operand.imm, Operand.none, Operand.none]),
Opcode.kEntryFixed: const Format(
Encoding.kAE, const [Operand.imm, Operand.imm, Operand.none]),
Opcode.kEntryOptional: const Format(
Encoding.kABC, const [Operand.imm, Operand.imm, Operand.imm]),
Opcode.kLoadConstant: const Format(
Encoding.kAE, const [Operand.reg, Operand.lit, Operand.none]),
Opcode.kFrame: const Format(
Encoding.kD, const [Operand.imm, Operand.none, Operand.none]),
Opcode.kCheckFunctionTypeArgs: const Format(
Encoding.kAE, const [Operand.imm, Operand.reg, Operand.none]),
Opcode.kCheckStack: const Format(
Encoding.kA, const [Operand.imm, Operand.none, Operand.none]),
Opcode.kDebugCheck: const Format(
Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
Opcode.kAllocate: const Format(
Encoding.kD, const [Operand.lit, Operand.none, Operand.none]),
Opcode.kAllocateT: const Format(
Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
Opcode.kCreateArrayTOS: const Format(
Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
Opcode.kAllocateContext: const Format(
Encoding.kAE, const [Operand.imm, Operand.imm, Operand.none]),
Opcode.kCloneContext: const Format(
Encoding.kAE, const [Operand.imm, Operand.imm, Operand.none]),
Opcode.kLoadContextParent: const Format(
Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
Opcode.kStoreContextParent: const Format(
Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
Opcode.kLoadContextVar: const Format(
Encoding.kAE, const [Operand.imm, Operand.imm, Operand.none]),
Opcode.kStoreContextVar: const Format(
Encoding.kAE, const [Operand.imm, Operand.imm, Operand.none]),
Opcode.kPushConstant: const Format(
Encoding.kD, const [Operand.lit, Operand.none, Operand.none]),
Opcode.kPushNull: const Format(
Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
Opcode.kPushTrue: const Format(
Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
Opcode.kPushFalse: const Format(
Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
Opcode.kPushInt: const Format(
Encoding.kX, const [Operand.imm, Operand.none, Operand.none]),
Opcode.kDrop1: const Format(
Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
Opcode.kPush: const Format(
Encoding.kX, const [Operand.xeg, Operand.none, Operand.none]),
Opcode.kPopLocal: const Format(
Encoding.kX, const [Operand.xeg, Operand.none, Operand.none]),
Opcode.kStoreLocal: const Format(
Encoding.kX, const [Operand.xeg, Operand.none, Operand.none]),
Opcode.kLoadFieldTOS: const Format(
Encoding.kD, const [Operand.lit, Operand.none, Operand.none]),
Opcode.kStoreFieldTOS: const Format(
Encoding.kD, const [Operand.lit, Operand.none, Operand.none]),
Opcode.kStoreIndexedTOS: const Format(
Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
Opcode.kInitLateField: const Format(
Encoding.kD, const [Operand.lit, Operand.none, Operand.none]),
Opcode.kPushUninitializedSentinel: const Format(
Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
Opcode.kJumpIfInitialized: const Format(
Encoding.kT, const [Operand.tgt, Operand.none, Operand.none]),
Opcode.kLoadStatic: const Format(
Encoding.kD, const [Operand.lit, Operand.none, Operand.none]),
Opcode.kStoreStaticTOS: const Format(
Encoding.kD, const [Operand.lit, Operand.none, Operand.none]),
Opcode.kJump: const Format(
Encoding.kT, const [Operand.tgt, Operand.none, Operand.none]),
Opcode.kJumpIfNoAsserts: const Format(
Encoding.kT, const [Operand.tgt, Operand.none, Operand.none]),
Opcode.kJumpIfNotZeroTypeArgs: const Format(
Encoding.kT, const [Operand.tgt, Operand.none, Operand.none]),
Opcode.kJumpIfEqStrict: const Format(
Encoding.kT, const [Operand.tgt, Operand.none, Operand.none]),
Opcode.kJumpIfNeStrict: const Format(
Encoding.kT, const [Operand.tgt, Operand.none, Operand.none]),
Opcode.kJumpIfTrue: const Format(
Encoding.kT, const [Operand.tgt, Operand.none, Operand.none]),
Opcode.kJumpIfFalse: const Format(
Encoding.kT, const [Operand.tgt, Operand.none, Operand.none]),
Opcode.kJumpIfNull: const Format(
Encoding.kT, const [Operand.tgt, Operand.none, Operand.none]),
Opcode.kJumpIfNotNull: const Format(
Encoding.kT, const [Operand.tgt, Operand.none, Operand.none]),
Opcode.kJumpIfUnchecked: const Format(
Encoding.kT, const [Operand.tgt, Operand.none, Operand.none]),
Opcode.kInterfaceCall: const Format(
Encoding.kDF, const [Operand.lit, Operand.imm, Operand.none]),
Opcode.kInstantiatedInterfaceCall: const Format(
Encoding.kDF, const [Operand.lit, Operand.imm, Operand.none]),
Opcode.kDynamicCall: const Format(
Encoding.kDF, const [Operand.lit, Operand.imm, Operand.none]),
Opcode.kNativeCall: const Format(
Encoding.kD, const [Operand.lit, Operand.none, Operand.none]),
Opcode.kReturnTOS: const Format(
Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
Opcode.kAssertAssignable: const Format(
Encoding.kAE, const [Operand.imm, Operand.lit, Operand.none]),
Opcode.kAssertBoolean: const Format(
Encoding.kA, const [Operand.imm, Operand.none, Operand.none]),
Opcode.kAssertSubtype: const Format(
Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
Opcode.kLoadTypeArgumentsField: const Format(
Encoding.kD, const [Operand.lit, Operand.none, Operand.none]),
Opcode.kInstantiateType: const Format(
Encoding.kD, const [Operand.lit, Operand.none, Operand.none]),
Opcode.kInstantiateTypeArgumentsTOS: const Format(
Encoding.kAE, const [Operand.imm, Operand.lit, Operand.none]),
Opcode.kThrow: const Format(
Encoding.kA, const [Operand.imm, Operand.none, Operand.none]),
Opcode.kMoveSpecial: const Format(
Encoding.kAY, const [Operand.spe, Operand.xeg, Operand.none]),
Opcode.kSetFrame: const Format(
Encoding.kA, const [Operand.imm, Operand.none, Operand.none]),
Opcode.kBooleanNegateTOS: const Format(
Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
Opcode.kEqualsNull: const Format(
Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
Opcode.kNullCheck: const Format(
Encoding.kD, const [Operand.lit, Operand.none, Operand.none]),
Opcode.kNegateInt: const Format(
Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
Opcode.kAddInt: const Format(
Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
Opcode.kSubInt: const Format(
Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
Opcode.kMulInt: const Format(
Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
Opcode.kTruncDivInt: const Format(
Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
Opcode.kModInt: const Format(
Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
Opcode.kBitAndInt: const Format(
Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
Opcode.kBitOrInt: const Format(
Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
Opcode.kBitXorInt: const Format(
Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
Opcode.kShlInt: const Format(
Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
Opcode.kShrInt: const Format(
Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
Opcode.kCompareIntEq: const Format(
Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
Opcode.kCompareIntGt: const Format(
Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
Opcode.kCompareIntLt: const Format(
Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
Opcode.kCompareIntGe: const Format(
Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
Opcode.kCompareIntLe: const Format(
Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
Opcode.kDirectCall: const Format(
Encoding.kDF, const [Operand.lit, Operand.imm, Operand.none]),
Opcode.kUncheckedDirectCall: const Format(
Encoding.kDF, const [Operand.lit, Operand.imm, Operand.none]),
Opcode.kAllocateClosure: const Format(
Encoding.kD, const [Operand.lit, Operand.none, Operand.none]),
Opcode.kUncheckedClosureCall: const Format(
Encoding.kDF, const [Operand.lit, Operand.imm, Operand.none]),
Opcode.kUncheckedInterfaceCall: const Format(
Encoding.kDF, const [Operand.lit, Operand.imm, Operand.none]),
Opcode.kNegateDouble: const Format(
Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
Opcode.kAddDouble: const Format(
Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
Opcode.kSubDouble: const Format(
Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
Opcode.kMulDouble: const Format(
Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
Opcode.kDivDouble: const Format(
Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
Opcode.kCompareDoubleEq: const Format(
Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
Opcode.kCompareDoubleGt: const Format(
Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
Opcode.kCompareDoubleLt: const Format(
Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
Opcode.kCompareDoubleGe: const Format(
Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
Opcode.kCompareDoubleLe: const Format(
Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
};
// Should match constant in runtime/vm/stack_frame_kbc.h.
const int kParamEndSlotFromFp = 4;
enum SpecialIndex {
exception,
stackTrace,
}
/// Returns [true] if there is a wide variant for the given opcode.
bool hasWideVariant(Opcode opcode) {
final encoding = BytecodeFormats[opcode].encoding;
switch (encoding) {
case Encoding.k0:
case Encoding.kA:
case Encoding.kABC:
return false;
case Encoding.kD:
case Encoding.kX:
case Encoding.kT:
case Encoding.kAE:
case Encoding.kAY:
case Encoding.kDF:
return true;
}
throw 'Unexpected instruction encoding $encoding';
}
bool isWideOpcode(Opcode opcode) {
return (BytecodeFormats[opcode] == null) &&
hasWideVariant(Opcode.values[opcode.index - kWideModifier]);
}
Opcode fromWideOpcode(Opcode opcode) {
assert(isWideOpcode(opcode));
return Opcode.values[opcode.index - kWideModifier];
}
void verifyBytecodeInstructionDeclarations() {
const String kWideSuffix = '_Wide';
for (Opcode opcode in Opcode.values) {
final format = BytecodeFormats[opcode];
if (opcode.toString().endsWith(kWideSuffix)) {
if (format != null) {
throw 'Bytecode format should not be defined for wide opcode $opcode.';
}
final Opcode compact = Opcode.values[opcode.index - kWideModifier];
if (compact.toString() + kWideSuffix != opcode.toString()) {
throw 'Wide opcode $opcode should immediately follow its compact opcode (previous opcode is $compact).';
}
if (!hasWideVariant(compact)) {
throw 'Wide opcode $opcode should not be defined for opcode $compact with encoding ${BytecodeFormats[compact].encoding}.';
}
}
if (format == null) {
continue;
}
if (hasWideVariant(opcode)) {
if (Opcode.values[opcode.index + kWideModifier].toString() !=
opcode.toString() + kWideSuffix) {
throw 'Opcode $opcode$kWideSuffix should immedialy follow $opcode.';
}
if (opcode.index.isOdd) {
throw 'Opcode $opcode (${format.encoding}) has a wide variant and should be even';
}
}
}
if (Opcode.values.length > kMaxOpcodes) {
throw 'Too many opcodes';
}
}
bool isJump(Opcode opcode) => BytecodeFormats[opcode].encoding == Encoding.kT;
bool isThrow(Opcode opcode) => opcode == Opcode.kThrow;
bool isCall(Opcode opcode) {
switch (opcode) {
case Opcode.kDirectCall:
case Opcode.kUncheckedDirectCall:
case Opcode.kInterfaceCall:
case Opcode.kInstantiatedInterfaceCall:
case Opcode.kUncheckedClosureCall:
case Opcode.kUncheckedInterfaceCall:
case Opcode.kDynamicCall:
case Opcode.kNativeCall:
return true;
default:
return false;
}
}
bool isReturn(Opcode opcode) => opcode == Opcode.kReturnTOS;
bool isControlFlow(Opcode opcode) =>
isJump(opcode) || isThrow(opcode) || isCall(opcode) || isReturn(opcode);
bool isPush(Opcode opcode) {
switch (opcode) {
case Opcode.kPush:
case Opcode.kPushConstant:
case Opcode.kPushNull:
case Opcode.kPushTrue:
case Opcode.kPushFalse:
case Opcode.kPushInt:
case Opcode.kPushUninitializedSentinel:
return true;
default:
return false;
}
}
// Bytecode instructions reference constant pool indices using
// unsigned 32-bit operands.
const int constantPoolIndexLimit = 1 << 32;
// Local variables are referenced using 32-bit signed operands.
const int localVariableIndexLimit = 1 << 31;
// Captured variables are referenced using 32-bit unsigned operands.
const int capturedVariableIndexLimit = 1 << 32;
// Context IDs are referenced using 8-bit unsigned operands.
const int contextIdLimit = 1 << 8;
// Number of arguments is encoded as 8-bit unsigned operand.
const int argumentsLimit = 1 << 8;
// Base class for exceptions thrown when certain limit of bytecode
// format is exceeded.
abstract class BytecodeLimitExceededException {}