Module JCode

module JCode: sig .. end

High level Ocaml representation of JVM opcodes.


Bytecode instructions.

type jconst = [ `ANull
| `Byte of int
| `Class of JBasics.object_type
| `Double of float
| `Float of float
| `Int of int32
| `Long of int64
| `MethodHandle of JBasics.method_handle
| `MethodType of JBasics.method_descriptor
| `Short of int
| `String of JBasics.jstr ]
type jinterface_or_class = [ `Class | `Interface ] 
type jopcode = 
| OpLoad of JBasics.jvm_type * int
| OpStore of JBasics.jvm_type * int
| OpIInc of int * int (*

index, increment

*)
| OpPop
| OpPop2
| OpDup
| OpDupX1
| OpDupX2
| OpDup2
| OpDup2X1
| OpDup2X2
| OpSwap
| OpConst of jconst
| OpAdd of JBasics.jvm_basic_type
| OpSub of JBasics.jvm_basic_type
| OpMult of JBasics.jvm_basic_type
| OpDiv of JBasics.jvm_basic_type
| OpRem of JBasics.jvm_basic_type
| OpNeg of JBasics.jvm_basic_type
| OpIShl
| OpLShl
| OpIShr
| OpLShr
| OpIUShr
| OpLUShr
| OpIAnd
| OpLAnd
| OpIOr
| OpLOr
| OpIXor
| OpLXor
| OpI2L
| OpI2F
| OpI2D
| OpL2I
| OpL2F
| OpL2D
| OpF2I
| OpF2L
| OpF2D
| OpD2I
| OpD2L
| OpD2F
| OpI2B
| OpI2C
| OpI2S
| OpCmp of [ `DG | `DL | `FG | `FL | `L ]
| OpIf of [ `Eq | `Ge | `Gt | `Le | `Lt | `Ne | `NonNull | `Null ] * int
| OpIfCmp of [ `AEq | `ANe | `IEq | `IGe | `IGt | `ILe | `ILt | `INe ] * int
| OpGoto of int
| OpJsr of int
| OpRet of int
| OpTableSwitch of int * int32 * int32 * int array (*

(default,low,high,jump offsets)

*)
| OpLookupSwitch of int * (int32 * int) list (*

(default, (match,offset) list)

*)
| OpNew of JBasics.class_name
| OpNewArray of JBasics.value_type
| OpAMultiNewArray of JBasics.object_type * int (*

ClassInfo, dims

*)
| OpCheckCast of JBasics.object_type
| OpInstanceOf of JBasics.object_type
| OpGetStatic of JBasics.class_name * JBasics.field_signature
| OpPutStatic of JBasics.class_name * JBasics.field_signature
| OpGetField of JBasics.class_name * JBasics.field_signature
| OpPutField of JBasics.class_name * JBasics.field_signature
| OpArrayLength
| OpArrayLoad of JBasics.jvm_array_type
| OpArrayStore of JBasics.jvm_array_type
| OpInvoke of [ `Dynamic of JBasics.bootstrap_method
| `Interface of JBasics.class_name
| `Special of jinterface_or_class * JBasics.class_name
| `Static of jinterface_or_class * JBasics.class_name
| `Virtual of JBasics.object_type ] * JBasics.method_signature
| OpReturn of JBasics.jvm_return_type
| OpThrow
| OpMonitorEnter
| OpMonitorExit
| OpNop
| OpBreakpoint
| OpInvalid (*

if opcodes.(i) = OpInvalid it means that there is an opcode that starts at position j, with j<i, an covers positions up to k, with k>=i. If an opcode array is forged, the number of OpInvalid plus one must match the number of bytes on which the preceding instruction must be encoded. E.g. [|OpLoad (`Int2Bool,1); OpInvalid|] is encoded as an iload 0X01; [|OpLoad (`Int2Bool,1)|] is encoded as an iload_1; [|OpLoad (`Int2Bool,1); OpInvalidOpInvalidOpInvalid|] is encoded as an wide;iload 0x0001.

*)
type jopcodes = jopcode array 
type exception_handler = {
   e_start : int;
   e_end : int;
   e_handler : int;
   e_catch_type : JBasics.class_name option;
}

Exception handler.

High level representation of code.

type jcode = {
   c_max_stack : int;
   c_max_locals : int;
   c_code : jopcodes;
   c_exc_tbl : exception_handler list; (*

The list is ordered in the same way as in the bytecode (See JVM Spec se8 §2.10).

*)
   c_line_number_table : (int * int) list option; (*

(start_pc, line_number)

*)
   c_local_variable_table : (int * int * string * JBasics.value_type * int) list option; (*

(start_pc, length, name, type, index)

*)
   c_local_variable_type_table : (int * int * string * JSignature.fieldTypeSignature * int) list option; (*

LocalVariableTable for generics, described in the JVM Spec se8, §4.7.14

*)
   c_stack_map : JBasics.stackmap_frame list option;
   c_attributes : (string * string) list;
}

Code structure.

val empty : jcode

Empty list of opcodes

Access functions.

val get_source_line_number : int -> jcode -> int option

get_source_line_number pp m returns the source line number corresponding to the program point pp of the method code m. The line number give a rough idea and may be wrong. It uses the attribute LineNumberTable (cf. JVM Spec se8 §4.7.12).

val get_source_line_number' : int -> (int * int) list -> int option

get_source_line_number pp lnt returns the source line number corresponding to the program point pp given the LineNumberTable attribute lnt. The line number give a rough idea and may be wrong. It uses the attribute LineNumberTable (cf. JVM Spec se8 §4.7.12).

val get_local_variable_info : int -> int -> jcode -> (string * JBasics.value_type) option

get_local_variable_info i pp m returns the name and signature of the local variable i at program point pp in the method code m (including the pp of the first assignement of i, it's not the case in c_local_variable_table), if they are defined in the local variable table (The bytecode needs to be compiled with the -g option). Otherwise the value None is returned.

Code modification functions.

val replace_code : ?update_max_stack:bool ->
jcode -> int -> jopcode list -> jcode

replace_code code pp l replaces the opcode present at program point pp in the code with the instructions contained in l. For consistency, the program point pp must not refer to an OpInvalid instruction, and the list of instructions l should contain a correct number of OpInvalid after each core instruction in order to fulfill a correct line numbering of the generated bytecode.

val insert_code : ?update_max_stack:bool ->
jcode -> int -> jopcode list -> jcode

insert_code code pp l insert the the instructions contained in l at program point pp in the code. For consistency, the program point pp must not refer to an OpInvalid instruction, and the list of instructions l should contain a correct number of OpInvalid after each core instruction in order to fulfill a correct line numbering of the generated bytecode.

Lambda manipulation.

type lambda_info = {
   functional_interface : JBasics.class_method_signature;
   captured_arguments : JBasics.value_type list;
   checkcast_arguments : JBasics.value_type list;
   lambda_handle : JBasics.method_handle;
}
val build_lambda_info : JBasics.bootstrap_method -> JBasics.method_signature -> lambda_info

build_lambda_info bm ms builds an information caracterizing the construction of the lambda expression referenced by the opcode OpInvoke (`Dynamic bm, ms).