Compare commits

...

2 Commits

Author SHA1 Message Date
Jesse Brault
652c1dd7f2 Add basic, but failing, implementation of load/store object. 2024-12-28 08:52:35 -06:00
Jesse Brault
574f7ea7a1 Add load_object to op codes documentation. 2024-12-27 11:31:19 -06:00
3 changed files with 157 additions and 2 deletions

View File

@ -152,9 +152,27 @@ The source register must contain a `DvmValue::Object` at runtime.
=== Load Boolean
=== Load Object
Loads the target register with the `DvmValue::Object` stored at the offset from the base of the object stored in the
source register.
[source]
----
load_object(
target_register: u8,
source_register: u8,
offset: usize
)
----
The source register must contain a `DvmValue::Object` at runtime, and the data at the offset from that object's base
must be a valid `Rc<DvmObject>`.
=== Store
Stores the value contained in the source register to the offset from the base of the object contained in the target register.
Stores the value contained in the source register to the offset from the base of the object contained in the target
register.
[source]
----
@ -180,7 +198,8 @@ alloc(
)
----
The `implementation_name` is the bytes array of a UTF-8-encoded string, and `implementation_name_length` is the length of that array.
The `implementation_name` is the bytes array of a UTF-8-encoded string, and `implementation_name_length` is the length
of that array.
=== Deallocate

View File

@ -213,6 +213,16 @@ macro_rules! next_64_le {
};
}
macro_rules! next_usize_le {
( $byte_code: expr ) => {{
let mut u: usize = 0;
for i in 0..std::mem::size_of::<usize>() {
u += next_8!($byte_code, usize) << (8 * i);
}
u
}};
}
macro_rules! read_array_u8 {
( $iter: expr ) => {{
let arr_length = next_8!($iter, u8);
@ -284,6 +294,70 @@ 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 => {
let target_register = next_8!(iter, usize);
let source_register = next_8!(iter, usize);
let offset = next_usize_le!(iter);
let source_object = state.registers
.get(source_register)
.unwrap()
.expect_object();
let object = unsafe {
Rc::from_raw(source_object.data.add(offset).cast::<DmAllocObject>())
};
state.registers[target_register] = DvmValue::Object(object);
}
STORE => {
let target_register = next_8!(iter, usize);
let offset = next_usize_le!(iter);
let source_register = next_8!(iter, usize);
let target_alloc_object = state
.registers
.get(target_register)
.unwrap()
.expect_object();
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.")
}
}
}
ALLOC => {
let target_register = next_8!(iter, usize);
let alloc_size = next_32_le!(iter, usize);
@ -516,6 +590,8 @@ pub fn run_byte_code(state: &mut DvmState, context: &DvmContext, byte_code: &[u8
#[cfg(test)]
mod run_code_tests {
use crate::vm::dm_type::DmType;
use crate::vm::object_type::{DmField, DmImplementation};
use super::*;
macro_rules! assert_register {
@ -530,6 +606,13 @@ mod run_code_tests {
fn setup() -> (DvmState, DvmContext) {
(DvmState::new(), 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);
dm_impl.fields.push(object_field);
dm_impl
}
#[test]
fn mov_1_as_int() {
@ -568,4 +651,29 @@ mod run_code_tests {
run_byte_code(&mut state, &context, &code);
assert_register!(DvmValue::Int(1), state, 0);
}
#[test]
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());
let (mut state, mut context) = setup();
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);
}
}

View File

@ -51,6 +51,10 @@ pub const MOV_SIZE_OF: u8 = 0x30;
pub const MULTIPLY: u8 = 0x40;
pub const LOAD_OBJECT: u8 = 0x50;
pub const STORE: u8 = 0x60;
macro_rules! push_number {
( $dest: expr, $num: expr ) => {
push_bytes!($dest, $num.to_le_bytes())
@ -113,6 +117,30 @@ pub fn add_mov_register_to(
code.push(source_register);
}
pub fn add_load_object(
code: &mut Vec<u8>,
target_register: u8,
source_register: u8,
offset: usize
) {
code.push(LOAD_OBJECT);
code.push(target_register);
code.push(source_register);
push_number!(code, offset);
}
pub fn add_store(
code: &mut Vec<u8>,
target_register: u8,
offset: usize,
source_register: u8,
) {
code.push(STORE);
code.push(target_register);
push_number!(code, offset);
code.push(source_register);
}
pub fn add_mov_const(
code: &mut Vec<u8>,
address_register: u8,