Skip to content

Commit

Permalink
use free lists to allow register re-use (#1612)
Browse files Browse the repository at this point in the history
  • Loading branch information
mthom committed Jan 8, 2023
1 parent aa7b8e5 commit bb624cc
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 21 deletions.
76 changes: 57 additions & 19 deletions src/codegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,41 @@ fn trim_structure_by_last_arg(instr: &mut Instruction, last_arg: &Term) {
}
}

trait AddToFreeList<'a, Target: CompilationTarget<'a>> {
fn add_term_to_free_list(&mut self, r: RegType);
fn add_subterm_to_free_list(&mut self, term: &Term);
}

impl<'a, 'b> AddToFreeList<'a, FactInstruction> for CodeGenerator<'b> {
#[inline(always)]
fn add_term_to_free_list(&mut self, r: RegType) {
self.marker.add_to_free_list(r);
}

fn add_subterm_to_free_list(&mut self, _term: &Term) {}
}

impl<'a, 'b> AddToFreeList<'a, QueryInstruction> for CodeGenerator<'b> {
fn add_term_to_free_list(&mut self, _r: RegType) {}

#[inline(always)]
fn add_subterm_to_free_list(&mut self, term: &Term) {
if let Some(cell) = structure_cell(term) {
self.marker.add_to_free_list(cell.get());
}
}
}

fn structure_cell(term: &Term) -> Option<&Cell<RegType>> {
match term {
&Term::Cons(ref cell, ..) |
&Term::Clause(ref cell, ..) |
Term::PartialString(ref cell, ..) |
Term::CompleteString(ref cell, ..) => Some(cell),
_ => None,
}
}

