putfield sets the value in the object,
using Rc<RefCell>. Not really happy, but it works
This commit is contained in:
parent
9a53f1785d
commit
b9d0a199a3
3 changed files with 44 additions and 33 deletions
|
|
@ -1,3 +1,4 @@
|
|||
use std::cell::RefCell;
|
||||
use crate::classloader::CpEntry;
|
||||
use crate::heap::Object;
|
||||
use anyhow::{anyhow, Error};
|
||||
|
|
@ -263,7 +264,7 @@ pub enum Value {
|
|||
F64(f64),
|
||||
BOOL(bool),
|
||||
CHAR(char),
|
||||
Ref(Rc<Object>),
|
||||
Ref(Rc<RefCell<Object>>),
|
||||
}
|
||||
|
||||
unsafe impl Send for Value {}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
use std::cell::RefCell;
|
||||
use crate::class::{Class, Value};
|
||||
use std::collections::HashMap;
|
||||
use std::fmt;
|
||||
|
|
@ -8,7 +9,7 @@ pub struct Object {
|
|||
// locked: bool,
|
||||
// hashcode: i32,
|
||||
pub class: Rc<Class>,
|
||||
pub data: HashMap<u16, Rc<Value>>, //TODO optimize
|
||||
pub data: HashMap<u16, Rc<RefCell<Value>>>, //TODO optimize
|
||||
}
|
||||
|
||||
unsafe impl Send for Object {}
|
||||
|
|
@ -16,7 +17,7 @@ unsafe impl Send for Object {}
|
|||
unsafe impl Sync for Object {}
|
||||
|
||||
impl Object {
|
||||
pub fn new(class: Rc<Class>, data: HashMap<u16, Rc<Value>>) -> Self {
|
||||
pub fn new(class: Rc<Class>, data: HashMap<u16, Rc<RefCell<Value>>>) -> Self {
|
||||
Self { class, data }
|
||||
}
|
||||
|
||||
|
|
@ -46,7 +47,7 @@ impl fmt::Debug for Object {
|
|||
}
|
||||
|
||||
pub(crate) struct Heap {
|
||||
objects: Vec<Rc<Object>>,
|
||||
objects: Vec<Rc<RefCell<Object>>>,
|
||||
}
|
||||
|
||||
impl Heap {
|
||||
|
|
@ -54,7 +55,7 @@ impl Heap {
|
|||
Self { objects: vec![] }
|
||||
}
|
||||
|
||||
pub(crate) fn new_object(&mut self, object: Rc<Object>) {
|
||||
pub(crate) fn new_object(&mut self, object: Rc<RefCell<Object>>) {
|
||||
self.objects.push(object);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
65
src/vm.rs
65
src/vm.rs
|
|
@ -1,4 +1,6 @@
|
|||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::rc::Rc;
|
||||
|
||||
use anyhow::{anyhow, Error};
|
||||
|
|
@ -13,7 +15,7 @@ use crate::opcodes::*;
|
|||
#[derive(Debug)]
|
||||
struct StackFrame {
|
||||
at: String,
|
||||
data: Vec<Rc<Value>>,
|
||||
data: Vec<Rc<RefCell<Value>>>,
|
||||
}
|
||||
|
||||
impl StackFrame {
|
||||
|
|
@ -24,11 +26,11 @@ impl StackFrame {
|
|||
Self { at, data: vec![] }
|
||||
}
|
||||
|
||||
fn push(&mut self, val: Rc<Value>) {
|
||||
fn push(&mut self, val: Rc<RefCell<Value>>) {
|
||||
self.data.push(val);
|
||||
}
|
||||
|
||||
fn pop(&mut self) -> Result<Rc<Value>, Error> {
|
||||
fn pop(&mut self) -> Result<Rc<RefCell<Value>>, Error> {
|
||||
Ok(self.data.pop().unwrap())
|
||||
}
|
||||
}
|
||||
|
|
@ -90,7 +92,7 @@ impl Vm {
|
|||
"L" => Value::Null,
|
||||
_ => Value::Void,
|
||||
};
|
||||
data.insert(f.name_index, Rc::new(value));
|
||||
data.insert(f.name_index, Rc::new(RefCell::new(value)));
|
||||
}
|
||||
Object::new(class.clone(), data)
|
||||
}
|
||||
|
|
@ -100,8 +102,8 @@ impl Vm {
|
|||
&mut self,
|
||||
class_name: &str,
|
||||
method_name: &str,
|
||||
args: Vec<Rc<Value>>,
|
||||
) -> Result<Rc<Value>, Error> {
|
||||
args: Vec<Rc<RefCell<Value>>>,
|
||||
) -> Result<Rc<RefCell<Value>>, Error> {
|
||||
println!("execute {}.{}", class_name, method_name);
|
||||
let class = self.get_class(class_name)?;
|
||||
let method = class.get_method(method_name)?;
|
||||
|
|
@ -118,7 +120,7 @@ impl Vm {
|
|||
BIPUSH => {
|
||||
println!("BISPUSH");
|
||||
let c = code.opcodes[pc] as i32;
|
||||
self.local_stack().push(Rc::new(Value::I32(c)));
|
||||
self.local_stack().push(Rc::new(RefCell::new(Value::I32(c))));
|
||||
pc += 1;
|
||||
}
|
||||
LDC => {
|
||||
|
|
@ -126,10 +128,10 @@ impl Vm {
|
|||
let cp_index = read_u8(&code.opcodes, pc) as u16;
|
||||
match method.constant_pool.get(&cp_index).unwrap() {
|
||||
CpEntry::Integer(i) => {
|
||||
self.local_stack().push(Rc::new(Value::I32(*i)));
|
||||
self.local_stack().push(Rc::new(RefCell::new(Value::I32(*i))));
|
||||
}
|
||||
CpEntry::Float(f) => {
|
||||
self.local_stack().push(Rc::new(Value::F32(*f)));
|
||||
self.local_stack().push(Rc::new(RefCell::new(Value::F32(*f))));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
|
@ -139,10 +141,10 @@ impl Vm {
|
|||
let cp_index = read_u16(&code.opcodes, pc);
|
||||
match method.constant_pool.get(&cp_index).unwrap() {
|
||||
CpEntry::Integer(i) => {
|
||||
self.local_stack().push(Rc::new(Value::I32(*i)));
|
||||
self.local_stack().push(Rc::new(RefCell::new(Value::I32(*i))));
|
||||
}
|
||||
CpEntry::Float(f) => {
|
||||
self.local_stack().push(Rc::new(Value::F32(*f)));
|
||||
self.local_stack().push(Rc::new(RefCell::new(Value::F32(*f))));
|
||||
}
|
||||
_ => {
|
||||
panic!("unexpected")
|
||||
|
|
@ -154,10 +156,10 @@ impl Vm {
|
|||
let cp_index = read_u16(&code.opcodes, pc);
|
||||
match method.constant_pool.get(&cp_index).unwrap() {
|
||||
CpEntry::Double(d) => {
|
||||
self.local_stack().push(Rc::new(Value::F64(*d)));
|
||||
self.local_stack().push(Rc::new(RefCell::new(Value::F64(*d))));
|
||||
}
|
||||
CpEntry::Long(l) => {
|
||||
self.local_stack().push(Rc::new(Value::I64(*l)));
|
||||
self.local_stack().push(Rc::new(RefCell::new(Value::I64(*l))));
|
||||
}
|
||||
_ => {
|
||||
panic!("unexpected")
|
||||
|
|
@ -220,7 +222,7 @@ impl Vm {
|
|||
RETURN_VOID => {
|
||||
println!("return");
|
||||
self.stack.pop();
|
||||
return Ok(Rc::new(Void));
|
||||
return Ok(Rc::new(RefCell::new(Void)));
|
||||
}
|
||||
GETFIELD => {
|
||||
println!("GETFIELD");
|
||||
|
|
@ -228,14 +230,14 @@ impl Vm {
|
|||
if let CpEntry::Fieldref(_class_index, name_and_type_index) =
|
||||
method.constant_pool.get(&cp_index).unwrap()
|
||||
{
|
||||
if let Value::Ref(inst) = &*self.local_stack().pop()? {
|
||||
if let Value::Ref(instance) = self.local_stack().pop()?.borrow().deref() {
|
||||
//TODO smell?
|
||||
if let CpEntry::NameAndType(name, _) =
|
||||
method.constant_pool.get(name_and_type_index).unwrap()
|
||||
{
|
||||
let value = inst.data.get(name).unwrap();
|
||||
println!("{:?}", value);
|
||||
self.local_stack().push(value.clone());
|
||||
let borrow = instance.borrow();
|
||||
let value = borrow.data.get(name).unwrap();
|
||||
self.local_stack().push(Rc::clone(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -247,10 +249,15 @@ impl Vm {
|
|||
if let CpEntry::Fieldref(_class_index, name_and_type_index) =
|
||||
method.constant_pool.get(&cp_index).unwrap()
|
||||
{
|
||||
let value = self.local_stack().pop()?;
|
||||
println!("value {:?}", value);
|
||||
let objectref = self.local_stack().pop()?;
|
||||
println!("objectref {:?}", objectref);
|
||||
if let CpEntry::NameAndType(name_index, _) = method.constant_pool.get(name_and_type_index).unwrap() {
|
||||
let value = self.local_stack().pop()?;
|
||||
let objectref = self.local_stack().pop()?;
|
||||
let mut b = objectref.borrow_mut();
|
||||
let b = b.deref_mut();
|
||||
if let Value::Ref(object) = b {
|
||||
object.borrow_mut().data.insert(*name_index, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
pc += 2;
|
||||
}
|
||||
|
|
@ -265,8 +272,9 @@ impl Vm {
|
|||
}
|
||||
args.insert(0, self.local_stack().pop()?);
|
||||
let return_value = self.execute(class.as_str(), signature, args)?;
|
||||
if let Void = *return_value {} else { // not let?
|
||||
self.local_stack().push(return_value);
|
||||
let borrow = return_value.borrow();
|
||||
if let &Void = borrow.deref() {
|
||||
self.local_stack().push(return_value.clone());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -284,8 +292,9 @@ impl Vm {
|
|||
}
|
||||
args.insert(0, self.local_stack().pop()?);
|
||||
let return_value = self.execute(class.as_str(), signature, args)?;
|
||||
if let Void = *return_value {} else { // not let?
|
||||
self.local_stack().push(return_value);
|
||||
let borrow = return_value.borrow();
|
||||
if let &Void = borrow.deref() {
|
||||
self.local_stack().push(return_value.clone());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -302,8 +311,8 @@ impl Vm {
|
|||
{
|
||||
println!("new {}", new_class);
|
||||
let class = self.get_class(new_class)?;
|
||||
let object = Rc::new(self.new_instance(class));
|
||||
self.local_stack().push(Rc::new(Value::Ref(object.clone())));
|
||||
let object = Rc::new(RefCell::new(self.new_instance(class)));
|
||||
self.local_stack().push(Rc::new(RefCell::new(Value::Ref(Rc::clone(&object)))));
|
||||
self.heap.new_object(object);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue