more opcodes, less duplication
This commit is contained in:
parent
723ab490b5
commit
e92f6e270f
2 changed files with 88 additions and 71 deletions
|
|
@ -1,7 +1,16 @@
|
||||||
// pub const aconst_null: u8 = 1; // (0x01)
|
pub const NOP:u8 = 0; //(0x0) Do nothing
|
||||||
// pub const fconst_0: u8 = 11; // (0xb) Push float 0
|
pub const ACONST_NULL: u8 = 1; // (0x01) Push null
|
||||||
// pub const fconst_1: u8 = 12; // (0xc) Push float 1
|
pub const ICONST_M1: u8 = 2; //(0x2) Push int constant -1
|
||||||
// pub const fconst_2: u8 = 13; // (0xd) Push float 2
|
pub const ICONST_0: u8 = 3; //(0x2) Push int constant 0
|
||||||
|
pub const ICONST_1: u8 = 4; //(0x2) Push int constant 1
|
||||||
|
pub const ICONST_2: u8 = 5; //(0x2) Push int constant 2
|
||||||
|
pub const ICONST_3: u8 = 6; //(0x2) Push int constant 3
|
||||||
|
pub const ICONST_4: u8 = 7; //(0x2) Push int constant 4
|
||||||
|
pub const ICONST_5: u8 = 8; //(0x2) Push int constant 5
|
||||||
|
|
||||||
|
pub const FCONST_0: u8 = 11; // (0xb) Push float 0
|
||||||
|
pub const FCONST_1: u8 = 12; // (0xc) Push float 1
|
||||||
|
pub const FCONST_2: u8 = 13; // (0xd) Push float 2
|
||||||
// pub const dconst_0:u8 = 14; // (0xe) push double 0
|
// pub const dconst_0:u8 = 14; // (0xe) push double 0
|
||||||
// pub const dconst_1:u8 = 15; // (0xf) push double 1
|
// pub const dconst_1:u8 = 15; // (0xf) push double 1
|
||||||
// TODO turn all into references
|
// TODO turn all into references
|
||||||
|
|
@ -13,14 +22,18 @@ pub const LDC2_W: u8 = 20; // (0x14) Push long or double from run-time constant
|
||||||
// pub const dload:u8 = 24; // (0x18) load double from local variable
|
// pub const dload:u8 = 24; // (0x18) load double from local variable
|
||||||
// pub const aload:u8 = 25; //0x19
|
// pub const aload:u8 = 25; //0x19
|
||||||
//
|
//
|
||||||
|
pub const ILOAD_0: u8 = 26; // (0x1a) Load int from local variable 0
|
||||||
|
pub const ILOAD_1: u8 = 27; // (0x1a) Load int from local variable 1
|
||||||
|
pub const ILOAD_2: u8 = 28; // (0x1a) Load int from local variable 2
|
||||||
|
pub const ILOAD_3: u8 = 29; // (0x1a) Load int from local variable 3
|
||||||
pub const FLOAD_0: u8 = 34; // (0x22) Load float from local variable 0
|
pub const FLOAD_0: u8 = 34; // (0x22) Load float from local variable 0
|
||||||
pub const FLOAD_1: u8 = 35; // (0x23) Load float from local variable 1
|
pub const FLOAD_1: u8 = 35; // (0x23) Load float from local variable 1
|
||||||
pub const FLOAD_2: u8 = 36; // (0x24) Load float from local variable 2
|
pub const FLOAD_2: u8 = 36; // (0x24) Load float from local variable 2
|
||||||
pub const FLOAD_3: u8 = 37; // (0x25) Load float from local variable 3
|
pub const FLOAD_3: u8 = 37; // (0x25) Load float from local variable 3
|
||||||
// pub const dload_0:u8 = 38; // (0x26) Load double 0 from local variable
|
pub const DLOAD_0:u8 = 38; // (0x26) Load double from local variable 0
|
||||||
// pub const dload_1:u8 = 39; // (0x27) Load double 1 from local variable
|
pub const DLOAD_1:u8 = 39; // (0x27) Load double from local variable 1
|
||||||
// pub const dload_2:u8 = 40; // (0x28) Load double 2 from local variable
|
pub const DLOAD_2:u8 = 40; // (0x28) Load double from local variable 2
|
||||||
// pub const dload_3:u8 = 41; // (0x29) Load double 3 from local variable
|
pub const DLOAD_3:u8 = 41; // (0x29) Load double from local variable 3
|
||||||
pub const ALOAD_0: u8 = 42; // (0x2a)
|
pub const ALOAD_0: u8 = 42; // (0x2a)
|
||||||
pub const ALOAD_1: u8 = 43;// (0x2a)
|
pub const ALOAD_1: u8 = 43;// (0x2a)
|
||||||
pub const ALOAD_2: u8 = 44;// (0x2b)
|
pub const ALOAD_2: u8 = 44;// (0x2b)
|
||||||
|
|
|
||||||
126
src/vm.rs
126
src/vm.rs
|
|
@ -26,7 +26,11 @@ impl StackFrame {
|
||||||
Self { at, data: vec![] }
|
Self { at, data: vec![] }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push(&mut self, val: Arc<UnsafeCell<Value>>) {
|
fn push(&mut self, val: Value) {
|
||||||
|
self.data.push(Arc::new(UnsafeCell::new(val)));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn push_arc(&mut self, val: Arc<UnsafeCell<Value>>) {
|
||||||
self.data.push(val);
|
self.data.push(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -43,10 +47,10 @@ pub struct Vm {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_family = "unix")]
|
#[cfg(target_family = "unix")]
|
||||||
const CP_SEP: char = ':';
|
const PATH_SEPARATOR: char = ':';
|
||||||
|
|
||||||
#[cfg(target_family = "windows")]
|
#[cfg(target_family = "windows")]
|
||||||
const CP_SEP: char = ';';
|
const PATH_SEPARATOR: char = ';';
|
||||||
|
|
||||||
|
|
||||||
impl Vm {
|
impl Vm {
|
||||||
|
|
@ -57,7 +61,7 @@ impl Vm {
|
||||||
|
|
||||||
pub fn new(classpath: &'static str) -> Self {
|
pub fn new(classpath: &'static str) -> Self {
|
||||||
Self {
|
Self {
|
||||||
classpath: classpath.split(CP_SEP).map(|s| s.to_owned()).collect(),
|
classpath: classpath.split(PATH_SEPARATOR).map(|s| s.to_owned()).collect(),
|
||||||
classes: HashMap::new(),
|
classes: HashMap::new(),
|
||||||
heap: Heap::new(),
|
heap: Heap::new(),
|
||||||
stack: vec![],
|
stack: vec![],
|
||||||
|
|
@ -119,20 +123,51 @@ impl Vm {
|
||||||
let opcode = read_u8(&code.opcodes, pc);
|
let opcode = read_u8(&code.opcodes, pc);
|
||||||
println!("opcode {} ", opcode);
|
println!("opcode {} ", opcode);
|
||||||
match opcode {
|
match opcode {
|
||||||
|
ACONST_NULL => {
|
||||||
|
self.local_stack().push(Value::Null)
|
||||||
|
}
|
||||||
|
ICONST_M1 => {
|
||||||
|
self.local_stack().push(Value::I32(-1))
|
||||||
|
}
|
||||||
|
ICONST_0 => {
|
||||||
|
self.local_stack().push(Value::I32(0))
|
||||||
|
}
|
||||||
|
ICONST_1 => {
|
||||||
|
self.local_stack().push(Value::I32(1))
|
||||||
|
}
|
||||||
|
ICONST_2 => {
|
||||||
|
self.local_stack().push(Value::I32(2))
|
||||||
|
}
|
||||||
|
ICONST_3 => {
|
||||||
|
self.local_stack().push(Value::I32(3))
|
||||||
|
}
|
||||||
|
ICONST_4 => {
|
||||||
|
self.local_stack().push(Value::I32(4))
|
||||||
|
}
|
||||||
|
ICONST_5 => {
|
||||||
|
self.local_stack().push(Value::I32(5))
|
||||||
|
}
|
||||||
|
FCONST_0 =>{
|
||||||
|
self.local_stack().push(Value::F32(0.0))
|
||||||
|
}
|
||||||
|
FCONST_1 =>{
|
||||||
|
self.local_stack().push(Value::F32(1.0))
|
||||||
|
}
|
||||||
|
FCONST_2 =>{
|
||||||
|
self.local_stack().push(Value::F32(2.0))
|
||||||
|
}
|
||||||
BIPUSH => {
|
BIPUSH => {
|
||||||
println!("BISPUSH");
|
|
||||||
let c = read_u8(&code.opcodes, pc);
|
let c = read_u8(&code.opcodes, pc);
|
||||||
self.local_stack().push(Arc::new(UnsafeCell::new(Value::I32(c as i32))));
|
self.local_stack().push(Value::I32(c as i32));
|
||||||
}
|
}
|
||||||
LDC => {
|
LDC => {
|
||||||
println!("LDC");
|
|
||||||
let cp_index = read_u8(&code.opcodes, pc) as u16;
|
let cp_index = read_u8(&code.opcodes, pc) as u16;
|
||||||
match method.constant_pool.get(&cp_index).unwrap() {
|
match method.constant_pool.get(&cp_index).unwrap() {
|
||||||
CpEntry::Integer(i) => {
|
CpEntry::Integer(i) => {
|
||||||
self.local_stack().push(Arc::new(UnsafeCell::new(Value::I32(*i))));
|
self.local_stack().push(Value::I32(*i));
|
||||||
}
|
}
|
||||||
CpEntry::Float(f) => {
|
CpEntry::Float(f) => {
|
||||||
self.local_stack().push(Arc::new(UnsafeCell::new(Value::F32(*f))));
|
self.local_stack().push(Value::F32(*f));
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
@ -141,10 +176,10 @@ impl Vm {
|
||||||
let cp_index = read_u16(&code.opcodes, pc);
|
let cp_index = read_u16(&code.opcodes, pc);
|
||||||
match method.constant_pool.get(&cp_index).unwrap() {
|
match method.constant_pool.get(&cp_index).unwrap() {
|
||||||
CpEntry::Integer(i) => {
|
CpEntry::Integer(i) => {
|
||||||
self.local_stack().push(Arc::new(UnsafeCell::new(Value::I32(*i))));
|
self.local_stack().push(Value::I32(*i));
|
||||||
}
|
}
|
||||||
CpEntry::Float(f) => {
|
CpEntry::Float(f) => {
|
||||||
self.local_stack().push(Arc::new(UnsafeCell::new(Value::F32(*f))));
|
self.local_stack().push(Value::F32(*f));
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
panic!("unexpected")
|
panic!("unexpected")
|
||||||
|
|
@ -155,74 +190,45 @@ impl Vm {
|
||||||
let cp_index = read_u16(&code.opcodes, pc);
|
let cp_index = read_u16(&code.opcodes, pc);
|
||||||
match method.constant_pool.get(&cp_index).unwrap() {
|
match method.constant_pool.get(&cp_index).unwrap() {
|
||||||
CpEntry::Double(d) => {
|
CpEntry::Double(d) => {
|
||||||
self.local_stack().push(Arc::new(UnsafeCell::new(Value::F64(*d))));
|
self.local_stack().push(Value::F64(*d));
|
||||||
}
|
}
|
||||||
CpEntry::Long(l) => {
|
CpEntry::Long(l) => {
|
||||||
self.local_stack().push(Arc::new(UnsafeCell::new(Value::I64(*l))));
|
self.local_stack().push(Value::I64(*l));
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
panic!("unexpected")
|
panic!("unexpected")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FLOAD_0 => {
|
ILOAD_0 | FLOAD_0 | DLOAD_0 | ALOAD_0 => {
|
||||||
self.local_stack().push(args[0].clone());
|
self.local_stack().push_arc(args[0].clone());
|
||||||
}
|
}
|
||||||
FLOAD_1 => {
|
ILOAD_1 | FLOAD_1 | DLOAD_1 | ALOAD_1 => {
|
||||||
println!("FLOAD_1");
|
self.local_stack().push_arc(args[1].clone());
|
||||||
self.local_stack().push(args[1].clone());
|
|
||||||
}
|
}
|
||||||
FLOAD_2 => {
|
ILOAD_2 | FLOAD_2 | DLOAD_2 | ALOAD_2 => {
|
||||||
self.local_stack().push(args[2].clone());
|
self.local_stack().push_arc(args[2].clone());
|
||||||
}
|
}
|
||||||
FLOAD_3 => {
|
ILOAD_3 | FLOAD_3 | DLOAD_3 | ALOAD_3 => {
|
||||||
self.local_stack().push(args[3].clone());
|
self.local_stack().push_arc(args[3].clone());
|
||||||
}
|
|
||||||
ALOAD_0 => {
|
|
||||||
println!("ALOAD_0");
|
|
||||||
self.local_stack().push(args[0].clone());
|
|
||||||
}
|
|
||||||
ALOAD_1 => {
|
|
||||||
println!("ALOAD_1");
|
|
||||||
self.local_stack().push(args[1].clone());
|
|
||||||
}
|
|
||||||
ALOAD_2 => {
|
|
||||||
println!("ALOAD_2");
|
|
||||||
self.local_stack().push(args[2].clone());
|
|
||||||
}
|
|
||||||
ALOAD_3 => {
|
|
||||||
println!("ALOAD_3");
|
|
||||||
self.local_stack().push(args[3].clone());
|
|
||||||
}
|
}
|
||||||
POP => {
|
POP => {
|
||||||
self.local_stack().pop().expect("Stack empty");
|
self.local_stack().pop().expect("Stack empty");
|
||||||
}
|
}
|
||||||
DUP => {
|
DUP => {
|
||||||
println!("DUP");
|
|
||||||
let value = self.local_stack().pop().expect("Stack empty");
|
let value = self.local_stack().pop().expect("Stack empty");
|
||||||
println!("{:?}", value);
|
println!("{:?}", value);
|
||||||
self.local_stack().push(value.clone());
|
self.local_stack().push_arc(value.clone());
|
||||||
self.local_stack().push(value);
|
self.local_stack().push_arc(value);
|
||||||
}
|
}
|
||||||
IRETURN => {
|
IRETURN | FRETURN | DRETURN => {
|
||||||
println!("return I");
|
|
||||||
return self.local_stack().pop();
|
|
||||||
}
|
|
||||||
DRETURN => {
|
|
||||||
println!("return D");
|
|
||||||
return self.local_stack().pop();
|
|
||||||
}
|
|
||||||
FRETURN => {
|
|
||||||
println!("return F");
|
|
||||||
return self.local_stack().pop();
|
return self.local_stack().pop();
|
||||||
}
|
}
|
||||||
RETURN_VOID => {
|
RETURN_VOID => {
|
||||||
println!("return");
|
self.stack.pop(); // Void is also returned as a value
|
||||||
self.stack.pop();
|
|
||||||
return Ok(Arc::new(UnsafeCell::new(Void)));
|
return Ok(Arc::new(UnsafeCell::new(Void)));
|
||||||
}
|
}
|
||||||
GETFIELD => {
|
GETFIELD => {
|
||||||
println!("GETFIELD");
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let cp_index = read_u16(&code.opcodes, pc);
|
let cp_index = read_u16(&code.opcodes, pc);
|
||||||
if let CpEntry::Fieldref(_class_index, name_and_type_index) =
|
if let CpEntry::Fieldref(_class_index, name_and_type_index) =
|
||||||
|
|
@ -233,14 +239,13 @@ impl Vm {
|
||||||
method.constant_pool.get(name_and_type_index).unwrap()
|
method.constant_pool.get(name_and_type_index).unwrap()
|
||||||
{
|
{
|
||||||
let value = (*(*instance).get()).data.get(name).unwrap();
|
let value = (*(*instance).get()).data.get(name).unwrap();
|
||||||
self.local_stack().push(Arc::clone(value));
|
self.local_stack().push_arc(Arc::clone(value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PUTFIELD => {
|
PUTFIELD => {
|
||||||
println!("PUTFIELD");
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let cp_index = read_u16(&code.opcodes, pc);
|
let cp_index = read_u16(&code.opcodes, pc);
|
||||||
if let CpEntry::Fieldref(_class_index, name_and_type_index) =
|
if let CpEntry::Fieldref(_class_index, name_and_type_index) =
|
||||||
|
|
@ -268,13 +273,12 @@ impl Vm {
|
||||||
let mut returnvalue = self.execute(&invocation.class_name, &invocation.method.name, args)?;
|
let mut returnvalue = self.execute(&invocation.class_name, &invocation.method.name, args)?;
|
||||||
match *returnvalue.get() {
|
match *returnvalue.get() {
|
||||||
Void => {}
|
Void => {}
|
||||||
_ => { self.local_stack().push(returnvalue.clone()); }
|
_ => { self.local_stack().push_arc(returnvalue.clone()); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
INVOKESPECIAL => {
|
INVOKESPECIAL => {
|
||||||
println!("INVOKESPECIAL");
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let cp_index = read_u16(&code.opcodes, pc);
|
let cp_index = read_u16(&code.opcodes, pc);
|
||||||
if let Some(invocation) = get_signature_for_invoke(Rc::clone(&method.constant_pool), cp_index) {
|
if let Some(invocation) = get_signature_for_invoke(Rc::clone(&method.constant_pool), cp_index) {
|
||||||
|
|
@ -286,7 +290,7 @@ impl Vm {
|
||||||
let mut returnvalue = self.execute(&invocation.class_name, &invocation.method.name, args)?;
|
let mut returnvalue = self.execute(&invocation.class_name, &invocation.method.name, args)?;
|
||||||
match *returnvalue.get() {
|
match *returnvalue.get() {
|
||||||
Void => {}
|
Void => {}
|
||||||
_ => { self.local_stack().push(returnvalue.clone()); }
|
_ => { self.local_stack().push_arc(returnvalue.clone()); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -303,7 +307,7 @@ impl Vm {
|
||||||
println!("new {}", new_class);
|
println!("new {}", new_class);
|
||||||
let class = self.get_class(new_class)?;
|
let class = self.get_class(new_class)?;
|
||||||
let object = Arc::new(UnsafeCell::new(self.new_instance(class)));
|
let object = Arc::new(UnsafeCell::new(self.new_instance(class)));
|
||||||
self.local_stack().push(Arc::new(UnsafeCell::new(Value::Ref(Arc::clone(&object)))));
|
self.local_stack().push(Value::Ref(Arc::clone(&object)));
|
||||||
self.heap.new_object(object);
|
self.heap.new_object(object);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -339,7 +343,7 @@ fn get_signature_for_invoke(cp: Rc<HashMap<u16, CpEntry>>, index: u16) -> Option
|
||||||
if let CpEntry::Utf8(class_name) = cp.get(class_name_index).unwrap() {
|
if let CpEntry::Utf8(class_name) = cp.get(class_name_index).unwrap() {
|
||||||
return Some(Invocation {
|
return Some(Invocation {
|
||||||
class_name: class_name.into(),
|
class_name: class_name.into(),
|
||||||
method: method_signature
|
method: method_signature,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue