JVMTranslator

class JVMTranslator(val code: A_RawFunction?, chunkName: String, sourceFileName: String?, controlFlowGraph: L2ControlFlowGraph, instructions: List<L2Instruction>)

A JVMTranslator converts a single L2Chunk into a JVMChunk in a naive fashion. Instruction selection is optimized, but no other optimizations are attempted; all significant optimizations should occur on the L2Chunk's control flow graph and be reflected in the L2Chunk to be translated.

Author

Todd L Smith

Parameters

code

The source L1 code, or null for the unoptimized chunk.

chunkName

The descriptive (non-unique) name of the chunk being translated.

sourceFileName

The name of the Avail source file that produced the code. Use null if no such file exists.

controlFlowGraph

The L2ControlFlowGraph which produced the sequence of instructions.

instructions

The source L2Instructions to translate to JVM bytecodes.

Constructors

Link copied to clipboard
constructor(code: A_RawFunction?, chunkName: String, sourceFileName: String?, controlFlowGraph: L2ControlFlowGraph, instructions: List<L2Instruction>)

Construct a new JVMTranslator to translate the specified array of L2Instructions to a JVMChunk.

Types

Link copied to clipboard
object Companion
Link copied to clipboard
class LiteralAccessor(val classLoaderIndex: Int, val fieldName: String?, val getter: (MethodVisitor) -> Unit, val setter: (MethodVisitor) -> Unit?)

A LiteralAccessor aggregates means of accessing a literal Object in various contexts.

Properties

Link copied to clipboard

The internal name of the generated class.

Link copied to clipboard

The name of the generated class, formed from a UUID to ensure that no collisions occur.

Link copied to clipboard
val classNode: ClassNode

The ClassWriter responsible for writing the JVMChunk subclass. The ClassWriter is configured to automatically compute stack map frames and method limits (e.g., stack depths).

Link copied to clipboard

The source L1 code.

Link copied to clipboard
val jumper: Label

An entry point near the end of the method, which jumps back to the methodHead for the purpose of performing a jump to a specified L2 offset without having the Fernflower Java decompiler produce tons of spurious nested blocks, breaks, and duplicated code. It's not very good.

Link copied to clipboard
val labels: MutableMap<Int, Label>

The L2PcOperand's encapsulated program counters, mapped to their labels.

Link copied to clipboard

The literals used by the L2Chunk that must be embedded into the translated JVMChunk, mapped to their accessors.

Link copied to clipboard

As the code is being generated and we encounter an L2_SAVE_ALL_AND_PC_TO_INT, we examine its corresponding target block to figure out which registers actually have to be captured at the save, and restored at the L2_ENTER_L2_CHUNK. At that point, we look up the local numbers from the JVMTranslator and record them by RegisterKind in this field.

Link copied to clipboard

The mapping of registers to locals, partitioned by kind.

Link copied to clipboard
val methodHead: Label

The start of the runChunk method, where the offset is used to jump to the start of the control flow graph, or the specified entry point.

Functions

Link copied to clipboard
fun branch(method: MethodVisitor, instruction: L2Instruction, opcode: Int, success: L2PcOperand, failure: L2PcOperand, successCounter: LongAdder, failureCounter: LongAdder)

Emit code to conditionally branch to one of the specified program counters.

Link copied to clipboard

The final phase of JVM code generation.

Link copied to clipboard

Populate classBytes, dumping to a file for debugging if indicated.

Link copied to clipboard
fun doubleConstant(method: MethodVisitor, value: Double)

Emit the effect of loading a constant double to the specified MethodVisitor.

Link copied to clipboard
fun endLocal(localNumber: Int, type: Type)

A local variable has just ended scope. Ensure it was the most recently allocated local, and deallocate the slot(s) that were used for it.

Link copied to clipboard
fun floatConstant(method: MethodVisitor, value: Float)

Emit the effect of loading a constant float to the specified MethodVisitor.

Link copied to clipboard

Generate the default constructor `()V` of the target JVMChunk.

Link copied to clipboard

Generate the JVMChunk.name method of the target JVMChunk.

Link copied to clipboard
fun generateReificationPreamble(method: MethodVisitor, onReification: L2PcOperand)

