From c821944fac4389ef8e77501ac0b44bf3647295fc Mon Sep 17 00:00:00 2001 From: Sander Hautvast Date: Sat, 30 Sep 2023 18:01:25 +0200 Subject: [PATCH] method invocations! --- src/class.rs | 10 ++++++++++ src/heap.rs | 34 ++++++++++++++++++++++++++++++---- src/opcodes.rs | 1 + src/vm.rs | 35 ++++++++++++++++++++++++++++------- tests/FloatBean.class | Bin 323 -> 282 bytes tests/FloatBean.java | 2 -- 6 files changed, 69 insertions(+), 13 deletions(-) diff --git a/src/class.rs b/src/class.rs index 541ea3b..92bc4d2 100644 --- a/src/class.rs +++ b/src/class.rs @@ -33,9 +33,19 @@ impl Class { .get(name) .ok_or(anyhow!("Method {} not found", name)) } + + pub fn get_name(&self) -> &str { + if let CpEntry::ClassRef(name_index ) = self.constant_pool.get(&self.this_class).unwrap(){ + if let CpEntry::Utf8(name) = self.constant_pool.get(name_index).unwrap(){ + return name; + } + } + panic!(); + } } unsafe impl Send for Class {} unsafe impl Sync for Class {} + pub struct Method { pub(crate) constant_pool: Rc>, access_flags: u16, diff --git a/src/heap.rs b/src/heap.rs index ddba19d..1c156d6 100644 --- a/src/heap.rs +++ b/src/heap.rs @@ -1,21 +1,47 @@ use crate::class::{Class, Value}; use std::collections::HashMap; +use std::fmt; use std::sync::Arc; +use crate::classloader::CpEntry; -#[derive(Debug)] pub struct Object { // locked: bool, // hashcode: i32, - _class: Arc, + pub class: Arc, pub data: HashMap>, //TODO optimize } unsafe impl Send for Object {} + unsafe impl Sync for Object {} impl Object { - pub fn new(_class: Arc, data: HashMap>) -> Self { - Self { _class, data } + pub fn new(class: Arc, data: HashMap>) -> Self { + Self { class, data } + } + + fn get_field(&self, cp_index: &u16) -> &str { + if let CpEntry::Utf8(name) = self.class.constant_pool.get(&cp_index).unwrap() { + return name; + } + panic!() + } +} + +impl fmt::Debug for Object { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let fields: Vec = self.data.iter().map(|(k, v)| { + let mut r: String = self.get_field(k).into(); + r.push(':'); + r.push_str(format!("{:?}", v).as_str()); + r + } + ).collect(); + write!( + f, + "{} {{ {:?} }}", + self.class.get_name(), fields + ) } } diff --git a/src/opcodes.rs b/src/opcodes.rs index e163d82..b517260 100644 --- a/src/opcodes.rs +++ b/src/opcodes.rs @@ -51,6 +51,7 @@ pub const ALOAD_0: &u8 = &42; // (0x2a) // pub const bastore:u8 = 84; // (0x54) // // pub const castore:u8 = 85; // (0x55) +pub const POP: &u8 = &87; // (0x57) Pop the top operand stack value pub const DUP: &u8 = &89; // (0x59) duplicate the top operand stack value // pub const dup_x1: u8 = 90; // (0x5a) Duplicate the top operand stack value and insert two values down // pub const dup_x2: u8 = 91; // (0x5b) Duplicate the top operand stack value and insert two or three values down diff --git a/src/vm.rs b/src/vm.rs index 934fda3..a3ebf2b 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -63,9 +63,9 @@ impl Vm { println!("get_class {}", class_name); let entry = self.classes.entry(class_name.into()); let entry = entry.or_insert_with(|| { - print!("read class {} ", class_name); + // print!("read class {} ", class_name); let resolved_path = find_class(&self.classpath, class_name).expect("Class not found"); - println!("full path {}", resolved_path); + // println!("full path {}", resolved_path); let bytecode = read_bytecode(resolved_path).unwrap(); Arc::new(load_class(bytecode).unwrap()) }); @@ -171,26 +171,35 @@ impl Vm { } } } + POP =>{ + self.local_stack().pop().expect("Stack empty"); + } DUP => { println!("DUP"); let value = self.local_stack().pop().expect("Stack empty"); + println!("{:?}", value); self.local_stack().push(value.clone()); self.local_stack().push(value); } IRETURN => { + println!("return I"); return self.local_stack().pop(); } DRETURN => { + println!("return D"); return self.local_stack().pop(); } FRETURN => { + println!("return F"); return self.local_stack().pop(); } RETURN_VOID => { + println!("return"); self.stack.pop(); - return Ok(Arc::new(Void)) + return Ok(Arc::new(Void)); } GETFIELD => { + println!("GETFIELD"); 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() @@ -201,22 +210,34 @@ impl Vm { method.constant_pool.get(name_and_type_index).unwrap() { let value = inst.data.get(name).unwrap(); - // println!("{:?}", value); + println!("{:?}", value); self.local_stack().push(value.clone()); } } } pc += 2; } - INVOKEVIRTUAL =>{ - //TODO implement + INVOKEVIRTUAL => { + let cp_index = read_u16(&code.opcodes, pc); + let instance = self.local_stack().pop().unwrap(); + if let Some((class, method)) = get_signature_for_invoke(Rc::clone(&method.constant_pool), cp_index) { + let return_value = self.execute(class.as_str(), method.as_str(), Some(instance))?; + if let Void = *return_value {} else { // not let? + self.local_stack().push(return_value); + } + } + + pc += 2; } INVOKESPECIAL => { println!("INVOKESPECIAL"); let cp_index = read_u16(&code.opcodes, pc); let instance = self.local_stack().pop().unwrap(); if let Some((class, method)) = get_signature_for_invoke(Rc::clone(&method.constant_pool), cp_index) { - self.execute(class.as_str(), method.as_str(), Some(instance)); + let return_value = self.execute(class.as_str(), method.as_str(), Some(instance))?; + if let Void = *return_value {} else { // not let? + self.local_stack().push(return_value); + } } pc += 2; diff --git a/tests/FloatBean.class b/tests/FloatBean.class index 748e4401f7024bd4a36d5be3ed85caaf8afda878..d24f713cb6caef45ef24b0712001b637c4b84998 100644 GIT binary patch delta 164 zcmX@iG>b{?)W2Q(7#JAL8HBkQSQz*@8JHOa*ck-b8H5-aSj!S~N>dpb7~Lk?N3yXq zaPTm&PMoKe&B(ySz{?_y7O^ delta 187 zcmbQmbePHh)W2Q(7#JAL8N|34SQvyj8JHP_*%?IG8AKTw7}J2*jgf)ZIX|zsBr&ff zEHS4vmBmSefq{{MwG70Ws20h_#lX$Oz&Wv1D}aeXih-4Z4JgYFG?R&e1Bf|+d=Q(F z0jLg0@&I|VK$;OqvubT;VB82~0PO&hAdMh4BLg1;Kak{^_+CsDA;AF@5&$Y-Vh{uX Db?Fsc diff --git a/tests/FloatBean.java b/tests/FloatBean.java index 977f0f8..a19b968 100644 --- a/tests/FloatBean.java +++ b/tests/FloatBean.java @@ -1,7 +1,5 @@ public class FloatBean { - private final static float f =42.0F; - private float value; public float getValue(){