From a0823788d8afade61deba1df88bd3a505125707c Mon Sep 17 00:00:00 2001 From: Sander Hautvast Date: Tue, 10 Oct 2023 21:52:22 +0200 Subject: [PATCH] local params and first part of array stores --- src/class.rs | 5 +- src/opcodes.rs | 39 +++++++++------ src/vm.rs | 130 +++++++++++++++++++++++++++++-------------------- 3 files changed, 103 insertions(+), 71 deletions(-) diff --git a/src/class.rs b/src/class.rs index 726f1be..f8f9e8a 100644 --- a/src/class.rs +++ b/src/class.rs @@ -256,9 +256,8 @@ impl MethodCode { #[derive(Debug)] pub enum Value { - Void, - Null, - // the $1_000_000 mistake + Void, // variant returned for void methods + Null, // 'pointer' to nothing I32(i32), I64(i64), F32(f32), diff --git a/src/opcodes.rs b/src/opcodes.rs index a38dede..ba9deaf 100644 --- a/src/opcodes.rs +++ b/src/opcodes.rs @@ -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 SALOAD: u8 = 53; // (0x34) Load short from array pub const ISTORE: u8 = 54; // (0x36) Store int 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 astore:u8 = 58; // (0x3a) -// -// pub const dstore_0: u8 = 71; // (0x47) store double 0 in local variable -// pub const dstore_1: u8 = 72; // (0x48) store double 1 in local variable -// pub const dstore_2: u8 = 73; // (0x49) store double 2 in local variable -// pub const dstore_3: u8 = 74; // (0x4a) store double 3 in local variable -// 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 LSTORE: u8 = 55; // (0x37) Store long 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 ASTORE :u8 = 58; // (0x3a) +pub const ISTORE_0:u8 = 59; // (0x3b) Store int into local variable 0 +pub const ISTORE_1:u8 = 60; // (0x3c) Store int into local variable 1 +pub const ISTORE_2:u8 = 61; // (0x3d) Store int into local variable 2 +pub const ISTORE_3:u8 = 62; // (0x3e) Store int into local variable 3 +pub const LSTORE_0:u8 = 63; // (0x3f) Store long into local variable 0 +pub const LSTORE_1:u8 = 64; // (0x40) Store long into local variable 1 +pub const LSTORE_2:u8 = 65; // (0x41) Store long into local variable 2 +pub const LSTORE_3:u8 = 66; // (0x42) Store long into local variable 3 +pub const FSTORE_0:u8 = 67; // (0x43) Store float into local variable 0 +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 aastore: u8 = 83; // (0x53) // diff --git a/src/vm.rs b/src/vm.rs index 59071c6..fdf20b5 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -111,6 +111,7 @@ impl Vm { method_name: &str, args: Vec>>, ) -> Result>, Error> { + let mut local_params: Vec>>> = args.clone().iter().map(|e| Some(e.clone())).collect(); println!("execute {}.{}", class_name, method_name); let class = self.get_class(class_name)?; let method = class.get_method(method_name)?; @@ -237,20 +238,38 @@ impl Vm { // let index = self.local_stack().pop()?; // let array_ref = self.local_stack().pop()?; } - ISTORE => { - unsafe { - let index = read_u8(&code.opcodes, pc); - let value = self.local_stack().pop()?; - if let Value::I32(int) = *value.get() { - // TODO local vars + ISTORE | LSTORE | FSTORE | DSTORE | ASTORE => { + let index = read_u8(&code.opcodes, pc) as usize; + self.store(&mut local_params, index)?; + } + ISTORE_0 | LSTORE_0 | DSTORE_0 | ASTORE_0 | FSTORE_0 => { + 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 => { - self.local_stack().pop().expect("Stack empty"); + self.local_stack().pop()?; } DUP => { - let value = self.local_stack().pop().expect("Stack empty"); + let value = self.local_stack().pop()?; println!("{:?}", value); self.local_stack().push_arc(value.clone()); self.local_stack().push_arc(value); @@ -282,57 +301,51 @@ impl Vm { } } } - PUTFIELD => { - 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 => { + PUTFIELD => unsafe { let cp_index = read_u16(&code.opcodes, pc); - unsafe { - 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()); } - } + 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"); + } + } // else? } } } - 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()?); - } + INVOKEVIRTUAL => 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()?); - let mut returnvalue = self.execute(&invocation.class_name, &invocation.method.name, args)?; - match *returnvalue.get() { - Void => {} - _ => { self.local_stack().push_arc(returnvalue.clone()); } - } + } + 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()); } + } + } + } + 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") } + + fn store(&mut self, local_params: &mut Vec>>>, 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(()) + } }