fixed jumping
This commit is contained in:
parent
715fa29cfd
commit
dae02cec32
2 changed files with 154 additions and 23 deletions
|
|
@ -1,4 +1,5 @@
|
||||||
use std::collections::{BTreeMap};
|
use std::collections::{BTreeMap};
|
||||||
|
use log::debug;
|
||||||
|
|
||||||
use crate::classloader::io::{read_i16, read_i32, read_lookupswitch, read_tableswitch, read_u16, read_u8, read_wide_opcode};
|
use crate::classloader::io::{read_i16, read_i32, read_lookupswitch, read_tableswitch, read_u16, read_u8, read_wide_opcode};
|
||||||
use crate::vm::opcodes::Opcode::{self, *};
|
use crate::vm::opcodes::Opcode::{self, *};
|
||||||
|
|
@ -7,14 +8,17 @@ pub(crate) fn parse_code(opcodes: &[u8]) -> Vec<Opcode> {
|
||||||
let mut code: BTreeMap<u16, (u16, Opcode)> = BTreeMap::new();
|
let mut code: BTreeMap<u16, (u16, Opcode)> = BTreeMap::new();
|
||||||
let mut c = 0;
|
let mut c = 0;
|
||||||
let mut opcode_index: u16 = 0;
|
let mut opcode_index: u16 = 0;
|
||||||
|
let mut index_before_read: u16;
|
||||||
while c < opcodes.len() {
|
while c < opcodes.len() {
|
||||||
|
index_before_read = c as u16;
|
||||||
let opcode = get_opcode(opcodes, &mut c);
|
let opcode = get_opcode(opcodes, &mut c);
|
||||||
code.insert(c as u16, (opcode_index, opcode));
|
code.insert(index_before_read, (opcode_index, opcode));
|
||||||
opcode_index += 1;
|
opcode_index += 1;
|
||||||
}
|
}
|
||||||
let code2 = code.clone(); //clone to look up
|
let code2 = code.clone(); //clone to look up
|
||||||
|
|
||||||
// for jumps, map index of opcode as u8 to index of opcode as enum
|
// for jumps, map index of opcode as u8 to index of opcode as enum
|
||||||
|
debug!("{:?}", code);
|
||||||
code.into_iter().map(|(_, (_, opcode))|
|
code.into_iter().map(|(_, (_, opcode))|
|
||||||
match opcode {
|
match opcode {
|
||||||
IFNULL(goto) => {
|
IFNULL(goto) => {
|
||||||
|
|
@ -23,6 +27,44 @@ pub(crate) fn parse_code(opcodes: &[u8]) -> Vec<Opcode> {
|
||||||
IFNONNULL(goto) => {
|
IFNONNULL(goto) => {
|
||||||
IFNONNULL(code2.get(&goto).unwrap().0)
|
IFNONNULL(code2.get(&goto).unwrap().0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IF_ICMPEQ(goto) => {
|
||||||
|
IF_ICMPEQ(code2.get(&goto).unwrap().0)
|
||||||
|
}
|
||||||
|
IF_ICMPNE(goto) => {
|
||||||
|
IF_ICMPNE(code2.get(&goto).unwrap().0)
|
||||||
|
}
|
||||||
|
IF_ICMPGT(goto) => {
|
||||||
|
IF_ICMPGT(code2.get(&goto).unwrap().0)
|
||||||
|
}
|
||||||
|
IF_ICMPGE(goto) => {
|
||||||
|
IF_ICMPGE(code2.get(&goto).unwrap().0)
|
||||||
|
}
|
||||||
|
IF_ICMPLT(goto) => {
|
||||||
|
IF_ICMPLT(code2.get(&goto).unwrap().0)
|
||||||
|
}
|
||||||
|
IF_ICMPLE(goto) => {
|
||||||
|
IF_ICMPLE(code2.get(&goto).unwrap().0)
|
||||||
|
}
|
||||||
|
IFEQ(goto) => {
|
||||||
|
IFEQ(code2.get(&goto).unwrap().0)
|
||||||
|
}
|
||||||
|
IFNE(goto) => {
|
||||||
|
IFNE(code2.get(&goto).unwrap().0)
|
||||||
|
}
|
||||||
|
IFGT(goto) => {
|
||||||
|
IFGT(code2.get(&goto).unwrap().0)
|
||||||
|
}
|
||||||
|
IFGE(goto) => {
|
||||||
|
IFGE(code2.get(&goto).unwrap().0)
|
||||||
|
}
|
||||||
|
IFLT(goto) => {
|
||||||
|
IFLT(code2.get(&goto).unwrap().0)
|
||||||
|
}
|
||||||
|
IFLE(goto) => {
|
||||||
|
IFLE(code2.get(&goto).unwrap().0)
|
||||||
|
}
|
||||||
|
|
||||||
//TODO more jump instructions
|
//TODO more jump instructions
|
||||||
_ => opcode
|
_ => opcode
|
||||||
}
|
}
|
||||||
|
|
@ -184,20 +226,20 @@ fn get_opcode(opcodes: &[u8], c: &mut usize) -> Opcode {
|
||||||
150 => FCMPG,
|
150 => FCMPG,
|
||||||
151 => DCMPL,
|
151 => DCMPL,
|
||||||
152 => DCMPG,
|
152 => DCMPG,
|
||||||
153 => IFEQ(read_u16(opcodes, c)),
|
153 => IFEQ(offset(opcodes, c)),
|
||||||
154 => IFNE(read_u16(opcodes, c)),
|
154 => IFNE(offset(opcodes, c)),
|
||||||
155 => IFLT(read_u16(opcodes, c)),
|
155 => IFLT(offset(opcodes, c)),
|
||||||
156 => IFGE(read_u16(opcodes, c)),
|
156 => IFGE(offset(opcodes, c)),
|
||||||
157 => IFGT(read_u16(opcodes, c)),
|
157 => IFGT(offset(opcodes, c)),
|
||||||
158 => IFLE(read_u16(opcodes, c)),
|
158 => IFLE(offset(opcodes, c)),
|
||||||
159 => IF_ICMPEQ(read_u16(opcodes, c)),
|
159 => IF_ICMPEQ(offset(opcodes, c)),
|
||||||
160 => IF_ICMPNE(read_u16(opcodes, c)),
|
160 => IF_ICMPNE(offset(opcodes, c)),
|
||||||
161 => IF_ICMPLT(read_u16(opcodes, c)),
|
161 => IF_ICMPLT(offset(opcodes, c)),
|
||||||
162 => IF_ICMPGE(read_u16(opcodes, c)),
|
162 => IF_ICMPGE(offset(opcodes, c)),
|
||||||
163 => IF_ICMPGT(read_u16(opcodes, c)),
|
163 => IF_ICMPGT(offset(opcodes, c)),
|
||||||
164 => IF_ICMPLE(read_u16(opcodes, c)),
|
164 => IF_ICMPLE(offset(opcodes, c)),
|
||||||
165 => IF_ACMPEQ(read_u16(opcodes, c)),
|
165 => IF_ACMPEQ(offset(opcodes, c)),
|
||||||
166 => IF_ACMPNE(read_u16(opcodes, c)),
|
166 => IF_ACMPNE(offset(opcodes, c)),
|
||||||
167 => GOTO(read_u16(opcodes, c)),
|
167 => GOTO(read_u16(opcodes, c)),
|
||||||
168 => JSR(read_u16(opcodes, c)),
|
168 => JSR(read_u16(opcodes, c)),
|
||||||
169 => RET(read_u8(opcodes, c)),
|
169 => RET(read_u8(opcodes, c)),
|
||||||
|
|
@ -239,19 +281,22 @@ fn get_opcode(opcodes: &[u8], c: &mut usize) -> Opcode {
|
||||||
196 => WIDE(Box::new(read_wide_opcode(opcodes, c))),
|
196 => WIDE(Box::new(read_wide_opcode(opcodes, c))),
|
||||||
197 => MULTIANEWARRAY(read_u16(opcodes, c), read_u8(opcodes, c)),
|
197 => MULTIANEWARRAY(read_u16(opcodes, c), read_u8(opcodes, c)),
|
||||||
198 => {
|
198 => {
|
||||||
let j = read_i16(opcodes, c);
|
IFNULL(offset(opcodes, c))
|
||||||
IFNULL((*c as i16 + j - 3) as u16)
|
|
||||||
}
|
}
|
||||||
199 => {
|
199 => {
|
||||||
let j = read_i16(opcodes, c);
|
IFNONNULL(offset(opcodes, c))
|
||||||
IFNONNULL((*c as i16 + j - 3) as u16)
|
|
||||||
}
|
}
|
||||||
200 => GOTOW(read_i32(opcodes, c)),
|
200 => GOTOW(read_i32(opcodes, c)),
|
||||||
201 => JSR_W(read_i32(opcodes, c)),
|
201 => JSR_W(read_i32(opcodes, c)),
|
||||||
|
|
||||||
|
|
||||||
_ => panic!("{}", opcode_u8),
|
_ => panic!("{}", opcode_u8),
|
||||||
};
|
};
|
||||||
|
debug!("{}: {:?}", c, opcode);
|
||||||
opcode
|
opcode
|
||||||
|
}
|
||||||
|
|
||||||
|
fn offset(opcodes: &[u8], c: &mut usize) -> u16 {
|
||||||
|
let j = read_i16(opcodes, c);
|
||||||
|
debug!("JUMP TO {} + {}",c, j);
|
||||||
|
(*c as i16 + j - 3) as u16
|
||||||
}
|
}
|
||||||
|
|
@ -10,7 +10,7 @@ use crate::classloader::classdef::{CpEntry, Modifier};
|
||||||
use crate::classloader::io::PATH_SEPARATOR;
|
use crate::classloader::io::PATH_SEPARATOR;
|
||||||
use crate::classmanager::ClassManager;
|
use crate::classmanager::ClassManager;
|
||||||
use crate::value::Value::{self, *};
|
use crate::value::Value::{self, *};
|
||||||
use crate::vm::array::array_load;
|
use crate::vm::array::{array_load, array_store};
|
||||||
use crate::vm::object;
|
use crate::vm::object;
|
||||||
use crate::vm::object::ObjectRef;
|
use crate::vm::object::ObjectRef;
|
||||||
use crate::vm::object::ObjectRef::Object;
|
use crate::vm::object::ObjectRef::Object;
|
||||||
|
|
@ -19,6 +19,8 @@ use crate::vm::opcodes::Opcode::*;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use crate::vm::native::invoke_native;
|
use crate::vm::native::invoke_native;
|
||||||
|
|
||||||
|
const MASK_LOWER_5BITS: i32 = 0b00011111;
|
||||||
|
|
||||||
pub struct Vm {
|
pub struct Vm {
|
||||||
pub stack: Vec<Stackframe>,
|
pub stack: Vec<Stackframe>,
|
||||||
}
|
}
|
||||||
|
|
@ -99,6 +101,7 @@ impl Stackframe {
|
||||||
while self.pc < len {
|
while self.pc < len {
|
||||||
let opcode: &Opcode = code.get(self.pc).unwrap();
|
let opcode: &Opcode = code.get(self.pc).unwrap();
|
||||||
debug!("\tat {}.{}: {} #{:?} - {:?}", classname, method_name, self.pc, opcode, self.stack);
|
debug!("\tat {}.{}: {} #{:?} - {:?}", classname, method_name, self.pc, opcode, self.stack);
|
||||||
|
self.pc += 1;
|
||||||
match opcode {
|
match opcode {
|
||||||
NOP => {}
|
NOP => {}
|
||||||
ACONST_NULL => {
|
ACONST_NULL => {
|
||||||
|
|
@ -175,6 +178,64 @@ impl Stackframe {
|
||||||
ISTORE(c) | LSTORE(c) | FSTORE(c) | DSTORE(c) | ASTORE(c) => {
|
ISTORE(c) | LSTORE(c) | FSTORE(c) | DSTORE(c) | ASTORE(c) => {
|
||||||
self.store(*c).unwrap();
|
self.store(*c).unwrap();
|
||||||
}
|
}
|
||||||
|
BASTORE | IASTORE | LASTORE | CASTORE | SASTORE | FASTORE | DASTORE
|
||||||
|
| AASTORE => {
|
||||||
|
let value = self.pop();
|
||||||
|
let index = self.pop();
|
||||||
|
let arrayref = self.pop();
|
||||||
|
array_store(value, index, arrayref).unwrap()//TODO
|
||||||
|
}
|
||||||
|
POP => {
|
||||||
|
self.pop();
|
||||||
|
}
|
||||||
|
DUP => {
|
||||||
|
let value = self.pop();
|
||||||
|
self.push(value.clone());
|
||||||
|
self.push(value);
|
||||||
|
}
|
||||||
|
IADD => {
|
||||||
|
let value2 = self.pop();
|
||||||
|
let value1 = self.pop();
|
||||||
|
debug!("{:?}+{:?}", value1, value2);
|
||||||
|
self.push(I32(value1.into_i32() + value2.into_i32()));
|
||||||
|
}
|
||||||
|
ISUB => {
|
||||||
|
let value2 = self.pop();
|
||||||
|
let value1 = self.pop();
|
||||||
|
debug!("{:?}-{:?}", value1, value2);
|
||||||
|
self.push(I32(value1.into_i32() - value2.into_i32()));
|
||||||
|
}
|
||||||
|
IDIV => {
|
||||||
|
let value2 = self.pop();
|
||||||
|
let value1 = self.pop();
|
||||||
|
self.push(I32(value1.into_i32() / value2.into_i32()));
|
||||||
|
}
|
||||||
|
ISHL => {
|
||||||
|
let value2 = self.pop();
|
||||||
|
let value1 = self.pop();
|
||||||
|
debug!("{:?} shl {:?}", value1, value2);
|
||||||
|
self.push(I32(value1.into_i32() << (value2.into_i32() & MASK_LOWER_5BITS)));
|
||||||
|
}
|
||||||
|
ISHR => {
|
||||||
|
let value2 = self.pop();
|
||||||
|
let value1 = self.pop();
|
||||||
|
debug!("{:?} shr {:?}", value1, value2);
|
||||||
|
self.push(I32(value1.into_i32() >> (value2.into_i32() & MASK_LOWER_5BITS)));
|
||||||
|
}
|
||||||
|
IFEQ(jmp_to) | IFNE(jmp_to) | IFLT(jmp_to) | IFGE(jmp_to) | IFGT(jmp_to) | IFLE(jmp_to) => {
|
||||||
|
let value = self.pop();
|
||||||
|
if_cmp(&mut self.pc, opcode, jmp_to, &value, &I32(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
IF_ICMPEQ(jmp_to) | IF_ICMPNE(jmp_to) | IF_ICMPGT(jmp_to) | IF_ICMPGE(jmp_to) | IF_ICMPLT(jmp_to) | IF_ICMPLE(jmp_to) => {
|
||||||
|
let value1 = self.pop();
|
||||||
|
let value2 = self.pop();
|
||||||
|
if_cmp(&mut self.pc, opcode, jmp_to, &value1, &value2);
|
||||||
|
}
|
||||||
|
GOTO(jmp_to) => {
|
||||||
|
self.pc += *jmp_to as usize;
|
||||||
|
// debug!("GOTO {}", *pc)
|
||||||
|
}
|
||||||
INVOKEVIRTUAL(c) => {
|
INVOKEVIRTUAL(c) => {
|
||||||
if let Some(invocation) =
|
if let Some(invocation) =
|
||||||
get_signature_for_invoke(&constant_pool, *c)
|
get_signature_for_invoke(&constant_pool, *c)
|
||||||
|
|
@ -391,6 +452,10 @@ impl Stackframe {
|
||||||
unreachable!("array length {:?}", val);
|
unreachable!("array length {:?}", val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ATHROW => {
|
||||||
|
let value = self.pop();
|
||||||
|
panic!("{:?}", value);
|
||||||
|
}
|
||||||
MONITORENTER | MONITOREXIT => {
|
MONITORENTER | MONITOREXIT => {
|
||||||
self.pop();
|
self.pop();
|
||||||
} //TODO implement
|
} //TODO implement
|
||||||
|
|
@ -414,7 +479,6 @@ impl Stackframe {
|
||||||
}
|
}
|
||||||
_ => { panic!("opcode not implemented") }
|
_ => { panic!("opcode not implemented") }
|
||||||
}
|
}
|
||||||
self.pc += 1;
|
|
||||||
}
|
}
|
||||||
Void
|
Void
|
||||||
}
|
}
|
||||||
|
|
@ -465,6 +529,28 @@ pub(crate) fn get_name_and_type(cp: &HashMap<u16, CpEntry>, index: u16) -> Optio
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn if_cmp(pc: &mut usize, opcode: &Opcode, jmp_to: &u16, value1: &Value, value2: &Value) {
|
||||||
|
if let I32(value1) = value1 {
|
||||||
|
if let I32(value2) = value2 {
|
||||||
|
let jump = match opcode {
|
||||||
|
IF_ICMPEQ(_) | IFEQ(_) => value1 == value2,
|
||||||
|
IF_ICMPNE(_) | IFNE(_) => value1 != value2,
|
||||||
|
IF_ICMPGT(_) | IFGT(_) => value1 > value2,
|
||||||
|
IF_ICMPGE(_) | IFGE(_) => value1 >= value2,
|
||||||
|
IF_ICMPLT(_) | IFLT(_) => value1 < value2,
|
||||||
|
IF_ICMPLE(_) | IFLE(_) => value1 <= value2,
|
||||||
|
_ => false,
|
||||||
|
};
|
||||||
|
if jump {
|
||||||
|
debug!("\t\tIF({}) JMP {}", jump, *jmp_to as usize);
|
||||||
|
*pc = *jmp_to as usize;
|
||||||
|
} else {
|
||||||
|
debug!("\t\tIF({}) NO JMP", jump);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn get_num_args(signature: &str) -> usize {
|
fn get_num_args(signature: &str) -> usize {
|
||||||
let mut num = 0;
|
let mut num = 0;
|
||||||
let mut i = 1;
|
let mut i = 1;
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue