new implementation using Arc<UnsafeCell>
This commit is contained in:
parent
1bef6d6caa
commit
2b50279c07
3 changed files with 81 additions and 74 deletions
|
|
@ -1,10 +1,11 @@
|
||||||
use std::cell::RefCell;
|
use std::cell::{RefCell, UnsafeCell};
|
||||||
use crate::classloader::CpEntry;
|
use crate::classloader::CpEntry;
|
||||||
use crate::heap::Object;
|
use crate::heap::Object;
|
||||||
use anyhow::{anyhow, Error};
|
use anyhow::{anyhow, Error};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
use crate::io::read_u16;
|
use crate::io::read_u16;
|
||||||
|
|
||||||
|
|
@ -264,7 +265,7 @@ pub enum Value {
|
||||||
F64(f64),
|
F64(f64),
|
||||||
BOOL(bool),
|
BOOL(bool),
|
||||||
CHAR(char),
|
CHAR(char),
|
||||||
Ref(Rc<RefCell<Object>>),
|
Ref(Arc<UnsafeCell<Object>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl Send for Value {}
|
unsafe impl Send for Value {}
|
||||||
|
|
|
||||||
15
src/heap.rs
15
src/heap.rs
|
|
@ -1,15 +1,16 @@
|
||||||
use std::cell::RefCell;
|
use std::cell::{RefCell, UnsafeCell};
|
||||||
use crate::class::{Class, Value};
|
use crate::class::{Class, Value};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
use std::sync::Arc;
|
||||||
use crate::classloader::CpEntry;
|
use crate::classloader::CpEntry;
|
||||||
|
|
||||||
pub struct Object {
|
pub struct Object {
|
||||||
// locked: bool,
|
// locked: bool,
|
||||||
// hashcode: i32,
|
// hashcode: i32,
|
||||||
pub class: Rc<Class>,
|
pub class: Rc<Class>,
|
||||||
pub data: HashMap<u16, Rc<RefCell<Value>>>, //TODO optimize
|
pub data: HashMap<u16, Arc<UnsafeCell<Value>>>, //TODO optimize
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl Send for Object {}
|
unsafe impl Send for Object {}
|
||||||
|
|
@ -17,7 +18,7 @@ unsafe impl Send for Object {}
|
||||||
unsafe impl Sync for Object {}
|
unsafe impl Sync for Object {}
|
||||||
|
|
||||||
impl Object {
|
impl Object {
|
||||||
pub fn new(class: Rc<Class>, data: HashMap<u16, Rc<RefCell<Value>>>) -> Self {
|
pub fn new(class: Rc<Class>, data: HashMap<u16, Arc<UnsafeCell<Value>>>) -> Self {
|
||||||
Self { class, data }
|
Self { class, data }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -27,6 +28,10 @@ impl Object {
|
||||||
}
|
}
|
||||||
panic!()
|
panic!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe fn get_mut<T>(ptr: &UnsafeCell<T>) -> &mut T {
|
||||||
|
unsafe { &mut *ptr.get() }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for Object {
|
impl fmt::Debug for Object {
|
||||||
|
|
@ -47,7 +52,7 @@ impl fmt::Debug for Object {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) struct Heap {
|
pub(crate) struct Heap {
|
||||||
objects: Vec<Rc<RefCell<Object>>>,
|
objects: Vec<Arc<UnsafeCell<Object>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Heap {
|
impl Heap {
|
||||||
|
|
@ -55,7 +60,7 @@ impl Heap {
|
||||||
Self { objects: vec![] }
|
Self { objects: vec![] }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn new_object(&mut self, object: Rc<RefCell<Object>>) {
|
pub(crate) fn new_object(&mut self, object: Arc<UnsafeCell<Object>>) {
|
||||||
self.objects.push(object);
|
self.objects.push(object);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
135
src/vm.rs
135
src/vm.rs
|
|
@ -1,7 +1,8 @@
|
||||||
use std::cell::RefCell;
|
use std::cell::{RefCell, UnsafeCell};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
use anyhow::{anyhow, Error};
|
use anyhow::{anyhow, Error};
|
||||||
|
|
||||||
|
|
@ -15,7 +16,7 @@ use crate::opcodes::*;
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct StackFrame {
|
struct StackFrame {
|
||||||
at: String,
|
at: String,
|
||||||
data: Vec<Rc<RefCell<Value>>>,
|
data: Vec<Arc<UnsafeCell<Value>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StackFrame {
|
impl StackFrame {
|
||||||
|
|
@ -26,11 +27,11 @@ impl StackFrame {
|
||||||
Self { at, data: vec![] }
|
Self { at, data: vec![] }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push(&mut self, val: Rc<RefCell<Value>>) {
|
fn push(&mut self, val: Arc<UnsafeCell<Value>>) {
|
||||||
self.data.push(val);
|
self.data.push(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pop(&mut self) -> Result<Rc<RefCell<Value>>, Error> {
|
fn pop(&mut self) -> Result<Arc<UnsafeCell<Value>>, Error> {
|
||||||
Ok(self.data.pop().unwrap())
|
Ok(self.data.pop().unwrap())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -92,7 +93,7 @@ impl Vm {
|
||||||
"L" => Value::Null,
|
"L" => Value::Null,
|
||||||
_ => Value::Void,
|
_ => Value::Void,
|
||||||
};
|
};
|
||||||
data.insert(f.name_index, Rc::new(RefCell::new(value)));
|
data.insert(f.name_index, Arc::new(UnsafeCell::new(value)));
|
||||||
}
|
}
|
||||||
Object::new(class.clone(), data)
|
Object::new(class.clone(), data)
|
||||||
}
|
}
|
||||||
|
|
@ -102,8 +103,8 @@ impl Vm {
|
||||||
&mut self,
|
&mut self,
|
||||||
class_name: &str,
|
class_name: &str,
|
||||||
method_name: &str,
|
method_name: &str,
|
||||||
args: Vec<Rc<RefCell<Value>>>,
|
args: Vec<Arc<UnsafeCell<Value>>>,
|
||||||
) -> Result<Rc<RefCell<Value>>, Error> {
|
) -> Result<Arc<UnsafeCell<Value>>, Error> {
|
||||||
println!("execute {}.{}", class_name, method_name);
|
println!("execute {}.{}", class_name, method_name);
|
||||||
let class = self.get_class(class_name)?;
|
let class = self.get_class(class_name)?;
|
||||||
let method = class.get_method(method_name)?;
|
let method = class.get_method(method_name)?;
|
||||||
|
|
@ -120,7 +121,7 @@ impl Vm {
|
||||||
BIPUSH => {
|
BIPUSH => {
|
||||||
println!("BISPUSH");
|
println!("BISPUSH");
|
||||||
let c = code.opcodes[pc] as i32;
|
let c = code.opcodes[pc] as i32;
|
||||||
self.local_stack().push(Rc::new(RefCell::new(Value::I32(c))));
|
self.local_stack().push(Arc::new(UnsafeCell::new(Value::I32(c))));
|
||||||
pc += 1;
|
pc += 1;
|
||||||
}
|
}
|
||||||
LDC => {
|
LDC => {
|
||||||
|
|
@ -128,10 +129,10 @@ impl Vm {
|
||||||
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(Rc::new(RefCell::new(Value::I32(*i))));
|
self.local_stack().push(Arc::new(UnsafeCell::new(Value::I32(*i))));
|
||||||
}
|
}
|
||||||
CpEntry::Float(f) => {
|
CpEntry::Float(f) => {
|
||||||
self.local_stack().push(Rc::new(RefCell::new(Value::F32(*f))));
|
self.local_stack().push(Arc::new(UnsafeCell::new(Value::F32(*f))));
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
@ -141,10 +142,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(Rc::new(RefCell::new(Value::I32(*i))));
|
self.local_stack().push(Arc::new(UnsafeCell::new(Value::I32(*i))));
|
||||||
}
|
}
|
||||||
CpEntry::Float(f) => {
|
CpEntry::Float(f) => {
|
||||||
self.local_stack().push(Rc::new(RefCell::new(Value::F32(*f))));
|
self.local_stack().push(Arc::new(UnsafeCell::new(Value::F32(*f))));
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
panic!("unexpected")
|
panic!("unexpected")
|
||||||
|
|
@ -156,10 +157,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::Double(d) => {
|
CpEntry::Double(d) => {
|
||||||
self.local_stack().push(Rc::new(RefCell::new(Value::F64(*d))));
|
self.local_stack().push(Arc::new(UnsafeCell::new(Value::F64(*d))));
|
||||||
}
|
}
|
||||||
CpEntry::Long(l) => {
|
CpEntry::Long(l) => {
|
||||||
self.local_stack().push(Rc::new(RefCell::new(Value::I64(*l))));
|
self.local_stack().push(Arc::new(UnsafeCell::new(Value::I64(*l))));
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
panic!("unexpected")
|
panic!("unexpected")
|
||||||
|
|
@ -222,22 +223,22 @@ impl Vm {
|
||||||
RETURN_VOID => {
|
RETURN_VOID => {
|
||||||
println!("return");
|
println!("return");
|
||||||
self.stack.pop();
|
self.stack.pop();
|
||||||
return Ok(Rc::new(RefCell::new(Void)));
|
return Ok(Arc::new(UnsafeCell::new(Void)));
|
||||||
}
|
}
|
||||||
GETFIELD => {
|
GETFIELD => {
|
||||||
println!("GETFIELD");
|
println!("GETFIELD");
|
||||||
let cp_index = read_u16(&code.opcodes, pc);
|
unsafe {
|
||||||
if let CpEntry::Fieldref(_class_index, name_and_type_index) =
|
let cp_index = read_u16(&code.opcodes, pc);
|
||||||
method.constant_pool.get(&cp_index).unwrap()
|
if let CpEntry::Fieldref(_class_index, name_and_type_index) =
|
||||||
{
|
method.constant_pool.get(&cp_index).unwrap()
|
||||||
if let Value::Ref(instance) = self.local_stack().pop()?.borrow().deref() {
|
{
|
||||||
//TODO smell?
|
if let Value::Ref(instance) = &*self.local_stack().pop()?.get() {
|
||||||
if let CpEntry::NameAndType(name, _) =
|
if let CpEntry::NameAndType(name, _) =
|
||||||
method.constant_pool.get(name_and_type_index).unwrap()
|
method.constant_pool.get(name_and_type_index).unwrap()
|
||||||
{
|
{
|
||||||
let borrow = instance.borrow();
|
let value = (*(instance.deref()).get()).data.get(name).unwrap();
|
||||||
let value = borrow.data.get(name).unwrap();
|
self.local_stack().push(Arc::clone(value));
|
||||||
self.local_stack().push(Rc::clone(value));
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -245,17 +246,17 @@ impl Vm {
|
||||||
}
|
}
|
||||||
PUTFIELD => {
|
PUTFIELD => {
|
||||||
println!("PUTFIELD");
|
println!("PUTFIELD");
|
||||||
let cp_index = read_u16(&code.opcodes, pc);
|
unsafe {
|
||||||
if let CpEntry::Fieldref(_class_index, name_and_type_index) =
|
let cp_index = read_u16(&code.opcodes, pc);
|
||||||
method.constant_pool.get(&cp_index).unwrap()
|
if let CpEntry::Fieldref(_class_index, name_and_type_index) =
|
||||||
{
|
method.constant_pool.get(&cp_index).unwrap()
|
||||||
if let CpEntry::NameAndType(name_index, _) = method.constant_pool.get(name_and_type_index).unwrap() {
|
{
|
||||||
let value = self.local_stack().pop()?;
|
if let CpEntry::NameAndType(name_index, _) = method.constant_pool.get(name_and_type_index).unwrap() {
|
||||||
let objectref = self.local_stack().pop()?;
|
let value = self.local_stack().pop()?;
|
||||||
let mut b = objectref.borrow_mut();
|
let mut objectref = &*self.local_stack().pop()?.get();
|
||||||
let b = b.deref_mut();
|
if let Value::Ref(instance) = objectref {
|
||||||
if let Value::Ref(object) = b {
|
(*(instance.deref()).get()).data.insert(*name_index, value);
|
||||||
object.borrow_mut().data.insert(*name_index, value);
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -263,43 +264,43 @@ impl Vm {
|
||||||
}
|
}
|
||||||
INVOKEVIRTUAL => {
|
INVOKEVIRTUAL => {
|
||||||
let cp_index = read_u16(&code.opcodes, pc);
|
let cp_index = read_u16(&code.opcodes, pc);
|
||||||
if let Some((class, method)) = get_signature_for_invoke(Rc::clone(&method.constant_pool), cp_index) {
|
unsafe {
|
||||||
let signature = method.0.as_str();
|
if let Some((class, method)) = get_signature_for_invoke(Rc::clone(&method.constant_pool), cp_index) {
|
||||||
let num_args = method.1;
|
let signature = method.0.as_str();
|
||||||
let mut args = Vec::with_capacity(num_args);
|
let num_args = method.1;
|
||||||
for _ in 0..num_args {
|
let mut args = Vec::with_capacity(num_args);
|
||||||
|
for _ in 0..num_args {
|
||||||
|
args.insert(0, self.local_stack().pop()?);
|
||||||
|
}
|
||||||
args.insert(0, self.local_stack().pop()?);
|
args.insert(0, self.local_stack().pop()?);
|
||||||
}
|
let mut returnvalue = self.execute(class.as_str(), signature, args)?;
|
||||||
args.insert(0, self.local_stack().pop()?);
|
match *returnvalue.get() {
|
||||||
let return_value = self.execute(class.as_str(), signature, args)?;
|
Void => {}
|
||||||
let borrow = return_value.borrow();
|
_ => { self.local_stack().push(returnvalue.clone()); }
|
||||||
match borrow.deref() {
|
}
|
||||||
&Void => {}
|
|
||||||
_ => { self.local_stack().push(return_value.clone()); }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pc += 2;
|
pc += 2;
|
||||||
}
|
}
|
||||||
INVOKESPECIAL => {
|
INVOKESPECIAL => {
|
||||||
println!("INVOKESPECIAL");
|
println!("INVOKESPECIAL");
|
||||||
let cp_index = read_u16(&code.opcodes, pc);
|
unsafe {
|
||||||
if let Some((class, method)) = get_signature_for_invoke(Rc::clone(&method.constant_pool), cp_index) {
|
let cp_index = read_u16(&code.opcodes, pc);
|
||||||
let signature = method.0.as_str();
|
if let Some((class, method)) = get_signature_for_invoke(Rc::clone(&method.constant_pool), cp_index) {
|
||||||
let num_args = method.1;
|
let signature = method.0.as_str();
|
||||||
let mut args = vec![];
|
let num_args = method.1;
|
||||||
for _ in 0..num_args {
|
let mut args = vec![];
|
||||||
|
for _ in 0..num_args {
|
||||||
|
args.insert(0, self.local_stack().pop()?);
|
||||||
|
}
|
||||||
args.insert(0, self.local_stack().pop()?);
|
args.insert(0, self.local_stack().pop()?);
|
||||||
}
|
let mut returnvalue = self.execute(class.as_str(), signature, args)?;
|
||||||
args.insert(0, self.local_stack().pop()?);
|
match *returnvalue.get() {
|
||||||
let return_value = self.execute(class.as_str(), signature, args)?;
|
Void => {}
|
||||||
let borrow = return_value.borrow();
|
_ => { self.local_stack().push(returnvalue.clone()); }
|
||||||
match borrow.deref() {
|
}
|
||||||
&Void => {}
|
|
||||||
_ => { self.local_stack().push(return_value.clone()); }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pc += 2;
|
pc += 2;
|
||||||
}
|
}
|
||||||
NEW => {
|
NEW => {
|
||||||
|
|
@ -313,8 +314,8 @@ 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 = Rc::new(RefCell::new(self.new_instance(class)));
|
let object = Arc::new(UnsafeCell::new(self.new_instance(class)));
|
||||||
self.local_stack().push(Rc::new(RefCell::new(Value::Ref(Rc::clone(&object)))));
|
self.local_stack().push(Arc::new(UnsafeCell::new(Value::Ref(Arc::clone(&object)))));
|
||||||
self.heap.new_object(object);
|
self.heap.new_object(object);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue