diff --git a/src/vm.rs b/src/vm.rs index d167263..a7cf744 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -50,7 +50,7 @@ impl StackFrame { pub struct Vm { pub classpath: Vec, heap: Heap, - stack: Vec, + stackframes: Vec, } #[cfg(target_family = "unix")] @@ -63,9 +63,9 @@ const PATH_SEPARATOR: char = ';'; //TODO goto //TODO error handling impl Vm { - fn local_stack(&mut self) -> &mut StackFrame { - let i = self.stack.len() - 1; - self.stack.get_mut(i).unwrap() + fn current_frame(&mut self) -> &mut StackFrame { + let i = self.stackframes.len() - 1; + self.stackframes.get_mut(i).unwrap() } pub fn new(classpath: &'static str) -> Self { @@ -75,7 +75,7 @@ impl Vm { .map(|s| s.to_owned()) .collect(), heap: Heap::new(), - stack: vec![], + stackframes: vec![], } } @@ -115,80 +115,81 @@ impl Vm { } if let AttributeType::Code(code) = method.attributes.get("Code").unwrap() { let stackframe = StackFrame::new(&this_class.borrow().name, &method.name()); - self.stack.push(stackframe); + self.stackframes.push(stackframe); let mut pc = &mut 0; while *pc < code.opcodes.len() { let opcode = read_u8(&code.opcodes, pc); - println!("stack {} opcode {} ", self.local_stack().len(), opcode); + println!("stack {} opcode {} ", self.current_frame().len(), opcode); match opcode { ACONST_NULL => { - self.local_stack().push(Value::Null); + self.current_frame().push(Value::Null); } ICONST_M1 => { - self.local_stack().push(Value::I32(-1)); + self.current_frame().push(Value::I32(-1)); } ICONST_0 => { println!("ICONST_0"); - self.local_stack().push(Value::I32(0)); + self.current_frame().push(Value::I32(0)); } ICONST_1 => { - self.local_stack().push(Value::I32(1)); + self.current_frame().push(Value::I32(1)); } ICONST_2 => { - self.local_stack().push(Value::I32(2)); + self.current_frame().push(Value::I32(2)); } ICONST_3 => { - self.local_stack().push(Value::I32(3)); + self.current_frame().push(Value::I32(3)); } ICONST_4 => { - self.local_stack().push(Value::I32(4)); + self.current_frame().push(Value::I32(4)); } ICONST_5 => { - self.local_stack().push(Value::I32(5)); + self.current_frame().push(Value::I32(5)); } LCONST_0 => { - self.local_stack().push(Value::I64(0)); + self.current_frame().push(Value::I64(0)); } LCONST_1 => { - self.local_stack().push(Value::I64(1)); + self.current_frame().push(Value::I64(1)); } FCONST_0 => { - self.local_stack().push(Value::F32(0.0)); + self.current_frame().push(Value::F32(0.0)); } FCONST_1 => { - self.local_stack().push(Value::F32(1.0)); + self.current_frame().push(Value::F32(1.0)); } FCONST_2 => { - self.local_stack().push(Value::F32(2.0)); + self.current_frame().push(Value::F32(2.0)); } DCONST_0 => { - self.local_stack().push(Value::F64(0.0)); + self.current_frame().push(Value::F64(0.0)); } DCONST_1 => { - self.local_stack().push(Value::F64(1.0)); + self.current_frame().push(Value::F64(1.0)); } SIPUSH => { let s = read_u16(&code.opcodes, pc) as i32; - self.local_stack().push(Value::I32(s)); + self.current_frame().push(Value::I32(s)); } BIPUSH => { let c = read_u8(&code.opcodes, pc) as i32; - self.local_stack().push(Value::I32(c)); + self.current_frame().push(Value::I32(c)); } LDC => { + println!("LDC"); let cp_index = read_u8(&code.opcodes, pc) as u16; let c = method.constant_pool.get(&cp_index).unwrap(); println!("{:?}", c); match c { CpEntry::Integer(i) => { - self.local_stack().push(Value::I32(*i)); + self.current_frame().push(Value::I32(*i)); } CpEntry::Float(f) => { - self.local_stack().push(Value::F32(*f)); + self.current_frame().push(Value::F32(*f)); } CpEntry::Double(d) => { - self.local_stack().push(Value::F64(*d)); + self.current_frame().push(Value::F64(*d)); } CpEntry::StringRef(utf8) => { //TODO @@ -198,22 +199,23 @@ impl Vm { )))); 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)); + self.current_frame().push(Value::Ref(stringinstance)); } CpEntry::Long(l) => { - self.local_stack().push(Value::I64(*l)); + self.current_frame().push(Value::I64(*l)); } _ => {} } } LDC_W => { + println!("LDC_W"); let cp_index = read_u16(&code.opcodes, pc); match method.constant_pool.get(&cp_index).unwrap() { CpEntry::Integer(i) => { - self.local_stack().push(Value::I32(*i)); + self.current_frame().push(Value::I32(*i)); } CpEntry::Float(f) => { - self.local_stack().push(Value::F32(*f)); + self.current_frame().push(Value::F32(*f)); } _ => { panic!("unexpected") @@ -221,13 +223,14 @@ impl Vm { } } LDC2_W => { + println!("LDC2_W"); let cp_index = read_u16(&code.opcodes, pc); match method.constant_pool.get(&cp_index).unwrap() { CpEntry::Double(d) => { - self.local_stack().push(Value::F64(*d)); + self.current_frame().push(Value::F64(*d)); } CpEntry::Long(l) => { - self.local_stack().push(Value::I64(*l)); + self.current_frame().push(Value::I64(*l)); } _ => { panic!("unexpected") @@ -237,23 +240,24 @@ impl Vm { ILOAD | LLOAD | FLOAD | DLOAD | ALOAD => { // omitting the type checks so far let n = read_u8(&code.opcodes, pc) as usize; - self.local_stack() + self.current_frame() .push_arc(local_params[n].as_ref().unwrap().clone()); } ILOAD_0 | LLOAD_0 | FLOAD_0 | DLOAD_0 | ALOAD_0 => { - self.local_stack() + println!("LOAD"); + self.current_frame() .push_arc(local_params[0].as_ref().unwrap().clone()); } ILOAD_1 | LLOAD_1 | FLOAD_1 | DLOAD_1 | ALOAD_1 => { - self.local_stack() + self.current_frame() .push_arc(local_params[1].as_ref().unwrap().clone()); } ILOAD_2 | LLOAD_2 | FLOAD_2 | DLOAD_2 | ALOAD_2 => { - self.local_stack() + self.current_frame() .push_arc(local_params[2].as_ref().unwrap().clone()); } ILOAD_3 | LLOAD_3 | FLOAD_3 | DLOAD_3 | ALOAD_3 => { - self.local_stack() + self.current_frame() .push_arc(local_params[3].as_ref().unwrap().clone()); } IALOAD | LALOAD | FALOAD | DALOAD | AALOAD | BALOAD | CALOAD | SALOAD => unsafe { @@ -267,6 +271,7 @@ impl Vm { self.store(&mut local_params, 0)?; } ISTORE_1 | LSTORE_1 | DSTORE_1 | ASTORE_1 | FSTORE_1 => { + println!("STORE"); self.store(&mut local_params, 1)?; } ISTORE_2 | LSTORE_2 | DSTORE_2 | ASTORE_2 | FSTORE_2 => { @@ -278,19 +283,23 @@ impl Vm { BASTORE | IASTORE | LASTORE | CASTORE | SASTORE | FASTORE | DASTORE | AASTORE => unsafe { self.array_store()? }, POP => { - self.local_stack().pop()?; + self.current_frame().pop()?; } DUP => { - let value = self.local_stack().pop()?; + let value = self.current_frame().pop()?; println!("{:?}", value); - self.local_stack().push_arc(value.clone()); - self.local_stack().push_arc(value); + self.current_frame().push_arc(value.clone()); + self.current_frame().push_arc(value); } IRETURN | FRETURN | DRETURN => { - return self.local_stack().pop(); + println!("RETURN"); + let result = self.current_frame().pop(); + self.stackframes.pop(); + return result; } RETURN_VOID => { - println!("RETURN"); + println!("RETURN void"); + self.stackframes.pop(); return Ok(Value::void()); } GETSTATIC => { @@ -307,7 +316,7 @@ impl Vm { let that_borrow = that.borrow(); let (_, val_index) = that_borrow.static_field_mapping.get(that_class_name).unwrap().get(name).unwrap(); println!("get static field {}", name); - self.local_stack().push_arc(borrow.static_data.get(*val_index).unwrap().as_ref().unwrap().clone()); + self.current_frame().push_arc(borrow.static_data.get(*val_index).unwrap().as_ref().unwrap().clone()); } PUTSTATIC => { println!("PUTSTATIC"); @@ -324,13 +333,13 @@ impl Vm { 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()?; + let value = self.current_frame().pop()?; borrow.static_data[val_index] = Some(value); } else { let that = get_class(self, Some(&borrow.name), that_class_name.as_str())?; let that_borrow = that.borrow(); // if already borrowed, then that_class == this_class let (_, val_index) = that_borrow.static_field_mapping.get(that_class_name).unwrap().get(name).unwrap(); - let value = self.local_stack().pop()?; + let value = self.current_frame().pop()?; borrow.static_data[*val_index] = Some(value); } } @@ -345,11 +354,11 @@ impl Vm { let class_name = borrow.cp_utf8(class_name_index).unwrap(); let field_name = borrow.cp_utf8(field_name_index).unwrap(); - let mut objectref = self.local_stack().pop()?; + let mut objectref = self.current_frame().pop()?; if let Value::Ref(instance) = &mut *objectref.get() { if let ObjectRef::Object(ref mut object) = &mut *instance.get() { let value = object.get(class_name, field_name); - self.local_stack().push_arc(Arc::clone(value)); + self.current_frame().push_arc(Arc::clone(value)); } } }, @@ -364,8 +373,8 @@ impl Vm { let class_name = borrow.cp_utf8(class_name_index).unwrap(); let field_name = borrow.cp_utf8(field_name_index).unwrap(); - let value = self.local_stack().pop()?; - let mut objectref = self.local_stack().pop()?; + let value = self.current_frame().pop()?; + let mut objectref = self.current_frame().pop()?; if let Value::Ref(instance) = &mut *objectref.get() { if let ObjectRef::Object(ref mut object) = &mut *instance.get() { object.set(class_name, field_name, value); @@ -381,9 +390,9 @@ impl Vm { { 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.current_frame().pop()?); } - args.insert(0, self.local_stack().pop()?); + args.insert(0, self.current_frame().pop()?); let mut return_value = self.execute( Some(this_class.borrow().name.as_str()), &invocation.class_name, @@ -393,9 +402,10 @@ impl Vm { match *return_value.get() { Void => {} _ => { - self.local_stack().push_arc(return_value.clone()); + self.current_frame().push_arc(return_value.clone()); } } + println!("stack {} at {}", self.current_frame().len(), self.current_frame().at) } }, INVOKESTATIC => unsafe { @@ -405,7 +415,7 @@ impl Vm { { 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.current_frame().pop()?); } let mut returnvalue = self.execute( Some(this_class.borrow().name.as_str()), @@ -416,7 +426,7 @@ impl Vm { match *returnvalue.get() { Void => {} _ => { - self.local_stack().push_arc(returnvalue.clone()); + self.current_frame().push_arc(returnvalue.clone()); } } } @@ -432,7 +442,7 @@ impl Vm { let object = Arc::new(UnsafeCell::new(ObjectRef::Object(Box::new( Vm::new_instance(class_to_instantiate), )))); - self.local_stack().push(Value::Ref(Arc::clone(&object))); + self.current_frame().push(Value::Ref(Arc::clone(&object))); self.heap.new_object(object); } ANEWARRAY => unsafe{ @@ -442,13 +452,13 @@ impl Vm { 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()?; + let count = self.current_frame().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.current_frame().push(Value::Ref(Arc::clone(&array))); + println!("{}",self.current_frame().len()); self.heap.new_object(array); } else { panic!(); @@ -458,7 +468,7 @@ impl Vm { //TODO implement all opcodes _ => { - panic!("opcode not implemented {:?}", self.stack) + panic!("opcode not implemented {:?}", self.stackframes) //TODO implement proper --stacktraces-- error handling } } @@ -468,40 +478,40 @@ impl Vm { } unsafe fn array_load(&mut self) -> Result<(), Error> { - if let Value::I32(index) = &*self.local_stack().pop()?.get() { + if let Value::I32(index) = &*self.current_frame().pop()?.get() { let index = *index as usize; - let arrayref = &*self.local_stack().pop()?.get(); + let arrayref = &*self.current_frame().pop()?.get(); if let Value::Null = arrayref { return Err(anyhow!("NullpointerException")); } if let Value::Ref(ref objectref) = arrayref { match &*objectref.get() { ObjectRef::ByteArray(ref array) => { - self.local_stack().push(Value::I32(array[index] as i32)); + self.current_frame().push(Value::I32(array[index] as i32)); } ObjectRef::ShortArray(ref array) => { - self.local_stack().push(Value::I32(array[index] as i32)); + self.current_frame().push(Value::I32(array[index] as i32)); } ObjectRef::IntArray(ref array) => { - self.local_stack().push(Value::I32(array[index])); + self.current_frame().push(Value::I32(array[index])); } ObjectRef::BooleanArray(ref array) => { - self.local_stack().push(Value::I32(array[index] as i32)); + self.current_frame().push(Value::I32(array[index] as i32)); } ObjectRef::CharArray(ref array) => { - self.local_stack().push(Value::CHAR(array[index])); + self.current_frame().push(Value::CHAR(array[index])); } ObjectRef::LongArray(ref array) => { - self.local_stack().push(Value::I64(array[index])); + self.current_frame().push(Value::I64(array[index])); } ObjectRef::FloatArray(ref array) => { - self.local_stack().push(Value::F32(array[index])); + self.current_frame().push(Value::F32(array[index])); } ObjectRef::DoubleArray(ref array) => { - self.local_stack().push(Value::F64(array[index])); + self.current_frame().push(Value::F64(array[index])); } ObjectRef::ObjectArray(_arraytype, ref data) => { - self.local_stack() + self.current_frame() .push(Value::Ref(data[index].clone())); } ObjectRef::Object(_) => {} //throw error? @@ -512,9 +522,9 @@ impl Vm { } unsafe fn array_store(&mut self) -> Result<(), Error> { - let value = self.local_stack().pop()?; - let index = &mut *self.local_stack().pop()?.get(); - let mut arrayref = &mut *self.local_stack().pop()?.get(); + let value = self.current_frame().pop()?; + let index = &mut *self.current_frame().pop()?.get(); + let mut arrayref = &mut *self.current_frame().pop()?.get(); if let Value::Null = arrayref { return Err(anyhow!("NullpointerException")); @@ -582,7 +592,7 @@ impl Vm { local_params: &mut Vec>, index: usize, ) -> Result<(), Error> { - let value = self.local_stack().pop()?; + let value = self.current_frame().pop()?; while local_params.len() < index + 1 { local_params.push(None); } diff --git a/tests/Main.class b/tests/Main.class index 0578c20..7d29e53 100644 Binary files a/tests/Main.class and b/tests/Main.class differ diff --git a/tests/Main.java b/tests/Main.java index 6c23145..cb3d6d5 100644 --- a/tests/Main.java +++ b/tests/Main.java @@ -1,9 +1,9 @@ public class Main { - final static String a; + final static int a; static{ - a=""; + a=1; } public static void main(String[] args){