feat(machine): reduce term allocations

* remove term from VBuiltin
* and also means we don't need the useless wrapping

Co-authored-by: Lucas Rosa <x@rvcas.dev>
This commit is contained in:
microproofs 2023-04-12 16:09:42 -04:00 committed by Lucas
parent 70f12d3fc5
commit 09a6ea51d6
3 changed files with 33 additions and 46 deletions

View File

@ -1,9 +1,6 @@
use std::rc::Rc; use std::rc::Rc;
use crate::{ use crate::ast::{Constant, NamedDeBruijn, Term, Type};
ast::{Constant, NamedDeBruijn, Term, Type},
builtins::DefaultFunction,
};
pub mod cost_model; pub mod cost_model;
mod discharge; mod discharge;
@ -147,11 +144,7 @@ impl Machine {
Ok(MachineState::Return( Ok(MachineState::Return(
context, context,
Value::Builtin { Value::Builtin { fun, runtime },
fun,
term: term.into(),
runtime,
},
)) ))
} }
} }
@ -183,21 +176,21 @@ impl Machine {
Value::Delay(body, env) => { Value::Delay(body, env) => {
Ok(MachineState::Compute(context, env, body.as_ref().clone())) Ok(MachineState::Compute(context, env, body.as_ref().clone()))
} }
Value::Builtin { Value::Builtin { fun, mut runtime } => {
fun,
term,
mut runtime,
} => {
let force_term = Term::Force(term);
if runtime.needs_force() { if runtime.needs_force() {
runtime.consume_force(); runtime.consume_force();
let res = self.eval_builtin_app(fun, force_term.into(), runtime)?; let res = if runtime.is_ready() {
self.eval_builtin_app(runtime)?
} else {
Value::Builtin { fun, runtime }
};
Ok(MachineState::Return(context, res)) Ok(MachineState::Return(context, res))
} else { } else {
Err(Error::BuiltinTermArgumentExpected(force_term)) Err(Error::BuiltinTermArgumentExpected(Term::Constant(
Constant::Unit.into(),
)))
} }
} }
rest => Err(Error::NonPolymorphicInstantiation(rest)), rest => Err(Error::NonPolymorphicInstantiation(rest)),
@ -222,47 +215,40 @@ impl Machine {
body.as_ref().clone(), body.as_ref().clone(),
)) ))
} }
Value::Builtin { fun, term, runtime } => { Value::Builtin { fun, runtime } => {
let arg_term = discharge::value_as_term(argument.clone()); // let arg_term = discharge::value_as_term(argument.clone());
let t = Rc::new(Term::<NamedDeBruijn>::Apply {
function: term,
argument: arg_term,
});
if runtime.is_arrow() && !runtime.needs_force() { if runtime.is_arrow() && !runtime.needs_force() {
let mut runtime = runtime; let mut runtime = runtime;
runtime.push(argument)?; runtime.push(argument)?;
let res = self.eval_builtin_app(fun, t, runtime.to_owned())?; let res = if runtime.is_ready() {
self.eval_builtin_app(runtime)?
} else {
Value::Builtin { fun, runtime }
};
Ok(MachineState::Return(context, res)) Ok(MachineState::Return(context, res))
} else { } else {
Err(Error::UnexpectedBuiltinTermArgument(t.as_ref().clone())) Err(Error::UnexpectedBuiltinTermArgument(Term::Constant(
Constant::Unit.into(),
)))
} }
} }
rest => Err(Error::NonFunctionalApplication(rest, argument)), rest => Err(Error::NonFunctionalApplication(rest, argument)),
} }
} }
fn eval_builtin_app( fn eval_builtin_app(&mut self, runtime: BuiltinRuntime) -> Result<Value, Error> {
&mut self, let cost = match self.version {
fun: DefaultFunction, Language::PlutusV1 => runtime.to_ex_budget_v1(&self.costs.builtin_costs),
term: Rc<Term<NamedDeBruijn>>, Language::PlutusV2 => runtime.to_ex_budget_v2(&self.costs.builtin_costs),
runtime: BuiltinRuntime, };
) -> Result<Value, Error> {
if runtime.is_ready() {
let cost = match self.version {
Language::PlutusV1 => runtime.to_ex_budget_v1(&self.costs.builtin_costs),
Language::PlutusV2 => runtime.to_ex_budget_v2(&self.costs.builtin_costs),
};
self.spend_budget(cost)?;
runtime.call(&mut self.logs) self.spend_budget(cost)?;
} else {
Ok(Value::Builtin { fun, term, runtime }) runtime.call(&mut self.logs)
}
} }
fn lookup_var(&mut self, name: &NamedDeBruijn, env: &[Value]) -> Result<Value, Error> { fn lookup_var(&mut self, name: &NamedDeBruijn, env: &[Value]) -> Result<Value, Error> {

View File

@ -1,6 +1,6 @@
use std::rc::Rc; use std::rc::Rc;
use crate::ast::{NamedDeBruijn, Term}; use crate::ast::{Constant, NamedDeBruijn, Term};
use super::value::{Env, Value}; use super::value::{Env, Value};
@ -28,7 +28,9 @@ pub(super) fn value_as_term(value: Value) -> Rc<Term<NamedDeBruijn>> {
match stack_frame { match stack_frame {
DischargeStep::DischargeValue(value) => match value { DischargeStep::DischargeValue(value) => match value {
Value::Con(x) => arg_stack.push(Term::Constant(x.clone()).into()), Value::Con(x) => arg_stack.push(Term::Constant(x.clone()).into()),
Value::Builtin { term, .. } => arg_stack.push(term.clone()), Value::Builtin { .. } => {
arg_stack.push(Term::Constant(Constant::Unit.into()).into())
}
Value::Delay(body, env) => { Value::Delay(body, env) => {
stack.push(DischargeStep::DischargeValueEnv( stack.push(DischargeStep::DischargeValueEnv(
0, 0,

View File

@ -24,7 +24,6 @@ pub enum Value {
}, },
Builtin { Builtin {
fun: DefaultFunction, fun: DefaultFunction,
term: Rc<Term<NamedDeBruijn>>,
runtime: BuiltinRuntime, runtime: BuiltinRuntime,
}, },
} }