]> Repositorios git - scryer-prolog.git/commitdiff
use free lists to allow register re-use (#1612)
authorMark Thom <[email protected]>
Sun, 8 Jan 2023 19:10:38 +0000 (12:10 -0700)
committerMark Thom <[email protected]>
Sun, 8 Jan 2023 19:11:04 +0000 (12:11 -0700)
src/codegen.rs
src/debray_allocator.rs

index 6f7223360c610c0258b14a28aecfae8eb69f6bc7..dc03a19a4d705fe479709f53b2e56d5544063205 100644 (file)
@@ -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 {
@@ -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);
@@ -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);
             }
@@ -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);
             }
         };
     }
@@ -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();
 
@@ -352,6 +382,8 @@ 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);
@@ -359,15 +391,24 @@ impl<'b> CodeGenerator<'b> {
                     }
 
                     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);
@@ -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);
@@ -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() {
@@ -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);
@@ -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);
@@ -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);
 
@@ -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 {
@@ -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);
index 1c81fcdd2a9bb67b7f3966b7363237f806a427ee..98c1bd6e5b16aa653fcde8557e887984770ff20e 100644 (file)
@@ -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;
 
@@ -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 {
@@ -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
     }
@@ -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 {
@@ -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![],
         }
     }
 
@@ -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) {