From 420db38f70844f0843651a8c8f4393a7dc8f7b8a Mon Sep 17 00:00:00 2001 From: Jesse Brault Date: Sat, 28 Dec 2024 15:10:56 -0600 Subject: [PATCH] Properly implement load and store instructions. --- src/bin/dvm/main.rs | 39 ++++--- src/vm/dm_type.rs | 2 - src/vm/dvm_value.rs | 7 ++ src/vm/mem.rs | 128 +++++++++++++---------- src/vm/mod.rs | 174 ++++++-------------------------- src/vm/object.rs | 46 ++++++--- src/vm/object_type.rs | 18 +--- src/vm/op_codes.rs | 17 ++-- src/vm/platform/std_lib/core.rs | 35 ++----- 9 files changed, 176 insertions(+), 290 deletions(-) diff --git a/src/bin/dvm/main.rs b/src/bin/dvm/main.rs index 09e272d..a386e64 100644 --- a/src/bin/dvm/main.rs +++ b/src/bin/dvm/main.rs @@ -2,7 +2,7 @@ use deimos::vm::dm_type::DmType; use deimos::vm::lib::{DmConstant, DmLib}; use deimos::vm::object_type::{DmField, DmFn, DmImplementation, DmInterface, DmMethod}; use deimos::vm::op_codes::{ - add_alloc, add_invoke_fn, add_mov_const, add_mov_register_to, add_platform_call, + add_alloc, add_dealloc, add_invoke_fn, add_mov_const, add_platform_call, add_store, }; use deimos::vm::platform::init_platform_functions; use deimos::vm::{call_fn, DvmContext, DvmState}; @@ -28,9 +28,9 @@ fn main() { Some(array_int_rc.clone()), ); - let array_impl_ptr_address_fld = DmField::new("ptr_address", DmType::USize, 0); - let array_impl_ptr_size_fld = DmField::new("ptr_size", DmType::USize, 8); - let array_impl_length_fld = DmField::new("length", DmType::Long, 16); + let array_impl_ptr_address_fld = DmField::new("ptr_address", DmType::USize); + let array_impl_ptr_size_fld = DmField::new("ptr_size", DmType::USize); + let array_impl_length_fld = DmField::new("length", DmType::Long); array_impl.fields.push(array_impl_ptr_address_fld); array_impl.fields.push(array_impl_ptr_size_fld); @@ -44,9 +44,9 @@ fn main() { // ) let mut array_impl_ctor_0_bytecode: Vec = Vec::new(); - add_mov_register_to(&mut array_impl_ctor_0_bytecode, 0, 0, 1); - add_mov_register_to(&mut array_impl_ctor_0_bytecode, 0, 8, 2); - add_mov_register_to(&mut array_impl_ctor_0_bytecode, 0, 16, 3); + add_store(&mut array_impl_ctor_0_bytecode, 0, 0, 1); + add_store(&mut array_impl_ctor_0_bytecode, 0, 1, 2); + add_store(&mut array_impl_ctor_0_bytecode, 0, 2, 3); let array_impl_ctor_0_fn = DmFn::new( "std::core::ArrayImpl::_ctor_0", @@ -70,7 +70,7 @@ fn main() { let mut string_impl = DmImplementation::new("std::core::StringImpl", "StringImpl", None); - let bytes_field = DmField::new("bytes", DmType::Object, 0); + let bytes_field = DmField::new("bytes", DmType::Object); string_impl.fields.push(bytes_field); // std::core::String::_ctor_0( @@ -78,7 +78,7 @@ fn main() { // r1: Array bytes // ) let mut string_ctor_0_bytecode: Vec = Vec::new(); - add_mov_register_to(&mut string_ctor_0_bytecode, 0, 0, 1); + add_store(&mut string_ctor_0_bytecode, 0, 0, 1); let string_ctor_0_fn = DmFn::new( "std::core::StringImpl::_ctor_0", @@ -91,7 +91,6 @@ fn main() { let string_ctor_0_method = DmMethod::new(string_ctor_0_fn, None); string_impl.methods.push(Rc::new(string_ctor_0_method)); - let core_string_impl_size = string_impl.size_in_bytes(); string_lib.interfaces.push(Rc::new(string_int)); string_lib.implementations.push(Rc::new(string_impl)); @@ -110,12 +109,7 @@ fn main() { add_mov_const(&mut main_byte_code, 0, 1, "greeting", 0); // Alloc Array greeting bytes - add_alloc( - &mut main_byte_code, - 2, - array_impl_rc.size_in_bytes() as u32, - "std::core::ArrayImpl", - ); + add_alloc(&mut main_byte_code, 2, "std::core::ArrayImpl"); // Call ArrayImpl(ptr_address, ptr_size, length) add_invoke_fn( @@ -126,12 +120,7 @@ fn main() { ); // Alloc StringImpl greeting - add_alloc( - &mut main_byte_code, - 4, - core_string_impl_size as u32, - "std::core::StringImpl", - ); + add_alloc(&mut main_byte_code, 4, "std::core::StringImpl"); // Call StringImpl(greeting_bytes) add_invoke_fn( @@ -144,6 +133,12 @@ fn main() { // Call println(greeting) add_platform_call(&mut main_byte_code, "std::core::println", 6, &[4]); + // Dealloc StringImpl + add_dealloc(&mut main_byte_code, 4); + + // Dealloc ArrayImpl + add_dealloc(&mut main_byte_code, 2); + let main_dm_fn = DmFn::new("main", "main", main_byte_code, 7, None); greeting_lib.functions.push(Rc::new(main_dm_fn)); diff --git a/src/vm/dm_type.rs b/src/vm/dm_type.rs index a0b9379..7204c61 100644 --- a/src/vm/dm_type.rs +++ b/src/vm/dm_type.rs @@ -7,7 +7,6 @@ pub enum DmType { Boolean, Object, USize, - Unit, } impl DmType { @@ -20,7 +19,6 @@ impl DmType { DmType::Boolean => size_of::(), DmType::Object => size_of::(), DmType::USize => size_of::(), - DmType::Unit => todo!("Need to determine size of Unit... is it dependent on the size of the thing which is Unit?") } } } diff --git a/src/vm/dvm_value.rs b/src/vm/dvm_value.rs index 4cb2ff9..aece25e 100644 --- a/src/vm/dvm_value.rs +++ b/src/vm/dvm_value.rs @@ -30,6 +30,13 @@ impl DvmValue { panic!("Expected DvmValue::Object, but found DvmValue::{:?}", self); } } + + pub fn is_object(&self) -> bool { + match self { + DvmValue::Object(_) => true, + _ => false, + } + } pub fn expect_usize(&self) -> usize { if let DvmValue::USize(u) = self { diff --git a/src/vm/mem.rs b/src/vm/mem.rs index 18f6aed..f47cfcc 100644 --- a/src/vm/mem.rs +++ b/src/vm/mem.rs @@ -1,70 +1,86 @@ use crate::vm::dm_type::DmType; use crate::vm::dvm_value::DvmValue; use crate::vm::object::DvmObject; -use crate::vm::object_type::DmField; use std::rc::Rc; -pub unsafe fn get_field_value(dm_field: &DmField, self_object: &DvmObject) -> DvmValue { - let data_size = dm_field.dm_type().size_in_bytes(); - let mut raw_data: Vec = Vec::with_capacity(data_size); - for i in dm_field.data_offset()..(dm_field.data_offset() + data_size) { - raw_data.push(self_object.data.offset(i as isize).read()); - } - match dm_field.dm_type() { - DmType::Byte => DvmValue::Byte(raw_data[0]), - DmType::Int => DvmValue::Int(i32::from_ne_bytes( - raw_data[0..data_size].try_into().unwrap(), - )), - DmType::Long => DvmValue::Long(i64::from_ne_bytes( - raw_data[0..data_size].try_into().unwrap(), - )), - DmType::Double => DvmValue::Double(f64::from_ne_bytes( - raw_data[0..data_size].try_into().unwrap(), - )), - DmType::Boolean => DvmValue::Boolean(raw_data[0] != 0), - DmType::Object => { - // read the pointer's (address) value - let address = usize::from_ne_bytes(raw_data[0..data_size].try_into().unwrap()); - DvmValue::Object(Rc::from_raw(address as *const DvmObject)) - } - DmType::USize => DvmValue::USize(usize::from_ne_bytes( - raw_data[0..data_size].try_into().unwrap(), - )), - DmType::Unit => DvmValue::Uninit, +unsafe fn read_field(data_pointer: *const u8, dm_type: &DmType) -> DvmValue { + match dm_type { + DmType::Byte => DvmValue::Byte(data_pointer.read()), + DmType::Int => DvmValue::Int(data_pointer.cast::().read()), + DmType::Long => DvmValue::Long(data_pointer.cast::().read()), + DmType::USize => DvmValue::USize(data_pointer.cast::().read()), + DmType::Double => DvmValue::Double(data_pointer.cast::().read()), + DmType::Boolean => DvmValue::Boolean(data_pointer.cast::().read()), + DmType::Object => DvmValue::Object(data_pointer.cast::>().read()), } } -macro_rules! read_array { - ( $T: ty, $raw_data: expr, $length: expr ) => {{ - let t_size = size_of::<$T>(); - let mut arr: Vec<$T> = Vec::with_capacity($length); - for i in 0..$length { - arr.push(<$T>::from_ne_bytes( - $raw_data[(i * t_size)..(i * t_size + t_size)] - .try_into() - .unwrap(), - )) +pub fn read_field_by_name(field_name: &str, self_object: &DvmObject) -> DvmValue { + let (field_index, field) = self_object + .implementation() + .fields + .iter() + .enumerate() + .find(|(_index, field)| field.name() == field_name) + .expect(&format!( + "Cannot find field {} in {}", + field_name, + self_object.implementation().fqn + )); + let data_pointer = self_object.data()[field_index]; + unsafe { read_field(data_pointer, field.dm_type()) } +} + +pub fn read_field_by_index(index: usize, self_object: &DvmObject) -> DvmValue { + let field = &self_object.implementation().fields[index]; + let data_pointer = self_object.data()[index]; + unsafe { read_field(data_pointer, field.dm_type()) } +} + +unsafe fn write_field(data_pointer: *mut u8, value: DvmValue) { + match value { + DvmValue::Byte(b) => { + data_pointer.write(b); } - arr - }}; + DvmValue::Int(i) => { + data_pointer.cast::().write(i); + } + DvmValue::Long(l) => { + data_pointer.cast::().write(l); + } + DvmValue::USize(u) => { + data_pointer.cast::().write(u); + } + DvmValue::Double(d) => { + data_pointer.cast::().write(d); + } + DvmValue::Boolean(b) => { + data_pointer.cast::().write(b); + } + DvmValue::Object(o) => { + data_pointer.cast::>().write(o); + } + DvmValue::Uninit => panic!("Cannot write DvmValue::Uninit to field."), + DvmValue::Void => panic!("Cannot write DvmValue::Void to field."), + } } -fn read_i32_array(raw_data: &Vec, length: usize) -> Vec { - read_array!(i32, raw_data, length) +pub fn write_field_by_name(field_name: &str, self_object: &DvmObject, value: DvmValue) { + let field_index = self_object + .implementation() + .fields + .iter() + .position(|field| field.name() == field_name) + .expect(&format!( + "Cannot find field {} in {}", + field_name, + self_object.implementation().fqn + )); + let data_pointer = self_object.data()[field_index]; + unsafe { write_field(data_pointer, value) }; } -fn read_i64_array(raw_data: &Vec, length: usize) -> Vec { - read_array!(i64, raw_data, length) -} - -fn read_f64_array(raw_data: &Vec, length: usize) -> Vec { - read_array!(f64, raw_data, length) -} - -fn read_bool_array(raw_data: &Vec) -> Vec { - raw_data.iter().map(|b| *b == 1).collect() -} - -fn read_usize_array(raw_data: &Vec, length: usize) -> Vec { - read_array!(usize, raw_data, length) +pub fn write_field_by_index(index: usize, self_object: &DvmObject, value: DvmValue) { + let data_pointer = self_object.data()[index]; + unsafe { write_field(data_pointer, value) }; } diff --git a/src/vm/mod.rs b/src/vm/mod.rs index eb993e3..1e7fc9d 100644 --- a/src/vm/mod.rs +++ b/src/vm/mod.rs @@ -11,6 +11,7 @@ pub mod util; use crate::vm::dvm_value::DvmValue; use crate::vm::lib::{DmConstant, DmLib}; +use crate::vm::mem::{read_field_by_index, write_field_by_index}; use crate::vm::object::DvmObject; use crate::vm::object_type::DmFn; use op_codes::*; @@ -294,10 +295,10 @@ pub fn run_byte_code(state: &mut DvmState, context: &DvmContext, byte_code: &[u8 let source_value = state.registers.get(source_register).unwrap(); state.registers[target_register] = source_value.clone(); } - LOAD_OBJECT => { + LOAD => { let target_register = next_8!(iter, usize); let source_register = next_8!(iter, usize); - let offset = next_usize_le!(iter); + let source_object_field_index = next_usize_le!(iter); let source_object = state .registers @@ -305,17 +306,15 @@ pub fn run_byte_code(state: &mut DvmState, context: &DvmContext, byte_code: &[u8 .unwrap() .expect_object(); - let object = - unsafe { Rc::from_raw(source_object.data.add(offset).cast::()) }; - - state.registers[target_register] = DvmValue::Object(object); + state.registers[target_register] = + read_field_by_index(source_object_field_index, &source_object); } STORE => { let target_register = next_8!(iter, usize); - let offset = next_usize_le!(iter); + let target_object_field_index = next_usize_le!(iter); let source_register = next_8!(iter, usize); - let target_alloc_object = state + let target_object = state .registers .get(target_register) .unwrap() @@ -323,45 +322,10 @@ pub fn run_byte_code(state: &mut DvmState, context: &DvmContext, byte_code: &[u8 let source_value = std::mem::replace(&mut state.registers[source_register], DvmValue::Uninit); - - match source_value { - DvmValue::Int(i) => { - write_bytes!(target_alloc_object.data, offset, i.to_ne_bytes()); - } - DvmValue::Byte(b) => unsafe { - target_alloc_object.data.add(offset).write(b); - }, - DvmValue::Long(l) => { - write_bytes!(target_alloc_object.data, offset, l.to_ne_bytes()); - } - DvmValue::Double(d) => { - write_bytes!(target_alloc_object.data, offset, d.to_ne_bytes()); - } - DvmValue::Boolean(b) => unsafe { - target_alloc_object.data.add(offset).write(b as u8); - }, - DvmValue::Object(source_object) => { - let source_object_ptr = Rc::into_raw(source_object); - write_bytes!( - target_alloc_object.data, - offset, - (source_object_ptr as usize).to_ne_bytes() - ); - } - DvmValue::USize(u) => { - write_bytes!(target_alloc_object.data, offset, u.to_ne_bytes()); - } - DvmValue::Uninit => { - panic!("Cannot store DvmValue::Uninit to object.") - } - DvmValue::Void => { - panic!("Cannot store DvmValue::Void to object.") - } - } + write_field_by_index(target_object_field_index, &target_object, source_value); } ALLOC => { let target_register = next_8!(iter, usize); - let alloc_size = next_32_le!(iter, usize); let impl_name = read_string!(iter); let implementation = context @@ -374,86 +338,19 @@ pub fn run_byte_code(state: &mut DvmState, context: &DvmContext, byte_code: &[u8 }) .expect(&format!("Implementation not found: {}", impl_name)); - let dm_alloc_object = DvmObject::new(alloc_size, implementation.clone()); + let dm_alloc_object = DvmObject::new(implementation.clone()); state.registers[target_register] = DvmValue::Object(Rc::new(dm_alloc_object)); } DEALLOC => { let target_register = next_8!(iter, usize); - let dm_alloc_object = state + let dvm_object = state .registers .get(target_register) .unwrap() .expect_object(); - drop(dm_alloc_object); // explicit + drop(dvm_object); // explicit state.registers[target_register] = DvmValue::Uninit; } - MOV_INT_TO => { - let target_register = next_8!(iter, usize); - let offset = next_32_le!(iter, usize); - let operand = next_32_le!(iter, u32) as i32; - - let dm_alloc_object = state - .registers - .get(target_register) - .unwrap() - .expect_object(); - write_bytes!(dm_alloc_object.data, offset, operand.to_ne_bytes()); - } - MOV_LONG_TO => { - todo!() - } - MOV_DOUBLE_TO => { - todo!() - } - MOV_REGISTER_TO => { - // Moves the value from the source register to the object pointed to by the target - // register, at the given offset. - let target_register = next_8!(iter, usize); - let offset = next_32_le!(iter, usize); - let source_register = next_8!(iter, usize); - - let target_alloc_object = state - .registers - .get(target_register) - .unwrap() - .expect_object(); - - let source_value = state.registers.get(source_register).unwrap(); - match source_value { - DvmValue::Int(i) => { - write_bytes!(target_alloc_object.data, offset, i.to_ne_bytes()); - } - DvmValue::Byte(b) => unsafe { - target_alloc_object.data.add(offset).write(*b); - }, - DvmValue::Long(l) => { - write_bytes!(target_alloc_object.data, offset, l.to_ne_bytes()); - } - DvmValue::Double(d) => { - write_bytes!(target_alloc_object.data, offset, d.to_ne_bytes()); - } - DvmValue::Boolean(b) => unsafe { - target_alloc_object.data.add(offset).write(*b as u8); - }, - DvmValue::Object(source_object) => { - let source_object_ptr = Rc::into_raw(source_object.clone()); - write_bytes!( - target_alloc_object.data, - offset, - (source_object_ptr as usize).to_ne_bytes() - ); - } - DvmValue::USize(us) => { - write_bytes!(target_alloc_object.data, offset, us.to_ne_bytes()); - } - DvmValue::Uninit => { - panic!("Cannot move DvmValue::Uninit to object.") - } - DvmValue::Void => { - panic!("Cannot move DvmValue::Void to object.") - } - } - } MOV_CONST => { // Decode let address_register = next_8!(iter, usize); @@ -565,7 +462,7 @@ pub fn run_byte_code(state: &mut DvmState, context: &DvmContext, byte_code: &[u8 let self_obj = args.get(0).unwrap().expect_object(); let method = self_obj - .implementation + .implementation() .get_method(&symbol_name, &self_obj) .expect(&format!("Could not find method: {}", symbol_name)); let dm_fn = method.dm_fn(); @@ -604,13 +501,17 @@ mod run_code_tests { }; } - fn setup() -> (DvmState, DvmContext) { - (DvmState::new(), DvmContext::new()) + fn setup(number_of_registers: usize) -> (DvmState, DvmContext) { + let mut state = DvmState::new(); + state + .registers + .resize(number_of_registers, DvmValue::Uninit); + (state, DvmContext::new()) } fn impl_with_object_field() -> DmImplementation { let mut dm_impl = DmImplementation::new("ImplWithObjectField", "ImplWithObjectField", None); - let object_field = DmField::new("object_field", DmType::Object, 0); + let object_field = DmField::new("object_field", DmType::Object); dm_impl.fields.push(object_field); dm_impl } @@ -619,7 +520,7 @@ mod run_code_tests { fn mov_1_as_int() { let mut code = Vec::new(); add_mov_int(&mut code, 0, 1); - let (mut state, context) = setup(); + let (mut state, context) = setup(1); run_byte_code(&mut state, &context, &code); assert_register!(DvmValue::Int(1), state, 0); } @@ -628,7 +529,7 @@ mod run_code_tests { fn move_65535_as_int() { let mut code = Vec::new(); add_mov_int(&mut code, 0, 0xffff); - let (mut state, context) = setup(); + let (mut state, context) = setup(1); run_byte_code(&mut state, &context, &code); assert_register!(DvmValue::Int(0xffff), state, 0); } @@ -637,7 +538,7 @@ mod run_code_tests { fn move_int_max_as_int() { let mut code = Vec::new(); add_mov_int(&mut code, 0, 0x0fff_ffff); - let (mut state, context) = setup(); + let (mut state, context) = setup(1); run_byte_code(&mut state, &context, &code); assert_register!(DvmValue::Int(0x0fff_ffff), state, 0); } @@ -647,8 +548,7 @@ mod run_code_tests { let mut code = Vec::new(); add_mov_int(&mut code, 1, 1); add_mov_register(&mut code, 0, 1); - let (mut state, context) = setup(); - state.registers.resize(2, DvmValue::Uninit); + let (mut state, context) = setup(2); run_byte_code(&mut state, &context, &code); assert_register!(DvmValue::Int(1), state, 0); } @@ -657,36 +557,20 @@ mod run_code_tests { fn load_object() { let dummy_impl = impl_with_object_field(); let dummy_impl_rc = Rc::new(dummy_impl); - let dummy_impl_object_field = dummy_impl_rc - .fields - .iter() - .find(|field| field.name() == "object_field") - .unwrap(); let mut dummy_lib = DmLib::new("dummy"); dummy_lib.implementations.push(dummy_impl_rc.clone()); let mut code = Vec::new(); - add_alloc( - &mut code, - 0, - dummy_impl_rc.size_in_bytes() as u32, - &dummy_impl_rc.fqn, - ); - add_alloc( - &mut code, - 1, - dummy_impl_rc.size_in_bytes() as u32, - &dummy_impl_rc.fqn, - ); - add_store(&mut code, 0, dummy_impl_object_field.data_offset(), 1); - add_load_object(&mut code, 2, 0, dummy_impl_object_field.data_offset()); + add_alloc(&mut code, 0, &dummy_impl_rc.fqn); + add_alloc(&mut code, 1, &dummy_impl_rc.fqn); + add_store(&mut code, 0, 0, 1); + add_load(&mut code, 2, 0, 0); - let (mut state, mut context) = setup(); + let (mut state, mut context) = setup(3); state.registers.resize(3, DvmValue::Uninit); context.load_libs(vec![Rc::new(dummy_lib)]); run_byte_code(&mut state, &context, &code); - let referenced_object = state.registers.get(1).unwrap().expect_object(); - assert_register!(DvmValue::Object(referenced_object), state, 2); + assert!(state.registers[2].is_object()) } } diff --git a/src/vm/object.rs b/src/vm/object.rs index be3f57c..5275d15 100644 --- a/src/vm/object.rs +++ b/src/vm/object.rs @@ -1,34 +1,52 @@ +use crate::vm::dm_type::DmType; use crate::vm::object_type::DmImplementation; use std::alloc::{alloc, dealloc, Layout}; -use std::collections::HashSet; +use std::ptr; use std::rc::Rc; #[derive(Debug, PartialEq, Eq)] pub struct DvmObject { - pub data: *mut u8, - pub units: HashSet, - pub size: usize, - pub layout: Layout, - pub implementation: Rc, + data: Vec<*mut u8>, + implementation: Rc, +} + +fn layout_for(dm_type: &DmType) -> Layout { + match dm_type { + DmType::Byte => Layout::new::(), + DmType::Int => Layout::new::(), + DmType::Long => Layout::new::(), + DmType::USize => Layout::new::(), + DmType::Double => Layout::new::(), + DmType::Boolean => Layout::new::(), + DmType::Object => Layout::new::>(), + } } impl DvmObject { - pub fn new(size: usize, implementation: Rc) -> Self { - let layout = Layout::from_size_align(size, 1).unwrap(); + pub fn new(implementation: Rc) -> Self { + let mut data = vec![ptr::null_mut(); implementation.fields.len()]; + for (index, field) in implementation.fields.iter().enumerate() { + data[index] = unsafe { alloc(layout_for(field.dm_type())) } + } DvmObject { - data: unsafe { alloc(layout) }, - units: HashSet::new(), - size, - layout, + data, implementation, } } + + pub fn data(&self) -> &[*mut u8] { + &self.data + } + + pub fn implementation(&self) -> &DmImplementation { + &self.implementation + } } impl Drop for DvmObject { fn drop(&mut self) { - unsafe { - dealloc(self.data, self.layout); + for (index, field) in self.implementation.fields.iter().enumerate() { + unsafe { dealloc(self.data[index], layout_for(field.dm_type())) } } } } diff --git a/src/vm/object_type.rs b/src/vm/object_type.rs index 83cdd51..36854a3 100644 --- a/src/vm/object_type.rs +++ b/src/vm/object_type.rs @@ -138,7 +138,7 @@ impl DmInterface { .find(|&dm_fn| dm_fn.fqn == name) .is_some() { - return self_object.implementation.get_method(name, self_object); + return self_object.implementation().get_method(name, self_object); } None } @@ -216,10 +216,6 @@ impl DmImplementation { pub fn get_field(&self, name: &str, self_object: &DvmObject) -> Option<&DmField> { self.fields.iter().find(|field| field.name == name) } - - pub fn size_in_bytes(&self) -> usize { - self.fields.iter().map(|field| field.size_in_bytes()).sum() - } } #[derive(Debug, Eq)] @@ -239,7 +235,6 @@ impl PartialEq for DmProperty { pub struct DmField { name: String, dm_type: DmType, - data_offset: usize, } impl PartialEq for DmField { @@ -249,11 +244,10 @@ impl PartialEq for DmField { } impl DmField { - pub fn new(name: &str, dm_type: DmType, data_offset: usize) -> Self { + pub fn new(name: &str, dm_type: DmType) -> Self { DmField { name: name.to_string(), dm_type, - data_offset, } } @@ -264,12 +258,4 @@ impl DmField { pub fn dm_type(&self) -> &DmType { &self.dm_type } - - pub fn data_offset(&self) -> usize { - self.data_offset - } - - pub fn size_in_bytes(&self) -> usize { - self.dm_type.size_in_bytes() - } } diff --git a/src/vm/op_codes.rs b/src/vm/op_codes.rs index d5d5508..053ef2a 100644 --- a/src/vm/op_codes.rs +++ b/src/vm/op_codes.rs @@ -51,7 +51,7 @@ pub const MOV_SIZE_OF: u8 = 0x30; pub const MULTIPLY: u8 = 0x40; -pub const LOAD_OBJECT: u8 = 0x50; +pub const LOAD: u8 = 0x50; pub const STORE: u8 = 0x60; @@ -79,10 +79,9 @@ pub fn add_mov_register(code: &mut Vec, target_register: u8, source_register code.push(source_register); } -pub fn add_alloc(code: &mut Vec, target_register: u8, size: u32, implementation_name: &str) { +pub fn add_alloc(code: &mut Vec, target_register: u8, implementation_name: &str) { code.push(ALLOC); code.push(target_register); - push_number!(code, size); push_number!(code, implementation_name.len() as u32); push_string!(code, implementation_name); } @@ -117,27 +116,27 @@ pub fn add_mov_register_to( code.push(source_register); } -pub fn add_load_object( +pub fn add_load( code: &mut Vec, target_register: u8, source_register: u8, - offset: usize + field_index: usize ) { - code.push(LOAD_OBJECT); + code.push(LOAD); code.push(target_register); code.push(source_register); - push_number!(code, offset); + push_number!(code, field_index); } pub fn add_store( code: &mut Vec, target_register: u8, - offset: usize, + field_index: usize, source_register: u8, ) { code.push(STORE); code.push(target_register); - push_number!(code, offset); + push_number!(code, field_index); code.push(source_register); } diff --git a/src/vm/platform/std_lib/core.rs b/src/vm/platform/std_lib/core.rs index 815b3a5..208e7df 100644 --- a/src/vm/platform/std_lib/core.rs +++ b/src/vm/platform/std_lib/core.rs @@ -1,5 +1,5 @@ use crate::vm::dvm_value::DvmValue; -use crate::vm::mem::get_field_value; +use crate::vm::mem::read_field_by_name; use crate::vm::object::DvmObject; use crate::vm::{DvmContext, DvmState}; use std::rc::Rc; @@ -8,9 +8,7 @@ pub fn dm_print(args: Vec, _state: &mut DvmState, _context: &DvmContex if args.len() != 1 { return DvmValue::Void; // TODO: make exception } - unsafe { - print!("{}", get_string(&args[0])); - } + print!("{}", get_string(&args[0])); DvmValue::Void } @@ -18,13 +16,11 @@ pub fn dm_println(args: Vec, _state: &mut DvmState, _context: &DvmCont if args.len() != 1 { return DvmValue::Uninit; } - unsafe { - println!("{}", get_string(&args[0])); - } + println!("{}", get_string(&args[0])); DvmValue::Void } -unsafe fn get_string(dvm_value: &DvmValue) -> String { +fn get_string(dvm_value: &DvmValue) -> String { match dvm_value { DvmValue::Byte(b) => b.to_string(), DvmValue::Int(i) => i.to_string(), @@ -39,7 +35,7 @@ unsafe fn get_string(dvm_value: &DvmValue) -> String { } fn object_to_string(alloc_object_rc: Rc) -> String { - if alloc_object_rc.implementation.fqn == "std::core::StringImpl" { + if alloc_object_rc.implementation().fqn == "std::core::StringImpl" { extract_string_from_string(alloc_object_rc.clone()) } else { todo!("what happens if we don't have a String?") @@ -47,26 +43,13 @@ fn object_to_string(alloc_object_rc: Rc) -> String { } fn extract_string_from_string(string_object: Rc) -> String { - let bytes_field = string_object - .implementation - .get_field("bytes", &string_object) - .expect("Could not get String.bytes field."); - let bytes_object = unsafe { get_field_value(&bytes_field, &string_object) }.expect_object(); - if bytes_object.implementation.fqn != "std::core::ArrayImpl" { + let bytes_object = read_field_by_name("bytes", &string_object).expect_object(); + if bytes_object.implementation().fqn != "std::core::ArrayImpl" { panic!("String.bytes field is not a std::core::ArrayImpl"); } - let ptr_address_field = bytes_object - .implementation - .get_field("ptr_address", &bytes_object) - .expect("Could not get ArrayImpl.ptr_address field."); - let address = unsafe { get_field_value(&ptr_address_field, &bytes_object) }.expect_usize(); - - let ptr_size_field = bytes_object - .implementation - .get_field("ptr_size", &bytes_object) - .expect("Could not get ArrayImpl.ptr_size field."); - let size = unsafe { get_field_value(&ptr_size_field, &bytes_object) }.expect_usize(); + let address = read_field_by_name("ptr_address", &bytes_object).expect_usize(); + let size = read_field_by_name("ptr_size", &bytes_object).expect_usize(); let raw_bytes_pointer = address as *mut u8; let mut v: Vec = Vec::new();