From 89109d78e7aa2820c5ac0d307e4c907e6e186bd3 Mon Sep 17 00:00:00 2001 From: ForAeons Date: Sat, 20 Apr 2024 11:07:54 +0800 Subject: [PATCH] Inline micro_code functions --- README.md | 18 ++++++++++++++++++ vm/ignite/src/micro_code/apply_builtin.rs | 1 + vm/ignite/src/micro_code/assign.rs | 1 + vm/ignite/src/micro_code/binop.rs | 1 + vm/ignite/src/micro_code/call.rs | 1 + vm/ignite/src/micro_code/done.rs | 1 + vm/ignite/src/micro_code/enter_scope.rs | 1 + vm/ignite/src/micro_code/exit_scope.rs | 1 + vm/ignite/src/micro_code/goto.rs | 1 + vm/ignite/src/micro_code/jof.rs | 1 + vm/ignite/src/micro_code/join.rs | 1 + vm/ignite/src/micro_code/ld.rs | 1 + vm/ignite/src/micro_code/ldc.rs | 1 + vm/ignite/src/micro_code/ldf.rs | 1 + vm/ignite/src/micro_code/pop.rs | 1 + vm/ignite/src/micro_code/post.rs | 1 + vm/ignite/src/micro_code/reset.rs | 1 + vm/ignite/src/micro_code/sem_create.rs | 1 + vm/ignite/src/micro_code/spawn.rs | 1 + vm/ignite/src/micro_code/unop.rs | 1 + vm/ignite/src/micro_code/wait.rs | 1 + vm/ignite/src/micro_code/yield_.rs | 1 + vm/ignite/src/runtime/gc.rs | 1 + vm/ignite/src/runtime/run.rs | 7 +++++++ vm/ignite/src/thread.rs | 1 + 25 files changed, 48 insertions(+) diff --git a/README.md b/README.md index c63ef63..d002e04 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,24 @@ oxidate example/hello-world.rst # Should generate example.o2 ignite hello-world.o2 ``` +## Testing + +- To run all tests: + +```bash +# Ensure you are in the root directory of rustscript repository +cargo test +``` + +- To run specific tests: + +```bash +# Example, to run all tests on join micro code +cargo test test_join +# ^ ^ +# first few characters of the testing function +``` + ## Project Deliverables - **Syntax**: RustScript's syntax is a harmonious blend of Rust and TypeScript, offering a familiar yet unique coding experience. diff --git a/vm/ignite/src/micro_code/apply_builtin.rs b/vm/ignite/src/micro_code/apply_builtin.rs index 6f752a2..14f2223 100644 --- a/vm/ignite/src/micro_code/apply_builtin.rs +++ b/vm/ignite/src/micro_code/apply_builtin.rs @@ -3,6 +3,7 @@ use bytecode::{builtin, Value}; use crate::{Runtime, VmError}; +#[inline] pub fn apply_builtin(mut rt: Runtime, sym: &str, args: Vec) -> Result { match sym { builtin::READ_LINE_SYM => { diff --git a/vm/ignite/src/micro_code/assign.rs b/vm/ignite/src/micro_code/assign.rs index 8672348..b1bbc34 100644 --- a/vm/ignite/src/micro_code/assign.rs +++ b/vm/ignite/src/micro_code/assign.rs @@ -15,6 +15,7 @@ use crate::{Runtime, VmError}; /// /// If the stack is empty. /// If the symbol is not found in the environment chain. +#[inline] pub fn assign(mut rt: Runtime, sym: Symbol) -> Result { let val = rt .current_thread diff --git a/vm/ignite/src/micro_code/binop.rs b/vm/ignite/src/micro_code/binop.rs index 674ceef..fee47ab 100644 --- a/vm/ignite/src/micro_code/binop.rs +++ b/vm/ignite/src/micro_code/binop.rs @@ -20,6 +20,7 @@ use crate::{Runtime, VmError}; /// /// If the stack has fewer than two values or the operation is not supported /// for the types of the values on the stack. +#[inline] pub fn binop(mut rt: Runtime, op: BinOp) -> Result { let rhs_val = rt .current_thread diff --git a/vm/ignite/src/micro_code/call.rs b/vm/ignite/src/micro_code/call.rs index e43a6e5..c4dad1e 100644 --- a/vm/ignite/src/micro_code/call.rs +++ b/vm/ignite/src/micro_code/call.rs @@ -26,6 +26,7 @@ use super::apply_builtin; /// /// If the operand stack does not contain enough values to pop (arity + 1). /// If the closure is not of type closure or the arity of the closure does not match the number of arguments. +#[inline] pub fn call(mut rt: Runtime, arity: usize) -> Result { let mut args = Vec::new(); args.reserve_exact(arity); diff --git a/vm/ignite/src/micro_code/done.rs b/vm/ignite/src/micro_code/done.rs index 77ef633..6bd4e34 100644 --- a/vm/ignite/src/micro_code/done.rs +++ b/vm/ignite/src/micro_code/done.rs @@ -12,6 +12,7 @@ use crate::{Runtime, VmError, MAIN_THREAD_ID}; /// # Errors /// /// * If the current thread is not the main thread and there are no threads in the ready queue. +#[inline] pub fn done(mut rt: Runtime) -> Result { // If the current thread is the main thread, then we are done if rt.current_thread.thread_id == MAIN_THREAD_ID { diff --git a/vm/ignite/src/micro_code/enter_scope.rs b/vm/ignite/src/micro_code/enter_scope.rs index 1a8f0ad..7ccab2c 100644 --- a/vm/ignite/src/micro_code/enter_scope.rs +++ b/vm/ignite/src/micro_code/enter_scope.rs @@ -15,6 +15,7 @@ use crate::{extend_environment, Runtime}; /// # Errors /// /// Infallible. +#[inline] pub fn enter_scope(mut rt: Runtime, syms: Vec) -> Result { let current_env = rt.current_thread.env.clone(); diff --git a/vm/ignite/src/micro_code/exit_scope.rs b/vm/ignite/src/micro_code/exit_scope.rs index 624c757..a042ee0 100644 --- a/vm/ignite/src/micro_code/exit_scope.rs +++ b/vm/ignite/src/micro_code/exit_scope.rs @@ -11,6 +11,7 @@ use crate::{Runtime, VmError}; /// # Errors /// /// If the runtime stack is empty. +#[inline] pub fn exit_scope(mut rt: Runtime) -> Result { let prev_frame = rt .current_thread diff --git a/vm/ignite/src/micro_code/goto.rs b/vm/ignite/src/micro_code/goto.rs index 7c0d003..f712b6c 100644 --- a/vm/ignite/src/micro_code/goto.rs +++ b/vm/ignite/src/micro_code/goto.rs @@ -13,6 +13,7 @@ use anyhow::Result; /// # Errors /// /// Infallible. +#[inline] pub fn goto(mut rt: Runtime, pc: usize) -> Result { rt.current_thread.pc = pc; Ok(rt) diff --git a/vm/ignite/src/micro_code/jof.rs b/vm/ignite/src/micro_code/jof.rs index 07d55da..c96029b 100644 --- a/vm/ignite/src/micro_code/jof.rs +++ b/vm/ignite/src/micro_code/jof.rs @@ -13,6 +13,7 @@ use crate::{Runtime, VmError}; /// # Errors /// /// If the stack is empty or the top of the stack is not a boolean. +#[inline] pub fn jof(mut rt: Runtime, pc: usize) -> Result { let cond = rt .current_thread diff --git a/vm/ignite/src/micro_code/join.rs b/vm/ignite/src/micro_code/join.rs index d4c0f0e..8823570 100644 --- a/vm/ignite/src/micro_code/join.rs +++ b/vm/ignite/src/micro_code/join.rs @@ -21,6 +21,7 @@ use super::yield_; /// * If the thread with the given ID is not found in the thread state hashmap. /// * If the operand stack is empty. /// * If the value on the operand stack is not an integer. +#[inline] pub fn join(mut rt: Runtime) -> Result { let tid: i64 = rt .current_thread diff --git a/vm/ignite/src/micro_code/ld.rs b/vm/ignite/src/micro_code/ld.rs index 4a882cc..3b74efc 100644 --- a/vm/ignite/src/micro_code/ld.rs +++ b/vm/ignite/src/micro_code/ld.rs @@ -14,6 +14,7 @@ use crate::{Runtime, VmError}; /// # Errors /// /// If the symbol is not found. +#[inline] pub fn ld(mut rt: Runtime, sym: Symbol) -> Result { let val = rt .current_thread diff --git a/vm/ignite/src/micro_code/ldc.rs b/vm/ignite/src/micro_code/ldc.rs index 4f3177a..397acbc 100644 --- a/vm/ignite/src/micro_code/ldc.rs +++ b/vm/ignite/src/micro_code/ldc.rs @@ -14,6 +14,7 @@ use crate::Runtime; /// # Errors /// /// Infallible. +#[inline] pub fn ldc(mut rt: Runtime, val: Value) -> Result { rt.current_thread.operand_stack.push(val); Ok(rt) diff --git a/vm/ignite/src/micro_code/ldf.rs b/vm/ignite/src/micro_code/ldf.rs index 5ea903e..2e68b59 100644 --- a/vm/ignite/src/micro_code/ldf.rs +++ b/vm/ignite/src/micro_code/ldf.rs @@ -16,6 +16,7 @@ use crate::Runtime; /// # Errors /// /// Infallible. +#[inline] pub fn ldf(mut rt: Runtime, addr: usize, prms: Vec) -> Result { let closure = Value::Closure { fn_type: FnType::User, diff --git a/vm/ignite/src/micro_code/pop.rs b/vm/ignite/src/micro_code/pop.rs index 4651570..6c0372d 100644 --- a/vm/ignite/src/micro_code/pop.rs +++ b/vm/ignite/src/micro_code/pop.rs @@ -11,6 +11,7 @@ use crate::{Runtime, VmError}; /// # Errors /// /// If the stack is empty. +#[inline] pub fn pop(mut rt: Runtime) -> Result { rt.current_thread .operand_stack diff --git a/vm/ignite/src/micro_code/post.rs b/vm/ignite/src/micro_code/post.rs index 3645f58..77548f8 100644 --- a/vm/ignite/src/micro_code/post.rs +++ b/vm/ignite/src/micro_code/post.rs @@ -17,6 +17,7 @@ use crate::{Runtime, VmError}; /// /// If the stack is empty. /// If the top value on stack is not a semaphore. +#[inline] pub fn post(mut rt: Runtime) -> Result { let sem: Semaphore = rt .current_thread diff --git a/vm/ignite/src/micro_code/reset.rs b/vm/ignite/src/micro_code/reset.rs index 41f8cda..243072f 100644 --- a/vm/ignite/src/micro_code/reset.rs +++ b/vm/ignite/src/micro_code/reset.rs @@ -14,6 +14,7 @@ use bytecode::FrameType; /// # Errors /// /// If the runtime stack underflows. i.e. there are no frames of the given type. +#[inline] pub fn reset(mut rt: Runtime, ft: FrameType) -> Result { loop { let frame = rt diff --git a/vm/ignite/src/micro_code/sem_create.rs b/vm/ignite/src/micro_code/sem_create.rs index 98da00e..6d6fd33 100644 --- a/vm/ignite/src/micro_code/sem_create.rs +++ b/vm/ignite/src/micro_code/sem_create.rs @@ -12,6 +12,7 @@ use crate::Runtime; /// # Errors /// /// Infallible. +#[inline] pub fn sem_create(mut rt: Runtime) -> Result { rt.current_thread .operand_stack diff --git a/vm/ignite/src/micro_code/spawn.rs b/vm/ignite/src/micro_code/spawn.rs index c04f6ad..db73c21 100644 --- a/vm/ignite/src/micro_code/spawn.rs +++ b/vm/ignite/src/micro_code/spawn.rs @@ -17,6 +17,7 @@ use crate::Runtime; /// # Errors /// /// Infallible. +#[inline] pub fn spawn(mut rt: Runtime, addr: usize) -> Result { rt.thread_count += 1; diff --git a/vm/ignite/src/micro_code/unop.rs b/vm/ignite/src/micro_code/unop.rs index 2512121..fed84c1 100644 --- a/vm/ignite/src/micro_code/unop.rs +++ b/vm/ignite/src/micro_code/unop.rs @@ -16,6 +16,7 @@ use bytecode::{type_of, UnOp, Value}; /// /// If the stack is empty or the operation is not supported for /// the type of the value on the stack. +#[inline] pub fn unop(mut rt: Runtime, op: UnOp) -> Result { let val = rt .current_thread diff --git a/vm/ignite/src/micro_code/wait.rs b/vm/ignite/src/micro_code/wait.rs index 9087dd9..39e1063 100644 --- a/vm/ignite/src/micro_code/wait.rs +++ b/vm/ignite/src/micro_code/wait.rs @@ -21,6 +21,7 @@ use crate::{Runtime, VmError}; /// If the stack is empty. /// If the top value on stack is not a semaphore. /// If there are no threads in the ready queue when the current thread is blocked. +#[inline] pub fn wait(mut rt: Runtime) -> Result { let sem: Semaphore = rt .current_thread diff --git a/vm/ignite/src/micro_code/yield_.rs b/vm/ignite/src/micro_code/yield_.rs index 2965993..4884797 100644 --- a/vm/ignite/src/micro_code/yield_.rs +++ b/vm/ignite/src/micro_code/yield_.rs @@ -15,6 +15,7 @@ use crate::{Runtime, VmError}; /// # Errors /// /// Returns an error if there are no threads in the ready queue. +#[inline] pub fn yield_(mut rt: Runtime) -> Result { let current_thread = rt.current_thread; rt.ready_queue.push_back(current_thread); diff --git a/vm/ignite/src/runtime/gc.rs b/vm/ignite/src/runtime/gc.rs index 9162964..9a6f757 100644 --- a/vm/ignite/src/runtime/gc.rs +++ b/vm/ignite/src/runtime/gc.rs @@ -19,6 +19,7 @@ impl Runtime { /// - Go through the runtime stack and mark all the environments and environment of closure values in /// their respective environment, and the chain of parent environments /// - Go through the operand stack and mark all the environments of closure values, and the chain of parent environments + #[inline] pub fn mark_and_weep(self) -> Self { let marked = mark(&self); sweep(self, marked) diff --git a/vm/ignite/src/runtime/run.rs b/vm/ignite/src/runtime/run.rs index 371c9ca..97565b1 100644 --- a/vm/ignite/src/runtime/run.rs +++ b/vm/ignite/src/runtime/run.rs @@ -17,6 +17,7 @@ impl Runtime { /// # Errors /// /// If the program counter is out of bounds. + #[inline] pub fn fetch_instr(&mut self) -> Result { let instr = self .instrs @@ -28,14 +29,17 @@ impl Runtime { } /// Check if the time quantum has expired. /// The time quantum is the maximum amount of time a thread can run before it is preempted. + #[inline] pub fn time_quantum_expired(&self) -> bool { self.time.elapsed() >= self.time_quantum } + #[inline] pub fn should_garbage_collect(&self) -> bool { self.gc_timer.elapsed() >= self.gc_interval } + #[inline] pub fn garbage_collect(mut self) -> Self { self = self.mark_and_weep(); self.gc_timer = Instant::now(); @@ -43,6 +47,7 @@ impl Runtime { } /// The program is done if the current thread is the main thread and the current thread is done. + #[inline] pub fn is_done(&self) -> bool { self.done } @@ -75,6 +80,7 @@ impl Runtime { /// # Errors /// /// If an error occurs during execution. +#[inline] pub fn run(mut rt: Runtime) -> Result { loop { if rt.is_done() { @@ -117,6 +123,7 @@ pub fn run(mut rt: Runtime) -> Result { /// # Errors /// /// If an error occurs during execution. +#[inline] pub fn execute(rt: Runtime, instr: ByteCode) -> Result { match instr { ByteCode::DONE => micro_code::done(rt), diff --git a/vm/ignite/src/thread.rs b/vm/ignite/src/thread.rs index 14e3aaf..d37e415 100644 --- a/vm/ignite/src/thread.rs +++ b/vm/ignite/src/thread.rs @@ -40,6 +40,7 @@ impl Thread { } } +#[inline] pub fn extend_environment( mut rt: Runtime, env: Weak>,