local params and first part of array stores

This commit is contained in:
Sander Hautvast 2023-10-10 21:52:22 +02:00
parent 6feebec373
commit a0823788d8
3 changed files with 103 additions and 71 deletions

View file

@ -256,9 +256,8 @@ impl MethodCode {
#[derive(Debug)] #[derive(Debug)]
pub enum Value { pub enum Value {
Void, Void, // variant returned for void methods
Null, Null, // 'pointer' to nothing
// the $1_000_000 mistake
I32(i32), I32(i32),
I64(i64), I64(i64),
F32(f32), F32(f32),

View file

@ -53,20 +53,31 @@ pub const BALOAD: u8 = 51; //(0x33) Load byte or boolean from array
pub const CALOAD: u8 = 52; // (0x34) Load char from array pub const CALOAD: u8 = 52; // (0x34) Load char from array
pub const SALOAD: u8 = 53; // (0x34) Load short from array pub const SALOAD: u8 = 53; // (0x34) Load short from array
pub const ISTORE: u8 = 54; // (0x36) Store int into local variable pub const ISTORE: u8 = 54; // (0x36) Store int into local variable
// pub const LSTORE: u8 = 55; // (0x37) Store long into local variable
// pub const fstore: u8 = 56; // (0x38) Store float into local variable pub const FSTORE: u8 = 56; // (0x38) Store float into local variable
// pub const dstore: u8 = 57; // (0x39) store double in local variable pub const DSTORE: u8 = 57; // (0x39) store double in local variable
// pub const astore:u8 = 58; // (0x3a) pub const ASTORE :u8 = 58; // (0x3a)
// pub const ISTORE_0:u8 = 59; // (0x3b) Store int into local variable 0
// pub const dstore_0: u8 = 71; // (0x47) store double 0 in local variable pub const ISTORE_1:u8 = 60; // (0x3c) Store int into local variable 1
// pub const dstore_1: u8 = 72; // (0x48) store double 1 in local variable pub const ISTORE_2:u8 = 61; // (0x3d) Store int into local variable 2
// pub const dstore_2: u8 = 73; // (0x49) store double 2 in local variable pub const ISTORE_3:u8 = 62; // (0x3e) Store int into local variable 3
// pub const dstore_3: u8 = 74; // (0x4a) store double 3 in local variable pub const LSTORE_0:u8 = 63; // (0x3f) Store long into local variable 0
// pub const astore_0: u8 = 75; // (0x4b) pub const LSTORE_1:u8 = 64; // (0x40) Store long into local variable 1
// pub const astore_1: u8 = 76; // (0x4c) pub const LSTORE_2:u8 = 65; // (0x41) Store long into local variable 2
// pub const astore_2: u8 = 77; // (0x4d) pub const LSTORE_3:u8 = 66; // (0x42) Store long into local variable 3
// pub const astore_3: u8 = 78; // (0x4e) pub const FSTORE_0:u8 = 67; // (0x43) Store float into local variable 0
// pub const fastore: u8 = 81; // (0x51) Store into float array pub const FSTORE_1:u8 = 68; // (0x44) Store float into local variable 1
pub const FSTORE_2:u8 = 69; // (0x45) Store float into local variable 2
pub const FSTORE_3:u8 = 70; // (0x46) Store float into local variable 3
pub const DSTORE_0: u8 = 71; // (0x47) store double in local variable 0
pub const DSTORE_1: u8 = 72; // (0x48) store double in local variable 1
pub const DSTORE_2: u8 = 73; // (0x49) store double in local variable 2
pub const DSTORE_3: u8 = 74; // (0x4a) store double in local variable 3
pub const ASTORE_0: u8 = 75; // (0x4b)
pub const ASTORE_1: u8 = 76; // (0x4c)
pub const ASTORE_2: u8 = 77; // (0x4d)
pub const ASTORE_3: u8 = 78; // (0x4e)
pub const FASTORE: u8 = 81; // (0x51) Store into float array
// pub const dastore:u8 = 82; //(0x52) store into double array // pub const dastore:u8 = 82; //(0x52) store into double array
// pub const aastore: u8 = 83; // (0x53) // pub const aastore: u8 = 83; // (0x53)
// //

130
src/vm.rs
View file

@ -111,6 +111,7 @@ impl Vm {
method_name: &str, method_name: &str,
args: Vec<Arc<UnsafeCell<Value>>>, args: Vec<Arc<UnsafeCell<Value>>>,
) -> Result<Arc<UnsafeCell<Value>>, Error> { ) -> Result<Arc<UnsafeCell<Value>>, Error> {
let mut local_params: Vec<Option<Arc<UnsafeCell<Value>>>> = args.clone().iter().map(|e| Some(e.clone())).collect();
println!("execute {}.{}", class_name, method_name); println!("execute {}.{}", class_name, method_name);
let class = self.get_class(class_name)?; let class = self.get_class(class_name)?;
let method = class.get_method(method_name)?; let method = class.get_method(method_name)?;
@ -237,20 +238,38 @@ impl Vm {
// let index = self.local_stack().pop()?; // let index = self.local_stack().pop()?;
// let array_ref = self.local_stack().pop()?; // let array_ref = self.local_stack().pop()?;
} }
ISTORE => { ISTORE | LSTORE | FSTORE | DSTORE | ASTORE => {
unsafe { let index = read_u8(&code.opcodes, pc) as usize;
let index = read_u8(&code.opcodes, pc); self.store(&mut local_params, index)?;
let value = self.local_stack().pop()?; }
if let Value::I32(int) = *value.get() { ISTORE_0 | LSTORE_0 | DSTORE_0 | ASTORE_0 | FSTORE_0 => {
// TODO local vars self.store(&mut local_params, 0)?;
}
ISTORE_1 | LSTORE_1 | DSTORE_1 | ASTORE_1 | FSTORE_1 => {
self.store(&mut local_params, 1)?;
}
ISTORE_2 | LSTORE_2 | DSTORE_2 | ASTORE_2 | FSTORE_2 => {
self.store(&mut local_params, 2)?;
}
ISTORE_3 | LSTORE_3 | DSTORE_3 | ASTORE_3 | FSTORE_3 => {
self.store(&mut local_params, 3)?;
}
FASTORE => unsafe {
if let Value::F32(value) = *self.local_stack().pop()?.get() {
if let Value::I32(index) = &mut *self.local_stack().pop()?.get() {
if let Value::Ref(ref mut objectref) = &mut *self.local_stack().pop()?.get() {
if let ObjectRef::FloatArray(ref mut array) = &mut *objectref.get() {
array[*index as usize] = value;
}
}
} }
} }
} }
POP => { POP => {
self.local_stack().pop().expect("Stack empty"); self.local_stack().pop()?;
} }
DUP => { DUP => {
let value = self.local_stack().pop().expect("Stack empty"); let value = self.local_stack().pop()?;
println!("{:?}", value); println!("{:?}", value);
self.local_stack().push_arc(value.clone()); self.local_stack().push_arc(value.clone());
self.local_stack().push_arc(value); self.local_stack().push_arc(value);
@ -282,57 +301,51 @@ impl Vm {
} }
} }
} }
PUTFIELD => { PUTFIELD => unsafe {
unsafe {
let cp_index = read_u16(&code.opcodes, pc);
if let CpEntry::Fieldref(_class_index, name_and_type_index) =
method.constant_pool.get(&cp_index).unwrap()
{
if let CpEntry::NameAndType(name_index, _) = method.constant_pool.get(name_and_type_index).unwrap() {
let value = self.local_stack().pop()?;
let mut objectref = self.local_stack().pop()?;
if let Value::Ref(instance) = &mut *objectref.get() {
if let ObjectRef::Object(ref mut object) = &mut *instance.get() {
object.data.insert(*name_index, value);
} else {
panic!("not an object, maybe array");
}
}
}
}
}
}
INVOKEVIRTUAL => {
let cp_index = read_u16(&code.opcodes, pc); let cp_index = read_u16(&code.opcodes, pc);
unsafe { if let CpEntry::Fieldref(_class_index, name_and_type_index) =
if let Some(invocation) = get_signature_for_invoke(Rc::clone(&method.constant_pool), cp_index) { method.constant_pool.get(&cp_index).unwrap()
let mut args = Vec::with_capacity(invocation.method.num_args); {
for _ in 0..invocation.method.num_args { if let CpEntry::NameAndType(name_index, _) = method.constant_pool.get(name_and_type_index).unwrap() {
args.insert(0, self.local_stack().pop()?); let value = self.local_stack().pop()?;
} let mut objectref = self.local_stack().pop()?;
args.insert(0, self.local_stack().pop()?); if let Value::Ref(instance) = &mut *objectref.get() {
let mut returnvalue = self.execute(&invocation.class_name, &invocation.method.name, args)?; if let ObjectRef::Object(ref mut object) = &mut *instance.get() {
match *returnvalue.get() { object.data.insert(*name_index, value);
Void => {} } else {
_ => { self.local_stack().push_arc(returnvalue.clone()); } panic!("not an object, maybe array");
} }
} // else?
} }
} }
} }
INVOKESPECIAL => { INVOKEVIRTUAL => unsafe {
unsafe { let cp_index = read_u16(&code.opcodes, pc);
let cp_index = read_u16(&code.opcodes, pc); if let Some(invocation) = get_signature_for_invoke(Rc::clone(&method.constant_pool), cp_index) {
if let Some(invocation) = get_signature_for_invoke(Rc::clone(&method.constant_pool), cp_index) { let mut args = Vec::with_capacity(invocation.method.num_args);
let mut args = Vec::with_capacity(invocation.method.num_args); for _ in 0..invocation.method.num_args {
for _ in 0..invocation.method.num_args {
args.insert(0, self.local_stack().pop()?);
}
args.insert(0, self.local_stack().pop()?); args.insert(0, self.local_stack().pop()?);
let mut returnvalue = self.execute(&invocation.class_name, &invocation.method.name, args)?; }
match *returnvalue.get() { args.insert(0, self.local_stack().pop()?);
Void => {} let mut returnvalue = self.execute(&invocation.class_name, &invocation.method.name, args)?;
_ => { self.local_stack().push_arc(returnvalue.clone()); } match *returnvalue.get() {
} Void => {}
_ => { self.local_stack().push_arc(returnvalue.clone()); }
}
}
}
INVOKESPECIAL => unsafe {
let cp_index = read_u16(&code.opcodes, pc);
if let Some(invocation) = get_signature_for_invoke(Rc::clone(&method.constant_pool), cp_index) {
let mut args = Vec::with_capacity(invocation.method.num_args);
for _ in 0..invocation.method.num_args {
args.insert(0, self.local_stack().pop()?);
}
args.insert(0, self.local_stack().pop()?);
let mut returnvalue = self.execute(&invocation.class_name, &invocation.method.name, args)?;
match *returnvalue.get() {
Void => {}
_ => { self.local_stack().push_arc(returnvalue.clone()); }
} }
} }
} }
@ -363,6 +376,15 @@ impl Vm {
} }
panic!("should not happen") panic!("should not happen")
} }
fn store(&mut self, local_params: &mut Vec<Option<Arc<UnsafeCell<Value>>>>, index: usize) -> Result<(), Error> {
let value = self.local_stack().pop()?;
while local_params.len() < index + 1 {
local_params.push(None);
}
local_params[index] = Some(value.clone());
Ok(())
}
} }