4.8 KiB
Frame and Bytecode Interpreter
Location: crates/core/src/frame/
Frame Structure
Each method invocation creates a Frame containing:
| Component | Description |
|---|---|
| Program Counter (PC) | i64 tracking current bytecode instruction |
| Operand Stack | Generic Vec-backed stack for intermediate values |
| Local Variables | Indexed slots, handles wide values (long/double occupy 2 slots) |
| Constant Pool | Arc reference to the class constant pool |
| Bytecode | Instructions for the method |
OperandStack (operand_stack.rs)
- Generic Vec-backed stack with push/pop/peek operations
pop_n(n)returns values in push order (not pop order) for method arguments- Supports underflow detection
LocalVariables (local_vars.rs)
- Vec-backed, indexed by slot
- Handles wide values (long, double) that occupy 2 slots with padding
from_args()automatically spaces wide values correctly- Prevents access to padding slots with runtime panic
Execution Loop
loop {
let (offset, op) = self.next().unwrap();
self.pc = offset as i64;
let result = self.execute_instruction(op.clone());
match result {
Ok(ExecutionResult::Advance(offset)) => self.pc += offset as i64,
Ok(_) => self.pc += 1,
Err(x) => return error with stack trace,
}
}
Opcode Dispatch
Location: frame.rs execute_instruction() (lines 199-1516)
- Single match statement over
Opsenum variants (defined ininstructions.rs) - 200+ opcodes: constants, loads/stores, math, stack ops, branches, references, method invocation
- Uses helper macros (
load!,store!,binary_op!,shift_op!, etc.) for common patterns - Each opcode returns one of:
ExecutionResult::Continue(auto-increment PC by 1)ExecutionResult::Advance(offset)(jump)ExecutionResult::Return(())orExecutionResult::ReturnValue(Value)(exit frame)VmErroron failure
Opcode Encoding (instructions.rs)
- Uses
dekuderive for binary deserialization - Each opcode has a u8 ID (0x00-0xFF)
- Some opcodes carry operands (e.g.,
iload(u8),goto(i16)) - Wide instruction prefix (0xC4) for accessing local slots > 255
Method Invocation
Location: thread.rs (lines 308-338)
Invocation Types
invoke(): Resolve method by class and descriptor, execute itinvoke_virtual(): Virtual dispatch - find method on actual runtime classinvoke_native(): Call native JNI method via FFI
Bytecode Invocation Instructions
invokevirtual: Virtual method dispatch - pop receiver + arguments, get actual class, callthread.invoke_virtual()invokespecial: Non-virtual (constructors, private, super) - pop receiver + arguments, callthread.invoke()with static resolutioninvokestatic: Static methods - pop arguments only (no receiver), callthread.invoke()invokeinterface: Interface method dispatch - similar toinvokevirtualwith interface resolution
Frame Creation & Execution
fn execute_method(&self, class: &Arc<RuntimeClass>, method: &MethodData, args: Vec<Value>) {
let mut frame = Frame::new(
class.clone(),
method_ref,
code_attr, // Contains max_stack, max_locals, bytecode
args, // Initialize local vars with parameters
...
);
self.frame_stack.lock().push(frame.clone());
frame.execute() // Bytecode interpretation loop
self.frame_stack.lock().pop();
}
Supported Instructions
Constants
aconst_null, iconst_*, lconst_*, fconst_*, dconst_*, bipush, sipush, ldc, ldc_w, ldc2_w
Load/Store
iload, lload, fload, dload, aload, istore, lstore, fstore, dstore, astore (including _0-3 variants)
Array Operations
iaload, laload, faload, daload, aaload, baload, caload, saload, iastore, lastore, fastore, dastore, aastore, bastore, castore, sastore, arraylength
Stack Manipulation
pop, pop2, dup, dup_x1, dup_x2, dup2, dup2_x1, dup2_x2, swap
Arithmetic
All int/long/float/double add, sub, mul, div, rem, neg operations
Bitwise
ishl, lshl, ishr, lshr, iushr, lushr, iand, land, ior, lor, ixor, lxor
Type Conversions
All primitive type conversions (i2l, l2i, f2d, etc.)
Comparisons
lcmp, fcmpl, fcmpg, dcmpl, dcmpg
Control Flow
ifeq, ifne, iflt, ifge, ifgt, ifle, if_icmp*, if_acmp*, goto, ifnull, ifnonnull, tableswitch, lookupswitch
Object Operations
new, newarray, anewarray, multianewarray, checkcast, instanceof
Field Access
getstatic, putstatic, getfield, putfield
Method Invocation
invokevirtual, invokespecial, invokestatic, invokeinterface
Returns
ireturn, lreturn, freturn, dreturn, areturn, return
Synchronization
monitorenter, monitorexit