Fill out more VM actions
This commit is contained in:
parent
b0f7ca7992
commit
0292a01162
@ -3,15 +3,16 @@ use std::ops::Add;
|
|||||||
use tracing::trace;
|
use tracing::trace;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
instruction::InstructionFields,
|
|
||||||
vm::{call_frame::RuntimeValue, Thread},
|
vm::{call_frame::RuntimeValue, Thread},
|
||||||
DustString,
|
DustString, Instruction,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn add_bytes(_: &mut usize, instruction: &InstructionFields, thread: &mut Thread) {
|
use super::Cache;
|
||||||
let destination_index = instruction.a_field as usize;
|
|
||||||
let left_index = instruction.b_field as usize;
|
pub fn add_bytes(_: &mut usize, instruction: &Instruction, thread: &mut Thread, _: &mut Cache) {
|
||||||
let right_index = instruction.c_field as usize;
|
let destination_index = instruction.a_field() as usize;
|
||||||
|
let left_index = instruction.b_field() as usize;
|
||||||
|
let right_index = instruction.c_field() as usize;
|
||||||
|
|
||||||
let current_frame = thread.current_frame_mut();
|
let current_frame = thread.current_frame_mut();
|
||||||
let left_value = current_frame.get_byte_from_register(left_index).clone();
|
let left_value = current_frame.get_byte_from_register(left_index).clone();
|
||||||
@ -26,12 +27,17 @@ pub fn add_bytes(_: &mut usize, instruction: &InstructionFields, thread: &mut Th
|
|||||||
.set_inner(sum);
|
.set_inner(sum);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_characters(_: &mut usize, instruction: &InstructionFields, thread: &mut Thread) {
|
pub fn add_characters(
|
||||||
let destination_index = instruction.a_field as usize;
|
_: &mut usize,
|
||||||
let left_index = instruction.b_field as usize;
|
instruction: &Instruction,
|
||||||
let left_is_constant = instruction.b_is_constant;
|
thread: &mut Thread,
|
||||||
let right = instruction.c_field as usize;
|
_: &mut Cache,
|
||||||
let right_is_constant = instruction.c_is_constant;
|
) {
|
||||||
|
let destination_index = instruction.a_field() as usize;
|
||||||
|
let left_index = instruction.b_field() as usize;
|
||||||
|
let left_is_constant = instruction.b_is_constant();
|
||||||
|
let right = instruction.c_field() as usize;
|
||||||
|
let right_is_constant = instruction.c_is_constant();
|
||||||
|
|
||||||
let current_frame = thread.current_frame_mut();
|
let current_frame = thread.current_frame_mut();
|
||||||
let left_value = if left_is_constant {
|
let left_value = if left_is_constant {
|
||||||
@ -60,12 +66,12 @@ pub fn add_characters(_: &mut usize, instruction: &InstructionFields, thread: &m
|
|||||||
.set(concatenated);
|
.set(concatenated);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_floats(_: &mut usize, instruction: &InstructionFields, thread: &mut Thread) {
|
pub fn add_floats(_: &mut usize, instruction: &Instruction, thread: &mut Thread, _: &mut Cache) {
|
||||||
let destination = instruction.a_field as usize;
|
let destination = instruction.a_field() as usize;
|
||||||
let left = instruction.b_field as usize;
|
let left = instruction.b_field() as usize;
|
||||||
let left_is_constant = instruction.b_is_constant;
|
let left_is_constant = instruction.b_is_constant();
|
||||||
let right = instruction.c_field as usize;
|
let right = instruction.c_field() as usize;
|
||||||
let right_is_constant = instruction.c_is_constant;
|
let right_is_constant = instruction.c_is_constant();
|
||||||
|
|
||||||
let current_frame = thread.current_frame_mut();
|
let current_frame = thread.current_frame_mut();
|
||||||
let left_value = if left_is_constant {
|
let left_value = if left_is_constant {
|
||||||
@ -90,12 +96,12 @@ pub fn add_floats(_: &mut usize, instruction: &InstructionFields, thread: &mut T
|
|||||||
.set_inner(sum);
|
.set_inner(sum);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_integers(_: &mut usize, instruction: &InstructionFields, thread: &mut Thread) {
|
pub fn add_integers(_: &mut usize, instruction: &Instruction, thread: &mut Thread, _: &mut Cache) {
|
||||||
let destination = instruction.a_field as usize;
|
let destination = instruction.a_field() as usize;
|
||||||
let left = instruction.b_field as usize;
|
let left = instruction.b_field() as usize;
|
||||||
let left_is_constant = instruction.b_is_constant;
|
let left_is_constant = instruction.b_is_constant();
|
||||||
let right = instruction.c_field as usize;
|
let right = instruction.c_field() as usize;
|
||||||
let right_is_constant = instruction.c_is_constant;
|
let right_is_constant = instruction.c_is_constant();
|
||||||
|
|
||||||
let current_frame = thread.current_frame_mut();
|
let current_frame = thread.current_frame_mut();
|
||||||
let left_value = if left_is_constant {
|
let left_value = if left_is_constant {
|
||||||
@ -120,12 +126,12 @@ pub fn add_integers(_: &mut usize, instruction: &InstructionFields, thread: &mut
|
|||||||
.set_inner(sum);
|
.set_inner(sum);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_strings(_: &mut usize, instruction: &InstructionFields, thread: &mut Thread) {
|
pub fn add_strings(_: &mut usize, instruction: &Instruction, thread: &mut Thread, _: &mut Cache) {
|
||||||
let destination = instruction.a_field as usize;
|
let destination = instruction.a_field() as usize;
|
||||||
let left = instruction.b_field as usize;
|
let left = instruction.b_field() as usize;
|
||||||
let left_is_constant = instruction.b_is_constant;
|
let left_is_constant = instruction.b_is_constant();
|
||||||
let right = instruction.c_field as usize;
|
let right = instruction.c_field() as usize;
|
||||||
let right_is_constant = instruction.c_is_constant;
|
let right_is_constant = instruction.c_is_constant();
|
||||||
|
|
||||||
let current_frame = thread.current_frame_mut();
|
let current_frame = thread.current_frame_mut();
|
||||||
let left_value = if left_is_constant {
|
let left_value = if left_is_constant {
|
||||||
@ -148,12 +154,17 @@ pub fn add_strings(_: &mut usize, instruction: &InstructionFields, thread: &mut
|
|||||||
.set_inner(concatenated);
|
.set_inner(concatenated);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_character_string(_: &mut usize, instruction: &InstructionFields, thread: &mut Thread) {
|
pub fn add_character_string(
|
||||||
let destination = instruction.a_field as usize;
|
_: &mut usize,
|
||||||
let left = instruction.b_field as usize;
|
instruction: &Instruction,
|
||||||
let left_is_constant = instruction.b_is_constant;
|
thread: &mut Thread,
|
||||||
let right = instruction.c_field as usize;
|
_: &mut Cache,
|
||||||
let right_is_constant = instruction.c_is_constant;
|
) {
|
||||||
|
let destination = instruction.a_field() as usize;
|
||||||
|
let left = instruction.b_field() as usize;
|
||||||
|
let left_is_constant = instruction.b_is_constant();
|
||||||
|
let right = instruction.c_field() as usize;
|
||||||
|
let right_is_constant = instruction.c_is_constant();
|
||||||
|
|
||||||
let current_frame = thread.current_frame_mut();
|
let current_frame = thread.current_frame_mut();
|
||||||
let left_value = if left_is_constant {
|
let left_value = if left_is_constant {
|
||||||
@ -176,12 +187,17 @@ pub fn add_character_string(_: &mut usize, instruction: &InstructionFields, thre
|
|||||||
.set_inner(concatenated);
|
.set_inner(concatenated);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_string_character(_: &mut usize, instruction: &InstructionFields, thread: &mut Thread) {
|
pub fn add_string_character(
|
||||||
let destination = instruction.a_field as usize;
|
_: &mut usize,
|
||||||
let left = instruction.b_field as usize;
|
instruction: &Instruction,
|
||||||
let left_is_constant = instruction.b_is_constant;
|
thread: &mut Thread,
|
||||||
let right = instruction.c_field as usize;
|
_: &mut Cache,
|
||||||
let right_is_constant = instruction.c_is_constant;
|
) {
|
||||||
|
let destination = instruction.a_field() as usize;
|
||||||
|
let left = instruction.b_field() as usize;
|
||||||
|
let left_is_constant = instruction.b_is_constant();
|
||||||
|
let right = instruction.c_field() as usize;
|
||||||
|
let right_is_constant = instruction.c_is_constant();
|
||||||
|
|
||||||
let current_frame = thread.current_frame_mut();
|
let current_frame = thread.current_frame_mut();
|
||||||
let left_value = if left_is_constant {
|
let left_value = if left_is_constant {
|
||||||
@ -206,22 +222,22 @@ pub fn add_string_character(_: &mut usize, instruction: &InstructionFields, thre
|
|||||||
|
|
||||||
pub fn optimized_add_integer(
|
pub fn optimized_add_integer(
|
||||||
_: &mut usize,
|
_: &mut usize,
|
||||||
instruction: &InstructionFields,
|
instruction: &Instruction,
|
||||||
thread: &mut Thread,
|
thread: &mut Thread,
|
||||||
cache: &mut Option<[RuntimeValue<i64>; 3]>,
|
cache: &mut Cache,
|
||||||
) {
|
) {
|
||||||
if let Some([destination, left, right]) = cache {
|
if let Cache::IntegerMath([destination, left, right]) = cache {
|
||||||
trace!("OPTIMIZED_ADD using integer cache");
|
trace!("OPTIMIZED_ADD using integer cache");
|
||||||
|
|
||||||
let sum = left.add(right);
|
let sum = left.add(right);
|
||||||
|
|
||||||
*destination.borrow_mut() = sum;
|
*destination.borrow_mut() = sum;
|
||||||
} else {
|
} else {
|
||||||
let destination_index = instruction.a_field as usize;
|
let destination_index = instruction.a_field() as usize;
|
||||||
let left_index = instruction.b_field as usize;
|
let left_index = instruction.b_field() as usize;
|
||||||
let left_is_constant = instruction.b_is_constant;
|
let left_is_constant = instruction.b_is_constant();
|
||||||
let right_index = instruction.c_field as usize;
|
let right_index = instruction.c_field() as usize;
|
||||||
let right_is_constant = instruction.c_is_constant;
|
let right_is_constant = instruction.c_is_constant();
|
||||||
let current_frame = thread.current_frame_mut();
|
let current_frame = thread.current_frame_mut();
|
||||||
let left_value = if left_is_constant {
|
let left_value = if left_is_constant {
|
||||||
let value = current_frame.get_integer_constant_mut(left_index).to_rc();
|
let value = current_frame.get_integer_constant_mut(left_index).to_rc();
|
||||||
@ -266,6 +282,6 @@ pub fn optimized_add_integer(
|
|||||||
value
|
value
|
||||||
};
|
};
|
||||||
|
|
||||||
*cache = Some([destination, left_value, right_value]);
|
*cache = Cache::IntegerMath([destination, left_value, right_value]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,18 @@
|
|||||||
use tracing::trace;
|
use tracing::trace;
|
||||||
|
|
||||||
use crate::{
|
use crate::{vm::Thread, Instruction};
|
||||||
instruction::InstructionFields,
|
|
||||||
vm::{RuntimeValue, Thread},
|
|
||||||
};
|
|
||||||
|
|
||||||
pub fn equal_booleans(ip: &mut usize, instruction: &InstructionFields, thread: &mut Thread) {
|
use super::Cache;
|
||||||
let left_index = instruction.b_field as usize;
|
|
||||||
let right_index = instruction.c_field as usize;
|
pub fn equal_booleans(
|
||||||
let comparator = instruction.d_field;
|
ip: &mut usize,
|
||||||
|
instruction: &Instruction,
|
||||||
|
thread: &mut Thread,
|
||||||
|
_: &mut Cache,
|
||||||
|
) {
|
||||||
|
let left_index = instruction.b_field() as usize;
|
||||||
|
let right_index = instruction.c_field() as usize;
|
||||||
|
let comparator = instruction.d_field();
|
||||||
|
|
||||||
let current_frame = thread.current_frame_mut();
|
let current_frame = thread.current_frame_mut();
|
||||||
let left_value = current_frame.get_boolean_from_register(left_index);
|
let left_value = current_frame.get_boolean_from_register(left_index);
|
||||||
@ -20,10 +24,10 @@ pub fn equal_booleans(ip: &mut usize, instruction: &InstructionFields, thread: &
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn equal_bytes(ip: &mut usize, instruction: &InstructionFields, thread: &mut Thread) {
|
pub fn equal_bytes(ip: &mut usize, instruction: &Instruction, thread: &mut Thread, _: &mut Cache) {
|
||||||
let left = instruction.b_field as usize;
|
let left = instruction.b_field() as usize;
|
||||||
let right = instruction.c_field as usize;
|
let right = instruction.c_field() as usize;
|
||||||
let comparator = instruction.d_field;
|
let comparator = instruction.d_field();
|
||||||
|
|
||||||
let current_frame = thread.current_frame_mut();
|
let current_frame = thread.current_frame_mut();
|
||||||
let left_value = current_frame.get_byte_from_register(left);
|
let left_value = current_frame.get_byte_from_register(left);
|
||||||
@ -35,12 +39,17 @@ pub fn equal_bytes(ip: &mut usize, instruction: &InstructionFields, thread: &mut
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn equal_characters(ip: &mut usize, instruction: &InstructionFields, thread: &mut Thread) {
|
pub fn equal_characters(
|
||||||
let left_index = instruction.b_field as usize;
|
ip: &mut usize,
|
||||||
let left_is_constant = instruction.b_is_constant;
|
instruction: &Instruction,
|
||||||
let right_index = instruction.c_field as usize;
|
thread: &mut Thread,
|
||||||
let right_is_constant = instruction.c_is_constant;
|
_: &mut Cache,
|
||||||
let comparator = instruction.d_field;
|
) {
|
||||||
|
let left_index = instruction.b_field() as usize;
|
||||||
|
let left_is_constant = instruction.b_is_constant();
|
||||||
|
let right_index = instruction.c_field() as usize;
|
||||||
|
let right_is_constant = instruction.c_is_constant();
|
||||||
|
let comparator = instruction.d_field();
|
||||||
|
|
||||||
let current_frame = thread.current_frame_mut();
|
let current_frame = thread.current_frame_mut();
|
||||||
let left_value = if left_is_constant {
|
let left_value = if left_is_constant {
|
||||||
@ -60,12 +69,12 @@ pub fn equal_characters(ip: &mut usize, instruction: &InstructionFields, thread:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn equal_floats(ip: &mut usize, instruction: &InstructionFields, thread: &mut Thread) {
|
pub fn equal_floats(ip: &mut usize, instruction: &Instruction, thread: &mut Thread, _: &mut Cache) {
|
||||||
let left = instruction.b_field as usize;
|
let left = instruction.b_field() as usize;
|
||||||
let left_is_constant = instruction.b_is_constant;
|
let left_is_constant = instruction.b_is_constant();
|
||||||
let right = instruction.c_field as usize;
|
let right = instruction.c_field() as usize;
|
||||||
let right_is_constant = instruction.c_is_constant;
|
let right_is_constant = instruction.c_is_constant();
|
||||||
let comparator = instruction.d_field;
|
let comparator = instruction.d_field();
|
||||||
|
|
||||||
let current_frame = thread.current_frame_mut();
|
let current_frame = thread.current_frame_mut();
|
||||||
let left_value = if left_is_constant {
|
let left_value = if left_is_constant {
|
||||||
@ -85,12 +94,17 @@ pub fn equal_floats(ip: &mut usize, instruction: &InstructionFields, thread: &mu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn equal_integers(ip: &mut usize, instruction: &InstructionFields, thread: &mut Thread) {
|
pub fn equal_integers(
|
||||||
let left = instruction.b_field as usize;
|
ip: &mut usize,
|
||||||
let left_is_constant = instruction.b_is_constant;
|
instruction: &Instruction,
|
||||||
let right = instruction.c_field as usize;
|
thread: &mut Thread,
|
||||||
let right_is_constant = instruction.c_is_constant;
|
_: &mut Cache,
|
||||||
let comparator = instruction.d_field;
|
) {
|
||||||
|
let left = instruction.b_field() as usize;
|
||||||
|
let left_is_constant = instruction.b_is_constant();
|
||||||
|
let right = instruction.c_field() as usize;
|
||||||
|
let right_is_constant = instruction.c_is_constant();
|
||||||
|
let comparator = instruction.d_field();
|
||||||
|
|
||||||
let current_frame = thread.current_frame_mut();
|
let current_frame = thread.current_frame_mut();
|
||||||
let left_value = if left_is_constant {
|
let left_value = if left_is_constant {
|
||||||
@ -110,12 +124,17 @@ pub fn equal_integers(ip: &mut usize, instruction: &InstructionFields, thread: &
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn equal_strings(ip: &mut usize, instruction: &InstructionFields, thread: &mut Thread) {
|
pub fn equal_strings(
|
||||||
let left = instruction.b_field as usize;
|
ip: &mut usize,
|
||||||
let left_is_constant = instruction.b_is_constant;
|
instruction: &Instruction,
|
||||||
let right = instruction.c_field as usize;
|
thread: &mut Thread,
|
||||||
let right_is_constant = instruction.c_is_constant;
|
_: &mut Cache,
|
||||||
let comparator = instruction.d_field;
|
) {
|
||||||
|
let left = instruction.b_field() as usize;
|
||||||
|
let left_is_constant = instruction.b_is_constant();
|
||||||
|
let right = instruction.c_field() as usize;
|
||||||
|
let right_is_constant = instruction.c_is_constant();
|
||||||
|
let comparator = instruction.d_field();
|
||||||
|
|
||||||
let current_frame = thread.current_frame_mut();
|
let current_frame = thread.current_frame_mut();
|
||||||
let left_value = if left_is_constant {
|
let left_value = if left_is_constant {
|
||||||
@ -137,11 +156,11 @@ pub fn equal_strings(ip: &mut usize, instruction: &InstructionFields, thread: &m
|
|||||||
|
|
||||||
pub fn optimized_equal_integers(
|
pub fn optimized_equal_integers(
|
||||||
ip: &mut usize,
|
ip: &mut usize,
|
||||||
instruction: &InstructionFields,
|
instruction: &Instruction,
|
||||||
thread: &mut Thread,
|
thread: &mut Thread,
|
||||||
cache: &mut Option<[RuntimeValue<i64>; 3]>,
|
cache: &mut Cache,
|
||||||
) {
|
) {
|
||||||
if let Some([_, left, right]) = cache {
|
if let Cache::IntegerComparison([left, right]) = cache {
|
||||||
trace!("equal_INTEGERS_OPTIMIZED using cache");
|
trace!("equal_INTEGERS_OPTIMIZED using cache");
|
||||||
|
|
||||||
let is_equal = left == right;
|
let is_equal = left == right;
|
||||||
@ -150,11 +169,11 @@ pub fn optimized_equal_integers(
|
|||||||
*ip += 1;
|
*ip += 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let left_index = instruction.b_field as usize;
|
let left_index = instruction.b_field() as usize;
|
||||||
let left_is_constant = instruction.b_is_constant;
|
let left_is_constant = instruction.b_is_constant();
|
||||||
let right_index = instruction.c_field as usize;
|
let right_index = instruction.c_field() as usize;
|
||||||
let right_is_constant = instruction.c_is_constant;
|
let right_is_constant = instruction.c_is_constant();
|
||||||
let comparator = instruction.d_field;
|
let comparator = instruction.d_field();
|
||||||
|
|
||||||
let current_frame = thread.current_frame_mut();
|
let current_frame = thread.current_frame_mut();
|
||||||
let left_value = if left_is_constant {
|
let left_value = if left_is_constant {
|
||||||
@ -193,6 +212,6 @@ pub fn optimized_equal_integers(
|
|||||||
*ip += 1;
|
*ip += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
*cache = Some([RuntimeValue::Raw(0), left_value, right_value]);
|
*cache = Cache::IntegerComparison([left_value, right_value]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
use tracing::trace;
|
use tracing::trace;
|
||||||
|
|
||||||
use crate::{instruction::InstructionFields, vm::Thread};
|
use crate::{vm::Thread, Instruction};
|
||||||
|
|
||||||
pub fn jump(ip: &mut usize, instruction: &InstructionFields, _: &mut Thread) {
|
use super::Cache;
|
||||||
let offset = instruction.b_field as usize;
|
|
||||||
let is_positive = instruction.c_field != 0;
|
pub fn jump(ip: &mut usize, instruction: &Instruction, _: &mut Thread, _: &mut Cache) {
|
||||||
|
let offset = instruction.b_field() as usize;
|
||||||
|
let is_positive = instruction.c_field() != 0;
|
||||||
|
|
||||||
if is_positive {
|
if is_positive {
|
||||||
trace!("JUMP +{}", offset);
|
trace!("JUMP +{}", offset);
|
||||||
@ -18,3 +20,29 @@ pub fn jump(ip: &mut usize, instruction: &InstructionFields, _: &mut Thread) {
|
|||||||
*ip -= offset + 1;
|
*ip -= offset + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn optimized_jump_forward(
|
||||||
|
ip: &mut usize,
|
||||||
|
instruction: &Instruction,
|
||||||
|
_: &mut Thread,
|
||||||
|
_: &mut Cache,
|
||||||
|
) {
|
||||||
|
let offset = instruction.b_field() as usize;
|
||||||
|
|
||||||
|
trace!("JUMP +{}", offset);
|
||||||
|
|
||||||
|
*ip += offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn optimized_jump_backward(
|
||||||
|
ip: &mut usize,
|
||||||
|
instruction: &Instruction,
|
||||||
|
_: &mut Thread,
|
||||||
|
_: &mut Cache,
|
||||||
|
) {
|
||||||
|
let offset = instruction.b_field() as usize;
|
||||||
|
|
||||||
|
trace!("JUMP -{}", offset);
|
||||||
|
|
||||||
|
*ip -= offset + 1;
|
||||||
|
}
|
||||||
|
@ -1,14 +1,18 @@
|
|||||||
use tracing::trace;
|
use tracing::trace;
|
||||||
|
|
||||||
use crate::{
|
use crate::{vm::Thread, Instruction};
|
||||||
instruction::InstructionFields,
|
|
||||||
vm::{RuntimeValue, Thread},
|
|
||||||
};
|
|
||||||
|
|
||||||
pub fn less_booleans(ip: &mut usize, instruction: &InstructionFields, thread: &mut Thread) {
|
use super::Cache;
|
||||||
let left_index = instruction.b_field as usize;
|
|
||||||
let right_index = instruction.c_field as usize;
|
pub fn less_booleans(
|
||||||
let comparator = instruction.d_field;
|
ip: &mut usize,
|
||||||
|
instruction: &Instruction,
|
||||||
|
thread: &mut Thread,
|
||||||
|
_: &mut Cache,
|
||||||
|
) {
|
||||||
|
let left_index = instruction.b_field() as usize;
|
||||||
|
let right_index = instruction.c_field() as usize;
|
||||||
|
let comparator = instruction.d_field();
|
||||||
|
|
||||||
let current_frame = thread.current_frame_mut();
|
let current_frame = thread.current_frame_mut();
|
||||||
let left_value = current_frame.get_boolean_from_register(left_index);
|
let left_value = current_frame.get_boolean_from_register(left_index);
|
||||||
@ -20,10 +24,10 @@ pub fn less_booleans(ip: &mut usize, instruction: &InstructionFields, thread: &m
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn less_bytes(ip: &mut usize, instruction: &InstructionFields, thread: &mut Thread) {
|
pub fn less_bytes(ip: &mut usize, instruction: &Instruction, thread: &mut Thread, _: &mut Cache) {
|
||||||
let left = instruction.b_field as usize;
|
let left = instruction.b_field() as usize;
|
||||||
let right = instruction.c_field as usize;
|
let right = instruction.c_field() as usize;
|
||||||
let comparator = instruction.d_field;
|
let comparator = instruction.d_field();
|
||||||
|
|
||||||
let current_frame = thread.current_frame_mut();
|
let current_frame = thread.current_frame_mut();
|
||||||
let left_value = current_frame.get_byte_from_register(left);
|
let left_value = current_frame.get_byte_from_register(left);
|
||||||
@ -35,12 +39,17 @@ pub fn less_bytes(ip: &mut usize, instruction: &InstructionFields, thread: &mut
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn less_characters(ip: &mut usize, instruction: &InstructionFields, thread: &mut Thread) {
|
pub fn less_characters(
|
||||||
let left_index = instruction.b_field as usize;
|
ip: &mut usize,
|
||||||
let left_is_constant = instruction.b_is_constant;
|
instruction: &Instruction,
|
||||||
let right_index = instruction.c_field as usize;
|
thread: &mut Thread,
|
||||||
let right_is_constant = instruction.c_is_constant;
|
_: &mut Cache,
|
||||||
let comparator = instruction.d_field;
|
) {
|
||||||
|
let left_index = instruction.b_field() as usize;
|
||||||
|
let left_is_constant = instruction.b_is_constant();
|
||||||
|
let right_index = instruction.c_field() as usize;
|
||||||
|
let right_is_constant = instruction.c_is_constant();
|
||||||
|
let comparator = instruction.d_field();
|
||||||
|
|
||||||
let current_frame = thread.current_frame_mut();
|
let current_frame = thread.current_frame_mut();
|
||||||
let left_value = if left_is_constant {
|
let left_value = if left_is_constant {
|
||||||
@ -60,12 +69,12 @@ pub fn less_characters(ip: &mut usize, instruction: &InstructionFields, thread:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn less_floats(ip: &mut usize, instruction: &InstructionFields, thread: &mut Thread) {
|
pub fn less_floats(ip: &mut usize, instruction: &Instruction, thread: &mut Thread, _: &mut Cache) {
|
||||||
let left = instruction.b_field as usize;
|
let left = instruction.b_field() as usize;
|
||||||
let left_is_constant = instruction.b_is_constant;
|
let left_is_constant = instruction.b_is_constant();
|
||||||
let right = instruction.c_field as usize;
|
let right = instruction.c_field() as usize;
|
||||||
let right_is_constant = instruction.c_is_constant;
|
let right_is_constant = instruction.c_is_constant();
|
||||||
let comparator = instruction.d_field;
|
let comparator = instruction.d_field();
|
||||||
|
|
||||||
let current_frame = thread.current_frame_mut();
|
let current_frame = thread.current_frame_mut();
|
||||||
let left_value = if left_is_constant {
|
let left_value = if left_is_constant {
|
||||||
@ -85,12 +94,17 @@ pub fn less_floats(ip: &mut usize, instruction: &InstructionFields, thread: &mut
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn less_integers(ip: &mut usize, instruction: &InstructionFields, thread: &mut Thread) {
|
pub fn less_integers(
|
||||||
let left = instruction.b_field as usize;
|
ip: &mut usize,
|
||||||
let left_is_constant = instruction.b_is_constant;
|
instruction: &Instruction,
|
||||||
let right = instruction.c_field as usize;
|
thread: &mut Thread,
|
||||||
let right_is_constant = instruction.c_is_constant;
|
_: &mut Cache,
|
||||||
let comparator = instruction.d_field;
|
) {
|
||||||
|
let left = instruction.b_field() as usize;
|
||||||
|
let left_is_constant = instruction.b_is_constant();
|
||||||
|
let right = instruction.c_field() as usize;
|
||||||
|
let right_is_constant = instruction.c_is_constant();
|
||||||
|
let comparator = instruction.d_field();
|
||||||
|
|
||||||
let current_frame = thread.current_frame_mut();
|
let current_frame = thread.current_frame_mut();
|
||||||
let left_value = if left_is_constant {
|
let left_value = if left_is_constant {
|
||||||
@ -110,12 +124,12 @@ pub fn less_integers(ip: &mut usize, instruction: &InstructionFields, thread: &m
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn less_strings(ip: &mut usize, instruction: &InstructionFields, thread: &mut Thread) {
|
pub fn less_strings(ip: &mut usize, instruction: &Instruction, thread: &mut Thread, _: &mut Cache) {
|
||||||
let left = instruction.b_field as usize;
|
let left = instruction.b_field() as usize;
|
||||||
let left_is_constant = instruction.b_is_constant;
|
let left_is_constant = instruction.b_is_constant();
|
||||||
let right = instruction.c_field as usize;
|
let right = instruction.c_field() as usize;
|
||||||
let right_is_constant = instruction.c_is_constant;
|
let right_is_constant = instruction.c_is_constant();
|
||||||
let comparator = instruction.d_field;
|
let comparator = instruction.d_field();
|
||||||
|
|
||||||
let current_frame = thread.current_frame_mut();
|
let current_frame = thread.current_frame_mut();
|
||||||
let left_value = if left_is_constant {
|
let left_value = if left_is_constant {
|
||||||
@ -137,11 +151,11 @@ pub fn less_strings(ip: &mut usize, instruction: &InstructionFields, thread: &mu
|
|||||||
|
|
||||||
pub fn optimized_less_integers(
|
pub fn optimized_less_integers(
|
||||||
ip: &mut usize,
|
ip: &mut usize,
|
||||||
instruction: &InstructionFields,
|
instruction: &Instruction,
|
||||||
thread: &mut Thread,
|
thread: &mut Thread,
|
||||||
cache: &mut Option<[RuntimeValue<i64>; 3]>,
|
cache: &mut Cache,
|
||||||
) {
|
) {
|
||||||
if let Some([_, left, right]) = cache {
|
if let Cache::IntegerComparison([left, right]) = cache {
|
||||||
trace!("OPTIMIZED_LESS using integer cache");
|
trace!("OPTIMIZED_LESS using integer cache");
|
||||||
|
|
||||||
let is_less_than = left < right;
|
let is_less_than = left < right;
|
||||||
@ -150,11 +164,11 @@ pub fn optimized_less_integers(
|
|||||||
*ip += 1;
|
*ip += 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let left_index = instruction.b_field as usize;
|
let left_index = instruction.b_field() as usize;
|
||||||
let left_is_constant = instruction.b_is_constant;
|
let left_is_constant = instruction.b_is_constant();
|
||||||
let right_index = instruction.c_field as usize;
|
let right_index = instruction.c_field() as usize;
|
||||||
let right_is_constant = instruction.c_is_constant;
|
let right_is_constant = instruction.c_is_constant();
|
||||||
let comparator = instruction.d_field;
|
let comparator = instruction.d_field();
|
||||||
|
|
||||||
let current_frame = thread.current_frame_mut();
|
let current_frame = thread.current_frame_mut();
|
||||||
let left_value = if left_is_constant {
|
let left_value = if left_is_constant {
|
||||||
@ -193,6 +207,6 @@ pub fn optimized_less_integers(
|
|||||||
*ip += 1;
|
*ip += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
*cache = Some([RuntimeValue::Raw(0), left_value, right_value]);
|
*cache = Cache::IntegerComparison([left_value, right_value]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,18 @@
|
|||||||
use tracing::trace;
|
use tracing::trace;
|
||||||
|
|
||||||
use crate::{
|
use crate::{vm::Thread, Instruction};
|
||||||
instruction::InstructionFields,
|
|
||||||
vm::{RuntimeValue, Thread},
|
|
||||||
};
|
|
||||||
|
|
||||||
pub fn less_equal_booleans(ip: &mut usize, instruction: &InstructionFields, thread: &mut Thread) {
|
use super::Cache;
|
||||||
let left_index = instruction.b_field as usize;
|
|
||||||
let right_index = instruction.c_field as usize;
|
pub fn less_equal_booleans(
|
||||||
let comparator = instruction.d_field;
|
ip: &mut usize,
|
||||||
|
instruction: &Instruction,
|
||||||
|
thread: &mut Thread,
|
||||||
|
_: &mut Cache,
|
||||||
|
) {
|
||||||
|
let left_index = instruction.b_field() as usize;
|
||||||
|
let right_index = instruction.c_field() as usize;
|
||||||
|
let comparator = instruction.d_field();
|
||||||
|
|
||||||
let current_frame = thread.current_frame_mut();
|
let current_frame = thread.current_frame_mut();
|
||||||
let left_value = current_frame.get_boolean_from_register(left_index);
|
let left_value = current_frame.get_boolean_from_register(left_index);
|
||||||
@ -20,10 +24,15 @@ pub fn less_equal_booleans(ip: &mut usize, instruction: &InstructionFields, thre
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn less_equal_bytes(ip: &mut usize, instruction: &InstructionFields, thread: &mut Thread) {
|
pub fn less_equal_bytes(
|
||||||
let left = instruction.b_field as usize;
|
ip: &mut usize,
|
||||||
let right = instruction.c_field as usize;
|
instruction: &Instruction,
|
||||||
let comparator = instruction.d_field;
|
thread: &mut Thread,
|
||||||
|
_: &mut Cache,
|
||||||
|
) {
|
||||||
|
let left = instruction.b_field() as usize;
|
||||||
|
let right = instruction.c_field() as usize;
|
||||||
|
let comparator = instruction.d_field();
|
||||||
|
|
||||||
let current_frame = thread.current_frame_mut();
|
let current_frame = thread.current_frame_mut();
|
||||||
let left_value = current_frame.get_byte_from_register(left);
|
let left_value = current_frame.get_byte_from_register(left);
|
||||||
@ -35,12 +44,17 @@ pub fn less_equal_bytes(ip: &mut usize, instruction: &InstructionFields, thread:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn less_equal_characters(ip: &mut usize, instruction: &InstructionFields, thread: &mut Thread) {
|
pub fn less_equal_characters(
|
||||||
let left_index = instruction.b_field as usize;
|
ip: &mut usize,
|
||||||
let left_is_constant = instruction.b_is_constant;
|
instruction: &Instruction,
|
||||||
let right_index = instruction.c_field as usize;
|
thread: &mut Thread,
|
||||||
let right_is_constant = instruction.c_is_constant;
|
_: &mut Cache,
|
||||||
let comparator = instruction.d_field;
|
) {
|
||||||
|
let left_index = instruction.b_field() as usize;
|
||||||
|
let left_is_constant = instruction.b_is_constant();
|
||||||
|
let right_index = instruction.c_field() as usize;
|
||||||
|
let right_is_constant = instruction.c_is_constant();
|
||||||
|
let comparator = instruction.d_field();
|
||||||
|
|
||||||
let current_frame = thread.current_frame_mut();
|
let current_frame = thread.current_frame_mut();
|
||||||
let left_value = if left_is_constant {
|
let left_value = if left_is_constant {
|
||||||
@ -60,12 +74,17 @@ pub fn less_equal_characters(ip: &mut usize, instruction: &InstructionFields, th
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn less_equal_floats(ip: &mut usize, instruction: &InstructionFields, thread: &mut Thread) {
|
pub fn less_equal_floats(
|
||||||
let left = instruction.b_field as usize;
|
ip: &mut usize,
|
||||||
let left_is_constant = instruction.b_is_constant;
|
instruction: &Instruction,
|
||||||
let right = instruction.c_field as usize;
|
thread: &mut Thread,
|
||||||
let right_is_constant = instruction.c_is_constant;
|
_: &mut Cache,
|
||||||
let comparator = instruction.d_field;
|
) {
|
||||||
|
let left = instruction.b_field() as usize;
|
||||||
|
let left_is_constant = instruction.b_is_constant();
|
||||||
|
let right = instruction.c_field() as usize;
|
||||||
|
let right_is_constant = instruction.c_is_constant();
|
||||||
|
let comparator = instruction.d_field();
|
||||||
|
|
||||||
let current_frame = thread.current_frame_mut();
|
let current_frame = thread.current_frame_mut();
|
||||||
let left_value = if left_is_constant {
|
let left_value = if left_is_constant {
|
||||||
@ -85,12 +104,17 @@ pub fn less_equal_floats(ip: &mut usize, instruction: &InstructionFields, thread
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn less_equal_integers(ip: &mut usize, instruction: &InstructionFields, thread: &mut Thread) {
|
pub fn less_equal_integers(
|
||||||
let left = instruction.b_field as usize;
|
ip: &mut usize,
|
||||||
let left_is_constant = instruction.b_is_constant;
|
instruction: &Instruction,
|
||||||
let right = instruction.c_field as usize;
|
thread: &mut Thread,
|
||||||
let right_is_constant = instruction.c_is_constant;
|
_: &mut Cache,
|
||||||
let comparator = instruction.d_field;
|
) {
|
||||||
|
let left = instruction.b_field() as usize;
|
||||||
|
let left_is_constant = instruction.b_is_constant();
|
||||||
|
let right = instruction.c_field() as usize;
|
||||||
|
let right_is_constant = instruction.c_is_constant();
|
||||||
|
let comparator = instruction.d_field();
|
||||||
|
|
||||||
let current_frame = thread.current_frame_mut();
|
let current_frame = thread.current_frame_mut();
|
||||||
let left_value = if left_is_constant {
|
let left_value = if left_is_constant {
|
||||||
@ -110,12 +134,17 @@ pub fn less_equal_integers(ip: &mut usize, instruction: &InstructionFields, thre
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn less_equal_strings(ip: &mut usize, instruction: &InstructionFields, thread: &mut Thread) {
|
pub fn less_equal_strings(
|
||||||
let left = instruction.b_field as usize;
|
ip: &mut usize,
|
||||||
let left_is_constant = instruction.b_is_constant;
|
instruction: &Instruction,
|
||||||
let right = instruction.c_field as usize;
|
thread: &mut Thread,
|
||||||
let right_is_constant = instruction.c_is_constant;
|
_: &mut Cache,
|
||||||
let comparator = instruction.d_field;
|
) {
|
||||||
|
let left = instruction.b_field() as usize;
|
||||||
|
let left_is_constant = instruction.b_is_constant();
|
||||||
|
let right = instruction.c_field() as usize;
|
||||||
|
let right_is_constant = instruction.c_is_constant();
|
||||||
|
let comparator = instruction.d_field();
|
||||||
|
|
||||||
let current_frame = thread.current_frame_mut();
|
let current_frame = thread.current_frame_mut();
|
||||||
let left_value = if left_is_constant {
|
let left_value = if left_is_constant {
|
||||||
@ -137,11 +166,11 @@ pub fn less_equal_strings(ip: &mut usize, instruction: &InstructionFields, threa
|
|||||||
|
|
||||||
pub fn optimized_less_equal_integers(
|
pub fn optimized_less_equal_integers(
|
||||||
ip: &mut usize,
|
ip: &mut usize,
|
||||||
instruction: &InstructionFields,
|
instruction: &Instruction,
|
||||||
thread: &mut Thread,
|
thread: &mut Thread,
|
||||||
cache: &mut Option<[RuntimeValue<i64>; 3]>,
|
cache: &mut Cache,
|
||||||
) {
|
) {
|
||||||
if let Some([_, left, right]) = cache {
|
if let Cache::IntegerComparison([left, right]) = cache {
|
||||||
trace!("LESS_INTEGERS_OPTIMIZED using cache");
|
trace!("LESS_INTEGERS_OPTIMIZED using cache");
|
||||||
|
|
||||||
let is_less_than_or_equal = left <= right;
|
let is_less_than_or_equal = left <= right;
|
||||||
@ -150,11 +179,11 @@ pub fn optimized_less_equal_integers(
|
|||||||
*ip += 1;
|
*ip += 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let left_index = instruction.b_field as usize;
|
let left_index = instruction.b_field() as usize;
|
||||||
let left_is_constant = instruction.b_is_constant;
|
let left_is_constant = instruction.b_is_constant();
|
||||||
let right_index = instruction.c_field as usize;
|
let right_index = instruction.c_field() as usize;
|
||||||
let right_is_constant = instruction.c_is_constant;
|
let right_is_constant = instruction.c_is_constant();
|
||||||
let comparator = instruction.d_field;
|
let comparator = instruction.d_field();
|
||||||
|
|
||||||
let current_frame = thread.current_frame_mut();
|
let current_frame = thread.current_frame_mut();
|
||||||
let left_value = if left_is_constant {
|
let left_value = if left_is_constant {
|
||||||
@ -193,6 +222,6 @@ pub fn optimized_less_equal_integers(
|
|||||||
*ip += 1;
|
*ip += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
*cache = Some([RuntimeValue::Raw(0), left_value, right_value]);
|
*cache = Cache::IntegerComparison([left_value, right_value]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,8 +8,11 @@ use add::{
|
|||||||
add_bytes, add_character_string, add_characters, add_floats, add_integers,
|
add_bytes, add_character_string, add_characters, add_floats, add_integers,
|
||||||
add_string_character, add_strings, optimized_add_integer,
|
add_string_character, add_strings, optimized_add_integer,
|
||||||
};
|
};
|
||||||
use equal::optimized_equal_integers;
|
use equal::{
|
||||||
use jump::jump;
|
equal_booleans, equal_bytes, equal_characters, equal_floats, equal_integers, equal_strings,
|
||||||
|
optimized_equal_integers,
|
||||||
|
};
|
||||||
|
use jump::{jump, optimized_jump_backward, optimized_jump_forward};
|
||||||
use less::{
|
use less::{
|
||||||
less_booleans, less_bytes, less_characters, less_floats, less_integers, less_strings,
|
less_booleans, less_bytes, less_characters, less_floats, less_integers, less_strings,
|
||||||
optimized_less_integers,
|
optimized_less_integers,
|
||||||
@ -23,16 +26,11 @@ use tracing::info;
|
|||||||
|
|
||||||
use std::fmt::{self, Display, Formatter};
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
|
||||||
use crate::{
|
use crate::{instruction::TypeCode, AbstractList, ConcreteValue, Instruction, Operation, Value};
|
||||||
instruction::{InstructionFields, TypeCode},
|
|
||||||
AbstractList, ConcreteValue, Operation, Value,
|
|
||||||
};
|
|
||||||
|
|
||||||
use super::{call_frame::RuntimeValue, thread::Thread, Pointer};
|
use super::{call_frame::RuntimeValue, thread::Thread, Pointer};
|
||||||
|
|
||||||
pub type ActionLogic = fn(&mut usize, &InstructionFields, &mut Thread);
|
pub type ActionLogic = fn(&mut usize, &Instruction, &mut Thread, &mut Cache);
|
||||||
pub type OptimizedActionLogicIntegers =
|
|
||||||
fn(&mut usize, &InstructionFields, &mut Thread, &mut Option<[RuntimeValue<i64>; 3]>);
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ActionSequence {
|
pub struct ActionSequence {
|
||||||
@ -40,35 +38,43 @@ pub struct ActionSequence {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ActionSequence {
|
impl ActionSequence {
|
||||||
pub fn new(instructions: Vec<InstructionFields>) -> Self {
|
pub fn new<T: IntoIterator<Item = Instruction> + DoubleEndedIterator<Item = Instruction>>(
|
||||||
let mut actions = Vec::with_capacity(instructions.len());
|
instructions: T,
|
||||||
let mut instructions_reversed = instructions.into_iter().rev();
|
) -> Self {
|
||||||
|
let mut actions = Vec::new();
|
||||||
|
let mut instructions_reversed = instructions.rev();
|
||||||
|
|
||||||
while let Some(instruction) = instructions_reversed.next() {
|
while let Some(instruction) = instructions_reversed.next() {
|
||||||
if instruction.operation == Operation::JUMP {
|
if instruction.operation() == Operation::JUMP {
|
||||||
let backward_offset = instruction.b_field as usize;
|
let backward_offset = instruction.b_field() as usize;
|
||||||
let is_positive = instruction.c_field != 0;
|
let is_positive = instruction.c_field() != 0;
|
||||||
|
|
||||||
if !is_positive {
|
if !is_positive {
|
||||||
let mut loop_actions = Vec::with_capacity(backward_offset + 1);
|
let mut loop_actions = Vec::with_capacity(backward_offset);
|
||||||
let jump_action = Action::optimized(&instruction);
|
let jump_action = Action::optimized(instruction);
|
||||||
|
|
||||||
loop_actions.push(jump_action);
|
loop_actions.push(jump_action);
|
||||||
|
|
||||||
for _ in 0..backward_offset {
|
for _ in 0..backward_offset {
|
||||||
let instruction = instructions_reversed.next().unwrap();
|
let instruction = instructions_reversed.next().unwrap();
|
||||||
let action = Action::optimized(&instruction);
|
let action = Action::optimized(instruction);
|
||||||
|
|
||||||
loop_actions.push(action);
|
loop_actions.push(action);
|
||||||
}
|
}
|
||||||
|
|
||||||
loop_actions.reverse();
|
loop_actions.reverse();
|
||||||
|
|
||||||
let r#loop = Action::r#loop(ActionSequence {
|
let cache = Cache::LoopActions(ActionSequence {
|
||||||
actions: loop_actions,
|
actions: loop_actions,
|
||||||
});
|
});
|
||||||
|
|
||||||
actions.push(r#loop);
|
let action = Action {
|
||||||
|
instruction,
|
||||||
|
logic: r#loop,
|
||||||
|
cache,
|
||||||
|
};
|
||||||
|
|
||||||
|
actions.push(action);
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -97,27 +103,12 @@ impl ActionSequence {
|
|||||||
|
|
||||||
info!("Run {action}");
|
info!("Run {action}");
|
||||||
|
|
||||||
match action {
|
(action.logic)(
|
||||||
Action::Unoptimized { logic, instruction } => {
|
&mut local_ip,
|
||||||
logic(&mut local_ip, &*instruction, thread);
|
&action.instruction,
|
||||||
}
|
thread,
|
||||||
Action::Loop { actions } => {
|
&mut action.cache,
|
||||||
actions.run(thread);
|
);
|
||||||
}
|
|
||||||
Action::OptimizedIntegers {
|
|
||||||
logic,
|
|
||||||
instruction,
|
|
||||||
cache,
|
|
||||||
} => {
|
|
||||||
logic(&mut local_ip, &*instruction, thread, cache);
|
|
||||||
}
|
|
||||||
Action::OptimizedJumpForward { offset } => {
|
|
||||||
local_ip += *offset;
|
|
||||||
}
|
|
||||||
Action::OptimizedJumpBackward { offset } => {
|
|
||||||
local_ip -= *offset + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -139,30 +130,23 @@ impl Display for ActionSequence {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
enum Action {
|
pub struct Action {
|
||||||
Unoptimized {
|
instruction: Instruction,
|
||||||
logic: ActionLogic,
|
logic: ActionLogic,
|
||||||
instruction: InstructionFields,
|
cache: Cache,
|
||||||
},
|
}
|
||||||
Loop {
|
|
||||||
actions: ActionSequence,
|
#[derive(Debug)]
|
||||||
},
|
pub enum Cache {
|
||||||
OptimizedIntegers {
|
Empty,
|
||||||
logic: OptimizedActionLogicIntegers,
|
IntegerMath([RuntimeValue<i64>; 3]),
|
||||||
instruction: InstructionFields,
|
IntegerComparison([RuntimeValue<i64>; 2]),
|
||||||
cache: Option<[RuntimeValue<i64>; 3]>,
|
LoopActions(ActionSequence),
|
||||||
},
|
|
||||||
OptimizedJumpForward {
|
|
||||||
offset: usize,
|
|
||||||
},
|
|
||||||
OptimizedJumpBackward {
|
|
||||||
offset: usize,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Action {
|
impl Action {
|
||||||
pub fn unoptimized(instruction: InstructionFields) -> Self {
|
pub fn unoptimized(instruction: Instruction) -> Self {
|
||||||
let logic = match instruction.operation {
|
let logic = match instruction.operation() {
|
||||||
Operation::POINT => point,
|
Operation::POINT => point,
|
||||||
Operation::CLOSE => close,
|
Operation::CLOSE => close,
|
||||||
Operation::LOAD_ENCODED => load_encoded,
|
Operation::LOAD_ENCODED => load_encoded,
|
||||||
@ -170,7 +154,7 @@ impl Action {
|
|||||||
Operation::LOAD_LIST => load_list,
|
Operation::LOAD_LIST => load_list,
|
||||||
Operation::LOAD_FUNCTION => load_function,
|
Operation::LOAD_FUNCTION => load_function,
|
||||||
Operation::LOAD_SELF => load_self,
|
Operation::LOAD_SELF => load_self,
|
||||||
Operation::ADD => match (instruction.b_type, instruction.c_type) {
|
Operation::ADD => match (instruction.b_type(), instruction.c_type()) {
|
||||||
(TypeCode::INTEGER, TypeCode::INTEGER) => add_integers,
|
(TypeCode::INTEGER, TypeCode::INTEGER) => add_integers,
|
||||||
(TypeCode::FLOAT, TypeCode::FLOAT) => add_floats,
|
(TypeCode::FLOAT, TypeCode::FLOAT) => add_floats,
|
||||||
(TypeCode::BYTE, TypeCode::BYTE) => add_bytes,
|
(TypeCode::BYTE, TypeCode::BYTE) => add_bytes,
|
||||||
@ -186,16 +170,16 @@ impl Action {
|
|||||||
Operation::MODULO => modulo,
|
Operation::MODULO => modulo,
|
||||||
Operation::NEGATE => negate,
|
Operation::NEGATE => negate,
|
||||||
Operation::NOT => not,
|
Operation::NOT => not,
|
||||||
Operation::EQUAL => match (instruction.b_type, instruction.c_type) {
|
Operation::EQUAL => match (instruction.b_type(), instruction.c_type()) {
|
||||||
(TypeCode::BOOLEAN, TypeCode::BOOLEAN) => equal::equal_booleans,
|
(TypeCode::BOOLEAN, TypeCode::BOOLEAN) => equal_booleans,
|
||||||
(TypeCode::BYTE, TypeCode::BYTE) => equal::equal_bytes,
|
(TypeCode::BYTE, TypeCode::BYTE) => equal_bytes,
|
||||||
(TypeCode::CHARACTER, TypeCode::CHARACTER) => equal::equal_characters,
|
(TypeCode::CHARACTER, TypeCode::CHARACTER) => equal_characters,
|
||||||
(TypeCode::FLOAT, TypeCode::FLOAT) => equal::equal_floats,
|
(TypeCode::FLOAT, TypeCode::FLOAT) => equal_floats,
|
||||||
(TypeCode::INTEGER, TypeCode::INTEGER) => equal::equal_integers,
|
(TypeCode::INTEGER, TypeCode::INTEGER) => equal_integers,
|
||||||
(TypeCode::STRING, TypeCode::STRING) => equal::equal_strings,
|
(TypeCode::STRING, TypeCode::STRING) => equal_strings,
|
||||||
_ => todo!(),
|
_ => todo!(),
|
||||||
},
|
},
|
||||||
Operation::LESS => match (instruction.b_type, instruction.c_type) {
|
Operation::LESS => match (instruction.b_type(), instruction.c_type()) {
|
||||||
(TypeCode::BOOLEAN, TypeCode::BOOLEAN) => less_booleans,
|
(TypeCode::BOOLEAN, TypeCode::BOOLEAN) => less_booleans,
|
||||||
(TypeCode::BYTE, TypeCode::BYTE) => less_bytes,
|
(TypeCode::BYTE, TypeCode::BYTE) => less_bytes,
|
||||||
(TypeCode::CHARACTER, TypeCode::CHARACTER) => less_characters,
|
(TypeCode::CHARACTER, TypeCode::CHARACTER) => less_characters,
|
||||||
@ -204,7 +188,7 @@ impl Action {
|
|||||||
(TypeCode::STRING, TypeCode::STRING) => less_strings,
|
(TypeCode::STRING, TypeCode::STRING) => less_strings,
|
||||||
_ => todo!(),
|
_ => todo!(),
|
||||||
},
|
},
|
||||||
Operation::LESS_EQUAL => match (instruction.b_type, instruction.c_type) {
|
Operation::LESS_EQUAL => match (instruction.b_type(), instruction.c_type()) {
|
||||||
(TypeCode::BOOLEAN, TypeCode::BOOLEAN) => less_equal_booleans,
|
(TypeCode::BOOLEAN, TypeCode::BOOLEAN) => less_equal_booleans,
|
||||||
(TypeCode::BYTE, TypeCode::BYTE) => less_equal_bytes,
|
(TypeCode::BYTE, TypeCode::BYTE) => less_equal_bytes,
|
||||||
(TypeCode::CHARACTER, TypeCode::CHARACTER) => less_equal_characters,
|
(TypeCode::CHARACTER, TypeCode::CHARACTER) => less_equal_characters,
|
||||||
@ -222,100 +206,80 @@ impl Action {
|
|||||||
_ => todo!(),
|
_ => todo!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
Action::Unoptimized { logic, instruction }
|
Action {
|
||||||
}
|
instruction,
|
||||||
|
logic,
|
||||||
pub fn optimized(instruction: &InstructionFields) -> Self {
|
cache: Cache::Empty,
|
||||||
match instruction.operation {
|
|
||||||
Operation::ADD => match (instruction.b_type, instruction.c_type) {
|
|
||||||
(TypeCode::INTEGER, TypeCode::INTEGER) => Action::OptimizedIntegers {
|
|
||||||
logic: optimized_add_integer,
|
|
||||||
instruction: *instruction,
|
|
||||||
cache: None,
|
|
||||||
},
|
|
||||||
_ => todo!(),
|
|
||||||
},
|
|
||||||
Operation::EQUAL => match (instruction.b_type, instruction.c_type) {
|
|
||||||
(TypeCode::INTEGER, TypeCode::INTEGER) => Action::OptimizedIntegers {
|
|
||||||
logic: optimized_equal_integers,
|
|
||||||
instruction: *instruction,
|
|
||||||
cache: None,
|
|
||||||
},
|
|
||||||
_ => todo!(),
|
|
||||||
},
|
|
||||||
Operation::LESS => match (instruction.b_type, instruction.c_type) {
|
|
||||||
(TypeCode::INTEGER, TypeCode::INTEGER) => Action::OptimizedIntegers {
|
|
||||||
logic: optimized_less_integers,
|
|
||||||
instruction: *instruction,
|
|
||||||
cache: None,
|
|
||||||
},
|
|
||||||
_ => todo!(),
|
|
||||||
},
|
|
||||||
Operation::LESS_EQUAL => match (instruction.b_type, instruction.c_type) {
|
|
||||||
(TypeCode::INTEGER, TypeCode::INTEGER) => Action::OptimizedIntegers {
|
|
||||||
logic: optimized_less_equal_integers,
|
|
||||||
instruction: *instruction,
|
|
||||||
cache: None,
|
|
||||||
},
|
|
||||||
_ => todo!(),
|
|
||||||
},
|
|
||||||
Operation::JUMP => {
|
|
||||||
let offset = instruction.b_field as usize;
|
|
||||||
let is_positive = instruction.c_field != 0;
|
|
||||||
|
|
||||||
if is_positive {
|
|
||||||
Action::OptimizedJumpForward { offset }
|
|
||||||
} else {
|
|
||||||
Action::OptimizedJumpBackward { offset }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => todo!(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn r#loop(actions: ActionSequence) -> Self {
|
pub fn optimized(instruction: Instruction) -> Self {
|
||||||
Action::Loop { actions }
|
let logic = match instruction.operation() {
|
||||||
|
Operation::JUMP => match instruction.c_field() {
|
||||||
|
0 => optimized_jump_backward,
|
||||||
|
_ => optimized_jump_forward,
|
||||||
|
},
|
||||||
|
Operation::ADD => match (instruction.b_type(), instruction.c_type()) {
|
||||||
|
(TypeCode::INTEGER, TypeCode::INTEGER) => optimized_add_integer,
|
||||||
|
_ => todo!(),
|
||||||
|
},
|
||||||
|
Operation::EQUAL => match (instruction.b_type(), instruction.c_type()) {
|
||||||
|
(TypeCode::INTEGER, TypeCode::INTEGER) => optimized_equal_integers,
|
||||||
|
_ => todo!(),
|
||||||
|
},
|
||||||
|
Operation::LESS => match (instruction.b_type(), instruction.c_type()) {
|
||||||
|
(TypeCode::INTEGER, TypeCode::INTEGER) => optimized_less_integers,
|
||||||
|
_ => todo!(),
|
||||||
|
},
|
||||||
|
Operation::LESS_EQUAL => match (instruction.b_type(), instruction.c_type()) {
|
||||||
|
(TypeCode::INTEGER, TypeCode::INTEGER) => optimized_less_equal_integers,
|
||||||
|
_ => todo!(),
|
||||||
|
},
|
||||||
|
_ => todo!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
Action {
|
||||||
|
instruction,
|
||||||
|
logic,
|
||||||
|
cache: Cache::Empty,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for Action {
|
impl Display for Action {
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
match self {
|
if let Cache::LoopActions(actions) = &self.cache {
|
||||||
Action::Unoptimized { instruction, .. } => {
|
write!(f, "LOOP: {actions}")?;
|
||||||
write!(f, "{}", instruction.operation)
|
} else {
|
||||||
}
|
write!(f, "{}", self.instruction.operation())?;
|
||||||
Action::Loop { actions } => {
|
|
||||||
write!(f, "LOOP: {actions}")
|
|
||||||
}
|
|
||||||
Action::OptimizedIntegers { instruction, .. } => {
|
|
||||||
write!(f, "OPTIMIZED_{}", instruction.operation)
|
|
||||||
}
|
|
||||||
Action::OptimizedJumpForward { offset } => {
|
|
||||||
write!(f, "JUMP +{offset}")
|
|
||||||
}
|
|
||||||
Action::OptimizedJumpBackward { offset } => {
|
|
||||||
write!(f, "JUMP -{offset}")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn point(_: &mut usize, instruction: &InstructionFields, thread: &mut Thread) {
|
fn r#loop(_: &mut usize, _: &Instruction, thread: &mut Thread, cache: &mut Cache) {
|
||||||
|
if let Cache::LoopActions(actions) = cache {
|
||||||
|
actions.run(thread);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn point(_: &mut usize, instruction: &Instruction, thread: &mut Thread, _: &mut Cache) {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn close(_: &mut usize, instruction: &InstructionFields, thread: &mut Thread) {
|
fn close(_: &mut usize, instruction: &Instruction, thread: &mut Thread, _: &mut Cache) {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_encoded(ip: &mut usize, instruction: &InstructionFields, thread: &mut Thread) {
|
fn load_encoded(ip: &mut usize, instruction: &Instruction, thread: &mut Thread, _: &mut Cache) {
|
||||||
let destination = instruction.a_field;
|
let destination = instruction.a_field();
|
||||||
let value_type = instruction.b_type;
|
let value_type = instruction.b_type();
|
||||||
let jump_next = instruction.c_field != 0;
|
let jump_next = instruction.c_field() != 0;
|
||||||
|
|
||||||
match value_type {
|
match value_type {
|
||||||
TypeCode::BOOLEAN => {
|
TypeCode::BOOLEAN => {
|
||||||
let value = instruction.b_field != 0;
|
let value = instruction.b_field() != 0;
|
||||||
|
|
||||||
thread
|
thread
|
||||||
.current_frame_mut()
|
.current_frame_mut()
|
||||||
@ -326,7 +290,7 @@ fn load_encoded(ip: &mut usize, instruction: &InstructionFields, thread: &mut Th
|
|||||||
.set_inner(value);
|
.set_inner(value);
|
||||||
}
|
}
|
||||||
TypeCode::BYTE => {
|
TypeCode::BYTE => {
|
||||||
let value = instruction.b_field as u8;
|
let value = instruction.b_field() as u8;
|
||||||
|
|
||||||
thread
|
thread
|
||||||
.current_frame_mut()
|
.current_frame_mut()
|
||||||
@ -344,11 +308,11 @@ fn load_encoded(ip: &mut usize, instruction: &InstructionFields, thread: &mut Th
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_constant(ip: &mut usize, instruction: &InstructionFields, thread: &mut Thread) {
|
fn load_constant(ip: &mut usize, instruction: &Instruction, thread: &mut Thread, _: &mut Cache) {
|
||||||
let destination = instruction.a_field as usize;
|
let destination = instruction.a_field() as usize;
|
||||||
let constant_index = instruction.b_field as usize;
|
let constant_index = instruction.b_field() as usize;
|
||||||
let constant_type = instruction.b_type;
|
let constant_type = instruction.b_type();
|
||||||
let jump_next = instruction.c_field != 0;
|
let jump_next = instruction.c_field() != 0;
|
||||||
let current_frame = thread.current_frame_mut();
|
let current_frame = thread.current_frame_mut();
|
||||||
|
|
||||||
match constant_type {
|
match constant_type {
|
||||||
@ -396,12 +360,12 @@ fn load_constant(ip: &mut usize, instruction: &InstructionFields, thread: &mut T
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_list(ip: &mut usize, instruction: &InstructionFields, thread: &mut Thread) {
|
fn load_list(ip: &mut usize, instruction: &Instruction, thread: &mut Thread, _: &mut Cache) {
|
||||||
let destination = instruction.a_field as usize;
|
let destination = instruction.a_field() as usize;
|
||||||
let start_register = instruction.b_field as usize;
|
let start_register = instruction.b_field() as usize;
|
||||||
let item_type = instruction.b_type;
|
let item_type = instruction.b_type();
|
||||||
let end_register = instruction.c_field as usize;
|
let end_register = instruction.c_field() as usize;
|
||||||
let jump_next = instruction.d_field;
|
let jump_next = instruction.d_field();
|
||||||
let current_frame = thread.current_frame_mut();
|
let current_frame = thread.current_frame_mut();
|
||||||
|
|
||||||
let mut item_pointers = Vec::with_capacity(end_register - start_register + 1);
|
let mut item_pointers = Vec::with_capacity(end_register - start_register + 1);
|
||||||
@ -489,58 +453,58 @@ fn load_list(ip: &mut usize, instruction: &InstructionFields, thread: &mut Threa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_function(_: &mut usize, _: &InstructionFields, _: &mut Thread) {
|
fn load_function(_: &mut usize, _: &Instruction, _: &mut Thread, _: &mut Cache) {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_self(_: &mut usize, _: &InstructionFields, _: &mut Thread) {
|
fn load_self(_: &mut usize, _: &Instruction, _: &mut Thread, _: &mut Cache) {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn subtract(_: &mut usize, instruction: &InstructionFields, thread: &mut Thread) {
|
fn subtract(_: &mut usize, instruction: &Instruction, thread: &mut Thread, _: &mut Cache) {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn multiply(_: &mut usize, instruction: &InstructionFields, thread: &mut Thread) {
|
fn multiply(_: &mut usize, instruction: &Instruction, thread: &mut Thread, _: &mut Cache) {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn divide(_: &mut usize, instruction: &InstructionFields, thread: &mut Thread) {
|
fn divide(_: &mut usize, instruction: &Instruction, thread: &mut Thread, _: &mut Cache) {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn modulo(_: &mut usize, instruction: &InstructionFields, thread: &mut Thread) {
|
fn modulo(_: &mut usize, instruction: &Instruction, thread: &mut Thread, _: &mut Cache) {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test(ip: &mut usize, instruction: &InstructionFields, thread: &mut Thread) {
|
fn test(ip: &mut usize, instruction: &Instruction, thread: &mut Thread, _: &mut Cache) {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_set(_: &mut usize, _: &InstructionFields, _: &mut Thread) {
|
fn test_set(_: &mut usize, _: &Instruction, _: &mut Thread, _: &mut Cache) {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn negate(_: &mut usize, _: &InstructionFields, _: &mut Thread) {
|
fn negate(_: &mut usize, _: &Instruction, _: &mut Thread, _: &mut Cache) {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn not(_: &mut usize, _: &InstructionFields, _: &mut Thread) {
|
fn not(_: &mut usize, _: &Instruction, _: &mut Thread, _: &mut Cache) {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call(_: &mut usize, _: &InstructionFields, _: &mut Thread) {
|
fn call(_: &mut usize, _: &Instruction, _: &mut Thread, _: &mut Cache) {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call_native(_: &mut usize, _: &InstructionFields, _: &mut Thread) {
|
fn call_native(_: &mut usize, _: &Instruction, _: &mut Thread, _: &mut Cache) {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn r#return(_: &mut usize, instruction: &InstructionFields, thread: &mut Thread) {
|
fn r#return(_: &mut usize, instruction: &Instruction, thread: &mut Thread, _: &mut Cache) {
|
||||||
let should_return_value = instruction.b_field != 0;
|
let should_return_value = instruction.b_field() != 0;
|
||||||
let return_register = instruction.c_field as usize;
|
let return_register = instruction.c_field() as usize;
|
||||||
let return_type = instruction.b_type;
|
let return_type = instruction.b_type();
|
||||||
let current_frame = thread.current_frame();
|
let current_frame = thread.current_frame();
|
||||||
|
|
||||||
if should_return_value {
|
if should_return_value {
|
||||||
|
@ -3,7 +3,6 @@ use std::{rc::Rc, thread::JoinHandle};
|
|||||||
use tracing::{info, trace};
|
use tracing::{info, trace};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
instruction::InstructionFields,
|
|
||||||
vm::{action::ActionSequence, CallFrame},
|
vm::{action::ActionSequence, CallFrame},
|
||||||
Chunk, DustString, Span, Value,
|
Chunk, DustString, Span, Value,
|
||||||
};
|
};
|
||||||
@ -39,13 +38,7 @@ impl Thread {
|
|||||||
.unwrap_or_else(|| DustString::from("anonymous"))
|
.unwrap_or_else(|| DustString::from("anonymous"))
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut actions = ActionSequence::new(
|
let mut actions = ActionSequence::new(self.chunk.instructions.iter().copied());
|
||||||
self.chunk
|
|
||||||
.instructions
|
|
||||||
.iter()
|
|
||||||
.map(InstructionFields::from)
|
|
||||||
.collect(),
|
|
||||||
);
|
|
||||||
|
|
||||||
trace!("Thread actions: {}", actions);
|
trace!("Thread actions: {}", actions);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user