diff --git a/src/heap.rs b/src/heap.rs index 4674255..e5464c5 100644 --- a/src/heap.rs +++ b/src/heap.rs @@ -20,7 +20,25 @@ pub enum ObjectRef { StringArray(Vec), ObjectArray(Type, Vec>>), Object(Box), - Class(Arc>) + Class(Arc>), +} + +impl ObjectRef { + pub fn get_array_length(&self) -> usize { + match self { + ByteArray(d) => d.len(), + ShortArray(d) => d.len(), + IntArray(d) => d.len(), + LongArray(d) => d.len(), + FloatArray(d) => d.len(), + DoubleArray(d) => d.len(), + BooleanArray(d) => d.len(), + CharArray(d) => d.len(), + StringArray(d) => d.len(), + ObjectArray(_, d) => d.len(), + _ => unreachable!("not an array") + } + } } fn into_vec_i8(v: Vec) -> Vec { diff --git a/src/opcodes.rs b/src/opcodes.rs index 99b29c5..cbac78f 100644 --- a/src/opcodes.rs +++ b/src/opcodes.rs @@ -286,7 +286,7 @@ pub const NEW: u8 = 187; // (0xbb) Create new object pub const ANEWARRAY: u8 = 189; // (0xbd) -pub const _ARRAYLENGTH: u8 = 190; +pub const ARRAYLENGTH: u8 = 190; // (0xbe) pub const _ATHROW: u8 = 191; // (0xbf) @@ -440,7 +440,7 @@ pub const OPCODES:Lazy> = Lazy::new(|| { opcodes[INVOKESTATIC as usize] = "INVOKESTATIC" ; opcodes[NEW as usize] = "NEW" ; opcodes[ANEWARRAY as usize] = "ANEWARRAY" ; - opcodes[_ARRAYLENGTH as usize] = "_ARRAYLENGTH" ; + opcodes[ARRAYLENGTH as usize] = "ARRAYLENGTH" ; opcodes[_ATHROW as usize] = "_ATHROW" ; opcodes[_CHECKCAST as usize] = "_CHECKCAST" ; opcodes[MONITORENTER as usize] = "MONITORENTER" ; diff --git a/src/vm.rs b/src/vm.rs index d3c1f65..1ba4cae 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -671,6 +671,15 @@ impl Vm { panic!(); } }, + ARRAYLENGTH => { + let val = self.current_frame().pop()?; + unsafe { + if let Ref(val) = &*val.get() { + let o = &*val.get(); + self.current_frame().push(I32(o.get_array_length() as i32)); + } + } + } MONITORENTER => { self.current_frame().pop()?; } //TODO implement @@ -734,10 +743,10 @@ impl Vm { if let I32(index) = &*value.get() { let index = *index as usize; let arrayref = self.current_frame().pop()?; - if let Value::Null = &*arrayref.get() { + if let Null = &*arrayref.get() { return Err(anyhow!("NullpointerException")); } - if let Value::Ref(objectref) = &*arrayref.get() { + if let Ref(objectref) = &*arrayref.get() { match &*objectref.get() { ObjectRef::ByteArray(array) => { self.current_frame().push(I32(array[index] as i32)); @@ -766,7 +775,7 @@ impl Vm { ObjectRef::ObjectArray(_arraytype, data) => { self.current_frame().push(Ref(data[index].clone())); } - ObjectRef::StringArray(array) =>{ + ObjectRef::StringArray(array) => { self.current_frame().push(Utf8(array[index].to_owned())); } ObjectRef::Class(_) => {