diff --git a/ristretto_vm/src/instruction/array.rs b/ristretto_vm/src/instruction/array.rs index 3602333d..c36b9cce 100644 --- a/ristretto_vm/src/instruction/array.rs +++ b/ristretto_vm/src/instruction/array.rs @@ -404,8 +404,33 @@ mod tests { Ok(()) } - // #[test] - // fn test_multianewarray() -> Result<()> { - // todo!() - // } + #[test] + fn test_multianewarray_single_dimension() -> Result<()> { + let (vm, mut call_stack, mut class) = crate::test::class()?; + let constant_pool = Arc::get_mut(&mut class).expect("class").constant_pool_mut(); + let class_index = constant_pool.add_class("java/lang/Object")?; + let method = Method::new( + MethodAccessFlags::STATIC, + "test", + "()V", + 10, + 10, + Vec::new(), + Vec::new(), + )?; + let arguments = Vec::new(); + let mut frame = Frame::new(&class, &Arc::new(method), arguments)?; + let stack = &mut frame.stack; + let class = frame.class; + + stack.push_int(0)?; + let result = multianewarray(&vm, &mut call_stack, stack, &class, class_index, 1)?; + assert_eq!(Continue, result); + let object = stack.pop()?; + assert!(matches!( + object, + Value::Object(Some(Reference::Array(_, _))) + )); + Ok(()) + } } diff --git a/ristretto_vm/src/instruction/field.rs b/ristretto_vm/src/instruction/field.rs index 19d721bb..a1c17929 100644 --- a/ristretto_vm/src/instruction/field.rs +++ b/ristretto_vm/src/instruction/field.rs @@ -4,7 +4,7 @@ use crate::operand_stack::OperandStack; use crate::Error::InvalidStackValue; use crate::Result; use ristretto_classfile::ConstantPool; -use ristretto_classloader::Reference; +use ristretto_classloader::{Reference, Value}; /// See: #[inline] @@ -13,8 +13,9 @@ pub(crate) fn getfield( constant_pool: &ConstantPool, index: u16, ) -> Result { - match stack.pop_object()? { - Some(Reference::Object(object)) => { + let value = stack.pop()?; + match value { + Value::Object(Some(Reference::Object(object))) => { let (_class_index, name_and_type_index) = constant_pool.try_get_field_ref(index)?; let (name_index, _descriptor_index) = constant_pool.try_get_name_and_type(*name_and_type_index)?; @@ -24,13 +25,9 @@ pub(crate) fn getfield( stack.push(value)?; Ok(Continue) } - Some(object) => Err(InvalidStackValue { - expected: "object".to_string(), - actual: object.to_string(), - }), - None => Err(InvalidStackValue { + _ => Err(InvalidStackValue { expected: "object".to_string(), - actual: "null".to_string(), + actual: value.to_string(), }), } } @@ -43,9 +40,9 @@ pub(crate) fn putfield( index: u16, ) -> Result { let value = stack.pop()?; - let mut object = stack.pop_object()?; - match object { - Some(Reference::Object(ref mut object)) => { + let mut object_value = stack.pop()?; + match object_value { + Value::Object(Some(Reference::Object(ref mut object))) => { let (_class_index, name_and_type_index) = constant_pool.try_get_field_ref(index)?; let (name_index, _descriptor_index) = constant_pool.try_get_name_and_type(*name_and_type_index)?; @@ -54,13 +51,9 @@ pub(crate) fn putfield( field.set_value(value)?; Ok(Continue) } - Some(object) => Err(InvalidStackValue { - expected: "object".to_string(), - actual: object.to_string(), - }), - None => Err(InvalidStackValue { + _ => Err(InvalidStackValue { expected: "object".to_string(), - actual: "null".to_string(), + actual: object_value.to_string(), }), } } @@ -153,7 +146,7 @@ mod test { assert!(matches!(result, Err(InvalidStackValue { expected, actual - }) if expected == "object" && actual == "null")); + }) if expected == "object" && actual == "object(null)")); Ok(()) } @@ -190,7 +183,7 @@ mod test { assert!(matches!(result, Err(InvalidStackValue { expected, actual - }) if expected == "object" && actual == "null")); + }) if expected == "object" && actual == "object(null)")); Ok(()) } diff --git a/ristretto_vm/src/instruction/object.rs b/ristretto_vm/src/instruction/object.rs index 20d46074..eab1b1f0 100644 --- a/ristretto_vm/src/instruction/object.rs +++ b/ristretto_vm/src/instruction/object.rs @@ -227,13 +227,13 @@ pub(crate) fn new( /// See: #[inline] pub(crate) fn checkcast(stack: &mut OperandStack, class_name: &str) -> Result { - let Value::Object(reference) = stack.peek()? else { + let Value::Object(object) = stack.peek()? else { return Err(RuntimeError("Expected object".to_string())); }; - if reference.is_none() { + let Some(object) = object else { return Ok(Continue); - } - if !is_instanceof(reference, class_name)? { + }; + if !is_instanceof(object, class_name)? { return Err(ClassCastError(class_name.to_string())); } Ok(Continue) @@ -243,10 +243,10 @@ pub(crate) fn checkcast(stack: &mut OperandStack, class_name: &str) -> Result Result { let object = stack.pop_object()?; - if object.is_none() { + let Some(object) = object else { stack.push_int(0)?; return Ok(Continue); - } + }; if is_instanceof(&object, class_name)? { stack.push_int(1)?; } else { @@ -256,11 +256,7 @@ pub(crate) fn instanceof(stack: &mut OperandStack, class_name: &str) -> Result, class_name: &str) -> Result { - let Some(object) = object else { - return Ok(false); - }; - +fn is_instanceof(object: &Reference, class_name: &str) -> Result { match object { Reference::ByteArray(_) | Reference::CharArray(_)