added more dups
This commit is contained in:
parent
bab0e0d8c2
commit
7b6a01dfda
2 changed files with 188 additions and 23 deletions
27
src/value.rs
27
src/value.rs
|
|
@ -17,13 +17,32 @@ pub enum Value {
|
||||||
Ref(ObjectRef),
|
Ref(ObjectRef),
|
||||||
// special object
|
// special object
|
||||||
Utf8(String),
|
Utf8(String),
|
||||||
F32Infinity,
|
}
|
||||||
F32Nan,
|
|
||||||
F64Infinity,
|
pub enum ComputationalType {
|
||||||
F64Nan
|
C1 = 1,
|
||||||
|
C2 = 2,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Value {
|
impl Value {
|
||||||
|
pub fn category_as_u8(&self) -> u8 {
|
||||||
|
self.category() as u8
|
||||||
|
}
|
||||||
|
pub fn category(&self) -> ComputationalType {
|
||||||
|
match self {
|
||||||
|
Value::Void
|
||||||
|
| Value::Null
|
||||||
|
| Value::I32(_)
|
||||||
|
| Value::F32(_)
|
||||||
|
| Value::BOOL(_)
|
||||||
|
| Value::CHAR(_)
|
||||||
|
| Value::Ref(_)
|
||||||
|
| Value::Utf8(_) => ComputationalType::C1,
|
||||||
|
Value::I64(_)
|
||||||
|
| Value::F64(_) => ComputationalType::C2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// panics if not correct type
|
// panics if not correct type
|
||||||
pub fn into_i32(self) -> i32 {
|
pub fn into_i32(self) -> i32 {
|
||||||
if let Value::I32(v) = self {
|
if let Value::I32(v) = self {
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ use anyhow::Error;
|
||||||
use log::debug;
|
use log::debug;
|
||||||
|
|
||||||
use crate::class::ClassId;
|
use crate::class::ClassId;
|
||||||
use crate::classloader::classdef::{CpEntry, Modifier};
|
use crate::classloader::classdef::{CpEntry::*, 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, *};
|
||||||
|
|
@ -18,6 +18,7 @@ use crate::vm::object::ObjectRef::Object;
|
||||||
use crate::vm::opcodes::Opcode;
|
use crate::vm::opcodes::Opcode;
|
||||||
use crate::vm::opcodes::Opcode::*;
|
use crate::vm::opcodes::Opcode::*;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
|
use crate::value::ComputationalType;
|
||||||
|
|
||||||
const MASK_LOWER_5BITS: i32 = 0b00011111;
|
const MASK_LOWER_5BITS: i32 = 0b00011111;
|
||||||
|
|
||||||
|
|
@ -46,8 +47,8 @@ impl Vm {
|
||||||
class_manager.load_class_by_name(class_name);
|
class_manager.load_class_by_name(class_name);
|
||||||
let system_id = *class_manager.get_classid("java/lang/System");
|
let system_id = *class_manager.get_classid("java/lang/System");
|
||||||
self.run2(&mut class_manager, system_id, "initPhase1()V");
|
self.run2(&mut class_manager, system_id, "initPhase1()V");
|
||||||
// let class_id = *class_manager.get_classid(class_name);
|
let class_id = *class_manager.get_classid(class_name);
|
||||||
// self.run2(&mut class_manager, class_id, method_name);
|
self.run2(&mut class_manager, class_id, method_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn run2(
|
pub(crate) fn run2(
|
||||||
|
|
@ -150,16 +151,16 @@ impl Stackframe {
|
||||||
LDC(c) | LDC_W(c) | LDC2_W(c) => {
|
LDC(c) | LDC_W(c) | LDC2_W(c) => {
|
||||||
let c = constant_pool.get(&c).unwrap();
|
let c = constant_pool.get(&c).unwrap();
|
||||||
match c {
|
match c {
|
||||||
CpEntry::Integer(i) => {
|
Integer(i) => {
|
||||||
self.push(I32(*i));
|
self.push(I32(*i));
|
||||||
}
|
}
|
||||||
CpEntry::Float(f) => {
|
Float(f) => {
|
||||||
self.push(F32(*f));
|
self.push(F32(*f));
|
||||||
}
|
}
|
||||||
CpEntry::Double(d) => {
|
Double(d) => {
|
||||||
self.push(F64(*d));
|
self.push(F64(*d));
|
||||||
}
|
}
|
||||||
CpEntry::StringRef(utf8) => {
|
StringRef(utf8) => {
|
||||||
//TODO
|
//TODO
|
||||||
let string = class_manager.get_classdef(&class_id).cp_utf8(&utf8);
|
let string = class_manager.get_classdef(&class_id).cp_utf8(&utf8);
|
||||||
let string: Vec<u8> = string.as_bytes().into();
|
let string: Vec<u8> = string.as_bytes().into();
|
||||||
|
|
@ -176,10 +177,10 @@ impl Stackframe {
|
||||||
|
|
||||||
self.push(Ref(Object(Rc::new(RefCell::new(stringinstance)))));
|
self.push(Ref(Object(Rc::new(RefCell::new(stringinstance)))));
|
||||||
}
|
}
|
||||||
CpEntry::Long(l) => {
|
Long(l) => {
|
||||||
self.push(I64(*l));
|
self.push(I64(*l));
|
||||||
}
|
}
|
||||||
CpEntry::ClassRef(utf8_index) => {
|
ClassRef(utf8_index) => {
|
||||||
let class_name = class_manager
|
let class_name = class_manager
|
||||||
.get_classdef(&class_id)
|
.get_classdef(&class_id)
|
||||||
.cp_utf8(&utf8_index)
|
.cp_utf8(&utf8_index)
|
||||||
|
|
@ -223,17 +224,162 @@ impl Stackframe {
|
||||||
self.push(value.clone());
|
self.push(value.clone());
|
||||||
self.push(value);
|
self.push(value);
|
||||||
}
|
}
|
||||||
IADD => {
|
DUP_X1 => {
|
||||||
let value2 = self.pop();
|
|
||||||
let value1 = self.pop();
|
let value1 = self.pop();
|
||||||
|
let value2 = self.pop();
|
||||||
|
self.push(value1.clone());
|
||||||
|
self.push(value2);
|
||||||
|
self.push(value1);
|
||||||
|
}
|
||||||
|
DUP_X2 => {
|
||||||
|
let value1 = self.pop();
|
||||||
|
let value2 = self.pop();
|
||||||
|
let value3 = self.pop();
|
||||||
|
self.push(value1.clone());
|
||||||
|
self.push(value3);
|
||||||
|
self.push(value2);
|
||||||
|
self.push(value1);
|
||||||
|
}
|
||||||
|
DUP2 => {
|
||||||
|
let value1 = self.pop();
|
||||||
|
match value1.category() {
|
||||||
|
ComputationalType::C1 => {
|
||||||
|
let value2 = self.pop();
|
||||||
|
self.push(value2.clone());
|
||||||
|
self.push(value1.clone());
|
||||||
|
self.push(value2);
|
||||||
|
self.push(value1);
|
||||||
|
}
|
||||||
|
ComputationalType::C2 => {
|
||||||
|
self.push(value1.clone());
|
||||||
|
self.push(value1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DUP2_X1 => {
|
||||||
|
let value1 = self.pop();
|
||||||
|
let value2 = self.pop();
|
||||||
|
if value1.category() as u8 == 2 && value2.category() as u8 == 1 {
|
||||||
|
self.push(value1.clone());
|
||||||
|
self.push(value2);
|
||||||
|
self.push(value1);
|
||||||
|
} else {
|
||||||
|
let value3 = self.pop();
|
||||||
|
self.push(value2.clone());
|
||||||
|
self.push(value1.clone());
|
||||||
|
self.push(value3);
|
||||||
|
self.push(value2);
|
||||||
|
self.push(value1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DUP2_X2 => {
|
||||||
|
let value1 = self.pop();
|
||||||
|
let value2 = self.pop();
|
||||||
|
if value1.category_as_u8() == 2
|
||||||
|
&& value2.category_as_u8() == 2 { // Form 4
|
||||||
|
self.push(value1.clone());
|
||||||
|
self.push(value2);
|
||||||
|
self.push(value1);
|
||||||
|
} else {
|
||||||
|
let value3 = self.pop();
|
||||||
|
if value1.category_as_u8() == 1
|
||||||
|
&& value2.category_as_u8() == 1
|
||||||
|
&& value3.category_as_u8() == 2 { // Form 3
|
||||||
|
self.push(value2.clone());
|
||||||
|
self.push(value1.clone());
|
||||||
|
self.push(value3);
|
||||||
|
self.push(value2);
|
||||||
|
self.push(value1);
|
||||||
|
} else if value1.category_as_u8() == 2 // Form 2
|
||||||
|
&& value2.category_as_u8() == 1
|
||||||
|
&& value3.category_as_u8() == 1 {
|
||||||
|
self.push(value1.clone());
|
||||||
|
self.push(value3);
|
||||||
|
self.push(value2);
|
||||||
|
self.push(value1);
|
||||||
|
} else { // Form 1
|
||||||
|
let value4 = self.pop();
|
||||||
|
self.push(value2.clone());
|
||||||
|
self.push(value1.clone());
|
||||||
|
self.push(value4);
|
||||||
|
self.push(value3);
|
||||||
|
self.push(value2);
|
||||||
|
self.push(value1);
|
||||||
|
}
|
||||||
|
// not sure about this,
|
||||||
|
// like what if v1:1, v2:1 v3:1 and v4:2 ?
|
||||||
|
// it would now fall into form1, which is not in line with the spec
|
||||||
|
// the alternative is stack corruption??
|
||||||
|
// unless the compiler prevents this combination from occurring
|
||||||
|
}
|
||||||
|
}
|
||||||
|
IADD => {
|
||||||
|
let value2 = self.pop().into_i32();
|
||||||
|
let value1 = self.pop().into_i32();
|
||||||
debug!("{:?}+{:?}", value1, value2);
|
debug!("{:?}+{:?}", value1, value2);
|
||||||
self.push(I32(value1.into_i32() + value2.into_i32()));
|
self.push(I32(value1 + value2));
|
||||||
|
}
|
||||||
|
LADD => {
|
||||||
|
let value2 = self.pop().into_i64();
|
||||||
|
let value1 = self.pop().into_i64();
|
||||||
|
debug!("{:?}-{:?}", value1, value2);
|
||||||
|
self.push(I64(value1 + value2));
|
||||||
|
}
|
||||||
|
FADD => {
|
||||||
|
let value2 = self.pop().into_f32();
|
||||||
|
let value1 = self.pop().into_f32();
|
||||||
|
debug!("{:?}-{:?}", value1, value2);
|
||||||
|
self.push(F32(value1 + value2));
|
||||||
|
}
|
||||||
|
DADD => {
|
||||||
|
let value2 = self.pop().into_f64();
|
||||||
|
let value1 = self.pop().into_f64();
|
||||||
|
debug!("{:?}-{:?}", value1, value2);
|
||||||
|
self.push(F64(value1 + value2));
|
||||||
}
|
}
|
||||||
ISUB => {
|
ISUB => {
|
||||||
let value2 = self.pop();
|
let value2 = self.pop().into_i32();
|
||||||
let value1 = self.pop();
|
let value1 = self.pop().into_i32();
|
||||||
debug!("{:?}-{:?}", value1, value2);
|
debug!("{:?}-{:?}", value1, value2);
|
||||||
self.push(I32(value1.into_i32() - value2.into_i32()));
|
self.push(I32(value1 - value2));
|
||||||
|
}
|
||||||
|
LSUB => {
|
||||||
|
let value2 = self.pop().into_i64();
|
||||||
|
let value1 = self.pop().into_i64();
|
||||||
|
debug!("{:?}-{:?}", value1, value2);
|
||||||
|
self.push(I64(value1 - value2));
|
||||||
|
}
|
||||||
|
FSUB => {
|
||||||
|
let value2 = self.pop().into_f32();
|
||||||
|
let value1 = self.pop().into_f32();
|
||||||
|
debug!("{:?}-{:?}", value1, value2);
|
||||||
|
self.push(F32(value1 - value2));
|
||||||
|
}
|
||||||
|
DSUB => {
|
||||||
|
let value2 = self.pop().into_f64();
|
||||||
|
let value1 = self.pop().into_f64();
|
||||||
|
debug!("{:?}-{:?}", value1, value2);
|
||||||
|
self.push(F64(value1 - value2));
|
||||||
|
}
|
||||||
|
IMUL => {
|
||||||
|
let value2 = self.pop().into_i32();
|
||||||
|
let value1 = self.pop().into_i32();
|
||||||
|
self.push(I32(value1 * value2))
|
||||||
|
}
|
||||||
|
LMUL => {
|
||||||
|
let value2 = self.pop().into_i64();
|
||||||
|
let value1 = self.pop().into_i64();
|
||||||
|
self.push(I64(value1 * value2))
|
||||||
|
}
|
||||||
|
FMUL => {
|
||||||
|
let value2 = self.pop().into_f32();
|
||||||
|
let value1 = self.pop().into_f32();
|
||||||
|
self.push(F32(value1 * value2))
|
||||||
|
}
|
||||||
|
DMUL => {
|
||||||
|
let value2 = self.pop().into_f64();
|
||||||
|
let value1 = self.pop().into_f64();
|
||||||
|
self.push(F64(value1 * value2))
|
||||||
}
|
}
|
||||||
IDIV => {
|
IDIV => {
|
||||||
let value2 = self.pop();
|
let value2 = self.pop();
|
||||||
|
|
@ -686,11 +832,11 @@ pub(crate) fn get_signature_for_invoke(
|
||||||
cp: &HashMap<u16, CpEntry>,
|
cp: &HashMap<u16, CpEntry>,
|
||||||
index: u16,
|
index: u16,
|
||||||
) -> Option<Invocation> {
|
) -> Option<Invocation> {
|
||||||
if let CpEntry::MethodRef(class_index, name_and_type_index)
|
if let MethodRef(class_index, name_and_type_index)
|
||||||
| CpEntry::InterfaceMethodref(class_index, name_and_type_index) = cp.get(&index).unwrap()
|
| InterfaceMethodref(class_index, name_and_type_index) = cp.get(&index).unwrap()
|
||||||
{
|
{
|
||||||
if let Some(method_signature) = get_name_and_type(cp, *name_and_type_index) {
|
if let Some(method_signature) = get_name_and_type(cp, *name_and_type_index) {
|
||||||
if let CpEntry::ClassRef(class_name_index) = cp.get(class_index).unwrap() {
|
if let ClassRef(class_name_index) = cp.get(class_index).unwrap() {
|
||||||
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::new(class_name.into(), method_signature));
|
return Some(Invocation::new(class_name.into(), method_signature));
|
||||||
}
|
}
|
||||||
|
|
@ -701,7 +847,7 @@ pub(crate) fn get_signature_for_invoke(
|
||||||
}
|
}
|
||||||
|
|
||||||
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> {
|
||||||
if let CpEntry::NameAndType(method_name_index, signature_index) = cp.get(&index).unwrap() {
|
if let NameAndType(method_name_index, signature_index) = cp.get(&index).unwrap() {
|
||||||
if let CpEntry::Utf8(method_name) = cp.get(method_name_index).unwrap() {
|
if let CpEntry::Utf8(method_name) = cp.get(method_name_index).unwrap() {
|
||||||
if let CpEntry::Utf8(signature) = cp.get(signature_index).unwrap() {
|
if let CpEntry::Utf8(signature) = cp.get(signature_index).unwrap() {
|
||||||
let mut method_signature: String = method_name.into();
|
let mut method_signature: String = method_name.into();
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue