Compare commits
No commits in common. "652c1dd7f2d2992d2b1bdbb90aa02ee793e2deac" and "a7a8b39836ce74204380cc6770809ad73e8ac31f" have entirely different histories.
652c1dd7f2
...
a7a8b39836
@ -152,27 +152,9 @@ The source register must contain a `DvmValue::Object` at runtime.
|
|||||||
|
|
||||||
=== Load Boolean
|
=== 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
|
=== Store
|
||||||
|
|
||||||
Stores the value contained in the source register to the offset from the base of the object contained in the target
|
Stores the value contained in the source register to the offset from the base of the object contained in the target register.
|
||||||
register.
|
|
||||||
|
|
||||||
[source]
|
[source]
|
||||||
----
|
----
|
||||||
@ -198,8 +180,7 @@ alloc(
|
|||||||
)
|
)
|
||||||
----
|
----
|
||||||
|
|
||||||
The `implementation_name` is the bytes array of a UTF-8-encoded string, and `implementation_name_length` is the length
|
The `implementation_name` is the bytes array of a UTF-8-encoded string, and `implementation_name_length` is the length of that array.
|
||||||
of that array.
|
|
||||||
|
|
||||||
=== Deallocate
|
=== Deallocate
|
||||||
|
|
||||||
|
108
src/vm/mod.rs
108
src/vm/mod.rs
@ -213,16 +213,6 @@ 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 {
|
macro_rules! read_array_u8 {
|
||||||
( $iter: expr ) => {{
|
( $iter: expr ) => {{
|
||||||
let arr_length = next_8!($iter, u8);
|
let arr_length = next_8!($iter, u8);
|
||||||
@ -294,70 +284,6 @@ pub fn run_byte_code(state: &mut DvmState, context: &DvmContext, byte_code: &[u8
|
|||||||
let source_value = state.registers.get(source_register).unwrap();
|
let source_value = state.registers.get(source_register).unwrap();
|
||||||
state.registers[target_register] = source_value.clone();
|
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 => {
|
ALLOC => {
|
||||||
let target_register = next_8!(iter, usize);
|
let target_register = next_8!(iter, usize);
|
||||||
let alloc_size = next_32_le!(iter, usize);
|
let alloc_size = next_32_le!(iter, usize);
|
||||||
@ -590,8 +516,6 @@ pub fn run_byte_code(state: &mut DvmState, context: &DvmContext, byte_code: &[u8
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod run_code_tests {
|
mod run_code_tests {
|
||||||
use crate::vm::dm_type::DmType;
|
|
||||||
use crate::vm::object_type::{DmField, DmImplementation};
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
macro_rules! assert_register {
|
macro_rules! assert_register {
|
||||||
@ -607,13 +531,6 @@ mod run_code_tests {
|
|||||||
(DvmState::new(), DvmContext::new())
|
(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]
|
#[test]
|
||||||
fn mov_1_as_int() {
|
fn mov_1_as_int() {
|
||||||
let mut code = Vec::new();
|
let mut code = Vec::new();
|
||||||
@ -651,29 +568,4 @@ mod run_code_tests {
|
|||||||
run_byte_code(&mut state, &context, &code);
|
run_byte_code(&mut state, &context, &code);
|
||||||
assert_register!(DvmValue::Int(1), state, 0);
|
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -51,10 +51,6 @@ pub const MOV_SIZE_OF: u8 = 0x30;
|
|||||||
|
|
||||||
pub const MULTIPLY: u8 = 0x40;
|
pub const MULTIPLY: u8 = 0x40;
|
||||||
|
|
||||||
pub const LOAD_OBJECT: u8 = 0x50;
|
|
||||||
|
|
||||||
pub const STORE: u8 = 0x60;
|
|
||||||
|
|
||||||
macro_rules! push_number {
|
macro_rules! push_number {
|
||||||
( $dest: expr, $num: expr ) => {
|
( $dest: expr, $num: expr ) => {
|
||||||
push_bytes!($dest, $num.to_le_bytes())
|
push_bytes!($dest, $num.to_le_bytes())
|
||||||
@ -117,30 +113,6 @@ pub fn add_mov_register_to(
|
|||||||
code.push(source_register);
|
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(
|
pub fn add_mov_const(
|
||||||
code: &mut Vec<u8>,
|
code: &mut Vec<u8>,
|
||||||
address_register: u8,
|
address_register: u8,
|
||||||
|
Loading…
Reference in New Issue
Block a user