bug fix array arg

This commit is contained in:
Shautvast 2023-11-05 09:09:44 +01:00
parent ceeec215e4
commit 769800ff71
8 changed files with 56 additions and 35 deletions

View file

@ -5,15 +5,16 @@ use std::io::Read;
use std::rc::Rc;
use anyhow::Error;
use log::debug;
use crate::classloader::io::{find_class, read_bytes, read_f32, read_f64, read_i32, read_i64, read_u16, read_u32, read_u8};
use crate::classloader::classdef::{AttributeType, ClassDef, CpEntry, Exception, Field, Method, MethodCode};
pub(crate) mod classdef;
pub mod classdef;
pub(crate) mod io;
pub(crate) fn get_classdef(classpath: &Vec<String>, class_name: &str) -> Result<ClassDef,Error> {
println!("read class {} ", class_name);
debug!("read class {} ", class_name);
let resolved_path = find_class(classpath, class_name)?;
let bytecode = read_bytecode(resolved_path)?;
load_class(bytecode)

View file

@ -1,4 +1,5 @@
use std::collections::{HashMap, LinkedList};
use log::debug;
use once_cell::sync::Lazy;
use crate::class::{Class, ClassId, ObjectRef, TypeIndex, Value::*, Value};
@ -200,8 +201,8 @@ impl ClassManager {
self.names.get(name)
.and_then(|id|
self.classes.insert(*id, Class {
id: *id,
self.classes.insert(this_classid, Class {
id: this_classid,
initialized: false,
name: name.into(),
superclass: superclass_id,
@ -258,6 +259,8 @@ impl ClassManager {
classes_to_load.append(&mut self.load_class_and_deps(classname.as_str()).1);
}
}
debug!("new class {} -> {}", name, id);
id
}

View file

@ -1,4 +1,4 @@
mod classloader;
pub mod classloader;
pub mod classmanager;
pub mod class;
pub mod vm;

View file

@ -1,7 +1,7 @@
#![allow(non_snake_case)]
use anyhow::Error;
use log::{info};
use log::{debug, info};
use once_cell::sync::Lazy;
use crate::class::{ObjectRef, Value};
@ -12,7 +12,7 @@ use crate::vm::stack::StackFrame;
use crate::vm::Vm;
pub fn invoke_native(vm: &mut Vm, stackframes: &mut Vec<StackFrame>, class_name: &String, method_name: &str, _args: Vec<Value>) -> Result<Value, Error> {
info!("native {}.{}", class_name, method_name);
debug!("native {}.{}", class_name, method_name);
match class_name.as_str() {
"java/lang/Class" => java_lang_class(vm, method_name),

View file

@ -293,6 +293,7 @@ pub const _ATHROW: u8 = 191;
pub const _CHECKCAST: u8 = 192;
// (0xc0)
pub const MONITORENTER: u8 = 194;
pub const MONITOREXIT: u8 = 195;
pub const IFNULL: u8 = 198;
pub const IFNONNULL: u8 = 199;
@ -445,6 +446,7 @@ pub const OPCODES:Lazy<Vec<&str>> = Lazy::new(|| {
opcodes[_ATHROW as usize] = "_ATHROW" ;
opcodes[_CHECKCAST as usize] = "_CHECKCAST" ;
opcodes[MONITORENTER as usize] = "MONITORENTER" ;
opcodes[MONITOREXIT as usize] = "MONITOREXIT" ;
opcodes[IFNULL as usize] = "IFNULL" ;
opcodes[IFNONNULL as usize] = "IFNONNULL" ;
opcodes

View file

@ -81,10 +81,23 @@ fn get_num_args(signature: &str) -> usize {
num += 1;
} else if chars[i] == ')' {
break;
} else if chars[i] == '[' {
i += 1;
} else {
i += 1;
num += 1;
}
}
num
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn num_args() {
let n = get_num_args("(Ljava/nio/charset/Charset;[BII)V");
assert_eq!(n, 4)
}
}

View file

@ -28,7 +28,6 @@ const PATH_SEPARATOR: char = ';';
//TODO goto
//TODO error handling
impl Vm {
/// for running static initializers
pub fn new_internal() -> Self {
Self {}
@ -48,12 +47,10 @@ impl Vm {
fn init(vm: &mut Vm, stack: &mut Vec<StackFrame>) {
classmanager::load_class_by_name("java/lang/Class");
Self::initialize_class(vm, stack, "java/lang/System");
vm.execute_static(stack, "java/lang/System", "initPhase1()V", vec![]).expect("cannot create VM");
classmanager::load_class_by_name("java/lang/String");
}
fn initialize_class(vm: &mut Vm, stack: &mut Vec<StackFrame>, class: &str) {
vm.execute_static(stack, class, "initPhase1()V", vec![]).expect("cannot create VM");
}
fn current_frame(stackframes: &mut Vec<StackFrame>) -> &mut StackFrame {
let i = stackframes.len() - 1;
@ -74,9 +71,9 @@ impl Vm {
) -> Result<Value, Error> {
for arg in &args {
if let Ref(r) = arg {
info!("arg {:?}",r);
debug!("arg {:?}",r);
} else {
info!("arg {:?}",arg);
debug!("arg {:?}",arg);
}
}
@ -153,7 +150,7 @@ impl Vm {
method_name: &str,
args: Vec<Value>,
) -> Result<Value, Error> {
info!("execute {}.{}", this_class.name, method_name);
debug!("execute {}.{}", this_class.name, method_name);
//TODO implement dynamic dispatch -> get method from instance
let method = classmanager::get_classdef(&this_class.id).get_method(method_name).unwrap();
@ -170,7 +167,7 @@ impl Vm {
while *pc < code.opcodes.len() {
let opcode = read_u8(&code.opcodes, pc);
let cur_frame = Self::current_frame(stackframes);
info!("\t{} #{} {} - {}", &cur_frame.at, &*pc - 1, opcodes::OPCODES[opcode as usize], cur_frame.len());
debug!("\t{} #{} {} - {}", &cur_frame.at, &*pc - 1, opcodes::OPCODES[opcode as usize], cur_frame.len());
match opcode {
ACONST_NULL => {
Self::current_frame(stackframes).push(Value::Null);
@ -245,11 +242,9 @@ impl Vm {
let stringinstance =
Ref(ObjectRef::Object(Vm::new_instance(stringclass)));
debug!("class id {}", this_class.id);
let string: Vec<u8> =
classmanager::get_classdef(&this_class.id).cp_utf8(utf8)
.to_owned()
.as_bytes()
.into();
classmanager::get_classdef(&this_class.id).cp_utf8(utf8).as_bytes().into();
self.execute_special(stackframes,
"java/lang/String",
@ -493,6 +488,7 @@ impl Vm {
if let Some(invocation) =
get_signature_for_invoke(&method.constant_pool, cp_index)
{
debug!("invoke {:?}", invocation);
let mut args = Vec::with_capacity(invocation.method.num_args);
for _ in 0..invocation.method.num_args {
args.insert(0, Self::current_frame(stackframes).pop()?.clone());
@ -505,10 +501,10 @@ impl Vm {
)?;
if let Ref(objectref) = &return_value {
if let ObjectRef::Object(object) = objectref {
info!("return {:?}", object);
debug!("return {:?}", object);
}
} else {
info!("return {:?}", return_value);
debug!("return {:?}", return_value);
}
match return_value {
Void => {}
@ -540,10 +536,10 @@ impl Vm {
)?;
if let Ref(objectref) = &return_value {
if let ObjectRef::Object(object) = objectref {
info!("return {:?}", object);
debug!("return {:?}", object);
}
} else {
info!("return {:?}", return_value);
debug!("return {:?}", return_value);
}
match return_value {
Void => {}
@ -571,10 +567,10 @@ impl Vm {
)?;
if let Ref(objectref) = &return_value {
if let ObjectRef::Object(object) = objectref {
info!("return {:?}", object);
debug!("return {:?}", object);
}
} else {
info!("return {:?}", return_value);
debug!("return {:?}", return_value);
}
match return_value {
Void => {}
@ -622,7 +618,7 @@ impl Vm {
Self::current_frame(stackframes).push(I32(val.get_array_length() as i32));
}
}
MONITORENTER => {
MONITORENTER | MONITOREXIT => {
Self::current_frame(stackframes).pop()?;
} //TODO implement
IFNULL | IFNONNULL => {
@ -631,21 +627,21 @@ impl Vm {
let its_null = if let Null = value { true } else { false };
if its_null && opcode == IFNULL {
info!("\t\tIF NULL =>{}: JMP {}", its_null, *pc + jmp_to as usize);
debug!("\t\tIF NULL =>{}: JMP {}", its_null, *pc + jmp_to as usize);
*pc += jmp_to as usize;
}
if !its_null && opcode == IFNONNULL {
info!("\t\tIF NOT NULL =>{}: JMP {}", its_null, *pc + jmp_to as usize);
debug!("\t\tIF NOT NULL =>{}: JMP {}", its_null, *pc + jmp_to as usize);
*pc += jmp_to as usize;
}
//debug info
if !its_null && opcode == IFNULL {
info!("\t\tIF NULL =>false: NO JMP");
debug!("\t\tIF NULL =>false: NO JMP");
}
if its_null && opcode == IFNONNULL {
info!("\t\tIF NONNULL =>false: NO JMP");
debug!("\t\tIF NONNULL =>false: NO JMP");
}
},
}
//TODO implement all opcodes
_ => {
panic!("opcode {} not implemented {:?}", opcode, stackframes)
@ -670,10 +666,10 @@ impl Vm {
_ => false,
};
if jump {
info!("\t\tIF({}) JMP {}", jump, *pc + jmp_to as usize);
debug!("\t\tIF({}) JMP {}", jump, *pc + jmp_to as usize);
*pc += jmp_to as usize;
} else {
info!("\t\tIF({}) NO JMP", jump);
debug!("\t\tIF({}) NO JMP", jump);
}
}
}
@ -696,6 +692,7 @@ impl Vm {
}
}
#[derive(Debug)]
pub(crate) struct Invocation {
class_name: String,
method: MethodSignature,
@ -710,6 +707,7 @@ impl Invocation {
}
}
#[derive(Debug)]
pub(crate) struct MethodSignature {
name: String,
num_args: usize,

View file

@ -1,7 +1,7 @@
mod test {
use java_rs::class::{Method, Modifier};
use std::collections::HashMap;
use std::rc::Rc;
use java_rs::classloader::classdef::{Method, Modifier};
#[test]
fn access_flags() {
@ -16,4 +16,8 @@ mod test {
assert!(m.is(Modifier::Static));
assert!(!m.is(Modifier::Private));
}
}