impl<'b> CodeGenerator<'b> {
pub(crate) fn new(atom_tbl: &'b mut AtomTable, settings: CodeGenSettings) -> Self {
CodeGenerator {
Expand Down Expand Up @@ -287,10 +322,9 @@ impl<'b> CodeGenerator<'b> {
cell: &'a Cell<VarReg>,
var: &Rc<String>,
term_loc: GenContext,
is_exposed: bool,
target: &mut Code,
) {
if is_exposed || self.get_var_count(var.as_ref()) > 1 {
if self.get_var_count(var.as_ref()) > 1 {
self.marker.mark_var::<Target>(var.clone(), Level::Deep, cell, term_loc, target);
} else {
Self::add_or_increment_void_instr::<Target>(target);
Expand All @@ -301,13 +335,9 @@ impl<'b> CodeGenerator<'b> {
&mut self,
subterm: &'a Term,
term_loc: GenContext,
is_exposed: bool,
target: &mut Code,
) {
match subterm {
&Term::AnonVar if is_exposed => {
self.marker.mark_anon_var::<Target>(Level::Deep, term_loc, target);
}
&Term::AnonVar => {
Self::add_or_increment_void_instr::<Target>(target);
}
Expand All @@ -322,7 +352,7 @@ impl<'b> CodeGenerator<'b> {
target.push(Target::constant_subterm(constant.clone()));
}
&Term::Var(ref cell, ref var) => {
self.deep_var_instr::<Target>(cell, var, term_loc, is_exposed, target);
self.deep_var_instr::<Target>(cell, var, term_loc, target);
}
};
}
Expand All @@ -331,11 +361,11 @@ impl<'b> CodeGenerator<'b> {
&mut self,
iter: Iter,
term_loc: GenContext,
is_exposed: bool,
) -> Code
where
Target: crate::targets::CompilationTarget<'a>,
Iter: Iterator<Item = TermRef<'a>>,
CodeGenerator<'b>: AddToFreeList<'a, Target>
{
let mut target: Code = Vec::new();

Expand All @@ -352,22 +382,33 @@ impl<'b> CodeGenerator<'b> {
self.marker.mark_non_var::<Target>(lvl, term_loc, cell, &mut target);
target.push(Target::to_structure(name, terms.len(), cell.get()));

<CodeGenerator<'b> as AddToFreeList<'a, Target>>::add_term_to_free_list(self, cell.get());

if let Some(instr) = target.last_mut() {
if let Some(term) = terms.last() {
trim_structure_by_last_arg(instr, term);
}
}

for subterm in terms {
self.subterm_to_instr::<Target>(subterm, term_loc, is_exposed, &mut target);
self.subterm_to_instr::<Target>(subterm, term_loc, &mut target);
}

for subterm in terms {
<CodeGenerator<'b> as AddToFreeList<'a, Target>>::add_subterm_to_free_list(self, subterm);
}
}
TermRef::Cons(lvl, cell, head, tail) => {
self.marker.mark_non_var::<Target>(lvl, term_loc, cell, &mut target);
target.push(Target::to_list(lvl, cell.get()));

self.subterm_to_instr::<Target>(head, term_loc, is_exposed, &mut target);
self.subterm_to_instr::<Target>(tail, term_loc, is_exposed, &mut target);
<CodeGenerator<'b> as AddToFreeList<'a, Target>>::add_term_to_free_list(self, cell.get());

self.subterm_to_instr::<Target>(head, term_loc, &mut target);
self.subterm_to_instr::<Target>(tail, term_loc, &mut target);

<CodeGenerator<'b> as AddToFreeList<'a, Target>>::add_subterm_to_free_list(self, head);
<CodeGenerator<'b> as AddToFreeList<'a, Target>>::add_subterm_to_free_list(self, tail);
}
TermRef::Literal(lvl @ Level::Shallow, cell, Literal::String(ref string)) => {
self.marker.mark_non_var::<Target>(lvl, term_loc, cell, &mut target);
Expand All @@ -382,7 +423,7 @@ impl<'b> CodeGenerator<'b> {
let atom = self.atom_tbl.build_with(&string);

target.push(Target::to_pstr(lvl, atom, cell.get(), true));
self.subterm_to_instr::<Target>(tail, term_loc, is_exposed, &mut target);
self.subterm_to_instr::<Target>(tail, term_loc, &mut target);
}
TermRef::CompleteString(lvl, cell, atom) => {
self.marker.mark_non_var::<Target>(lvl, term_loc, cell, &mut target);
Expand Down Expand Up @@ -823,7 +864,6 @@ impl<'b> CodeGenerator<'b> {
iter: ChunkedIterator<'a>,
conjunct_info: &ConjunctInfo<'a>,
code: &mut Code,
is_exposed: bool,
) -> Result<(), CompilationError> {
for (chunk_num, _, terms) in iter.rule_body_iter() {
for (i, term) in terms.iter().enumerate() {
Expand Down Expand Up @@ -859,7 +899,7 @@ impl<'b> CodeGenerator<'b> {
conjunct_info.perm_vs.vars_above_threshold(i + 1)
};

self.compile_query_line(term, term_loc, code, num_perm_vars, is_exposed);
self.compile_query_line(term, term_loc, code, num_perm_vars);

if self.marker.max_reg_allocated() > MAX_ARITY {
return Err(CompilationError::ExceededMaxArity);
Expand Down Expand Up @@ -931,7 +971,7 @@ impl<'b> CodeGenerator<'b> {
self.compile_seq_prelude(&conjunct_info, &mut code);

let iter = FactIterator::from_rule_head_clause(args);
let mut fact = self.compile_target::<FactInstruction, _>(iter, GenContext::Head, false);
let mut fact = self.compile_target::<FactInstruction, _>(iter, GenContext::Head);

if self.marker.max_reg_allocated() > MAX_ARITY {
return Err(CompilationError::ExceededMaxArity);
Expand All @@ -945,7 +985,7 @@ impl<'b> CodeGenerator<'b> {
}

let iter = ChunkedIterator::from_rule_body(p1, clauses);
self.compile_seq(iter, &conjunct_info, &mut code, false)?;
self.compile_seq(iter, &conjunct_info, &mut code)?;

unsafe_var_marker.mark_unsafe_instrs(&mut code);

Expand Down Expand Up @@ -994,7 +1034,6 @@ impl<'b> CodeGenerator<'b> {
let mut compiled_fact = self.compile_target::<FactInstruction, _>(
iter,
GenContext::Head,
false,
);

if self.marker.max_reg_allocated() > MAX_ARITY {
Expand All @@ -1018,12 +1057,11 @@ impl<'b> CodeGenerator<'b> {
term_loc: GenContext,
code: &mut Code,
num_perm_vars_left: usize,
is_exposed: bool,
) {
self.marker.reset_arg(term.arity());

let iter = query_term_post_order_iter(term);
let query = self.compile_target::<QueryInstruction, _>(iter, term_loc, is_exposed);
let query = self.compile_target::<QueryInstruction, _>(iter, term_loc);

code.extend(query.into_iter());
self.add_conditional_call(code, term, num_perm_vars_left);
Expand Down
24 changes: 22 additions & 2 deletions src/debray_allocator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::forms::Level;
use crate::instructions::*;
use crate::machine::machine_indices::*;
use crate::parser::ast::*;
use crate::targets::CompilationTarget;
use crate::targets::*;

use crate::temp_v;

Expand All @@ -24,6 +24,7 @@ pub(crate) struct DebrayAllocator {
arity: usize, // 0 if not at head.
contents: IndexMap<usize, Rc<String>, FxBuildHasher>,
in_use: BTreeSet<usize>,
free_list: Vec<usize>,
}

impl DebrayAllocator {
Expand Down Expand Up @@ -182,14 +183,21 @@ impl DebrayAllocator {
fn alloc_reg_to_non_var(&mut self) -> usize {
let mut final_index = 0;

while let Some(r) = self.free_list.pop() {
if !self.in_use.contains(&r) {
self.in_use.insert(r);
return r;
}
}

for index in self.temp_lb.. {
if !self.in_use.contains(&index) {
final_index = index;
self.in_use.insert(final_index);
break;
}
}

self.in_use.insert(final_index);
self.temp_lb = final_index + 1;
final_index
}
Expand All @@ -203,6 +211,15 @@ impl DebrayAllocator {
},
}
}

pub fn add_to_free_list(&mut self, r: RegType) {
if let RegType::Temp(r) = r {
if r > self.arity {
self.in_use.remove(&r);
self.free_list.push(r);
}
}
}
}

impl Allocator for DebrayAllocator {
Expand All @@ -214,6 +231,7 @@ impl Allocator for DebrayAllocator {
bindings: IndexMap::with_hasher(FxBuildHasher::default()),
contents: IndexMap::with_hasher(FxBuildHasher::default()),
in_use: BTreeSet::new(),
free_list: vec![],
}
}

Expand Down Expand Up @@ -356,11 +374,13 @@ impl Allocator for DebrayAllocator {
self.bindings.clear();
self.contents.clear();
self.in_use.clear();
self.free_list.clear();
}

fn reset_contents(&mut self) {
self.contents.clear();
self.in_use.clear();
self.free_list.clear();
}

fn advance_arg(&mut self) {
Expand Down

0 comments on commit bb624cc

Please sign in to comment.