copy semantics for primitives

This commit is contained in:
Shautvast 2023-10-17 18:39:15 +02:00
parent e3f58a7b9f
commit 656b6aa66a
2 changed files with 46 additions and 30 deletions

View file

@ -562,6 +562,7 @@ impl Into<UnsafeValue> for Value {
} }
pub type UnsafeValue = Arc<UnsafeCell<Value>>; pub type UnsafeValue = Arc<UnsafeCell<Value>>;
pub type UnsafeRef = Arc<UnsafeCell<ObjectRef>>; pub type UnsafeRef = Arc<UnsafeCell<ObjectRef>>;
pub fn unsafe_ref(object: ObjectRef) -> UnsafeRef{ pub fn unsafe_ref(object: ObjectRef) -> UnsafeRef{

View file

@ -1,14 +1,14 @@
use std::cell::{RefCell, UnsafeCell}; use std::cell::RefCell;
use std::collections::HashMap; use std::collections::HashMap;
use std::ops::Deref;
use std::rc::Rc; use std::rc::Rc;
use std::string;
use std::sync::Arc; use std::sync::Arc;
use anyhow::{anyhow, Error}; use anyhow::{anyhow, Error};
use Value::{*};
use crate::class::{AttributeType, Class, get_class, Modifier, unsafe_ref, unsafe_val, UnsafeValue, Value}; use crate::class::{AttributeType, Class, get_class, Modifier, unsafe_ref, unsafe_val, UnsafeValue, Value};
use crate::class::Value::Void; use crate::class::Value::{Null, Void};
use crate::classloader::CpEntry; use crate::classloader::CpEntry;
use crate::heap::{Heap, Object, ObjectRef}; use crate::heap::{Heap, Object, ObjectRef};
use crate::io::*; use crate::io::*;
@ -127,27 +127,27 @@ impl Vm {
self.current_frame().push(Value::Null); self.current_frame().push(Value::Null);
} }
ICONST_M1 => { ICONST_M1 => {
self.current_frame().push(Value::I32(-1)); self.current_frame().push(I32(-1));
} }
ICONST_0 => { ICONST_0 => {
println!("ICONST_0"); println!("ICONST_0");
self.current_frame().push(Value::I32(0)); self.current_frame().push(I32(0));
} }
ICONST_1 => { ICONST_1 => {
println!("ICONST_1"); println!("ICONST_1");
self.current_frame().push(Value::I32(1)); self.current_frame().push(I32(1));
} }
ICONST_2 => { ICONST_2 => {
self.current_frame().push(Value::I32(2)); self.current_frame().push(I32(2));
} }
ICONST_3 => { ICONST_3 => {
self.current_frame().push(Value::I32(3)); self.current_frame().push(I32(3));
} }
ICONST_4 => { ICONST_4 => {
self.current_frame().push(Value::I32(4)); self.current_frame().push(I32(4));
} }
ICONST_5 => { ICONST_5 => {
self.current_frame().push(Value::I32(5)); self.current_frame().push(I32(5));
} }
LCONST_0 => { LCONST_0 => {
self.current_frame().push(Value::I64(0)); self.current_frame().push(Value::I64(0));
@ -172,11 +172,11 @@ impl Vm {
} }
SIPUSH => { SIPUSH => {
let s = read_u16(&code.opcodes, pc) as i32; let s = read_u16(&code.opcodes, pc) as i32;
self.current_frame().push(Value::I32(s)); self.current_frame().push(I32(s));
} }
BIPUSH => { BIPUSH => {
let c = read_u8(&code.opcodes, pc) as i32; let c = read_u8(&code.opcodes, pc) as i32;
self.current_frame().push(Value::I32(c)); self.current_frame().push(I32(c));
} }
LDC => { LDC => {
println!("LDC"); println!("LDC");
@ -185,7 +185,7 @@ impl Vm {
println!("{:?}", c); println!("{:?}", c);
match c { match c {
CpEntry::Integer(i) => { CpEntry::Integer(i) => {
self.current_frame().push(Value::I32(*i)); self.current_frame().push(I32(*i));
} }
CpEntry::Float(f) => { CpEntry::Float(f) => {
self.current_frame().push(Value::F32(*f)); self.current_frame().push(Value::F32(*f));
@ -217,7 +217,7 @@ 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.current_frame().push(Value::I32(*i)); self.current_frame().push(I32(*i));
} }
CpEntry::Float(f) => { CpEntry::Float(f) => {
self.current_frame().push(Value::F32(*f)); self.current_frame().push(Value::F32(*f));
@ -411,7 +411,7 @@ impl Vm {
{ {
let mut args = Vec::with_capacity(invocation.method.num_args); let mut args = Vec::with_capacity(invocation.method.num_args);
for _ in 0..invocation.method.num_args { for _ in 0..invocation.method.num_args {
args.insert(0, self.current_frame().pop()?); args.insert(0, copy(self.current_frame().pop()?));
} }
args.insert(0, self.current_frame().pop()?); args.insert(0, self.current_frame().pop()?);
let mut return_value = self.execute( let mut return_value = self.execute(
@ -438,7 +438,7 @@ impl Vm {
{ {
let mut args = Vec::with_capacity(invocation.method.num_args); let mut args = Vec::with_capacity(invocation.method.num_args);
for _ in 0..invocation.method.num_args { for _ in 0..invocation.method.num_args {
args.insert(0, self.current_frame().pop()?); args.insert(0, copy(self.current_frame().pop()?));
} }
let mut returnvalue = self.execute( let mut returnvalue = self.execute(
Some(this_class.borrow().name.as_str()), Some(this_class.borrow().name.as_str()),
@ -478,7 +478,7 @@ impl Vm {
let class_name = borrow.cp_utf8(class_name_index).unwrap(); let class_name = borrow.cp_utf8(class_name_index).unwrap();
let arraytype = get_class(self, Some(&borrow.name), class_name)?; let arraytype = get_class(self, Some(&borrow.name), class_name)?;
let count = self.current_frame().pop()?; let count = self.current_frame().pop()?;
if let Value::I32(count) = *count.get() { // why does pop()?.get() give weird results? if let I32(count) = *count.get() { // why does pop()?.get() give weird results?
let array = ObjectRef::new_object_array(arraytype, count as usize); let array = ObjectRef::new_object_array(arraytype, count as usize);
let array = unsafe_ref(array); let array = unsafe_ref(array);
@ -504,7 +504,7 @@ impl Vm {
unsafe fn array_load(&mut self) -> Result<(), Error> { unsafe fn array_load(&mut self) -> Result<(), Error> {
let value = self.current_frame().pop()?; let value = self.current_frame().pop()?;
if let Value::I32(index) = &*value.get() { if let I32(index) = &*value.get() {
let index = *index as usize; let index = *index as usize;
let arrayref = self.current_frame().pop()?; let arrayref = self.current_frame().pop()?;
if let Value::Null = &*arrayref.get() { if let Value::Null = &*arrayref.get() {
@ -513,19 +513,19 @@ impl Vm {
if let Value::Ref(objectref) = &*arrayref.get() { if let Value::Ref(objectref) = &*arrayref.get() {
match &*objectref.get() { match &*objectref.get() {
ObjectRef::ByteArray(array) => { ObjectRef::ByteArray(array) => {
self.current_frame().push(Value::I32(array[index] as i32)); self.current_frame().push(I32(array[index] as i32));
} }
ObjectRef::ShortArray(array) => { ObjectRef::ShortArray(array) => {
self.current_frame().push(Value::I32(array[index] as i32)); self.current_frame().push(I32(array[index] as i32));
} }
ObjectRef::IntArray(array) => { ObjectRef::IntArray(array) => {
self.current_frame().push(Value::I32(array[index])); self.current_frame().push(I32(array[index]));
} }
ObjectRef::BooleanArray(array) => { ObjectRef::BooleanArray(array) => {
self.current_frame().push(Value::I32(array[index] as i32)); self.current_frame().push(I32(array[index] as i32));
} }
ObjectRef::CharArray(array) => { ObjectRef::CharArray(array) => {
self.current_frame().push(Value::CHAR(array[index])); self.current_frame().push(CHAR(array[index]));
} }
ObjectRef::LongArray(array) => { ObjectRef::LongArray(array) => {
self.current_frame().push(Value::I64(array[index])); self.current_frame().push(Value::I64(array[index]));
@ -556,11 +556,11 @@ impl Vm {
return Err(anyhow!("NullpointerException")); return Err(anyhow!("NullpointerException"));
} }
if let Value::I32(index) = &*index.get() { if let I32(index) = &*index.get() {
if let Value::Ref(ref mut objectref) = &mut *arrayref.get() { if let Value::Ref(ref mut objectref) = &mut *arrayref.get() {
match &mut *objectref.get() { match &mut *objectref.get() {
ObjectRef::ByteArray(ref mut array) => { ObjectRef::ByteArray(ref mut array) => {
if let Value::I32(value) = *value.get() { if let I32(value) = *value.get() {
// is i32 correct? // is i32 correct?
array[*index as usize] = value as i8; array[*index as usize] = value as i8;
} else { } else {
@ -568,7 +568,7 @@ impl Vm {
} }
} }
ObjectRef::ShortArray(ref mut array) => { ObjectRef::ShortArray(ref mut array) => {
if let Value::I32(value) = *value.get() { if let I32(value) = *value.get() {
// is i32 correct? // is i32 correct?
array[*index as usize] = value as i16; array[*index as usize] = value as i16;
} else { } else {
@ -576,21 +576,21 @@ impl Vm {
} }
} }
ObjectRef::IntArray(ref mut array) => { ObjectRef::IntArray(ref mut array) => {
if let Value::I32(value) = *value.get() { if let I32(value) = *value.get() {
array[*index as usize] = value; array[*index as usize] = value;
} else { } else {
unreachable!() unreachable!()
} }
} }
ObjectRef::BooleanArray(ref mut array) => { ObjectRef::BooleanArray(ref mut array) => {
if let Value::I32(value) = *value.get() { if let I32(value) = *value.get() {
array[*index as usize] = value > 0; array[*index as usize] = value > 0;
} else { } else {
unreachable!() unreachable!()
} }
} }
ObjectRef::CharArray(ref mut array) => { ObjectRef::CharArray(ref mut array) => {
if let Value::I32(value) = *value.get() { if let I32(value) = *value.get() {
array[*index as usize] = char::from_u32_unchecked(value as u32); array[*index as usize] = char::from_u32_unchecked(value as u32);
} else { } else {
unreachable!() unreachable!()
@ -676,6 +676,21 @@ fn get_signature_for_invoke(cp: &Rc<HashMap<u16, CpEntry>>, index: u16) -> Optio
None None
} }
unsafe fn copy(value: UnsafeValue) -> UnsafeValue {
unsafe_val(match (&*value.get()) {
Void => Void,
Null => Null,
BOOL(b)=> BOOL(*b),
CHAR(c)=> CHAR(*c),
I32(i)=> I32(*i),
I64(l)=> I64(*l),
F32(f)=> F32(*f),
F64(d)=> F64(*d),
Ref(r)=> Ref(r.clone()),
Utf8(s)=> Utf8(s.to_owned()),
})
}
fn get_name_and_type(cp: Rc<HashMap<u16, CpEntry>>, index: u16) -> Option<MethodSignature> { fn get_name_and_type(cp: Rc<HashMap<u16, CpEntry>>, index: u16) -> Option<MethodSignature> {
if let CpEntry::NameAndType(method_name_index, signature_index) = cp.get(&index).unwrap() { if let CpEntry::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() {