feat: less clone on symbol
This commit is contained in:
@@ -1,14 +1,17 @@
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::rc::Rc;
|
||||
|
||||
use crate::builtins::env;
|
||||
use crate::bytecode::{BinOp, OpCode, OpCodes, Program, UnOp, Func as F};
|
||||
use crate::error::*;
|
||||
use crate::ty::common::Symbol;
|
||||
use crate::ty::internal::*;
|
||||
use crate::ty::public as p;
|
||||
use crate::ty::public::{self as p, Symbol};
|
||||
|
||||
use crate::stack::Stack;
|
||||
|
||||
use derive_more::Constructor;
|
||||
use ecow::EcoString;
|
||||
pub use env::Env;
|
||||
pub use jit::JITContext;
|
||||
|
||||
@@ -24,37 +27,47 @@ pub fn run(prog: Program, jit: JITContext<'_>) -> Result<p::Value> {
|
||||
let vm = VM::new(
|
||||
prog.thunks,
|
||||
prog.funcs,
|
||||
RefCell::new(prog.symbols),
|
||||
RefCell::new(prog.symmap),
|
||||
jit
|
||||
);
|
||||
let env = env();
|
||||
let env = env(&vm);
|
||||
let temp = vm.eval(prog.top_level, env)?;
|
||||
let temp = temp.to_public(&vm);
|
||||
Ok(temp)
|
||||
}
|
||||
|
||||
#[derive(Constructor)]
|
||||
pub struct VM<'jit> {
|
||||
thunks: Box<[OpCodes]>,
|
||||
funcs: Box<[F]>,
|
||||
symbols: RefCell<Vec<EcoString>>,
|
||||
symmap: RefCell<HashMap<EcoString, usize>>,
|
||||
jit: JITContext<'jit>,
|
||||
}
|
||||
|
||||
impl<'vm, 'jit: 'vm> VM<'jit> {
|
||||
fn new(thunks: Box<[OpCodes]>, funcs: Box<[F]>, jit: JITContext<'jit>) -> Self {
|
||||
VM { thunks, funcs, jit }
|
||||
}
|
||||
|
||||
pub fn get_thunk(&self, idx: usize) -> &OpCodes {
|
||||
// SAFETY: The `idx` is within bounds as `thunks` is initialized with `prog.thunks`
|
||||
// and `idx` is expected to be a valid index into this collection.
|
||||
// The lifetime of the returned reference is tied to `&self`.
|
||||
unsafe { &*(&self.thunks[idx] as *const _) }
|
||||
&self.thunks[idx]
|
||||
}
|
||||
|
||||
pub fn get_func(&self, idx: usize) -> &F {
|
||||
// SAFETY: The `idx` is within bounds as `funcs` is initialized with `prog.funcs`
|
||||
// and `idx` is expected to be a valid index into this collection.
|
||||
// The lifetime of the returned reference is tied to `&self`.
|
||||
unsafe { &*(&self.funcs[idx] as *const _) }
|
||||
&self.funcs[idx]
|
||||
}
|
||||
|
||||
pub fn get_sym(&self, idx: usize) -> Symbol{
|
||||
self.symbols.borrow()[idx].clone().into()
|
||||
}
|
||||
|
||||
pub fn new_sym(&self, sym: impl Into<EcoString>) -> usize {
|
||||
let sym = sym.into();
|
||||
if let Some(&idx) = self.symmap.borrow().get(&sym) {
|
||||
idx
|
||||
} else {
|
||||
self.symmap.borrow_mut().insert(sym.clone(), self.symbols.borrow().len());
|
||||
self.symbols.borrow_mut().push(sym);
|
||||
self.symbols.borrow().len() - 1
|
||||
}
|
||||
}
|
||||
|
||||
pub fn eval(&'vm self, opcodes: OpCodes, env: Rc<Env<'vm>>) -> Result<Value<'vm>> {
|
||||
@@ -123,6 +136,7 @@ impl<'vm, 'jit: 'vm> VM<'jit> {
|
||||
let mut value = stack.pop();
|
||||
value.force(self)?;
|
||||
stack.push(match op {
|
||||
Neg => value.neg(),
|
||||
Not => value.not(),
|
||||
})?;
|
||||
}
|
||||
@@ -134,9 +148,13 @@ impl<'vm, 'jit: 'vm> VM<'jit> {
|
||||
rhs.force(self)?;
|
||||
stack.push(match op {
|
||||
Add => lhs.add(rhs),
|
||||
Sub => lhs.add(rhs.neg()),
|
||||
Mul => lhs.mul(rhs),
|
||||
Div => lhs.div(rhs),
|
||||
And => lhs.and(rhs),
|
||||
Or => lhs.or(rhs),
|
||||
Eq => lhs.eq(rhs),
|
||||
Lt => lhs.lt(rhs),
|
||||
Con => lhs.concat(rhs),
|
||||
Upd => lhs.update(rhs),
|
||||
})?;
|
||||
@@ -169,57 +187,56 @@ impl<'vm, 'jit: 'vm> VM<'jit> {
|
||||
}
|
||||
OpCode::PushStaticAttr { name } => {
|
||||
let val = stack.pop();
|
||||
stack.tos_mut()?.push_attr(Symbol::new(name.clone()), val);
|
||||
stack.tos_mut()?.push_attr(name, val);
|
||||
}
|
||||
OpCode::PushDynamicAttr => {
|
||||
let val = stack.pop();
|
||||
let mut sym = stack.pop();
|
||||
sym.force(self)?.coerce_to_string();
|
||||
let sym = sym.unwrap_const().unwrap_string().into();
|
||||
let sym = self.new_sym(sym.unwrap_const().unwrap_string());
|
||||
stack.tos_mut()?.push_attr(sym, val);
|
||||
}
|
||||
OpCode::Select { sym } => {
|
||||
stack.tos_mut()?.force(self)?.select(&Symbol::new(sym))?;
|
||||
stack.tos_mut()?.force(self)?.select(sym)?;
|
||||
}
|
||||
OpCode::SelectOrDefault { sym } => {
|
||||
let default = stack.pop();
|
||||
stack
|
||||
.tos_mut()?
|
||||
.force(self)?
|
||||
.select_with_default(&Symbol::new(sym), default)?;
|
||||
.select_with_default(sym, default)?;
|
||||
}
|
||||
OpCode::SelectDynamic => {
|
||||
let mut val = stack.pop();
|
||||
val.force(self)?;
|
||||
val.coerce_to_string();
|
||||
let sym = val.unwrap_const().unwrap_string().into();
|
||||
stack.tos_mut()?.force(self)?.select(&sym)?;
|
||||
let sym = self.new_sym(val.unwrap_const().unwrap_string());
|
||||
stack.tos_mut()?.force(self)?.select(sym)?;
|
||||
}
|
||||
OpCode::SelectDynamicOrDefault => {
|
||||
let default = stack.pop();
|
||||
let mut val = stack.pop();
|
||||
val.force(self)?;
|
||||
val.coerce_to_string();
|
||||
let sym = val.unwrap_const().unwrap_string().into();
|
||||
let sym = self.new_sym(val.unwrap_const().unwrap_string());
|
||||
stack
|
||||
.tos_mut()?
|
||||
.force(self)?
|
||||
.select_with_default(&sym, default)?;
|
||||
.select_with_default(sym, default)?;
|
||||
}
|
||||
OpCode::HasAttr { sym } => {
|
||||
stack.tos_mut()?.force(self)?.has_attr(&Symbol::new(sym));
|
||||
stack.tos_mut()?.force(self)?.has_attr(sym);
|
||||
}
|
||||
OpCode::HasDynamicAttr => {
|
||||
let mut val = stack.pop();
|
||||
val.coerce_to_string();
|
||||
let sym = val.unwrap_const().unwrap_string().into();
|
||||
stack.tos_mut()?.force(self)?.has_attr(&sym);
|
||||
let sym = self.new_sym(val.unwrap_const().unwrap_string());
|
||||
stack.tos_mut()?.force(self)?.has_attr(sym);
|
||||
}
|
||||
OpCode::LookUp { sym } => {
|
||||
let sym = Symbol::new(sym);
|
||||
stack.push(
|
||||
env.lookup(&sym)
|
||||
.ok_or_else(|| Error::EvalError(format!(r#""{sym}" not found"#)))?,
|
||||
env.lookup(sym)
|
||||
.ok_or_else(|| Error::EvalError(format!("{} not found", self.get_sym(sym))))?,
|
||||
)?;
|
||||
}
|
||||
OpCode::EnterEnv => match stack.pop() {
|
||||
|
||||
Reference in New Issue
Block a user