newarray
This commit is contained in:
parent
3f7e2e2786
commit
2f7442228b
6 changed files with 52 additions and 15 deletions
25
src/class.rs
25
src/class.rs
|
|
@ -119,11 +119,36 @@ impl ObjectRef {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum ArrayType {
|
||||||
|
BOOLEAN = 4,
|
||||||
|
CHAR = 5,
|
||||||
|
FLOAT = 6,
|
||||||
|
DOUBLE = 7,
|
||||||
|
BYTE = 8,
|
||||||
|
SHORT = 9,
|
||||||
|
INT = 10,
|
||||||
|
LONG = 11,
|
||||||
|
}
|
||||||
|
|
||||||
impl ObjectRef {
|
impl ObjectRef {
|
||||||
pub fn new_object_array(class: &Class, size: usize) -> Self {
|
pub fn new_object_array(class: &Class, size: usize) -> Self {
|
||||||
ObjectArray(class.id, Vec::with_capacity(size))
|
ObjectArray(class.id, Vec::with_capacity(size))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn new_array(arraytype: u8, size: usize) -> Self {
|
||||||
|
match arraytype {
|
||||||
|
8 => ByteArray(Vec::with_capacity(size)),
|
||||||
|
9 => ShortArray(Vec::with_capacity(size)),
|
||||||
|
10 => IntArray(Vec::with_capacity(size)),
|
||||||
|
11 => LongArray(Vec::with_capacity(size)),
|
||||||
|
6 => FloatArray(Vec::with_capacity(size)),
|
||||||
|
7 => DoubleArray(Vec::with_capacity(size)),
|
||||||
|
4 => BooleanArray(Vec::with_capacity(size)),
|
||||||
|
5 => CharArray(Vec::with_capacity(size)),
|
||||||
|
_ => unreachable!("impossible array type")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn new_int_array(size: usize) -> Self {
|
pub fn new_int_array(size: usize) -> Self {
|
||||||
IntArray(Vec::with_capacity(size))
|
IntArray(Vec::with_capacity(size))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -146,7 +146,6 @@ impl ClassManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_classdef(&self, id: &ClassId) -> &ClassDef {
|
fn get_classdef(&self, id: &ClassId) -> &ClassDef {
|
||||||
debug!("get_classdef {}", *id);
|
|
||||||
self.classdefs.get(&id).unwrap()
|
self.classdefs.get(&id).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ use anyhow::{anyhow, Error};
|
||||||
use crate::class::ObjectRef;
|
use crate::class::ObjectRef;
|
||||||
use crate::class::Value::{self, *};
|
use crate::class::Value::{self, *};
|
||||||
|
|
||||||
|
|
||||||
pub(crate) fn array_load(index: Value, arrayref: Value) -> Result<Value, Error> {
|
pub(crate) fn array_load(index: Value, arrayref: Value) -> Result<Value, Error> {
|
||||||
if let I32(index) = index {
|
if let I32(index) = index {
|
||||||
let index = index as usize;
|
let index = index as usize;
|
||||||
|
|
@ -92,7 +93,7 @@ pub(crate) fn array_store(value: Value, index: Value, arrayref: Value) -> Result
|
||||||
unreachable!()
|
unreachable!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ObjectRef::CharArray(ref mut array) => unsafe{
|
ObjectRef::CharArray(ref mut array) => unsafe {
|
||||||
if let I32(value) = value {
|
if let I32(value) = value {
|
||||||
array[index as usize] = char::from_u32_unchecked(value as u32);
|
array[index as usize] = char::from_u32_unchecked(value as u32);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -190,6 +190,7 @@ pub const _DUP2_X1: u8 = 93;
|
||||||
//(0x5d) Duplicate the top one or two operand stack values and insert two or three values down
|
//(0x5d) Duplicate the top one or two operand stack values and insert two or three values down
|
||||||
pub const _DUP2_X2: u8 = 94; // (0x5e) Duplicate the top one or two operand stack values and insert two, three, or four values down
|
pub const _DUP2_X2: u8 = 94; // (0x5e) Duplicate the top one or two operand stack values and insert two, three, or four values down
|
||||||
|
|
||||||
|
pub const IADD:u8 = 96;
|
||||||
pub const _FADD: u8 = 98;
|
pub const _FADD: u8 = 98;
|
||||||
// (0x62) Add float
|
// (0x62) Add float
|
||||||
pub const _DADD: u8 = 99; // (0x63) add double
|
pub const _DADD: u8 = 99; // (0x63) add double
|
||||||
|
|
@ -212,6 +213,7 @@ pub const _FNEG: u8 = 118;
|
||||||
// (0x76) Negate float
|
// (0x76) Negate float
|
||||||
pub const _DNEG: u8 = 119; // (0x77) Negate double
|
pub const _DNEG: u8 = 119; // (0x77) Negate double
|
||||||
|
|
||||||
|
pub const ISHR:u8 = 122;
|
||||||
pub const _F2I: u8 = 139;
|
pub const _F2I: u8 = 139;
|
||||||
// (0x8b) Convert float to int
|
// (0x8b) Convert float to int
|
||||||
pub const _F2L: u8 = 140;
|
pub const _F2L: u8 = 140;
|
||||||
|
|
@ -284,6 +286,7 @@ pub const INVOKESTATIC: u8 = 184;
|
||||||
// (0xb8) Invoke a class (static) method
|
// (0xb8) Invoke a class (static) method
|
||||||
pub const NEW: u8 = 187;
|
pub const NEW: u8 = 187;
|
||||||
// (0xbb) Create new object
|
// (0xbb) Create new object
|
||||||
|
pub const NEWARRAY:u8 = 188;
|
||||||
pub const ANEWARRAY: u8 = 189;
|
pub const ANEWARRAY: u8 = 189;
|
||||||
// (0xbd)
|
// (0xbd)
|
||||||
pub const ARRAYLENGTH: u8 = 190;
|
pub const ARRAYLENGTH: u8 = 190;
|
||||||
|
|
@ -393,6 +396,7 @@ pub const OPCODES:Lazy<Vec<&str>> = Lazy::new(|| {
|
||||||
opcodes[_DUP2 as usize] = "_DUP2" ;
|
opcodes[_DUP2 as usize] = "_DUP2" ;
|
||||||
opcodes[_DUP2_X1 as usize] = "_DUP2_X1" ;
|
opcodes[_DUP2_X1 as usize] = "_DUP2_X1" ;
|
||||||
opcodes[_DUP2_X2 as usize] = "_DUP2_X2" ;
|
opcodes[_DUP2_X2 as usize] = "_DUP2_X2" ;
|
||||||
|
opcodes[IADD as usize] = "IADD";
|
||||||
opcodes[_FADD as usize] = "_FADD" ;
|
opcodes[_FADD as usize] = "_FADD" ;
|
||||||
opcodes[_DADD as usize] = "_DADD" ;
|
opcodes[_DADD as usize] = "_DADD" ;
|
||||||
opcodes[_DSUB as usize] = "_DSUB" ;
|
opcodes[_DSUB as usize] = "_DSUB" ;
|
||||||
|
|
@ -405,6 +409,7 @@ pub const OPCODES:Lazy<Vec<&str>> = Lazy::new(|| {
|
||||||
opcodes[_DREM as usize] = "_DREM" ;
|
opcodes[_DREM as usize] = "_DREM" ;
|
||||||
opcodes[_FNEG as usize] = "_FNEG" ;
|
opcodes[_FNEG as usize] = "_FNEG" ;
|
||||||
opcodes[_DNEG as usize] = "_DNEG" ;
|
opcodes[_DNEG as usize] = "_DNEG" ;
|
||||||
|
opcodes[ISHR as usize] = "ISHR" ;
|
||||||
opcodes[_F2I as usize] = "_F2I" ;
|
opcodes[_F2I as usize] = "_F2I" ;
|
||||||
opcodes[_F2L as usize] = "_F2L" ;
|
opcodes[_F2L as usize] = "_F2L" ;
|
||||||
opcodes[_F2D as usize] = "_F2D" ;
|
opcodes[_F2D as usize] = "_F2D" ;
|
||||||
|
|
@ -441,6 +446,7 @@ pub const OPCODES:Lazy<Vec<&str>> = Lazy::new(|| {
|
||||||
opcodes[INVOKESPECIAL as usize] = "INVOKESPECIAL" ;
|
opcodes[INVOKESPECIAL as usize] = "INVOKESPECIAL" ;
|
||||||
opcodes[INVOKESTATIC as usize] = "INVOKESTATIC" ;
|
opcodes[INVOKESTATIC as usize] = "INVOKESTATIC" ;
|
||||||
opcodes[NEW as usize] = "NEW" ;
|
opcodes[NEW as usize] = "NEW" ;
|
||||||
|
opcodes[NEWARRAY as usize] = "NEWARRAY" ;
|
||||||
opcodes[ANEWARRAY as usize] = "ANEWARRAY" ;
|
opcodes[ANEWARRAY as usize] = "ANEWARRAY" ;
|
||||||
opcodes[ARRAYLENGTH as usize] = "ARRAYLENGTH" ;
|
opcodes[ARRAYLENGTH as usize] = "ARRAYLENGTH" ;
|
||||||
opcodes[_ATHROW as usize] = "_ATHROW" ;
|
opcodes[_ATHROW as usize] = "_ATHROW" ;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use anyhow::Error;
|
use anyhow::Error;
|
||||||
|
use log::debug;
|
||||||
|
|
||||||
use crate::class::{Class, Value};
|
use crate::class::{Class, Value};
|
||||||
use crate::classloader::classdef::CpEntry;
|
use crate::classloader::classdef::CpEntry;
|
||||||
|
|
@ -17,7 +18,6 @@ pub(crate) fn get_static(this_class: &Class, field_index: u16) -> Result<Value,
|
||||||
let (name_index, _) =
|
let (name_index, _) =
|
||||||
classdef.cp_name_and_type(field_name_and_type_index);
|
classdef.cp_name_and_type(field_name_and_type_index);
|
||||||
let field_name = classdef.cp_utf8(name_index);
|
let field_name = classdef.cp_utf8(name_index);
|
||||||
|
|
||||||
let that_class_name_index = classdef.cp_class_ref(class_index);
|
let that_class_name_index = classdef.cp_class_ref(class_index);
|
||||||
let that_class_name = classdef.cp_utf8(that_class_name_index);
|
let that_class_name = classdef.cp_utf8(that_class_name_index);
|
||||||
classmanager::load_class_by_name(that_class_name);
|
classmanager::load_class_by_name(that_class_name);
|
||||||
|
|
@ -30,7 +30,8 @@ pub(crate) fn get_static(this_class: &Class, field_index: u16) -> Result<Value,
|
||||||
.get(field_name)
|
.get(field_name)
|
||||||
.unwrap(); // safe because field must be there
|
.unwrap(); // safe because field must be there
|
||||||
|
|
||||||
Ok(classmanager::get_static(&this_class.id, type_index.index))
|
debug!("get_static {}.{}", that_class_name, field_name);
|
||||||
|
Ok(classmanager::get_static(&that_class.id, type_index.index))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn get_name_and_type(cp: &HashMap<u16, CpEntry>, index: u16) -> Option<MethodSignature> {
|
pub(crate) fn get_name_and_type(cp: &HashMap<u16, CpEntry>, index: u16) -> Option<MethodSignature> {
|
||||||
|
|
|
||||||
27
src/vm/vm.rs
27
src/vm/vm.rs
|
|
@ -1,11 +1,11 @@
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
|
|
||||||
use anyhow::Error;
|
use anyhow::Error;
|
||||||
use log::{debug, info};
|
use log::debug;
|
||||||
|
|
||||||
use crate::class::{Class, ClassId, Object, ObjectRef, Value};
|
use crate::class::{Class, Object, ObjectRef, Value};
|
||||||
use crate::class::Value::{F32, F64, I32, I64, Null, Ref, Utf8, Void};
|
use crate::class::Value::{F32, F64, I32, I64, Null, Ref, Utf8, Void};
|
||||||
use crate::classloader::classdef::{AttributeType, CpEntry, Method, Modifier};
|
use crate::classloader::classdef::{AttributeType, CpEntry, Modifier};
|
||||||
use crate::classloader::io::{read_u16, read_u8};
|
use crate::classloader::io::{read_u16, read_u8};
|
||||||
use crate::classmanager;
|
use crate::classmanager;
|
||||||
use crate::vm::array::{array_load, array_store};
|
use crate::vm::array::{array_load, array_store};
|
||||||
|
|
@ -137,14 +137,9 @@ impl Vm {
|
||||||
) -> Result<Value, Error> {
|
) -> Result<Value, Error> {
|
||||||
classmanager::load_class_by_name(class_name);
|
classmanager::load_class_by_name(class_name);
|
||||||
let class = classmanager::get_class_by_name(class_name).unwrap();
|
let class = classmanager::get_class_by_name(class_name).unwrap();
|
||||||
let _classdef = classmanager::get_classdef(&class.id);
|
|
||||||
self.execute_class(stack, class, method_name, args)
|
self.execute_class(stack, class, method_name, args)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn execute_class_id(&self, _stack: &mut Vec<StackFrame>, _this_class: ClassId, _method: &Method, _args: Vec<Value>) -> Result<Value, Error> {
|
|
||||||
Ok(Null)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn execute_class(
|
pub fn execute_class(
|
||||||
&mut self,
|
&mut self,
|
||||||
stackframes: &mut Vec<StackFrame>,
|
stackframes: &mut Vec<StackFrame>,
|
||||||
|
|
@ -370,6 +365,12 @@ impl Vm {
|
||||||
Self::current_frame(stackframes).push(value.clone());
|
Self::current_frame(stackframes).push(value.clone());
|
||||||
Self::current_frame(stackframes).push(value);
|
Self::current_frame(stackframes).push(value);
|
||||||
}
|
}
|
||||||
|
IADD => {
|
||||||
|
let stack = Self::current_frame(stackframes);
|
||||||
|
let value2 = stack.pop()?;
|
||||||
|
let value1 = stack.pop()?;
|
||||||
|
stack.push(I32(value1.into_i32() + value2.into_i32()));
|
||||||
|
}
|
||||||
IDIV => {
|
IDIV => {
|
||||||
let value2 = Self::current_frame(stackframes).pop()?;
|
let value2 = Self::current_frame(stackframes).pop()?;
|
||||||
let value1 = Self::current_frame(stackframes).pop()?;
|
let value1 = Self::current_frame(stackframes).pop()?;
|
||||||
|
|
@ -597,7 +598,12 @@ impl Vm {
|
||||||
class_to_instantiate,
|
class_to_instantiate,
|
||||||
));
|
));
|
||||||
Self::current_frame(stackframes).push(Ref(object));
|
Self::current_frame(stackframes).push(Ref(object));
|
||||||
// self.heap.new_object(object);
|
}
|
||||||
|
NEWARRAY =>{
|
||||||
|
let arraytype = read_u8(&code.opcodes, pc);
|
||||||
|
let count = Self::current_frame(stackframes).pop()?;
|
||||||
|
let array = ObjectRef::new_array(arraytype, count.into_i32() as usize);
|
||||||
|
Self::current_frame(stackframes).push(Ref(array));
|
||||||
}
|
}
|
||||||
ANEWARRAY => {
|
ANEWARRAY => {
|
||||||
let classdef = classmanager::get_classdef(&this_class.id);
|
let classdef = classmanager::get_classdef(&this_class.id);
|
||||||
|
|
@ -609,8 +615,7 @@ impl Vm {
|
||||||
let count = Self::current_frame(stackframes).pop()?;
|
let count = Self::current_frame(stackframes).pop()?;
|
||||||
if let I32(count) = count {
|
if let I32(count) = count {
|
||||||
let array = ObjectRef::new_object_array(arraytype, count as usize);
|
let array = ObjectRef::new_object_array(arraytype, count as usize);
|
||||||
|
Self::current_frame(stackframes).push(Ref(array));
|
||||||
Self::current_frame(stackframes).push(Value::Ref(array));
|
|
||||||
} else {
|
} else {
|
||||||
panic!();
|
panic!();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue