rusty-jvm 0.5.0

An implementation of a Java Virtual Machine (JVM).
Documentation
use crate::vm::error::{Error, Result};
use crate::vm::execution_engine::common::last_frame_mut;
use crate::vm::execution_engine::opcode::*;
use crate::vm::heap::heap::with_heap_write_lock;
use crate::vm::stack::stack_frame::{StackFrame, StackFrames};
use crate::vm::stack::stack_value::StackValue;
use std::fmt::Display;
use tracing::trace;

pub(crate) fn process(code: u8, stack_frames: &mut StackFrames) -> Result<()> {
    let stack_frame = last_frame_mut(stack_frames)?;
    match code {
        ISTORE => handle_pos_and_store::<i32>(stack_frame, "ISTORE "),
        LSTORE => handle_pos_and_store::<i64>(stack_frame, "LSTORE "),
        FSTORE => handle_pos_and_store::<f32>(stack_frame, "FSTORE "),
        DSTORE => handle_pos_and_store::<f64>(stack_frame, "DSTORE "),
        ASTORE => handle_pos_and_store::<i32>(stack_frame, "ASTORE "),
        ISTORE_0 | ISTORE_1 | ISTORE_2 | ISTORE_3 => {
            handle_store::<i32, _>(stack_frame, code - ISTORE_0, "ISTORE_")
        }
        LSTORE_0 | LSTORE_1 | LSTORE_2 | LSTORE_3 => {
            handle_store::<i64, _>(stack_frame, code - LSTORE_0, "LSTORE_")
        }
        FSTORE_0 | FSTORE_1 | FSTORE_2 | FSTORE_3 => {
            handle_store::<f32, _>(stack_frame, code - FSTORE_0, "FSTORE_")
        }
        DSTORE_0 | DSTORE_1 | DSTORE_2 | DSTORE_3 => {
            handle_store::<f64, _>(stack_frame, code - DSTORE_0, "DSTORE_")
        }
        ASTORE_0 | ASTORE_1 | ASTORE_2 | ASTORE_3 => {
            handle_store::<i32, _>(stack_frame, code - ASTORE_0, "ASTORE_")
        }
        IASTORE => handle_array_store::<i32>(stack_frame, "IASTORE")?,
        LASTORE => handle_array_store::<i64>(stack_frame, "LASTORE")?,
        FASTORE => handle_array_store::<f32>(stack_frame, "FASTORE")?,
        DASTORE => handle_array_store::<f64>(stack_frame, "DASTORE")?,
        AASTORE => handle_array_store::<i32>(stack_frame, "AASTORE")?,
        BASTORE => handle_array_store::<i32>(stack_frame, "BASTORE")?,
        CASTORE => handle_array_store::<i32>(stack_frame, "CASTORE")?,
        SASTORE => handle_array_store::<i32>(stack_frame, "SASTORE")?,
        _ => {
            return Err(Error::new_execution(&format!(
                "Unknown store opcode: {}",
                code
            )));
        }
    }

    Ok(())
}

fn handle_pos_and_store<T: StackValue + Display + Copy>(
    stack_frame: &mut StackFrame,
    name_starts: &str,
) {
    let pos = stack_frame.extract_one_byte();
    handle_store::<T, _>(stack_frame, pos, name_starts);
}

pub(crate) fn handle_store<T: StackValue + Display + Copy, POS: Display + Copy>(
    stack_frame: &mut StackFrame,
    pos: POS,
    name_starts: &str,
) where
    usize: From<POS>,
{
    let value: T = stack_frame.pop();
    stack_frame.set_local(pos.into(), value);

    stack_frame.incr_pc();
    trace!("{name_starts}{pos} -> value={value}");
}

fn handle_array_store<T: StackValue + Display + Copy>(
    stack_frame: &mut StackFrame,
    name_starts: &str,
) -> Result<()> {
    let value: T = stack_frame.pop();
    let index = stack_frame.pop();
    let arrayref: i32 = stack_frame.pop();
    let raw_value = value.to_vec();
    with_heap_write_lock(|heap| heap.set_array_value(arrayref, index, raw_value))?;

    stack_frame.incr_pc();
    trace!("{name_starts} -> arrayref={arrayref}, index={index}, value={value}");

    Ok(())
}