Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

site: call site caching #242

Open
wants to merge 9 commits into
base: status
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions rust/ares/src/jets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ pub mod hash;
pub mod list;
pub mod lock;
pub mod lute;
pub mod maps;
pub mod math;
pub mod nock;
pub mod parse;
Expand All @@ -27,6 +28,7 @@ use crate::jets::lock::aes::*;
use crate::jets::lock::ed::*;
use crate::jets::lock::sha::*;
use crate::jets::lute::*;
use crate::jets::maps::*;
use crate::jets::math::*;
use crate::jets::nock::*;
use crate::jets::parse::*;
Expand Down
15 changes: 15 additions & 0 deletions rust/ares/src/jets/hot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,11 @@ pub const URBIT_HOT_STATE: &[HotEntry] = &[
1,
jet_turn,
),
(
&[K_139, Left(b"one"), Left(b"two"), Left(b"roll")],
1,
jet_roll,
),
(
&[K_139, Left(b"one"), Left(b"two"), Left(b"zing")],
1,
Expand Down Expand Up @@ -219,6 +224,16 @@ pub const URBIT_HOT_STATE: &[HotEntry] = &[
1,
jet_jam,
),
(
&[K_139, Left(b"one"), Left(b"two"), Left(b"by"), Left(b"rep")],
1,
jet_by_rep,
),
matthew-levan marked this conversation as resolved.
Show resolved Hide resolved
(
&[K_139, Left(b"one"), Left(b"two"), Left(b"in"), Left(b"rep")],
1,
jet_by_rep, // +rep:in has the same signature as +rep:by
),
//
(
&[
Expand Down
116 changes: 37 additions & 79 deletions rust/ares/src/jets/list.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
/** Text processing jets
*/
use crate::interpreter::{interpret, Context};
use crate::interpreter::Context;
use crate::jets::util::{slot, BAIL_FAIL};
use crate::jets::Result;
use crate::noun::{Cell, Noun, D, T};
use bitvec::order::Lsb0;
use bitvec::slice::BitSlice;
use crate::site::{site_slam, Site};

crate::gdb!();

Expand All @@ -30,89 +29,48 @@ pub fn jet_turn(context: &mut Context, subject: Noun) -> Result {
let sample = slot(subject, 6)?;
let mut list = slot(sample, 2)?;
let mut gate = slot(sample, 3)?;
let mut gate_battery = slot(gate, 2)?;
let gate_context = slot(gate, 7)?;
let mut res = D(0);
let mut dest: *mut Noun = &mut res; // Mutable pointer because we cannot guarantee initialized

// Since the gate doesn't change, we can do a single jet check and use that through the whole
// loop
if let Some((jet, _path)) = context
.warm
.find_jet(&mut context.stack, &mut gate, &mut gate_battery)
.filter(|(_jet, mut path)| {
// check that 7 is a prefix of the parent battery axis,
// to ensure that the sample (axis 6) is not part of the jet match.
//
// XX TODO this check is pessimized since there could be multiple ways to match the
// jet and we only actually match one of them, but we check all of them and run
// unjetted if any have an axis outside 7.
let axis_7_bits: &BitSlice<u64, Lsb0> = BitSlice::from_element(&7u64);
let batteries_list = context.cold.find(&mut context.stack, &mut path);
let mut ret = true;
for mut batteries in batteries_list {
if let Some((_battery, parent_axis)) = batteries.next() {
let parent_axis_prefix_bits = &parent_axis.as_bitslice()[0..3];
if parent_axis_prefix_bits == axis_7_bits {
continue;
} else {
ret = false;
break;
}
} else {
ret = false;
break;
}
let site = Site::new(context, &mut gate);
loop {
if let Ok(list_cell) = list.as_cell() {
list = list_cell.tail();
unsafe {
let (new_cell, new_mem) = Cell::new_raw_mut(&mut context.stack);
(*new_mem).head = site_slam(context, &site, list_cell.head());
*dest = new_cell.as_noun();
dest = &mut (*new_mem).tail;
}
ret
})
{
loop {
if let Ok(list_cell) = list.as_cell() {
list = list_cell.tail();
let element_subject = T(
&mut context.stack,
&[gate_battery, list_cell.head(), gate_context],
);
unsafe {
let (new_cell, new_mem) = Cell::new_raw_mut(&mut context.stack);
(*new_mem).head = jet(context, element_subject)?;
*dest = new_cell.as_noun();
dest = &mut (*new_mem).tail;
}
} else {
if unsafe { !list.raw_equals(D(0)) } {
return Err(BAIL_FAIL);
}
unsafe {
*dest = D(0);
};
return Ok(res);
} else {
if unsafe { !list.raw_equals(D(0)) } {
return Err(BAIL_FAIL);
}
unsafe {
*dest = D(0);
};
return Ok(res);
}
} else {
loop {
if let Ok(list_cell) = list.as_cell() {
list = list_cell.tail();
let element_subject = T(
&mut context.stack,
&[gate_battery, list_cell.head(), gate_context],
);
unsafe {
let (new_cell, new_mem) = Cell::new_raw_mut(&mut context.stack);
(*new_mem).head = interpret(context, element_subject, gate_battery)?;
*dest = new_cell.as_noun();
dest = &mut (*new_mem).tail;
}
} else {
if unsafe { !list.raw_equals(D(0)) } {
return Err(BAIL_FAIL);
}
unsafe {
*dest = D(0);
};
return Ok(res);
}
}

pub fn jet_roll(context: &mut Context, subject: Noun) -> Result {
let sample = slot(subject, 6)?;
let mut list = slot(sample, 2)?;
let mut gate = slot(sample, 3)?;
let mut pro = slot(gate, 13)?;

let site = Site::new(context, &mut gate);
loop {
if let Ok(list_cell) = list.as_cell() {
list = list_cell.tail();
let sam = T(&mut context.stack, &[list_cell.head(), pro]);
pro = site_slam(context, &site, sam);
} else {
if unsafe { !list.raw_equals(D(0)) } {
return Err(BAIL_FAIL);
}
return Ok(pro);
}
}
}
Expand Down
34 changes: 34 additions & 0 deletions rust/ares/src/jets/maps.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/** Map jets. */
use crate::interpreter::Context;
use crate::jets::util::slot;
use crate::jets::Result;
use crate::noun::{Noun, D, T};
use crate::site::{site_slam, Site};

crate::gdb!();

fn by_rep(context: &mut Context, tree: Noun, site: &Site, out: &mut Noun) {
if unsafe { tree.raw_equals(D(0)) } {
} else if let Ok(node) = slot(tree, 2) {
let acc = T(&mut context.stack, &[node, *out]);
*out = site_slam(context, site, acc);

if let Ok(left) = slot(tree, 6) {
by_rep(context, left, site, out);
}

if let Ok(rite) = slot(tree, 7) {
by_rep(context, rite, site, out);
}
}
}

pub fn jet_by_rep(context: &mut Context, subject: Noun) -> Result {
let tree = slot(subject, 30)?;
let mut gate = slot(subject, 6)?;
let mut pro = slot(gate, 13)?;

let site = Site::new(context, &mut gate);
by_rep(context, tree, &site, &mut pro);
Ok(pro)
}
1 change: 1 addition & 0 deletions rust/ares/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ pub mod mug;
pub mod newt;
pub mod noun;
pub mod serf;
pub mod site;
//pub mod bytecode;
pub mod persist;
pub mod serialization;
Expand Down
70 changes: 70 additions & 0 deletions rust/ares/src/site.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/** Call site of a kick (Nock 9), used to cache call targets. */
use bitvec::order::Lsb0;
use bitvec::slice::BitSlice;

use crate::interpreter::{interpret, Context};
use crate::jets::util::slot;
use crate::jets::Jet;
use crate::noun::{Noun, D, T};

pub struct Site {
pub battery: Noun, // battery
pub context: Noun, // context
pub jet: Option<Jet>, // jet driver
pub path: Noun, // label
}

impl Site {
/// Prepare a locally cached gate to call repeatedly.
pub fn new(ctx: &mut Context, core: &mut Noun) -> Site {
let mut battery = slot(*core, 2).unwrap();
let context = slot(*core, 7).unwrap();

let warm_result = ctx
.warm
.find_jet(&mut ctx.stack, core, &mut battery)
.filter(|(_jet, mut path)| {
// check that 7 is a prefix of the parent battery axis,
// to ensure that the sample (axis 6) is not part of the jet match.
//
// XX TODO this check is pessimized since there could be multiple ways to match the
// jet and we only actually match one of them, but we check all of them and run
// unjetted if any have an axis outside 7.
let axis_7_bits: &BitSlice<u64, Lsb0> = BitSlice::from_element(&7u64);
let batteries_list = ctx.cold.find(&mut ctx.stack, &mut path);
let mut ret = true;
for mut batteries in batteries_list {
if let Some((_battery, parent_axis)) = batteries.next() {
let parent_axis_prefix_bits = &parent_axis.as_bitslice()[0..3];
if parent_axis_prefix_bits == axis_7_bits {
continue;
} else {
ret = false;
break;
}
} else {
ret = false;
break;
}
}
ret
});
Site {
battery,
context,
jet: warm_result.map(|(jet, _)| jet),
path: warm_result.map(|(_, path)| path).unwrap_or(D(0)),
}
}
}

/// Slam a cached call site.
pub fn site_slam(ctx: &mut Context, site: &Site, sample: Noun) -> Noun {
let subject = T(&mut ctx.stack, &[site.battery, sample, site.context]);
if site.jet.is_some() {
let jet = site.jet.unwrap();
jet(ctx, subject).unwrap()
} else {
interpret(ctx, subject, site.battery).unwrap()
}
}