We're at a point where reification has been requested. A StackReifier has already been stashed in the Interpreter, and already-popped calls may have already queued actions in the reifier, to be executed in reverse order.

Link copied to clipboard

Generate the JVMChunk.runChunk method of the target JVMChunk.

Link copied to clipboard

Generate the static initializer of the target JVMChunk. The static initializer is responsible for moving any of the parameters of the JVMChunk subclass's JVMChunkClassLoader into appropriate private static final fields.

Link copied to clipboard
fun intConstant(method: MethodVisitor, value: Int)

Emit the effect of loading a constant int to the specified MethodVisitor.

Link copied to clipboard
fun jump(method: MethodVisitor, operand: L2PcOperand)

Emit code to unconditionally branch to the specified program counter.

fun jump(method: MethodVisitor, instruction: L2Instruction, operand: L2PcOperand)

Emit code to unconditionally branch to the specified program counter. Skip if the edge indicates it follows the given instruction.

Link copied to clipboard
fun jumpIf(method: MethodVisitor, branchOpcode: Int, edge: L2PcOperand)

Emit code to jump to the target of the supplied edge conditionally, based on the supplied JVM branch opcode and the value on top of the stack. program counter. If condition is not satisfied, control continues at the next JVM instruction.

Link copied to clipboard

Answer the generated JVMChunk.

Link copied to clipboard
fun labelFor(offset: Int): Label

Answer the Label for the specified L2InstructionL2Instruction.offset.

Link copied to clipboard
fun literal(method: MethodVisitor, any: Any)

Emit code to push the specified literal on top of the stack.

fun literal(method: MethodVisitor?, operand: L2Operand)

Throw an UnsupportedOperationException. It is never valid to treat an L2Operand as a JVM literal, so this method is marked as Deprecated to protect against code cloning and refactoring errors by a programmer.

fun literal(method: MethodVisitor?, reg: L2Register?)

Throw an UnsupportedOperationException. It is never valid to treat an L2Register as a Java literal, so this method is marked as Deprecated to protect against code cloning and refactoring errors by a programmer.

Link copied to clipboard
fun load(method: MethodVisitor, register: L2Register)

Generate a load of the local associated with the specified L2Register.

Link copied to clipboard
fun loadClass()

Actually load the generated class into the running JVM. Note that a special JVMChunkClassLoader must be used, so that the static initialization has access to the necessary constants referenced from the bytecodes.

Link copied to clipboard
fun loadInterpreter(method: MethodVisitor)

Generate access to the JVM local for the Interpreter formal parameter of a generated implementation of JVMChunk.runChunk.

Link copied to clipboard
fun loadReceiver(method: MethodVisitor)

Generate access of the receiver (i.e., this).

Link copied to clipboard

Answer the JVM local number for this register. This is the position within the actual JVM stack frame layout.

Link copied to clipboard
fun longConstant(method: MethodVisitor, value: Long)

Emit the effect of loading a constant long to the specified MethodVisitor.

Link copied to clipboard
fun nextLocal(type: Type): Int

Answer the next JVM local for use within generated code produced by generateRunChunk.

Link copied to clipboard
fun objectArray(method: MethodVisitor, operands: List<L2ReadBoxedOperand>, arrayClass: Class<out A_BasicObject>)

Emit code to store each of the L2BoxedRegisters into a new array. Leave the new array on top of the stack.

Link copied to clipboard

Answer the JVM local for the offset formal parameter of a generated implementation of JVMChunk.runChunk.

Link copied to clipboard
fun prepare()

Prepare for JVM translation by visiting each of the L2Instructions to be translated.

Link copied to clipboard

Answer the JVM local for the StackReifier local variable of a generated implementation of JVMChunk.runChunk.

Link copied to clipboard
fun reverseOpcode(opcode: Int): Int

Answer the JVM branch opcode with the reversed sense.

Link copied to clipboard
fun store(method: MethodVisitor, register: L2Register)

Generate a store into the local associated with the specified L2Register. The value to be stored should already be on top of the stack and correctly typed.

Link copied to clipboard
fun translate()

Translate the embedded L2Chunk into a JVMChunk.