From 0292a011628baec83155e7178b7318d9b61f86c0 Mon Sep 17 00:00:00 2001 From: Jeff Date: Mon, 17 Feb 2025 06:18:34 -0500 Subject: [PATCH] Fill out more VM actions --- dust-lang/src/vm/action/add.rs | 118 +++++----- dust-lang/src/vm/action/equal.rs | 109 +++++---- dust-lang/src/vm/action/jump.rs | 36 ++- dust-lang/src/vm/action/less.rs | 104 +++++---- dust-lang/src/vm/action/less_equal.rs | 119 ++++++---- dust-lang/src/vm/action/mod.rs | 310 ++++++++++++-------------- dust-lang/src/vm/thread.rs | 9 +- 7 files changed, 434 insertions(+), 371 deletions(-) diff --git a/dust-lang/src/vm/action/add.rs b/dust-lang/src/vm/action/add.rs index 97fc659..e3fcc71 100644 --- a/dust-lang/src/vm/action/add.rs +++ b/dust-lang/src/vm/action/add.rs @@ -3,15 +3,16 @@ use std::ops::Add; use tracing::trace; use crate::{ - instruction::InstructionFields, vm::{call_frame::RuntimeValue, Thread}, - DustString, + DustString, Instruction, }; -pub fn add_bytes(_: &mut usize, instruction: &InstructionFields, thread: &mut Thread) { - let destination_index = instruction.a_field as usize; - let left_index = instruction.b_field as usize; - let right_index = instruction.c_field as usize; +use super::Cache; + +pub fn add_bytes(_: &mut usize, instruction: &Instruction, thread: &mut Thread, _: &mut Cache) { + 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 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); } -pub fn add_characters(_: &mut usize, instruction: &InstructionFields, thread: &mut Thread) { - 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; +pub fn add_characters( + _: &mut usize, + instruction: &Instruction, + thread: &mut Thread, + _: &mut Cache, +) { + 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 left_value = if left_is_constant { @@ -60,12 +66,12 @@ pub fn add_characters(_: &mut usize, instruction: &InstructionFields, thread: &m .set(concatenated); } -pub fn add_floats(_: &mut usize, instruction: &InstructionFields, thread: &mut Thread) { - 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; +pub fn add_floats(_: &mut usize, instruction: &Instruction, thread: &mut Thread, _: &mut Cache) { + 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 left_value = if left_is_constant { @@ -90,12 +96,12 @@ pub fn add_floats(_: &mut usize, instruction: &InstructionFields, thread: &mut T .set_inner(sum); } -pub fn add_integers(_: &mut usize, instruction: &InstructionFields, thread: &mut Thread) { - 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; +pub fn add_integers(_: &mut usize, instruction: &Instruction, thread: &mut Thread, _: &mut Cache) { + 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 left_value = if left_is_constant { @@ -120,12 +126,12 @@ pub fn add_integers(_: &mut usize, instruction: &InstructionFields, thread: &mut .set_inner(sum); } -pub fn add_strings(_: &mut usize, instruction: &InstructionFields, thread: &mut Thread) { - 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; +pub fn add_strings(_: &mut usize, instruction: &Instruction, thread: &mut Thread, _: &mut Cache) { + 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 left_value = if left_is_constant { @@ -148,12 +154,17 @@ pub fn add_strings(_: &mut usize, instruction: &InstructionFields, thread: &mut .set_inner(concatenated); } -pub fn add_character_string(_: &mut usize, instruction: &InstructionFields, thread: &mut Thread) { - 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; +pub fn add_character_string( + _: &mut usize, + instruction: &Instruction, + thread: &mut Thread, + _: &mut Cache, +) { + 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 left_value = if left_is_constant { @@ -176,12 +187,17 @@ pub fn add_character_string(_: &mut usize, instruction: &InstructionFields, thre .set_inner(concatenated); } -pub fn add_string_character(_: &mut usize, instruction: &InstructionFields, thread: &mut Thread) { - 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; +pub fn add_string_character( + _: &mut usize, + instruction: &Instruction, + thread: &mut Thread, + _: &mut Cache, +) { + 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 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( _: &mut usize, - instruction: &InstructionFields, + instruction: &Instruction, thread: &mut Thread, - cache: &mut Option<[RuntimeValue; 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"); let sum = left.add(right); *destination.borrow_mut() = sum; } else { - 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_index = instruction.c_field as usize; - 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_index = instruction.c_field() as usize; + let right_is_constant = instruction.c_is_constant(); let current_frame = thread.current_frame_mut(); let left_value = if left_is_constant { let value = current_frame.get_integer_constant_mut(left_index).to_rc(); @@ -266,6 +282,6 @@ pub fn optimized_add_integer( value }; - *cache = Some([destination, left_value, right_value]); + *cache = Cache::IntegerMath([destination, left_value, right_value]); } } diff --git a/dust-lang/src/vm/action/equal.rs b/dust-lang/src/vm/action/equal.rs index ed1b632..ed335cb 100644 --- a/dust-lang/src/vm/action/equal.rs +++ b/dust-lang/src/vm/action/equal.rs @@ -1,14 +1,18 @@ use tracing::trace; -use crate::{ - instruction::InstructionFields, - vm::{RuntimeValue, Thread}, -}; +use crate::{vm::Thread, Instruction}; -pub fn equal_booleans(ip: &mut usize, instruction: &InstructionFields, thread: &mut Thread) { - let left_index = instruction.b_field as usize; - let right_index = instruction.c_field as usize; - let comparator = instruction.d_field; +use super::Cache; + +pub fn equal_booleans( + 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 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) { - let left = instruction.b_field as usize; - let right = instruction.c_field as usize; - let comparator = instruction.d_field; +pub fn equal_bytes(ip: &mut usize, instruction: &Instruction, 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 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) { - 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; +pub fn equal_characters( + ip: &mut usize, + instruction: &Instruction, + thread: &mut Thread, + _: &mut Cache, +) { + 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 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) { - 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; +pub fn equal_floats(ip: &mut usize, instruction: &Instruction, thread: &mut Thread, _: &mut Cache) { + 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 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) { - 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; +pub fn equal_integers( + ip: &mut usize, + instruction: &Instruction, + thread: &mut Thread, + _: &mut Cache, +) { + 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 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) { - 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; +pub fn equal_strings( + ip: &mut usize, + instruction: &Instruction, + thread: &mut Thread, + _: &mut Cache, +) { + 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 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( ip: &mut usize, - instruction: &InstructionFields, + instruction: &Instruction, thread: &mut Thread, - cache: &mut Option<[RuntimeValue; 3]>, + cache: &mut Cache, ) { - if let Some([_, left, right]) = cache { + if let Cache::IntegerComparison([left, right]) = cache { trace!("equal_INTEGERS_OPTIMIZED using cache"); let is_equal = left == right; @@ -150,11 +169,11 @@ pub fn optimized_equal_integers( *ip += 1; } } else { - 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 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 left_value = if left_is_constant { @@ -193,6 +212,6 @@ pub fn optimized_equal_integers( *ip += 1; } - *cache = Some([RuntimeValue::Raw(0), left_value, right_value]); + *cache = Cache::IntegerComparison([left_value, right_value]); } } diff --git a/dust-lang/src/vm/action/jump.rs b/dust-lang/src/vm/action/jump.rs index a584c78..210bd04 100644 --- a/dust-lang/src/vm/action/jump.rs +++ b/dust-lang/src/vm/action/jump.rs @@ -1,10 +1,12 @@ use tracing::trace; -use crate::{instruction::InstructionFields, vm::Thread}; +use crate::{vm::Thread, Instruction}; -pub fn jump(ip: &mut usize, instruction: &InstructionFields, _: &mut Thread) { - let offset = instruction.b_field as usize; - let is_positive = instruction.c_field != 0; +use super::Cache; + +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 { trace!("JUMP +{}", offset); @@ -18,3 +20,29 @@ pub fn jump(ip: &mut usize, instruction: &InstructionFields, _: &mut Thread) { *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; +} diff --git a/dust-lang/src/vm/action/less.rs b/dust-lang/src/vm/action/less.rs index 4ef7936..edbfc2d 100644 --- a/dust-lang/src/vm/action/less.rs +++ b/dust-lang/src/vm/action/less.rs @@ -1,14 +1,18 @@ use tracing::trace; -use crate::{ - instruction::InstructionFields, - vm::{RuntimeValue, Thread}, -}; +use crate::{vm::Thread, Instruction}; -pub fn less_booleans(ip: &mut usize, instruction: &InstructionFields, thread: &mut Thread) { - let left_index = instruction.b_field as usize; - let right_index = instruction.c_field as usize; - let comparator = instruction.d_field; +use super::Cache; + +pub fn less_booleans( + 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 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) { - let left = instruction.b_field as usize; - let right = instruction.c_field as usize; - let comparator = instruction.d_field; +pub fn less_bytes(ip: &mut usize, instruction: &Instruction, 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 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) { - 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; +pub fn less_characters( + ip: &mut usize, + instruction: &Instruction, + thread: &mut Thread, + _: &mut Cache, +) { + 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 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) { - 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; +pub fn less_floats(ip: &mut usize, instruction: &Instruction, thread: &mut Thread, _: &mut Cache) { + 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 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) { - 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; +pub fn less_integers( + ip: &mut usize, + instruction: &Instruction, + thread: &mut Thread, + _: &mut Cache, +) { + 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 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) { - 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; +pub fn less_strings(ip: &mut usize, instruction: &Instruction, thread: &mut Thread, _: &mut Cache) { + 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 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( ip: &mut usize, - instruction: &InstructionFields, + instruction: &Instruction, thread: &mut Thread, - cache: &mut Option<[RuntimeValue; 3]>, + cache: &mut Cache, ) { - if let Some([_, left, right]) = cache { + if let Cache::IntegerComparison([left, right]) = cache { trace!("OPTIMIZED_LESS using integer cache"); let is_less_than = left < right; @@ -150,11 +164,11 @@ pub fn optimized_less_integers( *ip += 1; } } else { - 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 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 left_value = if left_is_constant { @@ -193,6 +207,6 @@ pub fn optimized_less_integers( *ip += 1; } - *cache = Some([RuntimeValue::Raw(0), left_value, right_value]); + *cache = Cache::IntegerComparison([left_value, right_value]); } } diff --git a/dust-lang/src/vm/action/less_equal.rs b/dust-lang/src/vm/action/less_equal.rs index 4be0c43..56a31d3 100644 --- a/dust-lang/src/vm/action/less_equal.rs +++ b/dust-lang/src/vm/action/less_equal.rs @@ -1,14 +1,18 @@ use tracing::trace; -use crate::{ - instruction::InstructionFields, - vm::{RuntimeValue, Thread}, -}; +use crate::{vm::Thread, Instruction}; -pub fn less_equal_booleans(ip: &mut usize, instruction: &InstructionFields, thread: &mut Thread) { - let left_index = instruction.b_field as usize; - let right_index = instruction.c_field as usize; - let comparator = instruction.d_field; +use super::Cache; + +pub fn less_equal_booleans( + 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 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) { - let left = instruction.b_field as usize; - let right = instruction.c_field as usize; - let comparator = instruction.d_field; +pub fn less_equal_bytes( + ip: &mut usize, + instruction: &Instruction, + 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 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) { - 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; +pub fn less_equal_characters( + ip: &mut usize, + instruction: &Instruction, + thread: &mut Thread, + _: &mut Cache, +) { + 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 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) { - 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; +pub fn less_equal_floats( + ip: &mut usize, + instruction: &Instruction, + thread: &mut Thread, + _: &mut Cache, +) { + 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 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) { - 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; +pub fn less_equal_integers( + ip: &mut usize, + instruction: &Instruction, + thread: &mut Thread, + _: &mut Cache, +) { + 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 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) { - 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; +pub fn less_equal_strings( + ip: &mut usize, + instruction: &Instruction, + thread: &mut Thread, + _: &mut Cache, +) { + 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 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( ip: &mut usize, - instruction: &InstructionFields, + instruction: &Instruction, thread: &mut Thread, - cache: &mut Option<[RuntimeValue; 3]>, + cache: &mut Cache, ) { - if let Some([_, left, right]) = cache { + if let Cache::IntegerComparison([left, right]) = cache { trace!("LESS_INTEGERS_OPTIMIZED using cache"); let is_less_than_or_equal = left <= right; @@ -150,11 +179,11 @@ pub fn optimized_less_equal_integers( *ip += 1; } } else { - 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 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 left_value = if left_is_constant { @@ -193,6 +222,6 @@ pub fn optimized_less_equal_integers( *ip += 1; } - *cache = Some([RuntimeValue::Raw(0), left_value, right_value]); + *cache = Cache::IntegerComparison([left_value, right_value]); } } diff --git a/dust-lang/src/vm/action/mod.rs b/dust-lang/src/vm/action/mod.rs index ee68795..29d5370 100644 --- a/dust-lang/src/vm/action/mod.rs +++ b/dust-lang/src/vm/action/mod.rs @@ -8,8 +8,11 @@ use add::{ add_bytes, add_character_string, add_characters, add_floats, add_integers, add_string_character, add_strings, optimized_add_integer, }; -use equal::optimized_equal_integers; -use jump::jump; +use equal::{ + 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::{ less_booleans, less_bytes, less_characters, less_floats, less_integers, less_strings, optimized_less_integers, @@ -23,16 +26,11 @@ use tracing::info; use std::fmt::{self, Display, Formatter}; -use crate::{ - instruction::{InstructionFields, TypeCode}, - AbstractList, ConcreteValue, Operation, Value, -}; +use crate::{instruction::TypeCode, AbstractList, ConcreteValue, Instruction, Operation, Value}; use super::{call_frame::RuntimeValue, thread::Thread, Pointer}; -pub type ActionLogic = fn(&mut usize, &InstructionFields, &mut Thread); -pub type OptimizedActionLogicIntegers = - fn(&mut usize, &InstructionFields, &mut Thread, &mut Option<[RuntimeValue; 3]>); +pub type ActionLogic = fn(&mut usize, &Instruction, &mut Thread, &mut Cache); #[derive(Debug)] pub struct ActionSequence { @@ -40,35 +38,43 @@ pub struct ActionSequence { } impl ActionSequence { - pub fn new(instructions: Vec) -> Self { - let mut actions = Vec::with_capacity(instructions.len()); - let mut instructions_reversed = instructions.into_iter().rev(); + pub fn new + DoubleEndedIterator>( + instructions: T, + ) -> Self { + let mut actions = Vec::new(); + let mut instructions_reversed = instructions.rev(); while let Some(instruction) = instructions_reversed.next() { - if instruction.operation == Operation::JUMP { - let backward_offset = instruction.b_field as usize; - let is_positive = instruction.c_field != 0; + if instruction.operation() == Operation::JUMP { + let backward_offset = instruction.b_field() as usize; + let is_positive = instruction.c_field() != 0; if !is_positive { - let mut loop_actions = Vec::with_capacity(backward_offset + 1); - let jump_action = Action::optimized(&instruction); + let mut loop_actions = Vec::with_capacity(backward_offset); + let jump_action = Action::optimized(instruction); loop_actions.push(jump_action); for _ in 0..backward_offset { let instruction = instructions_reversed.next().unwrap(); - let action = Action::optimized(&instruction); + let action = Action::optimized(instruction); loop_actions.push(action); } loop_actions.reverse(); - let r#loop = Action::r#loop(ActionSequence { + let cache = Cache::LoopActions(ActionSequence { actions: loop_actions, }); - actions.push(r#loop); + let action = Action { + instruction, + logic: r#loop, + cache, + }; + + actions.push(action); continue; } @@ -97,27 +103,12 @@ impl ActionSequence { info!("Run {action}"); - match action { - Action::Unoptimized { logic, instruction } => { - logic(&mut local_ip, &*instruction, thread); - } - Action::Loop { actions } => { - 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; - } - } + (action.logic)( + &mut local_ip, + &action.instruction, + thread, + &mut action.cache, + ); } } } @@ -139,30 +130,23 @@ impl Display for ActionSequence { } #[derive(Debug)] -enum Action { - Unoptimized { - logic: ActionLogic, - instruction: InstructionFields, - }, - Loop { - actions: ActionSequence, - }, - OptimizedIntegers { - logic: OptimizedActionLogicIntegers, - instruction: InstructionFields, - cache: Option<[RuntimeValue; 3]>, - }, - OptimizedJumpForward { - offset: usize, - }, - OptimizedJumpBackward { - offset: usize, - }, +pub struct Action { + instruction: Instruction, + logic: ActionLogic, + cache: Cache, +} + +#[derive(Debug)] +pub enum Cache { + Empty, + IntegerMath([RuntimeValue; 3]), + IntegerComparison([RuntimeValue; 2]), + LoopActions(ActionSequence), } impl Action { - pub fn unoptimized(instruction: InstructionFields) -> Self { - let logic = match instruction.operation { + pub fn unoptimized(instruction: Instruction) -> Self { + let logic = match instruction.operation() { Operation::POINT => point, Operation::CLOSE => close, Operation::LOAD_ENCODED => load_encoded, @@ -170,7 +154,7 @@ impl Action { Operation::LOAD_LIST => load_list, Operation::LOAD_FUNCTION => load_function, 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::FLOAT, TypeCode::FLOAT) => add_floats, (TypeCode::BYTE, TypeCode::BYTE) => add_bytes, @@ -186,16 +170,16 @@ impl Action { Operation::MODULO => modulo, Operation::NEGATE => negate, Operation::NOT => not, - Operation::EQUAL => match (instruction.b_type, instruction.c_type) { - (TypeCode::BOOLEAN, TypeCode::BOOLEAN) => equal::equal_booleans, - (TypeCode::BYTE, TypeCode::BYTE) => equal::equal_bytes, - (TypeCode::CHARACTER, TypeCode::CHARACTER) => equal::equal_characters, - (TypeCode::FLOAT, TypeCode::FLOAT) => equal::equal_floats, - (TypeCode::INTEGER, TypeCode::INTEGER) => equal::equal_integers, - (TypeCode::STRING, TypeCode::STRING) => equal::equal_strings, + Operation::EQUAL => match (instruction.b_type(), instruction.c_type()) { + (TypeCode::BOOLEAN, TypeCode::BOOLEAN) => equal_booleans, + (TypeCode::BYTE, TypeCode::BYTE) => equal_bytes, + (TypeCode::CHARACTER, TypeCode::CHARACTER) => equal_characters, + (TypeCode::FLOAT, TypeCode::FLOAT) => equal_floats, + (TypeCode::INTEGER, TypeCode::INTEGER) => equal_integers, + (TypeCode::STRING, TypeCode::STRING) => equal_strings, _ => 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::BYTE, TypeCode::BYTE) => less_bytes, (TypeCode::CHARACTER, TypeCode::CHARACTER) => less_characters, @@ -204,7 +188,7 @@ impl Action { (TypeCode::STRING, TypeCode::STRING) => less_strings, _ => 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::BYTE, TypeCode::BYTE) => less_equal_bytes, (TypeCode::CHARACTER, TypeCode::CHARACTER) => less_equal_characters, @@ -222,100 +206,80 @@ impl Action { _ => todo!(), }; - Action::Unoptimized { logic, instruction } - } - - pub fn optimized(instruction: &InstructionFields) -> Self { - 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!(), + Action { + instruction, + logic, + cache: Cache::Empty, } } - pub fn r#loop(actions: ActionSequence) -> Self { - Action::Loop { actions } + pub fn optimized(instruction: Instruction) -> Self { + 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 { fn fmt(&self, f: &mut Formatter) -> fmt::Result { - match self { - Action::Unoptimized { instruction, .. } => { - write!(f, "{}", 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}") - } + if let Cache::LoopActions(actions) = &self.cache { + write!(f, "LOOP: {actions}")?; + } else { + write!(f, "{}", self.instruction.operation())?; } + + 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!() } -fn close(_: &mut usize, instruction: &InstructionFields, thread: &mut Thread) { +fn close(_: &mut usize, instruction: &Instruction, thread: &mut Thread, _: &mut Cache) { todo!() } -fn load_encoded(ip: &mut usize, instruction: &InstructionFields, thread: &mut Thread) { - let destination = instruction.a_field; - let value_type = instruction.b_type; - let jump_next = instruction.c_field != 0; +fn load_encoded(ip: &mut usize, instruction: &Instruction, thread: &mut Thread, _: &mut Cache) { + let destination = instruction.a_field(); + let value_type = instruction.b_type(); + let jump_next = instruction.c_field() != 0; match value_type { TypeCode::BOOLEAN => { - let value = instruction.b_field != 0; + let value = instruction.b_field() != 0; thread .current_frame_mut() @@ -326,7 +290,7 @@ fn load_encoded(ip: &mut usize, instruction: &InstructionFields, thread: &mut Th .set_inner(value); } TypeCode::BYTE => { - let value = instruction.b_field as u8; + let value = instruction.b_field() as u8; thread .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) { - let destination = instruction.a_field as usize; - let constant_index = instruction.b_field as usize; - let constant_type = instruction.b_type; - let jump_next = instruction.c_field != 0; +fn load_constant(ip: &mut usize, instruction: &Instruction, thread: &mut Thread, _: &mut Cache) { + let destination = instruction.a_field() as usize; + let constant_index = instruction.b_field() as usize; + let constant_type = instruction.b_type(); + let jump_next = instruction.c_field() != 0; let current_frame = thread.current_frame_mut(); 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) { - let destination = instruction.a_field as usize; - let start_register = instruction.b_field as usize; - let item_type = instruction.b_type; - let end_register = instruction.c_field as usize; - let jump_next = instruction.d_field; +fn load_list(ip: &mut usize, instruction: &Instruction, thread: &mut Thread, _: &mut Cache) { + let destination = instruction.a_field() as usize; + let start_register = instruction.b_field() as usize; + let item_type = instruction.b_type(); + let end_register = instruction.c_field() as usize; + let jump_next = instruction.d_field(); let current_frame = thread.current_frame_mut(); 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!() } -fn load_self(_: &mut usize, _: &InstructionFields, _: &mut Thread) { +fn load_self(_: &mut usize, _: &Instruction, _: &mut Thread, _: &mut Cache) { todo!() } -fn subtract(_: &mut usize, instruction: &InstructionFields, thread: &mut Thread) { +fn subtract(_: &mut usize, instruction: &Instruction, thread: &mut Thread, _: &mut Cache) { todo!() } -fn multiply(_: &mut usize, instruction: &InstructionFields, thread: &mut Thread) { +fn multiply(_: &mut usize, instruction: &Instruction, thread: &mut Thread, _: &mut Cache) { todo!() } -fn divide(_: &mut usize, instruction: &InstructionFields, thread: &mut Thread) { +fn divide(_: &mut usize, instruction: &Instruction, thread: &mut Thread, _: &mut Cache) { todo!() } -fn modulo(_: &mut usize, instruction: &InstructionFields, thread: &mut Thread) { +fn modulo(_: &mut usize, instruction: &Instruction, thread: &mut Thread, _: &mut Cache) { todo!() } -fn test(ip: &mut usize, instruction: &InstructionFields, thread: &mut Thread) { +fn test(ip: &mut usize, instruction: &Instruction, thread: &mut Thread, _: &mut Cache) { todo!() } -fn test_set(_: &mut usize, _: &InstructionFields, _: &mut Thread) { +fn test_set(_: &mut usize, _: &Instruction, _: &mut Thread, _: &mut Cache) { todo!() } -fn negate(_: &mut usize, _: &InstructionFields, _: &mut Thread) { +fn negate(_: &mut usize, _: &Instruction, _: &mut Thread, _: &mut Cache) { todo!() } -fn not(_: &mut usize, _: &InstructionFields, _: &mut Thread) { +fn not(_: &mut usize, _: &Instruction, _: &mut Thread, _: &mut Cache) { todo!() } -fn call(_: &mut usize, _: &InstructionFields, _: &mut Thread) { +fn call(_: &mut usize, _: &Instruction, _: &mut Thread, _: &mut Cache) { todo!() } -fn call_native(_: &mut usize, _: &InstructionFields, _: &mut Thread) { +fn call_native(_: &mut usize, _: &Instruction, _: &mut Thread, _: &mut Cache) { todo!() } -fn r#return(_: &mut usize, instruction: &InstructionFields, thread: &mut Thread) { - let should_return_value = instruction.b_field != 0; - let return_register = instruction.c_field as usize; - let return_type = instruction.b_type; +fn r#return(_: &mut usize, instruction: &Instruction, thread: &mut Thread, _: &mut Cache) { + let should_return_value = instruction.b_field() != 0; + let return_register = instruction.c_field() as usize; + let return_type = instruction.b_type(); let current_frame = thread.current_frame(); if should_return_value { diff --git a/dust-lang/src/vm/thread.rs b/dust-lang/src/vm/thread.rs index 7eda000..559dd45 100644 --- a/dust-lang/src/vm/thread.rs +++ b/dust-lang/src/vm/thread.rs @@ -3,7 +3,6 @@ use std::{rc::Rc, thread::JoinHandle}; use tracing::{info, trace}; use crate::{ - instruction::InstructionFields, vm::{action::ActionSequence, CallFrame}, Chunk, DustString, Span, Value, }; @@ -39,13 +38,7 @@ impl Thread { .unwrap_or_else(|| DustString::from("anonymous")) ); - let mut actions = ActionSequence::new( - self.chunk - .instructions - .iter() - .map(InstructionFields::from) - .collect(), - ); + let mut actions = ActionSequence::new(self.chunk.instructions.iter().copied()); trace!("Thread actions: {}", actions);