diff --git a/pkg/dart2bytecode/docs/bytecode.md b/pkg/dart2bytecode/docs/bytecode.md new file mode 100644 index 000000000000..fb0ebdfb9b56 --- /dev/null +++ b/pkg/dart2bytecode/docs/bytecode.md @@ -0,0 +1,1364 @@ +# Dart Bytecode File Format + +## Overview + +This file describes the binary format of Dart bytecode files. + +Dart bytecode is a binary representation of dynamic modules +on the VM/AOT. It is generated by dart2bytecode tools and +can be executed by the VM and AOT runtime (built with dynamic modules support). + +## Basic types + +This document uses notation similar to [Dart kernel binary format](https://github.com/dart-lang/sdk/blob/main/pkg/kernel/binary.md). + +The follow basic data types are used to describe bytecode format. +``` +type Byte = a byte + +type UInt = packed (variable-length) unsigned integer, same format as kernel binary + +type SLEB128 = packed (variable-length) signed integer + +type UInt32 = little-endian 32-bit unsigned integer + +type List { + UInt length + T[length] items +} + +type Pair { + T0 first + T1 second +} + +// Offset in the source file + 1. +type FileOffset = UInt +``` + +## Bytecode file + +Each bytecode file describes a dynamic module, a set of Dart libraries +which can be loaded at runtime. + +All declarations in the Dart bytecode file are sliced into several layers, +which reside in different sections such as libraries, classes, members, code, etc. + +``` +type BytecodeFile { + UInt32 magic = 0x44424333; // 'DBC3' + UInt32 formatVersion = 1; + + // Descriptors of the sections below. + // Each section has a fixed index in the descriptors array. + Section[] sections; + + // Sections. The contents of the sections can occur in arbitrary + // order and with gaps between sections, so they should be located only via + // section descriptor. + + StringTable stringTable; + ObjectTable objectTable; + EntryPoint entryPoint; + LibraryUriAndOffset[] libraryIndex; + LibraryDeclaration[] libraries; + ClassDeclaration[] classes; + Members[] members; + Code[] codes; + SourcePositions[] sourcePositions; + SourceFile[] sourceFiles; + LineStarts[] lineStarts; + LocalVariables[] localVariables; + PackedObject[] annotations; +} + +type Section { + // Number of items in the section. + // Zero for string table, object table and entry point sections. + UInt32 numItems; + // Offset of the section relative to the beginning of the bytecode file, in bytes. + UInt32 offset; +} +``` + +### String table + +String table section contains strings encoded as 1-byte (Latin1) and 2-byte (UTF-16) characters. +Strings are not zero-terminated. + +This representation is aligned with Dart VM and allows VM to avoid extra copying and +decoding of string characters when loading a string. + +``` +type StringTable = { + UInt32 numOneByteStrings; + UInt32 numTwoByteStrings; + // Offsets are relative to stringContents. + UInt32[numOneByteStrings] oneByteStringEndOffsets; + UInt32[numTwoByteStrings] twoByteStringEndOffsets; + // Contains string characters of one-byte strings and then two-byte strings. + Byte[] stringContents; +} + +// Reference to a string in string table. +type PackedString { + // Bit 0: set for two-byte string + // Bits 1+: index of string in one-byte strings (0..numOneByteStrings-1) + // or two-byte strings (0..numTwoByteStrings-1). + UInt indexAndKind; +} +``` + +### Object table + +Object table section contains various objects referenced by declarations and constant pools. + +Object included into the object table can be shared by multiple constant pools, +so object table provides a way to de-duplicate objects, reducing bytecode file +size and bytecode loading time. + +Bytecode generator can choose to include particular object into the object table or write it inline. +Object is written inline (not included into object table) if there are only a few references to that object or +it is small and can be created efficiently (for example, int and bool constants are always written inline). + +``` +type ObjectTable { + UInt numEntries; + + // Total size of ‘objects’ in bytes. + UInt objectsSize; + + ObjectContents[numEntries] objects; + + // Offsets relative to ‘objects’. + UInt[numEntries] objectOffsets; +} + + +// Either reference to an object in the object table, or object contents +// written inline (determined by bit 0). +PackedObject = ObjectReference | ObjectContents; + +type ObjectReference { + // Bit 0 (reference bit): 1 + // Bits 1+: index in the object table + UInt reference; +} + +type ObjectContents { + // Bit 0 (reference bit): 0 + // Bits 1-4: object kind + // Bits 5+ object flags + UInt header; +} + +// Invalid/null object. Always present at index 0 of object table. +type InvalidObject extends ObjectContents { + kind = 0; +} + +type Library extends ObjectContents { + kind = 1; + PackedObject importUri; +} + +type Script extends ObjectContents { + kind = 2; + flags = (hasSourceFile); + PackedObject uri; + if hasSourceFile + // Offset of source file in ‘sourceFiles’ section of BytecodeFile. + UInt sourceFileOffset; +} + +type Class extends ObjectContents { + kind = 3; + PackedObject library; + // Empty name is used for artificial class containing top-level + // members of a library. + PackedObject name; +} + +type Member extends ObjectContents { + kind = 4; + flags = (isField, isConstructor); + PackedObject class; + PackedObject name; +} + +type Closure extends ObjectContents { + kind = 5; + PackedObject enclosingMember; + UInt closureIndex; +} + +type Name extends ObjectContents { + kind = 6; + flags = (isPublic); + + if !isPublic + PackedObject library; + + // Getters are prefixed with 'get:'. + // Setters are prefixed with 'set:'. + PackedString name; +} + +abstract type ConstObject extends ObjectContents { + kind = 7; + flags = constantTag (4 bits); +} + +type ConstInt extends ConstValue { + kind = 7; + constantTag = 1; + SLEB128 value; +} + +type ConstDouble extends ConstValue { + kind = 7; + constantTag = 2; + // double bits are reinterpreted as 64-bit int + SLEB128 value; +} + +type ConstBool extends ConstValue { + kind = 7; + constantTag = 3; + Byte isTrue; +} + +type ConstString extends ConstObject { + kind = 7; + constantTag = 4; + PackedString string; +} + +type ConstSymbol extends ConstObject { + kind = 7; + constantTag = 5; + PackedObject name; +} + +type ConstInstance extends ConstObject { + kind = 7; + constantTag = 6; + PackedObject type; + List> fieldValues; +} + +type ConstList extends ConstObject { + kind = 7; + constantTag = 7; + PackedObject elementType; + List elements; +} + +type ConstMap extends ConstObject { + kind = 7; + constantTag = 8; + // Map type. + PackedObject mapType; + // [key1, value1, key2, value2, ....] + List elements; +} + +type ConstSet extends ConstObject { + kind = 7; + constantTag = 9; + PackedObject elementType; + List elements; +} + +type ConstRecord extends ConstObject { + kind = 7; + constantTag = 10; + PackedObject recordType; + // Values of positional, then named fields. + List fieldValues; +} + +type ConstTearOff extends ConstObject { + kind = 7; + constantTag = 11; + PackedObject target; +} + +type ConstTearOffInstantiation extends ConstObject { + kind = 7; + constantTag = 12; + PackedObject tearOff; + PackedObject typeArguments; +} + +abstract type Type extends ObjectContents { + kind = 8; + flags = (typeTag (4 bits), isNullable); +} + +type DynamicType extends Type { + kind = 8; + typeTag = 1; +} + +type VoidType extends Type { + kind = 8; + typeTag = 2; +} + +type NullType extends Type { + kind = 8; + typeTag = 3; +} + +type NeverType extends Type { + kind = 8; + typeTag = 4; +} + +// Interface type without type arguments. +type SimpleType extends Type { + kind = 8; + typeTag = 5; + PackedObject class; +} + +// Generic interface type. +type GenericType extends Type { + kind = 8; + typeTag = 6; + PackedObject class; + PackedObject typeArguments; +} + +type TypeParameter extends Type { + kind = 8; + typeTag = 7; + // Class, Member or Closure declaring this type parameter. + // Null (Invalid) if declared by function type. + PackedObject parent; + // For type parameters declared by function types this index is in a concatenation + // of type parameters of all enclosing function types. + UInt indexInParent; +} + +type FunctionType extends Type { + kind = 8; + typeTag = 8; + + UInt functionTypeFlags = (hasOptionalPositionalParams, + hasOptionalNamedParams, + hasTypeParams); + + if hasTypeParams + TypeParametersDeclaration typeParameters; + + UInt numParameters; + + if hasOptionalPositionalParams || hasOptionalNamedParams + UInt numRequiredParameters; + + Type[] positionalParameters; + NameAndType[] namedParameters; + PackedObject returnType; +} + +type TypeParametersDeclaration { + UInt numTypeParameters; + PackedObject[numTypeParameters] names; + BoundAndDefaultType[numTypeParameters] boundsAndDefaultTypes; +} + +type BoundAndDefaultType { + PackedObject bound; + PackedObject defaultType; +} + +type NameAndType { + PackedObject name; + PackedObject type; +} + +type RecordType extends Type { + kind = 8; + typeTag = 9; + UInt numPositionalFields; + UInt numNamedFields; + Type[numPositionalFields] positionalFields; + NameAndType[numNamedFields] namedFields; +} + +// Type arguments vector. +type TypeArguments extends ObjectContents { + kind = 6; + List args; +} + +// Describes shape of arguments passed to a call. +type ArgDesc extends ObjectContents { + kind = 8; + flags = (hasNamedArgs, hasTypeArgs); + + UInt numArguments; + + if hasTypeArgs + UInt numTypeArguments; + + if hasNamedArgs + List argNames; +} +``` + +### Entry point + +Entry point section contains a reference to a dynamic module entry point function. + +``` +type EntryPoint { + PackedObject member; +} +``` + +### Library index + +Library index section contains the list of library "forward declarations" +in the form of library URI and offset of its full declaration. + +``` +type LibraryUriAndOffset { + PackedObject uri; + + // Offset of library declaration in the ‘libraries’ section of BytecodeFile. + UInt libraryOffset +} +``` + +### Libraries + +Libraries section contains declarations of libraries included into a dynamic module. +Number of items in the library index section and libraries section should be the same. + +``` +type LibraryDeclaration { + UInt flags = (usesDartMirrors, usesDartFfi); + PackedObject name; + PackedObject script; + + // Classes declared in this library. + // The first class is an artificial ‘top-level’ class containing top-level + // fields and functions, as well as library annotations. + List classes; +} + +type ClassNameAndOffset { + PackedObject className; + + // Offset of class declaration in the ‘classes’ section of BytecodeFile. + UInt classOffset; +} +``` + +### Classes + +Classes section contains declarations of classes included into a dynamic module. +Each class in the classes section should be mentioned in its library declaration. + +``` +type ClassDeclaration { + UInt flags = (isAbstract, isEnum, + hasTypeParams, hasTypeArguments, + isTransformedMixinApplication, + hasSourcePositions, hasAnnotations, hasPragma); + PackedObject script; + + if hasSourcePositions + FileOffset position; + FileOffset endPosition; + + if hasTypeArguments + UInt numTypeArguments; + if hasTypeParams + TypeParametersDeclaration typeParameters; + + PackedObject superType; + List interfaces; + + if hasAnnotations + UInt annotationsOffset; + + // Offset of class members in the ‘members’ section of BytecodeFile. + UInt membersOffset; +} +``` + +### Members + +Members section contains declaration of members (fields, methods and constructors). +Member declarations are organized per class. + +``` +type Members { + // Total number of functions, including field getters and setters. + UInt numFunctions; + + List fields; + List functions; +} + +type FieldDeclaration { + UInt flags = (isStatic, isConst, isFinal, isLate, + isCovariant, isCovariantByClass, + isExtensionMember, isReflectable, + hasGetter, hasSetter, + hasInitializer, hasNontrivialInitializer, hasInitializerCode, + hasSourcePositions, hasAnnotations, hasPragma, + hasCustomScript); + PackedObject name; + PackedObject type; + + if hasCustomScript + PackedObject script; + if hasSourcePositions + FileOffset position; + FileOffset endPosition; + + if hasInitializerCode + // Offset of initializer code in the ‘code’ section of BytecodeFile. + UInt initializerCodeOffset; + if !hasNontrivialInitializer + PackedObject value; + + if hasGetter + PackedObject getterName; + if hasSetter + PackedObject setterName; + if hasAnnotations + UInt annotationsOffset; +} + +type FunctionDeclaration { + UInt flags = (isStatic, isAbstract, isGetter, isSetter, + isConstructor, isFactory, isConst, + hasOptionalPositionalParams, hasOptionalNamedParams, + hasTypeParams, hasParameterFlags, + isExtensionMember, isReflectable, isDebuggable, + isAsync, isAsyncStar, isSyncStar, + isNoSuchMethodForwarder, isExternal, isNative, + hasSourcePositions, hasAnnotations, hasPragma, + hasCustomScript); + + PackedObject name; + + if hasCustomScript + PackedObject script; + if hasSourcePositions + FileOffset position; + FileOffset endPosition; + + if hasTypeParams + TypeParametersDeclaration typeParameters; + + UInt numParameters; + + if hasOptionalPositionalParams || hasOptionalNamedParams + UInt numRequiredParameters; + + NameAndType[numParameters] parameters; + if hasParameterFlags + // (isCovariant, isCovariantByClass, isFinal, isRequired) + List parameterFlags; + + PackedObject returnType; + + if isNative + PackedObject nativeName; + + if !isAbstract + // Offset of code in the ‘code’ section of BytecodeFile. + UInt codeOffset; + + if hasAnnotations + // Offset of function annotations in ‘annotations’ section of + // component, followed by parameter annotations. + UInt annotationsOffset; +} +``` + +### Code + +Code section contains bodies of members (including field initializers). + +``` +type Code { + UInt flags = (hasExceptionsTable, hasSourcePositions, hasNullableFields, + hasClosures, hasParameterFlags, hasForwardingStubTarget, + hasDefaultFunctionTypeArgs, hasLocalVariables) + + if hasParameterFlags + // (isCovariant, isCovariantByClass, isFinal, isRequired) + List flags; + + if hasForwardingStubTarget + ConstantIndex forwardingStubTarget; + + if hasDefaultFunctionTypeArgs + ConstantIndex defaultFunctionTypeArgs; + + if hasClosures + List closureDeclarations; + + ConstantPool constantPool; + + UInt bytecodeSizeInBytes + Byte[bytecodeSizeInBytes] bytecodes; + + if hasExceptionsTable + ExceptionsTable exceptionsTable; + + if hasSourcePositions + // Offset of SourcePositions in ‘sourcePositions’ section of BytecodeFile. + UInt sourcePositionsOffset; + + if hasLocalVariables + // Offset of LocalVariables in ‘localVariables’ section of BytecodeFile. + UInt localVariablesOffset; + + if hasNullableFields + List nullableFields; + + if hasClosures + // Parallel to closureDeclarations. + ClosureCode[] closures; +} + +type ClosureDeclaration { + UInt flags = (hasOptionalPositionalParams, hasOptionalNamedParams, + hasTypeParams, hasSourcePositions, + isAsync, isAsyncStar, isSyncStar, isDebuggable, + hasParameterFlags) + + // Member or Closure. + PackedObject parent; + PackedObject name; + + if hasSourcePositions + FileOffset position; + FileOffset endPosition; + + if hasTypeParams + TypeParametersDeclaration typeParameters; + + UInt numParameters; + + if hasOptionalPositionalParams || hasOptionalNamedParams + UInt numRequiredParameters; + + NameAndType[numParameters] parameters; + + if hasParameterFlags + // (isCovariant, isCovariantByClass, isFinal, isRequired) + List flags; + + PackedObject returnType; +} + +type ClosureCode { + UInt flags = (hasExceptionsTable, hasSourcePositions, hasLocalVariables) + + UInt bytecodeSizeInBytes; + Byte[bytecodeSizeInBytes] bytecodes; + + if hasExceptionsTable + ExceptionsTable exceptionsTable; + + if hasSourcePositions + // Offset of SourcePositions in ‘sourcePositions’ section of BytecodeFile. + UInt sourcePositionsOffset; + + if hasLocalVariables + // Offset of LocalVariables in ‘localVariables’ section of BytecodeFile. + UInt localVariablesOffset; +} +``` + +### Constant Pool + +Each member code has its own constant pool which describes an array of objects +used by the interpreter at runtime along with bytecode instructions. +Member constant pool is shared by all closure functions declared in the member. +Bytecode instructions reference constant pool entries by index. + +``` +type ConstantPool { + List entries; +} + +// Index of entry in the constant pool. +type ConstantIndex = UInt; + +abstract type ConstantPoolEntry { + Byte tag; +} + +type ConstantObjectRef extends ConstantPoolEntry { + Byte tag = 1; + PackedObject object; +} + +type ConstantClass extends ConstantPoolEntry { + Byte tag = 2; + PackedObject class; +} + +type ConstantType extends ConstantPoolEntry { + Byte tag = 3; + PackedObject type; +} + +type ConstantStaticField extends ConstantPoolEntry { + Byte tag = 4; + PackedObject field; +} + +// Occupies 2 entries in the constant pool. +// (to hold offset and field object). +type ConstantInstanceField extends ConstantPoolEntry { + Byte tag = 5; + PackedObject field; +} + +type ConstantTypeArgumentsField extends ConstantPoolEntry { + Byte tag = 6; + PackedObject class; +} + +type ConstantClosureFunction extends ConstantPoolEntry { + Byte tag = 7; + UInt closureIndex; +} + +type ConstantEndClosureFunctionScope extends ConstantPoolEntry { + Byte tag = 8; +} + +type ConstantSubtypeTestCache extends ConstantPoolEntry { + Byte tag = 9; +} + +type ConstantEmptyTypeArguments extends ConstantPoolEntry { + Byte tag = 10; +} + +// Occupies 2 entries in the constant pool +// (to hold target and arguments descriptor). +type ConstantDirectCall extends ConstantPoolEntry { + Byte tag = 11; + PackedObject target; + PackedObject argDesc; +} + +// Occupies 2 entries in the constant pool +// (to hold interface target and arguments descriptor). +type ConstantInterfaceCall extends ConstantPoolEntry { + Byte tag = 12; + PackedObject target; + PackedObject argDesc; +} + +// Occupies 3 entries in the constant pool. +type ConstantInstantiatedInterfaceCall extends ConstantPoolEntry { + Byte tag = 13; + PackedObject target; + PackedObject argDesc; + PackedObject staticReceiverType; +} + +// Occupies 2 entries in the constant pool +type ConstantDynamicCall extends ConstantPoolEntry { + Byte tag = 14; + PackedObject selectorName; + PackedObject argDesc; +} +``` + +### Exceptions table + +Each Code and ClosureCode may have an optional table of try blocks +which maps ranges of bytecode instructions to corresponding exception handlers. + +``` +// Offset of a bytecode instruction in 'bytecodes'. +type BytecodeOffset = UInt; + +type TryBlock { + UInt outerTryIndexPlus1; + BytecodeOffset startPC; // Inclusive. + BytecodeOffset endPC; // Exclusive. + BytecodeOffset handlerPC; + Byte flags = (needsStackTrace, isSynthetic); + List types; +} + +type ExceptionsTable { + // Ordered by startPC, then by nesting (outer precedes inner). + // Try blocks are properly nested. It means there are no partially + // overlapping try blocks - each pair of try block regions either + // has no intersection or one try block region encloses another. + List tryBlocks; +} +``` + +### Source positions + +Source positions information maps ranges of bytecode instructions to +corresponding source positions. This information is optional and resides in +the 'sourcePositions' section of BytecodeFile. + +``` +type SourcePositions { + UInt numEntries; + // Encoded list of pairs (PC, FileOffset), ordered by PC (offset of bytecode instruction). + // For two consecutive entries (PC1, FileOffset1), (PC2, FileOffset2) all + // bytecode instructions in range [PC1,PC2) correspond to a source + // position FileOffset1. + SourcePositionEntry[numEntries] entries +} + +type SourcePositionEntry = { + // Delta-encoded PC (delta from the PC of previous entry). + UInt PCDelta; + // Delta-encoded FileOffset (delta from the FileOffset of previous entry). + SLEB128 FileOffsetDelta; +} +``` + +### Source files and line starts + +``` +type SourceFile { + UInt flags = (hasLineStarts, hasSource) + PackedObject importUri; + + if hasLineStarts + // Offset of line starts in ‘lineStarts’ section of BytecodeFile. + UInt lineStartsOffset; + + if hasSource + PackedString source; +} + +type LineStarts { + // Can be also treated as line lengths. + List deltaEncodedLineStarts; +} +``` + +### Local variables + +``` +type LocalVariables { + UInt numEntries; + // Encoded list of entries ordered by PC (offset of bytecode instruction). + LocalVariableEntry[numEntries] entries; +} + +abstract type LocalVariableEntry = { + // Bits 0-3: kind + // Bits 4-7: flags + Byte kindAndFlags; + // Delta-encoded start PC. + SLEB128 startPCDelta; +} + +type Scope extends LocalVariableEntry { + kind = 1 + // Offset to the end PC relative to startPC. + UInt endPCDelta; + // Level of context containing captured variables in this scope. + // -1 if there is no context. + SLEB128 contextLevel; + FileOffset position; + FileOffset endPosition; +} + +// Variable declarations immediately follow their corresponding Scope +type VariableDeclaration extends LocalVariableEntry { + kind = 2 + flags = (isCaptured) + // Index of local variable in the stack frame or in the context. + SLEB128 index; + ConstantIndex name; + ConstantIndex type; + // Source position where variable is declared. + FileOffset position; + // Source position after variable is initialized. + FileOffset initializedPosition; +} + +type ContextVariable extends LocalVariableEntry { + kind = 3 + // Index of a local variable holding context (in the stack frame). + SLEB128 index; +} +``` + +## Bytecode instructions + +### Execution state + +Dart bytecode interpreter is a stack machine with local variables. + +Bytecode instructions should begin by creating a frame using +`Entry`, `EntryOptional` or `EntrySuspendable` instruction. + +After creating a frame, local variables and parameters can be referenced as `Locals[i]` up to the size of the frame. +For frames created with `Entry` instruction, parameter n is accessible via `Locals[-numParams-kParamEndSlotFromFp+n]` +(where `kParamEndSlotFromFp == 4`). For frames created with `EntryOptional` or `EntrySuspendable` instructions, +parameter n is copied to `Locals[n]`. + +Most bytecode instructions take values from the expression stack or push values onto the stack. +Stack and local variables are disjoint, e.g. instructions operating with locals cannot be used to access stack and vice versa. +Stack pointer is referred as `SP`, stack grows up. `SP[0]` is the value on top of the stack, `SP[-1]`, `SP[-2]` etc are values pushed previously. +Stack can be used after frame setup and initially empty. + +Data flow merges are not allowed on the stack: at each PC and stack location, +there should be exactly one bytecode instructions which could have pushed a value into that stack location, +regardless of how control reached that PC. + +Bytecode instructions can reference constant pool via `ConstantPool[i]`. + +### Instruction encoding + +Each instruction starts with opcode byte. Certain instructions have +wide encoding variant. In such case, the least significant bit of opcode is +0 for compact variant and 1 for wide variant. + +The following operand encodings are used: + +``` +0........8.......16.......24.......32.......40.......48 ++--------+ +| opcode | 0: no operands ++--------+ + ++--------+--------+ +| opcode | A | A: unsigned 8-bit operand ++--------+--------+ + ++--------+--------+ +| opcode | D | D: unsigned 8/32-bit operand ++--------+--------+ + ++--------+----------------------------------+ +| opcode | D | D (wide) ++--------+----------------------------------+ + ++--------+--------+ +| opcode | X | X: signed 8/32-bit operand ++--------+--------+ + ++--------+----------------------------------+ +| opcode | X | X (wide) ++--------+----------------------------------+ + ++--------+--------+ +| opcode | T | T: signed 8/24-bit operand ++--------+--------+ + ++--------+--------------------------+ +| opcode | T | T (wide) ++--------+--------------------------+ + ++--------+--------+--------+ +| opcode | A | E | A_E: unsigned 8-bit operand and ++--------+--------+--------+ unsigned 8/32-bit operand + ++--------+--------+----------------------------------+ +| opcode | A | E | A_E (wide) ++--------+--------+----------------------------------+ + ++--------+--------+--------+ +| opcode | A | Y | A_Y: unsigned 8-bit operand and ++--------+--------+--------+ signed 8/32-bit operand + ++--------+--------+----------------------------------+ +| opcode | A | Y | A_Y (wide) ++--------+--------+----------------------------------+ + ++--------+--------+--------+ +| opcode | D | F | D_F: unsigned 8/32-bit operand and ++--------+--------+--------+ unsigned 8-bit operand + ++--------+----------------------------------+--------+ +| opcode | D | F | D_F (wide) ++--------+----------------------------------+--------+ + ++--------+--------+--------+--------+ +| opcode | A | B | C | A_B_C: 3 unsigned 8-bit operands ++--------+--------+--------+--------+ +``` + +### Instruction Set + +#### Trap + +Unreachable instruction. + +#### Entry D + +Function prologue for the function. +D - number of local slots to reserve. + +#### EntryOptional A, B, C + +Function prologue for the function with optional or named arguments. +A - expected number of positional arguments. +B - number of optional positional arguments. +C - number of named arguments. + +Only one of B and C can be not 0. + +If B is not 0 then EntryOptional bytecode is followed by B LoadConstant +bytecodes specifying default values for optional positional arguments. + +If C is not 0 then EntryOptional is followed by 2 * C LoadConstant +bytecodes. +Bytecode at 2 * i specifies name of the i-th named argument and at +2 * i + 1 default value. ‘A’ operand of the LoadConstant bytecode specifies +the location of the parameter on the stack. Named arguments are +sorted alphabetically. + +Note: Unlike Entry bytecode EntryOptional does not setup the frame for +local variables. This is done by a separate bytecode Frame, which should +follow EntryOptional and its LoadConstant instructions. + +#### EntrySuspendable A, B, C + +Similar to EntryOptional, but also reserves a local variable slot +for suspend state variable. + +#### LoadConstant A, E + +Used in conjunction with EntryOptional and EntrySuspendable instructions to +describe names and default values of optional parameters. + +#### Frame D + +Reserve space for D local variables. Local variables are +initially initialized with null. + +#### CheckFunctionTypeArgs A, E + +Check for a passed-in type argument vector of length A and +store it at Locals[E]. + +#### CheckStack A + +Compare SP against stack limit and call stack overflow or interrupt handler if +necessary. Should be used in prologue (A = 0), or at the beginning of +a loop with depth A. + +#### Allocate D + +Allocate object of class ConstantPool[D] with no type arguments. + +#### AllocateT + +Allocate object of class SP[0] with type arguments SP[-1]. + +#### CreateArrayTOS + +Allocate array of length SP[0] with type arguments SP[-1]. + +#### AllocateContext A, E + +Allocate Context object holding E context variables. +A is a static ID of the context. Static ID of a context may be used to +disambiguate accesses to different context objects. +Context objects with the same ID should have the same number of +context variables. + +#### CloneContext A, E + +Clone Context object SP[0] holding E context variables. +A is a static ID of the context. Cloned context has the same ID. + +#### LoadContextParent + +Load parent from context SP[0]. + +#### StoreContextParent + +Store context SP[0] into `parent` field of context SP[-1]. + +#### LoadContextVar A, E + +Load value from context SP[0] at index E. +A is a static ID of the context. + +#### StoreContextVar A, E + +Store value SP[0] into context SP[-1] at index E. +A is a static ID of the context. + +#### PushConstant D + +Push value ConstantPool[D] onto the stack. + +#### PushNull + +Push `null` onto the stack. + +#### PushTrue + +Push `true` onto the stack. + +#### PushFalse + +Push `false` onto the stack. + +#### PushInt X + +Push int X onto the stack. + +#### Drop1 + +Drop 1 value from the stack + +#### Push X + +Push Locals[X] to the stack. + +#### StoreLocal X; PopLocal X + +Store top of the stack into Locals[X] and pop it if needed. + +#### LoadFieldTOS D + +Push value of field ConstantPool[D] from object SP[0]. + +#### StoreFieldTOS D + +Store value SP[0] into field ConstantPool[D] of object SP[-1]. + +#### StoreIndexedTOS + +Store SP[0] into array SP[-2] at index SP[-1]. No type or index checking is done. +SP[-2] is assumed to be an array (created with CreateArrayTOS), SP[-1] is an int. + +#### PushStatic D + +Pushes value of the static field ConstantPool[D] on to the stack. + +#### StoreStaticTOS D + +Stores SP[0] into the static field ConstantPool[D]. + +#### Jump target + +Jump to the given target. Target is specified as offset from the PC of the +jump instruction. + +#### JumpIfNoAsserts target + +Jump to the given target if assertions are not enabled. +Target is specified as offset from the PC of the jump instruction. + +#### JumpIfNotZeroTypeArgs target + +Jump to the given target if number of passed function type +arguments is not zero. +Target is specified as offset from the PC of the jump instruction. + +#### JumpIfUnchecked target + +May jump to the given target if current function was called through unchecked +call instruction (UncheckedInterfaceCall, UncheckedClosureCall). +This instruction can be used to skip checking of type argument bounds and +types of generic-covariant parameters. +This is an optimization, so it is valid to treat this instruction as a no-op. +Target is specified as offset from the PC of the jump instruction. + +#### JumpIfEqStrict target; JumpIfNeStrict target + +Jump to the given target if SP[-1] is the same (JumpIfEqStrict) / +not the same (JumpIfNeStrict) object as SP[0]. + +#### JumpIfTrue target; JumpIfFalse target; JumpIfNull target; JumpIfNotNull target + +Jump to the given target if SP[0] is true/false/null/not null. + +#### Suspend target + +Create a snapshot of the current frame and store it in the suspend +state object. Execution can be resumed from the suspend state +at the given target PC. +Target is specified as offset from the PC of the suspend instruction. +The filled suspend state object is stored into the reserved suspend +state local variable. Current function frame should be created with +EntrySuspendable instruction. + +#### DirectCall D, F + +Invoke the target function with arguments SP[-(F-1)], ..., SP[0]. +ContantPool[D] is a ConstantDirectCall specifying target and +arguments descriptor. + +#### InterfaceCall D, F + +Lookup and invoke instance method with arguments SP[-(F-1)], ..., SP[0]. +ContantPool[D] is a ConstantInterfaceCall specifying interface target and +arguments descriptor. +Method has to be declared (explicitly or implicitly) in an interface +implemented by a receiver SP[0], and passed arguments are valid for the +interface method declaration. + +#### UncheckedInterfaceCall D, F + +Same as InterfaceCall, but can omit type checks of generic-covariant +parameters. + +#### InstantiatedInterfaceCall D, F + +Same as InterfaceCall, but provides additional information about instantiated static +type of a (generic) receiver via ConstantInstantiatedInterfaceCall. At run time, if +actual type of receiver matches static type, then type checks of generic-covariant +Parameters can be omitted. + +#### UncheckedClosureCall D, F + +Call closure SP[0] with arguments SP[-F], ..., SP[-1]. +ContantPool[D] is a ConstantObjectRef with ArgDesc object specifying arguments +descriptor. +Closure should have a statically known function type; parameters should have +correct types according to the closure’s function type, so parameter type checks +can be omitted. + +#### DynamicCall D, F + +Lookup and invoke instance method with arguments SP[-(F-1)], ..., SP[0]. +ContantPool[D] is a ConstantDynamicCall specifying selector and +arguments descriptor. + +#### ReturnTOS + +Return to the caller using SP[0] as a result. + +#### AssertAssignable A, E + +Assert that instance SP[-4] is assignable to variable named SP[0] of +type SP[-1] with instantiator type arguments SP[-3] and function type +arguments SP[-2] using ConstantSubtypeTestCache at ConstantPool[E]. +If A is 1, then the instance may be an int. + +Instance remains on stack. Other arguments are consumed. + +#### AssertSubtype + +Assert that one type is a subtype of another. Throws a TypeError +otherwise. The stack has the following arguments on it: + +``` +SP[-4] instantiator type args +SP[-3] function type args +SP[-2] sub-type +SP[-1] super-type +SP[-0] destination name +``` + +All 5 arguments are consumed from the stack and no results is pushed. + +#### LoadTypeArgumentsField D + +Load instantiator type arguments from an instance SP[0]. +ConstantPool[D] should be a ConstantTypeArgumentsField corresponding +to an instance's generic (base) class. + +#### InstantiateType D + +Instantiate type ConstantPool[D] with instantiator type arguments SP[-1] and +function type arguments SP[0]. + +#### InstantiateTypeArgumentsTOS A, E + +Instantiate type arguments ConstantPool[E] with instantiator type arguments SP[-1] +and function type arguments SP[0]. A != 0 indicates that resulting type +arguments are all dynamic if both instantiator and function type arguments are +all dynamic. + +#### Throw A + +Throw (Rethrow if A != 0) exception. Exception object and stack object +are taken from the top of the stack. + +#### MoveSpecial A, Y + +Copy value from special variable to Locals[Y]. Currently only +used to pass exception object (A = 0) and stack trace object (A = 1) to +catch handler. + +#### SetFrame A + +Reset expression stack to empty. +‘A’ should be equal to the frame size allocated by prologue instructions. +Used to drop temporaries from the stack in the exception handler. + +#### BooleanNegateTOS + +SP[0] = !SP[0] + +#### EqualsNull + +SP[0] = (SP[0] == null) ? true : false + +#### NegateInt + +Equivalent to invocation of unary int operator-. +Receiver should have static type int. + +SP[0] = -SP[0] + +#### AddInt; SubInt; MulInt; TruncDivInt; ModInt; BitAndInt; BitOrInt; BitXorInt; ShlInt; ShrInt + +Equivalent to invocation of binary int operator +, -, *, ~/, %, &, |, +^, << or >>. Receiver and argument should have static type int. + +SP[0] = SP[-1] SP[0] + +#### CompareIntEq; CompareIntGt; CompareIntLt; CompareIntGe; CompareIntLe + +Equivalent to invocation of binary int operator ==, >, <, >= or <=. +Receiver and argument should have static type int. + +SP[0] = SP[-1] SP[0] ? true : false + +#### NegateDouble + +Equivalent to invocation of unary double operator-. +Receiver should have static type double. + +SP[0] = -SP[0] + +#### AddDouble; SubDouble; MulDouble; DivDouble + +Equivalent to invocation of binary double operator +, -, *, / +Receiver and argument should have static type double. + +SP[0] = SP[-1] SP[0] + +#### CompareDoubleEq; CompareDoubleGt; CompareDoubleLt; CompareDoubleGe; CompareDoubleLe + +Equivalent to invocation of binary double operator ==, >, <, >= or <=. +Receiver and argument should have static type double. + +SP[0] = SP[-1] SP[0] ? true : false + +#### AllocateClosure D + +Allocate closure object for closure function ConstantPool[D]. + +#### DebugCheck + +No-op. Provides a point where debugger can stop executing code when single stepping +or when it hits a breakpoint. + diff --git a/pkg/dart2bytecode/lib/constant_pool.dart b/pkg/dart2bytecode/lib/constant_pool.dart index 7c06148c20be..96e24c223534 100644 --- a/pkg/dart2bytecode/lib/constant_pool.dart +++ b/pkg/dart2bytecode/lib/constant_pool.dart @@ -14,100 +14,6 @@ import 'bytecode_serialization.dart' StringTable; import 'object_table.dart' show ObjectHandle, ObjectTable; -/* - -Constant pool is encoded in the following way -(using notation from pkg/kernel/binary.md): - -type ConstantPool { - List -} - -type ConstantIndex = UInt; - -abstract type ConstantPoolEntry { - Byte tag; -} - -type ConstantStaticField extends ConstantPoolEntry { - Byte tag = 1; - PackedObject field; -} - -// Occupies 2 entries in the constant pool. -type ConstantInstanceField extends ConstantPoolEntry { - Byte tag = 2; - PackedObject field; -} - -type ConstantClass extends ConstantPoolEntry { - Byte tag = 3; - PackedObject class; -} - -type ConstantTypeArgumentsField extends ConstantPoolEntry { - Byte tag = 4; - PackedObject class; -} - -type ConstantType extends ConstantPoolEntry { - Byte tag = 5; - PackedObject type; -} - -type ConstantClosureFunction extends ConstantPoolEntry { - Byte tag = 6; - UInt closureIndex; -} - -type ConstantEndClosureFunctionScope extends ConstantPoolEntry { - Byte tag = 7; -} - -type ConstantSubtypeTestCache extends ConstantPoolEntry { - Byte tag = 8; -} - -type ConstantEmptyTypeArguments extends ConstantPoolEntry { - Byte tag = 9; -} - -type ConstantObjectRef extends ConstantPoolEntry { - Byte tag = 10; - PackedObject object; -} - -// Occupies 2 entries in the constant pool. -type ConstantDirectCall extends ConstantPoolEntry { - Byte tag = 11; - PackedObject target; - PackedObject argDesc; -} - -// Occupies 2 entries in the constant pool. -type ConstantInterfaceCall extends ConstantPoolEntry { - Byte tag = 12; - PackedObject target; - PackedObject argDesc; -} - -// Occupies 3 entries in the constant pool. -type ConstantInstantiatedInterfaceCall extends ConstantPoolEntry { - Byte tag = 13; - PackedObject target; - PackedObject argDesc; - PackedObject staticReceiverType; -} - -// Occupies 2 entries in the constant pool -type ConstantDynamicCall extends ConstantPoolEntry { - Byte tag = 14; - PackedObject selectorName; - PackedObject argDesc; -} - -*/ - enum ConstantTag { kInvalid, kObjectRef, diff --git a/pkg/dart2bytecode/lib/exceptions.dart b/pkg/dart2bytecode/lib/exceptions.dart index 7b5602ef0705..d74109b918f4 100644 --- a/pkg/dart2bytecode/lib/exceptions.dart +++ b/pkg/dart2bytecode/lib/exceptions.dart @@ -4,33 +4,6 @@ import 'bytecode_serialization.dart' show BufferedWriter, BufferedReader; -/* - -In kernel binary, try blocks are encoded in the following way -(using notation from pkg/kernel/binary.md): - -// Offset of a bytecode instruction. -type BytecodeOffset = UInt; - -type TryBlock { - UInt outerTryIndexPlus1; - BytecodeOffset startPC; // Inclusive. - BytecodeOffset endPC; // Exclusive. - BytecodeOffset handlerPC; - Byte flags (needsStackTrace, isSynthetic); - List types; -} - -type ExceptionsTable { - // Ordered by startPC, then by nesting (outer precedes inner). - // Try blocks are properly nested. It means there are no partially - // overlapping try blocks - each pair of try block regions either - // has no intersection or one try block region encloses another. - List tryBlocks; -} - -*/ - class TryBlock { static const int flagNeedsStackTrace = 1 << 0; static const int flagIsSynthetic = 1 << 1; diff --git a/pkg/dart2bytecode/lib/object_table.dart b/pkg/dart2bytecode/lib/object_table.dart index c297dfb2e962..63130f9d7692 100644 --- a/pkg/dart2bytecode/lib/object_table.dart +++ b/pkg/dart2bytecode/lib/object_table.dart @@ -20,267 +20,6 @@ import 'bytecode_serialization.dart' StringWriter; import 'declarations.dart' show SourceFile, TypeParametersDeclaration; -/* - -Bytecode object table is encoded in the following way -(using notation from pkg/kernel/binary.md): - -type ObjectTable { - UInt numEntries - - // Total size of ‘objects’ in bytes. - UInt objectsSize - - ObjectContents[numEntries] objects - - // Offsets relative to ‘objects’. - UInt[numEntries] objectOffsets -} - - -// Either reference to an object in object table, or object contents -// written inline (determined by bit 0). -PackedObject = ObjectReference | ObjectContents - -type ObjectReference { - // Bit 0 (reference bit): 1 - // Bits 1+: index in object table - UInt reference -} - -type ObjectContents { - // Bit 0 (reference bit): 0 - // Bits 1-4: object kind - // Bits 5+ object flags - UInt header -} - -// Invalid/null object (always present at index 0). -type InvalidObject extends ObjectContents { - kind = 0; -} - -type Library extends ObjectContents { - kind = 1; - PackedObject importUri; -} - -type Class extends ObjectContents { - kind = 2; - PackedObject library; - // Empty name is used for artificial class containing top-level - // members of a library. - PackedObject name; -} - -type Member extends ObjectContents { - kind = 3; - flags = (isField, isConstructor); - PackedObject class; - PackedObject name; -} - -type Closure extends ObjectContents { - kind = 4; - PackedObject enclosingMember; - UInt closureIndex; -} - -type Name extends ObjectContents { - kind = 5; - - // Invalid for public names - PackedObject library; - - // Getters are prefixed with 'get:'. - // Setters are prefixed with 'set:'. - PackedString string; -} - -// Type arguments vector. -type TypeArguments extends ObjectContents { - kind = 6; - List args; -} - -abstract type ConstObject extends ObjectContents { - kind = 7; - flags = constantTag (4 bits) -} - -type ConstInstance extends ConstObject { - kind = 7 - constantTag (flags) = 1 - PackedObject type; - List> fieldValues; -} - -type ConstInt extends ConstValue { - kind = 7 - constantTag (flags) = 2 - SLEB128 value; -} - -type ConstDouble extends ConstValue { - kind = 7 - constantTag (flags) = 3 - // double bits are reinterpreted as 64-bit int - SLEB128 value; -} - -type ConstList extends ConstObject { - kind = 7 - constantTag (flags) = 4 - PackedObject elemType; - List entries; -} - -type ConstTearOff extends ConstObject { - kind = 7 - constantTag (flags) = 5 - PackedObject target; -} - -type ConstBool extends ConstValue { - kind = 7 - constantTag = 6 - Byte isTrue; -} - -type ConstSymbol extends ConstObject { - kind = 7 - constantTag (flags) = 7 - PackedObject name; -} - -type ConstTearOffInstantiation extends ConstObject { - kind = 7 - constantTag (flags) = 8 - PackedObject tearOff; - PackedObject typeArguments; -} - -type ArgDesc extends ObjectContents { - kind = 8; - flags = (hasNamedArgs, hasTypeArgs) - - UInt numArguments - - if hasTypeArgs - UInt numTypeArguments - - if hasNamedArgs - List argNames; -} - -type Script extends ObjectContents { - kind = 9 - flags = (hasSourceFile) - PackedObject uri - if hasSourceFile - UInt sourceFileOffset -} - -abstract type Type extends ObjectContents { - kind = 10 - flags = typeTag (4 bits) -} - -type DynamicType extends Type { - kind = 10 - typeTag (flags) = 1 -} - -type VoidType extends Type { - kind = 10 - typeTag (flags) = 2 -} - -// SimpleType can be used only for types without type arguments. -type SimpleType extends Type { - kind = 10 - typeTag (flags) = 3 - PackedObject class -} - -type TypeParameter extends Type { - kind = 10 - typeTag (flags) = 4 - // Class, Member or Closure declaring this type parameter. - // Null (Invalid) if declared by function type. - PackedObject parent - UInt indexInParent -} - -// Generic interface type. -type GenericType extends Type { - kind = 10 - typeTag (flags) = 5 - PackedObject class - // Flattened type arguments vector. - PackedObject typeArgs -} - -type FunctionType extends Type { - kind = 10 - typeTag (flags) = 6 - - UInt functionTypeFlags(hasOptionalPositionalParams, - hasOptionalNamedParams, - hasTypeParams) - - if hasTypeParams - TypeParametersDeclaration typeParameters - - UInt numParameters - - if hasOptionalPositionalParams || hasOptionalNamedParams - UInt numRequiredParameters - - Type[] positionalParameters - NameAndType[] namedParameters - PackedObject returnType -} - -type RecordType extends Type { - kind = 10 - typeTag (flags) = 7 - - UInt numPositionalFields - UInt numNamedFields - - Type[] positionalFields - NameAndType[] namedFields -} - -type NullType extends Type { - kind = 10 - typeTag (flags) = 8 -} - -type NeverType extends Type { - kind = 10 - typeTag (flags) = 9 -} - -type TypeParametersDeclaration { - UInt numTypeParameters - PackedObject[numTypeParameters] typeParameterNames - BoundAndDefaultType[numTypeParameters] typeParameterBoundsAndDefaultTypes -} - -type NameAndType { - PackedObject name; - PackedObject type; -} - -type BoundAndDefaultType { - PackedObject bound; - PackedObject defaultType; -} - -*/ - enum ObjectKind { kInvalid, kLibrary, diff --git a/runtime/vm/constants_kbc.h b/runtime/vm/constants_kbc.h index 45fb4fb52f91..3385e399dbf2 100644 --- a/runtime/vm/constants_kbc.h +++ b/runtime/vm/constants_kbc.h @@ -12,454 +12,12 @@ namespace dart { // clang-format off -// List of KernelBytecode instructions. -// -// INTERPRETER STATE -// -// current frame info (see stack_frame_kbc.h for layout) -// v-----^-----v -// ~----+----~ ~----+-------+-------+-~ ~-+-------+-------+-~ -// ~ | ~ ~ | FP[0] | FP[1] | ~ ~ | SP[-1]| SP[0] | -// ~----+----~ ~----+-------+-------+-~ ~-+-------+-------+-~ -// ^ ^ -// FP SP -// -// -// The state of execution is captured in few interpreter registers: -// -// FP - base of the current frame -// SP - top of the stack (TOS) for the current frame -// PP - object pool for the currently execution function -// -// Frame info stored below FP additionally contains pointers to the currently -// executing function and code. -// -// In the unoptimized code most of bytecodes take operands implicitly from -// stack and store results again on the stack. Constant operands are usually -// taken from the object pool by index. -// -// ENCODING -// -// Each instruction starts with opcode byte. Certain instructions have -// wide encoding variant. In such case, the least significant bit of opcode is -// not set for compact variant and set for wide variant. -// -// The following operand encodings are used: -// -// 0........8.......16.......24.......32.......40.......48 -// +--------+ -// | opcode | 0: no operands -// +--------+ -// -// +--------+--------+ -// | opcode | A | A: unsigned 8-bit operand -// +--------+--------+ -// -// +--------+--------+ -// | opcode | D | D: unsigned 8/32-bit operand -// +--------+--------+ -// -// +--------+----------------------------------+ -// | opcode | D | D (wide) -// +--------+----------------------------------+ -// -// +--------+--------+ -// | opcode | X | X: signed 8/32-bit operand -// +--------+--------+ -// -// +--------+----------------------------------+ -// | opcode | X | X (wide) -// +--------+----------------------------------+ -// -// +--------+--------+ -// | opcode | T | T: signed 8/24-bit operand -// +--------+--------+ -// -// +--------+--------------------------+ -// | opcode | T | T (wide) -// +--------+--------------------------+ -// -// +--------+--------+--------+ -// | opcode | A | E | A_E: unsigned 8-bit operand and -// +--------+--------+--------+ unsigned 8/32-bit operand -// -// +--------+--------+----------------------------------+ -// | opcode | A | E | A_E (wide) -// +--------+--------+----------------------------------+ -// -// +--------+--------+--------+ -// | opcode | A | Y | A_Y: unsigned 8-bit operand and -// +--------+--------+--------+ signed 8/32-bit operand -// -// +--------+--------+----------------------------------+ -// | opcode | A | Y | A_Y (wide) -// +--------+--------+----------------------------------+ -// -// +--------+--------+--------+ -// | opcode | D | F | D_F: unsigned 8/32-bit operand and -// +--------+--------+--------+ unsigned 8-bit operand -// -// +--------+----------------------------------+--------+ -// | opcode | D | F | D_F (wide) -// +--------+----------------------------------+--------+ -// -// +--------+--------+--------+--------+ -// | opcode | A | B | C | A_B_C: 3 unsigned 8-bit operands -// +--------+--------+--------+--------+ -// -// -// INSTRUCTIONS -// -// - Trap -// -// Unreachable instruction. -// -// - Entry rD -// -// Function prologue for the function -// rD - number of local slots to reserve; -// -// - EntryOptional A, B, C -// -// Function prologue for the function with optional or named arguments: -// A - expected number of positional arguments; -// B - number of optional arguments; -// C - number of named arguments; -// -// Only one of B and C can be not 0. -// -// If B is not 0 then EntryOptional bytecode is followed by B LoadConstant -// bytecodes specifying default values for optional arguments. -// -// If C is not 0 then EntryOptional is followed by 2 * C LoadConstant -// bytecodes. -// Bytecode at 2 * i specifies name of the i-th named argument and at -// 2 * i + 1 default value. rA part of the LoadConstant bytecode specifies -// the location of the parameter on the stack. Here named arguments are -// sorted alphabetically to enable linear matching similar to how function -// prologues are implemented on other architectures. -// -// Note: Unlike Entry bytecode EntryOptional does not setup the frame for -// local variables this is done by a separate bytecode Frame, which should -// follow EntryOptional and its LoadConstant instructions. -// -// - EntrySuspendable A, B, C -// -// Similar to EntryOptional, but also reserves a local variable slot -// for suspend state variable. -// -// - LoadConstant rA, D -// -// Used in conjunction with EntryOptional instruction to describe names and -// default values of optional parameters. -// -// - Frame D -// -// Reserve and initialize with null space for D local variables. -// -// - CheckFunctionTypeArgs A, D -// -// Check for a passed-in type argument vector of length A and -// store it at FP[D]. -// -// - CheckStack A -// -// Compare SP against isolate stack limit and call StackOverflow handler if -// necessary. Should be used in prologue (A = 0), or at the beginning of -// a loop with depth A. -// -// - Allocate D -// -// Allocate object of class PP[D] with no type arguments. -// -// - AllocateT -// -// Allocate object of class SP[0] with type arguments SP[-1]. -// -// - CreateArrayTOS -// -// Allocate array of length SP[0] with type arguments SP[-1]. -// -// - AllocateContext A, D -// -// Allocate Context object holding D context variables. -// A is a static ID of the context. Static ID of a context may be used to -// disambiguate accesses to different context objects. -// Context objects with the same ID should have the same number of -// context variables. -// -// - CloneContext A, D -// -// Clone Context object SP[0] holding D context variables. -// A is a static ID of the context. Cloned context has the same ID. -// -// - LoadContextParent -// -// Load parent from context SP[0]. -// -// - StoreContextParent -// -// Store context SP[0] into `parent` field of context SP[-1]. -// -// - LoadContextVar A, D -// -// Load value from context SP[0] at index D. -// A is a static ID of the context. -// -// - StoreContextVar A, D -// -// Store value SP[0] into context SP[-1] at index D. -// A is a static ID of the context. -// -// - PushConstant D -// -// Push value at index D from constant pool onto the stack. -// -// - PushNull -// -// Push `null` onto the stack. -// -// - PushTrue -// -// Push `true` onto the stack. -// -// - PushFalse -// -// Push `false` onto the stack. -// -// - PushInt rX -// -// Push int rX onto the stack. -// -// - Drop1 -// -// Drop 1 value from the stack -// -// - Push rX -// -// Push FP[rX] to the stack. -// -// - StoreLocal rX; PopLocal rX -// -// Store top of the stack into FP[rX] and pop it if needed. -// -// - LoadFieldTOS D -// -// Push value at offset (in words) PP[D] from object SP[0]. -// -// - StoreFieldTOS D -// -// Store value SP[0] into object SP[-1] at offset (in words) PP[D]. -// -// - StoreIndexedTOS -// -// Store SP[0] into array SP[-2] at index SP[-1]. No typechecking is done. -// SP[-2] is assumed to be a RawArray, SP[-1] to be a smi. -// -// - PushStatic D -// -// Pushes value of the static field PP[D] on to the stack. -// -// - StoreStaticTOS D -// -// Stores TOS into the static field PP[D]. -// -// - Jump target -// -// Jump to the given target. Target is specified as offset from the PC of the -// jump instruction. -// -// - JumpIfNoAsserts target -// -// Jump to the given target if assertions are not enabled. -// Target is specified as offset from the PC of the jump instruction. -// -// - JumpIfNotZeroTypeArgs target -// -// Jump to the given target if number of passed function type -// arguments is not zero. -// Target is specified as offset from the PC of the jump instruction. -// -// - JumpIfEqStrict target; JumpIfNeStrict target -// -// Jump to the given target if SP[-1] is the same (JumpIfEqStrict) / -// not the same (JumpIfNeStrict) object as SP[0]. -// -// - JumpIfTrue target; JumpIfFalse target -// - JumpIfNull target; JumpIfNotNull target -// -// Jump to the given target if SP[0] is true/false/null/not null. -// -// - Suspend target -// -// Create a snapshot of the current frame and store it in the suspend -// state object. Execution can be resumed from the suspend state -// at the given target PC. -// Target is specified as offset from the PC of the suspend instruction. -// The filled suspend state object is stored into the reserved suspend -// state local variable. Current function frame should be created with -// EntrySuspendable instruction. -// -// - IndirectStaticCall ArgC, D -// -// Invoke the function given by the ICData in SP[0] with arguments -// SP[-(1+ArgC)], ..., SP[-1] and argument descriptor PP[D], which -// indicates whether the first argument is a type argument vector. -// -// - DirectCall ArgC, D -// -// Invoke the function PP[D] with arguments -// SP[-(ArgC-1)], ..., SP[0] and argument descriptor PP[D+1]. -// -// - InterfaceCall ArgC, D -// -// Lookup and invoke method using ICData in PP[D] -// with arguments SP[-(1+ArgC)], ..., SP[-1]. -// Method has to be declared (explicitly or implicitly) in an interface -// implemented by a receiver, and passed arguments are valid for the -// interface method declaration. -// The ICData indicates whether the first argument is a type argument vector. -// -// - UncheckedInterfaceCall ArgC, D -// -// Same as InterfaceCall, but can omit type checks of generic-covariant -// parameters. -// -// - DynamicCall ArgC, D -// -// Lookup and invoke method using ICData in PP[D] -// with arguments SP[-(1+ArgC)], ..., SP[-1]. -// The ICData indicates whether the first argument is a type argument vector. -// -// - ReturnTOS -// -// Return to the caller using a value from the top-of-stack as a result. -// -// Note: return instruction knows how many arguments to remove from the -// stack because it can look at the call instruction at caller's PC and -// take argument count from it. -// -// - AssertAssignable A, D -// -// Assert that instance SP[-4] is assignable to variable named SP[0] of -// type SP[-1] with instantiator type arguments SP[-3] and function type -// arguments SP[-2] using SubtypeTestCache PP[D]. -// If A is 1, then the instance may be a Smi. -// -// Instance remains on stack. Other arguments are consumed. -// -// - AssertSubtype -// -// Assert that one type is a subtype of another. Throws a TypeError -// otherwise. The stack has the following arguments on it: -// -// SP[-4] instantiator type args -// SP[-3] function type args -// SP[-2] sub_type -// SP[-1] super_type -// SP[-0] dst_name -// -// All 5 arguments are consumed from the stack and no results is pushed. -// -// - LoadTypeArgumentsField D -// -// Load instantiator type arguments from an instance SP[0]. -// PP[D] = offset (in words) of type arguments field corresponding -// to an instance's class. -// -// - InstantiateType D -// -// Instantiate type PP[D] with instantiator type arguments SP[-1] and -// function type arguments SP[0]. -// -// - InstantiateTypeArgumentsTOS A, D -// -// Instantiate type arguments PP[D] with instantiator type arguments SP[-1] -// and function type arguments SP[0]. A != 0 indicates that resulting type -// arguments are all dynamic if both instantiator and function type -// arguments are all dynamic. -// -// - Throw A -// -// Throw (Rethrow if A != 0) exception. Exception object and stack object -// are taken from TOS. -// -// - MoveSpecial A, rX -// -// Copy value from special variable to FP[rX]. Currently only -// used to pass exception object (A = 0) and stack trace object (A = 1) to -// catch handler. -// -// - SetFrame A -// -// Reinitialize SP assuming that current frame has size A. -// Used to drop temporaries from the stack in the exception handler. -// -// - BooleanNegateTOS -// -// SP[0] = !SP[0] -// -// - EqualsNull -// -// SP[0] = (SP[0] == null) ? true : false -// -// - NegateInt -// -// Equivalent to invocation of unary int operator-. -// Receiver should have static type int. -// Check SP[0] for null; SP[0] = -SP[0]. -// -// - AddInt; SubInt; MulInt; TruncDivInt; ModInt; BitAndInt; BitOrInt; -// BitXorInt; ShlInt; ShrInt -// -// Equivalent to invocation of binary int operator +, -, *, ~/, %, &, |, -// ^, << or >>. Receiver and argument should have static type int. -// Check SP[-1] and SP[0] for null; push SP[-1] SP[0]. -// -// - CompareIntEq; CompareIntGt; CompareIntLt; CompareIntGe; CompareIntLe -// -// Equivalent to invocation of binary int operator ==, >, <, >= or <=. -// Receiver and argument should have static type int. -// Check SP[-1] and SP[0] for null; push SP[-1] SP[0] ? true : false. -// -// - NegateDouble -// -// Equivalent to invocation of unary double operator-. -// Receiver should have static type double. -// Check SP[0] for null; SP[0] = -SP[0]. -// -// - AddDouble; SubDouble; MulDouble; DivDouble -// -// Equivalent to invocation of binary int operator +, -, *, /. -// Receiver and argument should have static type double. -// Check SP[-1] and SP[0] for null; push SP[-1] SP[0]. -// -// - CompareDoubleEq; CompareDoubleGt; CompareDoubleLt; CompareDoubleGe; -// CompareDoubleLe -// -// Equivalent to invocation of binary double operator ==, >, <, >= or <=. -// Receiver and argument should have static type double. -// Check SP[-1] and SP[0] for null; push SP[-1] SP[0] ? true : false. -// -// - AllocateClosure -// -// Allocate closure object and initialize its fields: -// -// SP[-2] closure function -// SP[-1] context -// SP[0] instantiator type arguments -// -// These arguments are consumed from the stack and allocated -// object is pushed. -// -// BYTECODE LIST FORMAT -// -// KernelBytecode list below is specified using the following format: +// Bytecode instructions are specified using the following format: // // V(BytecodeName, OperandForm, BytecodeKind, Op1, Op2, Op3) // // - OperandForm specifies operand encoding and should be one of 0, A, D, X, T, -// A_E, A_Y, D_F or A_B_C (see ENCODING section above). +// A_E, A_Y, D_F or A_B_C. // // - BytecodeKind is one of WIDE, RESV (reserved), ORDN (ordinary) //