From 8f6651e303ef8f2351e50fb58b41248aa6385e30 Mon Sep 17 00:00:00 2001 From: Sander Hautvast Date: Tue, 17 Oct 2023 12:06:24 +0200 Subject: [PATCH] WIP Strings --- src/class.rs | 2 ++ src/classloader.rs | 3 ++- src/heap.rs | 24 ++++++++++++++++------- src/vm.rs | 46 +++++++++++++++++++++++++++++++++++++-------- tests/Main.class | Bin 584 -> 436 bytes tests/Main.java | 2 +- 6 files changed, 60 insertions(+), 17 deletions(-) diff --git a/src/class.rs b/src/class.rs index a557b57..2710acb 100644 --- a/src/class.rs +++ b/src/class.rs @@ -540,6 +540,7 @@ pub enum Value { BOOL(bool), CHAR(char), Ref(Arc>), + Utf8(String) } impl Value { @@ -555,6 +556,7 @@ impl Into for Value { } pub type UnsafeValue = Arc>; +pub type Type = Arc>; unsafe impl Send for Value {} diff --git a/src/classloader.rs b/src/classloader.rs index c6ca86b..4becf48 100644 --- a/src/classloader.rs +++ b/src/classloader.rs @@ -226,7 +226,7 @@ fn read_attribute( *index += attribute_length; if let CpEntry::Utf8(s) = &constant_pool.get(&attribute_name_index).unwrap() { - println!("Att [{}]", s); + // println!("Att [{}]", s); return match s.as_str() { "ConstantValue" => { assert_eq!(info.len(), 2); @@ -274,6 +274,7 @@ fn read_attribute( "BootstrapMethods" => Some(("".into(), AttributeType::BootstrapMethods)), //stub "InnerClasses" => Some(("".into(), AttributeType::InnerClasses)), //stub "Signature" => Some(("".into(), AttributeType::Signature)), //stub + "NestHost" => Some(("".into(), AttributeType::NestHost)), //stub //TODO more actual attribute implementations _ => None, }; diff --git a/src/heap.rs b/src/heap.rs index 4ddedce..cbf2707 100644 --- a/src/heap.rs +++ b/src/heap.rs @@ -1,9 +1,9 @@ use std::cell::{RefCell, UnsafeCell}; use std::fmt; -use std::ops::Deref; use std::sync::Arc; -use crate::class::{Class, UnsafeValue, Value}; +use crate::class::{Class, Type, UnsafeValue, Value}; +use crate::heap::ObjectRef::{IntArray, ObjectArray}; // can contain object or array #[derive(Debug)] @@ -16,10 +16,20 @@ pub enum ObjectRef { DoubleArray(Vec), BooleanArray(Vec), CharArray(Vec), - ObjectArray(Vec>>), + ObjectArray(Type, Vec>>), Object(Box), } +impl ObjectRef { + pub fn new_object_array(class: Type, size: usize) -> Self { + ObjectArray(class, Vec::with_capacity(size)) + } + + pub fn new_int_array(size: usize) -> Self { + IntArray(Vec::with_capacity(size)) + } +} + // trying to implement efficient object instance storage pub struct Object { // locked: bool, @@ -66,8 +76,8 @@ impl Object { } pub fn set(&mut self, class_name: &String, field_name: &String, value: UnsafeValue) { - let borrow = self.class.borrow(); - let (_type, index) =borrow + let borrow = self.class.borrow(); + let (_type, index) = borrow .object_field_mapping .get(class_name) .unwrap() @@ -77,8 +87,8 @@ impl Object { } pub fn get(&mut self, class_name: &String, field_name: &String) -> &UnsafeValue { - let borrow = self.class.borrow(); - let (_type, index) =borrow + let borrow = self.class.borrow(); + let (_type, index) = borrow .object_field_mapping .get(class_name) .unwrap() diff --git a/src/vm.rs b/src/vm.rs index 84191d0..d167263 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -129,6 +129,7 @@ impl Vm { self.local_stack().push(Value::I32(-1)); } ICONST_0 => { + println!("ICONST_0"); self.local_stack().push(Value::I32(0)); } ICONST_1 => { @@ -190,8 +191,14 @@ impl Vm { self.local_stack().push(Value::F64(*d)); } CpEntry::StringRef(utf8) => { - let string = get_class(self, Some(&this_class.borrow().name), "java/lang/String").unwrap(); - self.local_stack().push(Value::Ref(Arc::new(UnsafeCell::new(ObjectRef::Object(Box::new(Object::new(string))))))) + //TODO + let stringclass = get_class(self, Some(&this_class.borrow().name), "java/lang/String").unwrap(); + let stringinstance = Arc::new(UnsafeCell::new(ObjectRef::Object(Box::new( + Vm::new_instance(stringclass.clone()), + )))); + let string = this_class.borrow().cp_utf8(utf8).unwrap().to_owned(); + let s = self.execute_class(stringclass, "", vec![Arc::new(UnsafeCell::new(Value::Utf8(string)))])?; + self.local_stack().push(Value::Ref(stringinstance)); } CpEntry::Long(l) => { self.local_stack().push(Value::I64(*l)); @@ -283,7 +290,7 @@ impl Vm { return self.local_stack().pop(); } RETURN_VOID => { - self.stack.pop(); // Void is also returned as a value + println!("RETURN"); return Ok(Value::void()); } GETSTATIC => { @@ -303,7 +310,7 @@ impl Vm { self.local_stack().push_arc(borrow.static_data.get(*val_index).unwrap().as_ref().unwrap().clone()); } PUTSTATIC => { - println!("putstatic"); + println!("PUTSTATIC"); let mut borrow = this_class.borrow_mut(); let cp_index = read_u16(&code.opcodes, pc); let (class_index, field_name_and_type_index) = @@ -314,7 +321,7 @@ impl Vm { println!("field {}", name); let that_class_name = borrow.cp_utf8(class_name_index).unwrap(); - if &borrow.name == that_class_name { + if &borrow.name == that_class_name {// may have to apply this in GETSTATIC too let (_, val_index) = borrow.static_field_mapping.get(that_class_name).unwrap().get(name).as_ref().unwrap(); let val_index = *val_index; let value = self.local_stack().pop()?; @@ -366,6 +373,8 @@ impl Vm { } }, INVOKEVIRTUAL | INVOKESPECIAL => unsafe { + println!("INVOKE"); + // TODO differentiate these opcodes let cp_index = read_u16(&code.opcodes, pc); if let Some(invocation) = get_signature_for_invoke(&method.constant_pool, cp_index) @@ -413,6 +422,7 @@ impl Vm { } }, NEW => { + println!("NEW"); let class_index = &read_u16(&code.opcodes, pc); let borrow = this_class.borrow(); let class_name_index = borrow.cp_class_ref(class_index).unwrap(); @@ -425,6 +435,26 @@ impl Vm { self.local_stack().push(Value::Ref(Arc::clone(&object))); self.heap.new_object(object); } + ANEWARRAY => unsafe{ + println!("ANEWARRAY"); + let class_index = &read_u16(&code.opcodes, pc); + let borrow = this_class.borrow(); + let class_name_index = borrow.cp_class_ref(class_index).unwrap(); + let class_name = borrow.cp_utf8(class_name_index).unwrap(); + let arraytype = get_class(self, Some(&borrow.name), class_name)?; + let count = self.local_stack().pop()?; + if let Value::I32(count) = *count.get(){ // why does pop()?.get() give weird results? + let array = ObjectRef::new_object_array(arraytype, count as usize); + let array = Arc::new(UnsafeCell::new(array)); + + self.local_stack().push(Value::Ref(Arc::clone(&array))); + println!("{}",self.local_stack().len()); + self.heap.new_object(array); + } else { + panic!(); + } + + } //TODO implement all opcodes _ => { @@ -470,9 +500,9 @@ impl Vm { ObjectRef::DoubleArray(ref array) => { self.local_stack().push(Value::F64(array[index])); } - ObjectRef::ObjectArray(ref array) => { + ObjectRef::ObjectArray(_arraytype, ref data) => { self.local_stack() - .push(Value::Ref(array.get(index).unwrap().clone())); + .push(Value::Ref(data[index].clone())); } ObjectRef::Object(_) => {} //throw error? } @@ -535,7 +565,7 @@ impl Vm { array[*index as usize] = value } } - ObjectRef::ObjectArray(ref mut array) => { + ObjectRef::ObjectArray(arraytype, ref mut array) => { if let Value::Ref(ref value) = *value.get() { array[*index as usize] = value.clone(); } diff --git a/tests/Main.class b/tests/Main.class index 7474a5acaec0324e49e8bb3ef12c9c71f9efec23..0578c208d4267964b99293e5544e85eadcc1c480 100644 GIT binary patch delta 271 zcmYL^yKcfj5Jit)tPREl^9V^G5>zN4QPNRRQ1JsPDbgWm(o<6NDTpXYAf=A-L6i}9 zErgrdyEFGO^Xq?kqrd;t4>0DnNJPWXEaKAer+u*KF{Bj{@?>~6yzD01c1+nJnl0Ch z&*{fv71O5UKrDV~cNuQziXX|;p=EnQp0H%9iGCfu5)ix{arPOpqFTtBvgU#6jXKf_ zu4a`p?)wpMK1ls{7o1G2$1` literal 584 zcmZWnO;5r=6r6=ZORa!K5L8r9w1CRdgXjShPWX{vNQ|ciH>9Mr28xM4OHClr#2?^~ zGQLG38ZXFLF-2Ln&+^hB!6qj>r9);I4rk6jbaQ*n?%D zh?0u3fqfJhDC8odBrE9*@wxNMc29JC5*!M@#hsD#X4R#IU!dmW&=-9Q<&6lM{I+a+ zl`Bf^Q+C1olwIrojG**&hQw6nFOEUImn_Fcj=rctTVO~_cT@$brc`t;(Jf0)vW`$` z0`@conskPzO-hagmS@lt+EjqvW!@0DnIPCGo5~oWXN1dRsAFhzx(S7VIy6#`%H@-` ehUAZGemb6H%*YG$IZyr!Qal8e5GkqySos3r@@9Sj diff --git a/tests/Main.java b/tests/Main.java index 8f08233..6c23145 100644 --- a/tests/Main.java +++ b/tests/Main.java @@ -9,6 +9,6 @@ public class Main { public static void main(String[] args){ FloatBean f = new FloatBean(); f.setValue(42F); - System.out.println(f.getValue()); + } }