Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 29 additions & 4 deletions ristretto_vm/src/instruction/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(())
}
}
33 changes: 13 additions & 20 deletions ristretto_vm/src/instruction/field.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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: <https://docs.oracle.com/javase/specs/jvms/se23/html/jvms-6.html#jvms-6.5.getfield>
#[inline]
Expand All @@ -13,8 +13,9 @@ pub(crate) fn getfield(
constant_pool: &ConstantPool,
index: u16,
) -> Result<ExecutionResult> {
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)?;
Expand All @@ -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(),
}),
}
}
Expand All @@ -43,9 +40,9 @@ pub(crate) fn putfield(
index: u16,
) -> Result<ExecutionResult> {
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)?;
Expand All @@ -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(),
}),
}
}
Expand Down Expand Up @@ -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(())
}
Expand Down Expand Up @@ -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(())
}
Expand Down
18 changes: 7 additions & 11 deletions ristretto_vm/src/instruction/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -227,13 +227,13 @@ pub(crate) fn new(
/// See: <https://docs.oracle.com/javase/specs/jvms/se23/html/jvms-6.html#jvms-6.5.checkcast>
#[inline]
pub(crate) fn checkcast(stack: &mut OperandStack, class_name: &str) -> Result<ExecutionResult> {
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)
Expand All @@ -243,10 +243,10 @@ pub(crate) fn checkcast(stack: &mut OperandStack, class_name: &str) -> Result<Ex
#[inline]
pub(crate) fn instanceof(stack: &mut OperandStack, class_name: &str) -> Result<ExecutionResult> {
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 {
Expand All @@ -256,11 +256,7 @@ pub(crate) fn instanceof(stack: &mut OperandStack, class_name: &str) -> Result<E
}

#[inline]
fn is_instanceof(object: &Option<Reference>, class_name: &str) -> Result<bool> {
let Some(object) = object else {
return Ok(false);
};

fn is_instanceof(object: &Reference, class_name: &str) -> Result<bool> {
match object {
Reference::ByteArray(_)
| Reference::CharArray(_)
Expand Down