Revert "remove Term"
This reverts commit 3b5879841aedecba5057c70c71da0ba23e5cd84a.
This commit is contained in:
@@ -1,13 +1,10 @@
|
||||
use crate::allocator::*;
|
||||
use crate::atom_table::*;
|
||||
use crate::codegen::SubsumedBranchHits;
|
||||
use crate::forms::{GenContext, Level};
|
||||
use crate::instructions::*;
|
||||
use crate::machine::disjuncts::*;
|
||||
use crate::machine::heap::*;
|
||||
use crate::machine::disjuncts::VarData;
|
||||
use crate::parser::ast::*;
|
||||
use crate::targets::*;
|
||||
use crate::types::*;
|
||||
use crate::variable_records::*;
|
||||
|
||||
use bit_set::*;
|
||||
@@ -15,6 +12,7 @@ use bitvec::prelude::*;
|
||||
use fxhash::FxBuildHasher;
|
||||
use indexmap::IndexMap;
|
||||
|
||||
use std::cell::Cell;
|
||||
use std::collections::VecDeque;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
@@ -154,8 +152,6 @@ pub(crate) struct DebrayAllocator {
|
||||
in_use: BitSet<usize>, // deep and non-var allocations
|
||||
temp_free_list: Vec<usize>,
|
||||
perm_free_list: VecDeque<(usize, usize)>, // chunk_num, var_num
|
||||
non_var_registers: IndexMap<usize, usize, FxBuildHasher>,
|
||||
non_var_register_heap_locs: IndexMap<usize, usize, FxBuildHasher>,
|
||||
}
|
||||
|
||||
impl DebrayAllocator {
|
||||
@@ -172,9 +168,7 @@ impl DebrayAllocator {
|
||||
|
||||
for var_num in subsumed_hits {
|
||||
match &mut self.var_data.records[var_num].allocation {
|
||||
VarAlloc::Perm {
|
||||
ref mut allocation, ..
|
||||
} => {
|
||||
VarAlloc::Perm(_, ref mut allocation) => {
|
||||
if let PermVarAllocation::Done {
|
||||
shallow_safety,
|
||||
deep_safety,
|
||||
@@ -235,7 +229,7 @@ impl DebrayAllocator {
|
||||
let num_occurrences = self.var_data.records[var_num].num_occurrences;
|
||||
|
||||
match &mut self.var_data.records[var_num].allocation {
|
||||
VarAlloc::Perm { allocation, .. } => {
|
||||
VarAlloc::Perm(_, allocation) => {
|
||||
let shallow_safety = VarSafetyStatus::needed_if(
|
||||
shallow_safety.contains(var_num),
|
||||
branch_designator,
|
||||
@@ -372,7 +366,7 @@ impl DebrayAllocator {
|
||||
&mut self,
|
||||
chunk_num: usize,
|
||||
code: &mut CodeDeque,
|
||||
) -> Option<RegType> {
|
||||
) {
|
||||
if let Some((var_num, r)) = self.alloc_in_last_goal_hint(chunk_num) {
|
||||
let k = self.arg_c;
|
||||
|
||||
@@ -388,12 +382,8 @@ impl DebrayAllocator {
|
||||
.allocation
|
||||
.set_register(r.reg_num());
|
||||
self.in_use.insert(r.reg_num());
|
||||
|
||||
return Some(r);
|
||||
}
|
||||
};
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
fn alloc_reg_to_var<'a, Target: CompilationTarget<'a>>(
|
||||
@@ -443,7 +433,6 @@ impl DebrayAllocator {
|
||||
}
|
||||
|
||||
self.temp_lb = final_index + 1;
|
||||
|
||||
final_index
|
||||
}
|
||||
|
||||
@@ -467,11 +456,7 @@ impl DebrayAllocator {
|
||||
p
|
||||
};
|
||||
|
||||
self.var_data.records[var_num].allocation = VarAlloc::Perm {
|
||||
reg: p,
|
||||
allocation: PermVarAllocation::done(),
|
||||
};
|
||||
|
||||
self.var_data.records[var_num].allocation = VarAlloc::Perm(p, PermVarAllocation::done());
|
||||
p
|
||||
}
|
||||
|
||||
@@ -487,15 +472,10 @@ impl DebrayAllocator {
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn get_var_binding(&self, var_num: usize) -> RegType {
|
||||
pub fn get_binding(&self, var_num: usize) -> RegType {
|
||||
self.var_data.records[var_num].allocation.as_reg_type()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn get_non_var_binding(&self, heap_loc: usize) -> RegType {
|
||||
RegType::Temp(self.non_var_registers.get(&heap_loc).cloned().unwrap_or(0))
|
||||
}
|
||||
|
||||
pub fn num_perm_vars(&self) -> usize {
|
||||
self.perm_lb - 1
|
||||
}
|
||||
@@ -505,7 +485,7 @@ impl DebrayAllocator {
|
||||
}
|
||||
|
||||
fn add_perm_to_free_list(&mut self, chunk_num: usize, var_num: usize) {
|
||||
if let VarAlloc::Perm { .. } = &self.var_data.records[var_num].allocation {
|
||||
if let VarAlloc::Perm(..) = &self.var_data.records[var_num].allocation {
|
||||
self.perm_free_list.push_back((chunk_num, var_num));
|
||||
}
|
||||
}
|
||||
@@ -516,10 +496,7 @@ impl DebrayAllocator {
|
||||
self.perm_free_list.pop_front();
|
||||
|
||||
match &mut self.var_data.records[var_num].allocation {
|
||||
VarAlloc::Perm {
|
||||
reg: p,
|
||||
allocation: PermVarAllocation::Pending,
|
||||
} if *p > 0 => {
|
||||
VarAlloc::Perm(p, PermVarAllocation::Pending) if *p > 0 => {
|
||||
return Some(std::mem::replace(p, 0));
|
||||
}
|
||||
_ => {}
|
||||
@@ -533,12 +510,9 @@ impl DebrayAllocator {
|
||||
}
|
||||
|
||||
pub(crate) fn free_var(&mut self, chunk_num: usize, var_num: usize) {
|
||||
match &mut self.var_data.records[var_num].allocation {
|
||||
VarAlloc::Perm { allocation, .. } => {
|
||||
*allocation = PermVarAllocation::Pending;
|
||||
self.add_perm_to_free_list(chunk_num, var_num);
|
||||
}
|
||||
_ => {}
|
||||
if let VarAlloc::Perm(_, allocation) = &mut self.var_data.records[var_num].allocation {
|
||||
*allocation = PermVarAllocation::Pending;
|
||||
self.add_perm_to_free_list(chunk_num, var_num);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -546,15 +520,14 @@ impl DebrayAllocator {
|
||||
let branch_designator = self.branch_stack.current_branch_designator();
|
||||
|
||||
match &mut self.var_data.records[var_num].allocation {
|
||||
VarAlloc::Perm {
|
||||
allocation:
|
||||
PermVarAllocation::Done {
|
||||
deep_safety,
|
||||
shallow_safety,
|
||||
..
|
||||
},
|
||||
..
|
||||
} => {
|
||||
VarAlloc::Perm(
|
||||
_,
|
||||
PermVarAllocation::Done {
|
||||
deep_safety,
|
||||
shallow_safety,
|
||||
..
|
||||
},
|
||||
) => {
|
||||
*deep_safety = VarSafetyStatus::unneeded(branch_designator);
|
||||
*shallow_safety = VarSafetyStatus::unneeded(branch_designator);
|
||||
}
|
||||
@@ -562,8 +535,7 @@ impl DebrayAllocator {
|
||||
*safety = VarSafetyStatus::unneeded(branch_designator);
|
||||
}
|
||||
_ => {
|
||||
// the (permanent) variable might have been freed by
|
||||
// this point, in which case we do nothing.
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -572,15 +544,14 @@ impl DebrayAllocator {
|
||||
let branch_designator = self.branch_stack.current_branch_designator();
|
||||
|
||||
match &mut self.var_data.records[var_num].allocation {
|
||||
VarAlloc::Perm {
|
||||
allocation:
|
||||
PermVarAllocation::Done {
|
||||
deep_safety,
|
||||
shallow_safety,
|
||||
..
|
||||
},
|
||||
..
|
||||
} => {
|
||||
VarAlloc::Perm(
|
||||
_,
|
||||
PermVarAllocation::Done {
|
||||
deep_safety,
|
||||
shallow_safety,
|
||||
..
|
||||
},
|
||||
) => {
|
||||
// GetVariable in head chunk is considered safe.
|
||||
if lvl == Level::Deep {
|
||||
*deep_safety = VarSafetyStatus::unneeded(branch_designator);
|
||||
@@ -617,14 +588,13 @@ impl DebrayAllocator {
|
||||
let branch_designator = self.branch_stack.current_branch_designator();
|
||||
|
||||
match &mut self.var_data.records[var_num].allocation {
|
||||
VarAlloc::Perm {
|
||||
allocation:
|
||||
PermVarAllocation::Done {
|
||||
ref mut shallow_safety,
|
||||
..
|
||||
},
|
||||
..
|
||||
} => {
|
||||
VarAlloc::Perm(
|
||||
_,
|
||||
PermVarAllocation::Done {
|
||||
ref mut shallow_safety,
|
||||
..
|
||||
},
|
||||
) => {
|
||||
if !self.in_tail_position
|
||||
|| self
|
||||
.branch_stack
|
||||
@@ -654,14 +624,13 @@ impl DebrayAllocator {
|
||||
let branch_designator = self.branch_stack.current_branch_designator();
|
||||
|
||||
match &mut self.var_data.records[var_num].allocation {
|
||||
VarAlloc::Perm {
|
||||
allocation:
|
||||
PermVarAllocation::Done {
|
||||
ref mut deep_safety,
|
||||
..
|
||||
},
|
||||
..
|
||||
} => {
|
||||
VarAlloc::Perm(
|
||||
_,
|
||||
PermVarAllocation::Done {
|
||||
ref mut deep_safety,
|
||||
..
|
||||
},
|
||||
) => {
|
||||
if self
|
||||
.branch_stack
|
||||
.safety_unneeded_in_branch(deep_safety, &branch_designator)
|
||||
@@ -704,15 +673,13 @@ impl Allocator for DebrayAllocator {
|
||||
temp_free_list: vec![],
|
||||
perm_free_list: VecDeque::new(),
|
||||
branch_stack: BranchStack { stack: vec![] },
|
||||
non_var_registers: IndexMap::with_hasher(FxBuildHasher::default()),
|
||||
non_var_register_heap_locs: IndexMap::with_hasher(FxBuildHasher::default()),
|
||||
}
|
||||
}
|
||||
|
||||
fn mark_anon_var<'a, Target: CompilationTarget<'a>>(
|
||||
&mut self,
|
||||
lvl: Level,
|
||||
context: GenContext,
|
||||
term_loc: GenContext,
|
||||
code: &mut CodeDeque,
|
||||
) -> RegType {
|
||||
let r = RegType::Temp(self.alloc_reg_to_non_var());
|
||||
@@ -722,7 +689,7 @@ impl Allocator for DebrayAllocator {
|
||||
Level::Root | Level::Shallow => {
|
||||
let k = self.arg_c;
|
||||
|
||||
if let GenContext::Last(chunk_num) = context {
|
||||
if let GenContext::Last(chunk_num) = term_loc {
|
||||
self.evacuate_arg::<Target>(chunk_num, code);
|
||||
}
|
||||
|
||||
@@ -738,69 +705,55 @@ impl Allocator for DebrayAllocator {
|
||||
fn mark_non_var<'a, Target: CompilationTarget<'a>>(
|
||||
&mut self,
|
||||
lvl: Level,
|
||||
heap_loc: usize,
|
||||
context: GenContext,
|
||||
term_loc: GenContext,
|
||||
cell: &'a Cell<RegType>,
|
||||
code: &mut CodeDeque,
|
||||
) -> RegType {
|
||||
let r = self.get_non_var_binding(heap_loc);
|
||||
) {
|
||||
let r = cell.get();
|
||||
|
||||
let r = match lvl {
|
||||
Level::Shallow => {
|
||||
let k = self.arg_c;
|
||||
|
||||
if let GenContext::Last(chunk_num) = context {
|
||||
if let Some(new_r) = self.evacuate_arg::<Target>(chunk_num, code) {
|
||||
self.non_var_register_heap_locs
|
||||
.swap_remove(&k)
|
||||
.map(|old_heap_loc| {
|
||||
self.non_var_registers.insert(old_heap_loc, new_r.reg_num());
|
||||
self.non_var_register_heap_locs
|
||||
.insert(new_r.reg_num(), old_heap_loc);
|
||||
});
|
||||
|
||||
self.non_var_registers.insert(heap_loc, k);
|
||||
self.non_var_register_heap_locs.insert(k, heap_loc);
|
||||
}
|
||||
if let GenContext::Last(chunk_num) = term_loc {
|
||||
self.evacuate_arg::<Target>(chunk_num, code);
|
||||
}
|
||||
|
||||
self.arg_c += 1;
|
||||
RegType::Temp(k)
|
||||
}
|
||||
_ if r.reg_num() == 0 => {
|
||||
let r = RegType::Temp(self.alloc_reg_to_non_var());
|
||||
self.non_var_registers.insert(heap_loc, r.reg_num());
|
||||
self.non_var_register_heap_locs
|
||||
.insert(r.reg_num(), heap_loc);
|
||||
r
|
||||
}
|
||||
_ if r.reg_num() == 0 => RegType::Temp(self.alloc_reg_to_non_var()),
|
||||
_ => {
|
||||
self.in_use.insert(r.reg_num());
|
||||
r
|
||||
}
|
||||
};
|
||||
|
||||
r
|
||||
cell.set(r);
|
||||
}
|
||||
|
||||
fn mark_var<'a, Target: CompilationTarget<'a>>(
|
||||
&mut self,
|
||||
var_num: usize,
|
||||
lvl: Level,
|
||||
context: GenContext,
|
||||
cell: &Cell<VarReg>,
|
||||
term_loc: GenContext,
|
||||
code: &mut CodeDeque,
|
||||
) -> RegType {
|
||||
let (r, is_new_var) = match self.get_var_binding(var_num) {
|
||||
) {
|
||||
let (r, is_new_var) = match self.get_binding(var_num) {
|
||||
RegType::Temp(0) => {
|
||||
let o = self.alloc_reg_to_var::<Target>(var_num, lvl, context, code);
|
||||
let o = self.alloc_reg_to_var::<Target>(var_num, lvl, term_loc, code);
|
||||
cell.set(VarReg::Norm(RegType::Temp(o)));
|
||||
(RegType::Temp(o), true)
|
||||
}
|
||||
RegType::Perm(0) => {
|
||||
let p = self.alloc_perm_var(var_num, context.chunk_num());
|
||||
let p = self.alloc_perm_var(var_num, term_loc.chunk_num());
|
||||
cell.set(VarReg::Norm(RegType::Perm(p)));
|
||||
(RegType::Perm(p), true)
|
||||
}
|
||||
r @ RegType::Perm(_) => {
|
||||
let is_new_var = match &mut self.var_data.records[var_num].allocation {
|
||||
VarAlloc::Perm { allocation, .. } => {
|
||||
VarAlloc::Perm(_, allocation) => {
|
||||
if allocation.pending() {
|
||||
*allocation = PermVarAllocation::done();
|
||||
true
|
||||
@@ -816,29 +769,32 @@ impl Allocator for DebrayAllocator {
|
||||
r => (r, false),
|
||||
};
|
||||
|
||||
self.mark_reserved_var::<Target>(var_num, lvl, context, code, r, is_new_var)
|
||||
self.mark_reserved_var::<Target>(var_num, lvl, cell, term_loc, code, r, is_new_var);
|
||||
}
|
||||
|
||||
fn mark_reserved_var<'a, Target: CompilationTarget<'a>>(
|
||||
&mut self,
|
||||
var_num: usize,
|
||||
lvl: Level,
|
||||
context: GenContext,
|
||||
cell: &Cell<VarReg>,
|
||||
term_loc: GenContext,
|
||||
code: &mut CodeDeque,
|
||||
r: RegType,
|
||||
is_new_var: bool,
|
||||
) -> RegType {
|
||||
) {
|
||||
match lvl {
|
||||
Level::Root | Level::Shallow => {
|
||||
let k = self.arg_c;
|
||||
|
||||
if self.is_curr_arg_distinct_from(var_num) {
|
||||
self.evacuate_arg::<Target>(context.chunk_num(), code);
|
||||
self.evacuate_arg::<Target>(term_loc.chunk_num(), code);
|
||||
}
|
||||
|
||||
if !self.in_place(var_num, context, r, k) {
|
||||
cell.set(VarReg::ArgAndNorm(r, k));
|
||||
|
||||
if !self.in_place(var_num, term_loc, r, k) {
|
||||
if is_new_var {
|
||||
self.mark_safe_var(var_num, lvl, context);
|
||||
self.mark_safe_var(var_num, lvl, term_loc);
|
||||
code.push_back(Target::argument_to_variable(r, k));
|
||||
} else {
|
||||
code.push_back(self.argument_to_value::<Target>(var_num, r, k));
|
||||
@@ -848,15 +804,15 @@ impl Allocator for DebrayAllocator {
|
||||
self.arg_c += 1;
|
||||
}
|
||||
Level::Deep if is_new_var => {
|
||||
if let GenContext::Head = context {
|
||||
if let GenContext::Head = term_loc {
|
||||
if self.occurs_shallowly_in_head(var_num, r.reg_num()) {
|
||||
code.push_back(self.subterm_to_value::<Target>(var_num, r));
|
||||
} else {
|
||||
self.mark_safe_var(var_num, lvl, context);
|
||||
self.mark_safe_var(var_num, lvl, term_loc);
|
||||
code.push_back(Target::subterm_to_variable(r));
|
||||
}
|
||||
} else {
|
||||
self.mark_safe_var(var_num, lvl, context);
|
||||
self.mark_safe_var(var_num, lvl, term_loc);
|
||||
code.push_back(Target::subterm_to_variable(r));
|
||||
}
|
||||
}
|
||||
@@ -878,15 +834,14 @@ impl Allocator for DebrayAllocator {
|
||||
if record.running_count < record.num_occurrences {
|
||||
record.running_count += 1;
|
||||
} else {
|
||||
self.free_var(context.chunk_num(), var_num);
|
||||
self.free_var(term_loc.chunk_num(), var_num);
|
||||
}
|
||||
|
||||
self.in_use.insert(o);
|
||||
r
|
||||
}
|
||||
|
||||
fn mark_cut_var(&mut self, var_num: usize, chunk_num: usize) -> RegType {
|
||||
match self.get_var_binding(var_num) {
|
||||
match self.get_binding(var_num) {
|
||||
RegType::Perm(0) => RegType::Perm(self.alloc_perm_var(var_num, chunk_num)),
|
||||
RegType::Temp(0) => {
|
||||
let t = self.alloc_reg_to_non_var();
|
||||
@@ -910,8 +865,6 @@ impl Allocator for DebrayAllocator {
|
||||
fn reset(&mut self) {
|
||||
self.perm_lb = 1;
|
||||
self.shallow_temp_mappings.clear();
|
||||
self.non_var_registers.clear();
|
||||
self.non_var_register_heap_locs.clear();
|
||||
self.in_use.clear();
|
||||
self.temp_free_list.clear();
|
||||
}
|
||||
@@ -919,8 +872,6 @@ impl Allocator for DebrayAllocator {
|
||||
fn reset_contents(&mut self) {
|
||||
self.in_use.clear();
|
||||
self.shallow_temp_mappings.clear();
|
||||
self.non_var_registers.clear();
|
||||
self.non_var_register_heap_locs.clear();
|
||||
self.temp_free_list.clear();
|
||||
}
|
||||
|
||||
@@ -928,54 +879,24 @@ impl Allocator for DebrayAllocator {
|
||||
self.arg_c += 1;
|
||||
}
|
||||
|
||||
fn reset_at_head(&mut self, heap: &mut Heap, head_loc: usize) {
|
||||
let head_cell = heap_bound_store(heap, heap_bound_deref(heap, heap_loc_as_cell!(head_loc)));
|
||||
fn reset_at_head(&mut self, args: &[Term]) {
|
||||
self.reset_arg(args.len());
|
||||
self.arity = args.len();
|
||||
|
||||
read_heap_cell!(head_cell,
|
||||
(HeapCellValueTag::Str, s) => {
|
||||
let arity = cell_as_atom_cell!(heap[s]).get_arity();
|
||||
for (idx, arg) in args.iter().enumerate() {
|
||||
if let Term::Var(_, ref var) = arg {
|
||||
let var_num = var.to_var_num().unwrap();
|
||||
let r = self.get_binding(var_num);
|
||||
|
||||
self.reset_arg(arity);
|
||||
self.arity = arity;
|
||||
|
||||
for (c_idx, heap_idx) in (s+1 ..= s+arity).enumerate() {
|
||||
let arg = heap[heap_idx];
|
||||
|
||||
if arg.is_var() {
|
||||
let var = heap_bound_store(
|
||||
heap,
|
||||
heap_bound_deref(heap, arg),
|
||||
);
|
||||
|
||||
if !var.is_var() {
|
||||
continue;
|
||||
}
|
||||
|
||||
let term_loc = var.get_value() as usize;
|
||||
|
||||
match self.var_data.var_locs_to_nums.get(
|
||||
VarPtrIndex { chunk_num: 0, term_loc },
|
||||
) {
|
||||
VarPtr::Numbered(var_num) => {
|
||||
let r = self.get_var_binding(var_num);
|
||||
|
||||
if !r.is_perm() && r.reg_num() == 0 {
|
||||
self.in_use.insert(c_idx + 1);
|
||||
self.shallow_temp_mappings.insert(c_idx + 1, var_num);
|
||||
self.var_data.records[var_num]
|
||||
.allocation
|
||||
.set_register(c_idx + 1);
|
||||
}
|
||||
}
|
||||
VarPtr::Anon => {}
|
||||
}
|
||||
}
|
||||
if !r.is_perm() && r.reg_num() == 0 {
|
||||
self.in_use.insert(idx + 1);
|
||||
self.shallow_temp_mappings.insert(idx + 1, var_num);
|
||||
self.var_data.records[var_num]
|
||||
.allocation
|
||||
.set_register(idx + 1);
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
self.reset_arg(0);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn reset_arg(&mut self, arity: usize) {
|
||||
|
||||
Reference in New Issue
Block a user