use crate::try_numeric_result;
+use fxhash::FxBuildHasher;
+
macro_rules! step_or_fail {
($self:expr, $step_e:expr) => {
if $self.machine_st.fail {
Ok(())
}
+
+ #[inline(always)]
+ pub(crate) fn select_switch_on_term_index(
+ &self,
+ addr: HeapCellValue,
+ v: IndexingCodePtr,
+ c: IndexingCodePtr,
+ l: IndexingCodePtr,
+ s: IndexingCodePtr,
+ ) -> IndexingCodePtr {
+ read_heap_cell!(addr,
+ (HeapCellValueTag::Var |
+ HeapCellValueTag::StackVar |
+ HeapCellValueTag::AttrVar) => {
+ v
+ }
+ (HeapCellValueTag::PStrLoc |
+ HeapCellValueTag::Lis |
+ HeapCellValueTag::CStr) => {
+ l
+ }
+ (HeapCellValueTag::Fixnum |
+ HeapCellValueTag::Char |
+ HeapCellValueTag::F64) => {
+ c
+ }
+ (HeapCellValueTag::Atom, (_name, arity)) => {
+ // if arity == 0 { c } else { s }
+ debug_assert!(arity == 0);
+ c
+ }
+ (HeapCellValueTag::Str, st) => {
+ let (name, arity) = cell_as_atom_cell!(self.heap[st])
+ .get_name_and_arity();
+
+ match (name, arity) {
+ (atom!("."), 2) => l,
+ (_, 0) => c,
+ _ => s,
+ }
+ }
+ (HeapCellValueTag::Cons, ptr) => {
+ match ptr.get_tag() {
+ ArenaHeaderTag::Rational | ArenaHeaderTag::Integer => {
+ c
+ }
+ _ => {
+ IndexingCodePtr::Fail
+ }
+ }
+ }
+ _ => {
+ unreachable!();
+ }
+ )
+ }
+
+ #[inline(always)]
+ pub(crate) fn constant_to_literal(&self, addr: HeapCellValue) -> Literal {
+ read_heap_cell!(addr,
+ (HeapCellValueTag::Char, c) => {
+ Literal::Char(c)
+ }
+ (HeapCellValueTag::Fixnum, n) => {
+ Literal::Fixnum(n)
+ }
+ (HeapCellValueTag::F64, f) => {
+ Literal::Float(f.as_offset())
+ }
+ (HeapCellValueTag::Atom, (atom, arity)) => {
+ debug_assert_eq!(arity, 0);
+ Literal::Atom(atom)
+ }
+ (HeapCellValueTag::Str, s) => {
+ Literal::Atom(cell_as_atom_cell!(self.heap[s]).get_name())
+ }
+ (HeapCellValueTag::Cons, cons_ptr) => {
+ match_untyped_arena_ptr!(cons_ptr,
+ (ArenaHeaderTag::Rational, r) => {
+ Literal::Rational(r)
+ }
+ (ArenaHeaderTag::Integer, n) => {
+ Literal::Integer(n)
+ }
+ _ => {
+ unreachable!()
+ }
+ )
+ }
+ _ => {
+ unreachable!()
+ }
+ )
+ }
+
+ #[inline(always)]
+ pub(crate) fn select_switch_on_structure_index(
+ &self,
+ addr: HeapCellValue,
+ hm: &IndexMap<(Atom, usize), IndexingCodePtr, FxBuildHasher>,
+ ) -> IndexingCodePtr {
+ read_heap_cell!(addr,
+ (HeapCellValueTag::Atom, (name, arity)) => {
+ match hm.get(&(name, arity)) {
+ Some(offset) => *offset,
+ None => IndexingCodePtr::Fail,
+ }
+ }
+ (HeapCellValueTag::Str, s) => {
+ let (name, arity) = cell_as_atom_cell!(self.heap[s])
+ .get_name_and_arity();
+
+ match hm.get(&(name, arity)) {
+ Some(offset) => *offset,
+ None => IndexingCodePtr::Fail,
+ }
+ }
+ _ => {
+ IndexingCodePtr::Fail
+ }
+ )
+ }
}
impl Machine {
loop {
match &indexing_lines[index] {
&IndexingLine::Indexing(IndexingInstruction::SwitchOnTerm(_, v, c, l, s)) => {
- let offset = read_heap_cell!(addr,
- (HeapCellValueTag::Var |
- HeapCellValueTag::StackVar |
- HeapCellValueTag::AttrVar) => {
- v
- }
- (HeapCellValueTag::PStrLoc |
- HeapCellValueTag::Lis |
- HeapCellValueTag::CStr) => {
- l
- }
- (HeapCellValueTag::Fixnum |
- HeapCellValueTag::Char |
- HeapCellValueTag::F64) => {
- c
- }
- (HeapCellValueTag::Atom, (_name, arity)) => {
- // if arity == 0 { c } else { s }
- debug_assert!(arity == 0);
- c
- }
- (HeapCellValueTag::Str, st) => {
- let (name, arity) = cell_as_atom_cell!(self.machine_st.heap[st])
- .get_name_and_arity();
-
- match (name, arity) {
- (atom!("."), 2) => l,
- (_, 0) => c,
- _ => s,
- }
- }
- (HeapCellValueTag::Cons, ptr) => {
- match ptr.get_tag() {
- ArenaHeaderTag::Rational | ArenaHeaderTag::Integer => {
- c
- }
- _ => {
- IndexingCodePtr::Fail
- }
- }
- }
- _ => {
- unreachable!();
- }
- );
+ let offset = self.machine_st.select_switch_on_term_index(addr, v, c, l, s);
match offset {
IndexingCodePtr::Fail => {
}
}
}
- &IndexingLine::Indexing(IndexingInstruction::SwitchOnConstant(ref hm)) => {
- let lit = read_heap_cell!(addr,
- (HeapCellValueTag::Char, c) => {
- Literal::Char(c)
- }
- (HeapCellValueTag::Fixnum, n) => {
- Literal::Fixnum(n)
- }
- (HeapCellValueTag::F64, f) => {
- Literal::Float(f.as_offset())
- }
- (HeapCellValueTag::Atom, (atom, arity)) => {
- debug_assert_eq!(arity, 0);
- Literal::Atom(atom)
- }
- (HeapCellValueTag::Str, s) => {
- Literal::Atom(cell_as_atom_cell!(self.machine_st.heap[s]).get_name())
- }
- (HeapCellValueTag::Cons, cons_ptr) => {
- match_untyped_arena_ptr!(cons_ptr,
- (ArenaHeaderTag::Rational, r) => {
- Literal::Rational(r)
- }
- (ArenaHeaderTag::Integer, n) => {
- Literal::Integer(n)
- }
- _ => {
- unreachable!()
- }
- )
- }
- _ => {
- unreachable!()
- }
- );
+ IndexingLine::Indexing(IndexingInstruction::SwitchOnConstant(hm)) => {
+ let lit = self.machine_st.constant_to_literal(addr);
let offset = match hm.get(&lit) {
Some(offset) => *offset,
}
}
}
- &IndexingLine::Indexing(IndexingInstruction::SwitchOnStructure(ref hm)) => {
- let offset = read_heap_cell!(addr,
- (HeapCellValueTag::Atom, (name, arity)) => {
- match hm.get(&(name, arity)) {
- Some(offset) => *offset,
- None => IndexingCodePtr::Fail,
- }
- }
- (HeapCellValueTag::Str, s) => {
- let (name, arity) = cell_as_atom_cell!(self.machine_st.heap[s])
- .get_name_and_arity();
-
- match hm.get(&(name, arity)) {
- Some(offset) => *offset,
- None => IndexingCodePtr::Fail,
- }
- }
- _ => {
- IndexingCodePtr::Fail
- }
- );
+ IndexingLine::Indexing(IndexingInstruction::SwitchOnStructure(hm)) => {
+ let offset = self.machine_st.select_switch_on_structure_index(addr, hm);
match offset {
IndexingCodePtr::Fail => {
fixnum_as_cell!(Fixnum::build_with(self.machine_st.cc as i64));
self.machine_st.num_of_args += 1;
- self.machine_st.try_me_else(next_i);
+ self.try_me_else(next_i);
self.machine_st.num_of_args -= 1;
}
None => {
fixnum_as_cell!(Fixnum::build_with(self.machine_st.cc as i64));
self.machine_st.num_of_args += 1;
- self.machine_st.try_me_else(next_i);
+ self.try_me_else(next_i);
self.machine_st.num_of_args -= 1;
}
None => {
}
}
&Instruction::TryMeElse(offset) => {
- self.machine_st.try_me_else(offset);
+ self.try_me_else(offset);
}
&Instruction::DefaultRetryMeElse(offset) => {
self.retry_me_else(offset);
step_or_fail!(self, self.machine_st.p += 1);
}
- &Instruction::GetStructure(name, arity, reg) => {
+ &Instruction::GetStructure(_lvl, name, arity, reg) => {
let deref_v = self.machine_st.deref(self.machine_st[reg]);
let store_v = self.machine_st.store(deref_v);
IndexingLine::IndexedChoice(ref indexed_choice) => {
match &indexed_choice[self.machine_st.iip as usize] {
&IndexedChoiceInstruction::Try(offset) => {
- self.machine_st.indexed_try(offset);
+ self.indexed_try(offset);
}
&IndexedChoiceInstruction::Retry(l) => {
self.retry(l);
fixnum_as_cell!(Fixnum::build_with(self.machine_st.cc as i64));
self.machine_st.num_of_args += 1;
- self.machine_st.indexed_try(offset);
+ self.indexed_try(offset);
self.machine_st.num_of_args -= 1;
}
None => {
self.machine_st.verify_attr_interrupt(p, arity);
}
+ fn next_clause_applicable(&mut self, mut offset: usize) -> bool {
+ loop {
+ match &self.code[offset] {
+ Instruction::IndexingCode(indexing_lines) => {
+ let mut oip = 0;
+ let mut cell = empty_list_as_cell!();
+
+ loop {
+ let indexing_code_ptr = match &indexing_lines[oip] {
+ &IndexingLine::Indexing(IndexingInstruction::SwitchOnTerm(arg, v, c, l, s)) => {
+ cell = self.deref_register(arg);
+ self.machine_st.select_switch_on_term_index(cell, v, c, l, s)
+ }
+ IndexingLine::Indexing(IndexingInstruction::SwitchOnConstant(hm)) => {
+ let lit = self.machine_st.constant_to_literal(cell);
+ hm.get(&lit).cloned().unwrap_or(IndexingCodePtr::Fail)
+ }
+ IndexingLine::Indexing(IndexingInstruction::SwitchOnStructure(hm)) => {
+ self.machine_st.select_switch_on_structure_index(cell, hm)
+ }
+ _ => {
+ offset += 1;
+ break;
+ }
+ };
+
+ match indexing_code_ptr {
+ IndexingCodePtr::External(_) | IndexingCodePtr::DynamicExternal(_) => {
+ offset += 1;
+ break;
+ }
+ IndexingCodePtr::Internal(i) => oip += i,
+ IndexingCodePtr::Fail => return false,
+ }
+ }
+ }
+ &Instruction::GetConstant(Level::Shallow, lit, RegType::Temp(t)) => {
+ let cell = self.deref_register(t);
+
+ if cell.is_var() {
+ offset += 1;
+ } else if lit.get_tag() == HeapCellValueTag::CStr {
+ read_heap_cell!(cell,
+ (HeapCellValueTag::CStr) => {
+ if cell == lit {
+ offset += 1;
+ } else {
+ return false;
+ }
+ }
+ (HeapCellValueTag::Lis | HeapCellValueTag::PStrLoc) => {
+ offset += 1;
+ }
+ (HeapCellValueTag::Str, s) => {
+ let (name, arity) = cell_as_atom_cell!(self.machine_st.heap[s])
+ .get_name_and_arity();
+
+ if name == atom!(".") && arity == 2 {
+ offset += 1;
+ } else {
+ return false;
+ }
+ }
+ _ => {
+ return false;
+ }
+ );
+ } else {
+ self.machine_st.write_literal_to_var(cell, lit);
+
+ if self.machine_st.fail {
+ self.machine_st.fail = false;
+ return false;
+ } else {
+ offset += 1;
+ }
+ }
+ }
+ &Instruction::GetList(Level::Shallow, RegType::Temp(t)) => {
+ let cell = self.deref_register(t);
+
+ read_heap_cell!(cell,
+ (HeapCellValueTag::Lis | HeapCellValueTag::PStrLoc | HeapCellValueTag::CStr) => {
+ offset += 1;
+ }
+ (HeapCellValueTag::Str, s) => {
+ let (name, arity) = cell_as_atom_cell!(self.machine_st.heap[s]).get_name_and_arity();
+
+ if name == atom!(".") && arity == 2 {
+ offset += 1;
+ } else {
+ return false;
+ }
+ }
+ (HeapCellValueTag::AttrVar | HeapCellValueTag::Var | HeapCellValueTag::StackVar) => {
+ offset += 1;
+ }
+ _ => {
+ return false;
+ }
+ );
+ }
+ &Instruction::GetStructure(Level::Shallow, name, arity, RegType::Temp(t)) => {
+ let cell = self.deref_register(t);
+
+ read_heap_cell!(cell,
+ (HeapCellValueTag::Str, s) => {
+ if (name, arity) == cell_as_atom_cell!(self.machine_st.heap[s]).get_name_and_arity() {
+ offset += 1;
+ } else {
+ return false;
+ }
+ }
+ (HeapCellValueTag::AttrVar | HeapCellValueTag::Var | HeapCellValueTag::StackVar) => {
+ offset += 1;
+ }
+ _ => {
+ return false;
+ }
+ );
+ }
+ &Instruction::GetPartialString(Level::Shallow, string, RegType::Temp(t), has_tail) => {
+ let cell = self.deref_register(t);
+
+ read_heap_cell!(cell,
+ (HeapCellValueTag::CStr, cstr) => {
+ if !has_tail && string != cstr {
+ return false;
+ }
+
+ offset += 1;
+ }
+ (HeapCellValueTag::Lis | HeapCellValueTag::PStrLoc) => {
+ offset += 1;
+ }
+ (HeapCellValueTag::Str, s) => {
+ let (name, arity) = cell_as_atom_cell!(self.machine_st.heap[s]).get_name_and_arity();
+
+ if name == atom!(".") && arity == 2 {
+ offset += 1;
+ } else {
+ return false;
+ }
+ }
+ (HeapCellValueTag::AttrVar | HeapCellValueTag::Var | HeapCellValueTag::StackVar) => {
+ offset += 1;
+ }
+ _ => {
+ return false;
+ }
+ );
+ }
+ Instruction::GetConstant(..) |
+ Instruction::GetList(..) |
+ Instruction::GetStructure(..) |
+ Instruction::GetPartialString(..) |
+ &Instruction::UnifyVoid(..) |
+ &Instruction::UnifyConstant(..) |
+ &Instruction::GetVariable(..) |
+ &Instruction::GetValue(..) |
+ &Instruction::UnifyVariable(..) |
+ &Instruction::UnifyValue(..) |
+ &Instruction::UnifyLocalValue(..) => {
+ offset += 1;
+ }
+ _ => {
+ break;
+ }
+ }
+ }
+
+ true
+ }
+
+ fn next_applicable_clause(&mut self, mut offset: usize) -> Option<usize> {
+ while !self.next_clause_applicable(self.machine_st.p + offset + 1) {
+ match &self.code[self.machine_st.p + offset] {
+ &Instruction::DefaultRetryMeElse(o) | &Instruction::RetryMeElse(o) |
+ &Instruction::DynamicElse(.., NextOrFail::Next(o)) |
+ &Instruction::DynamicInternalElse(.., NextOrFail::Next(o)) => offset += o,
+ _ => {
+ return None;
+ }
+ }
+ }
+
+ Some(offset)
+ }
+
+ fn next_inner_applicable_clause(&mut self) -> Option<u32> {
+ let mut inner_offset = 1u32;
+
+ loop {
+ match &self.code[self.machine_st.p] {
+ Instruction::IndexingCode(indexing_lines) => {
+ match &indexing_lines[self.machine_st.oip as usize] {
+ IndexingLine::IndexedChoice(indexed_choice) => {
+ match &indexed_choice[(self.machine_st.iip + inner_offset) as usize] {
+ &IndexedChoiceInstruction::Retry(o) => {
+ if self.next_clause_applicable(self.machine_st.p + o) {
+ return Some(inner_offset);
+ }
+
+ inner_offset += 1;
+ }
+ &IndexedChoiceInstruction::Trust(o) => {
+ return if self.next_clause_applicable(self.machine_st.p + o) {
+ Some(inner_offset)
+ } else {
+ None
+ };
+ }
+ _ => unreachable!(),
+ }
+ }
+ IndexingLine::DynamicIndexedChoice(indexed_choice) => {
+ let idx = (self.machine_st.iip + inner_offset) as usize;
+ let o = indexed_choice[idx];
+
+ if idx + 1 == indexed_choice.len() {
+ return if self.next_clause_applicable(self.machine_st.p + o) {
+ Some(inner_offset)
+ } else {
+ None
+ };
+ } else {
+ if self.next_clause_applicable(self.machine_st.p + o) {
+ return Some(inner_offset);
+ }
+
+ inner_offset += 1;
+ }
+ }
+ _ => unreachable!(),
+ }
+ }
+ _ => unreachable!(),
+ }
+ }
+ }
+
+ #[inline(always)]
+ pub(super) fn try_me_else(&mut self, offset: usize) {
+ if let Some(offset) = self.next_applicable_clause(offset) {
+ let n = self.machine_st.num_of_args;
+ let b = self.machine_st.stack.allocate_or_frame(n);
+ let or_frame = self.machine_st.stack.index_or_frame_mut(b);
+
+ or_frame.prelude.num_cells = n;
+ or_frame.prelude.e = self.machine_st.e;
+ or_frame.prelude.cp = self.machine_st.cp;
+ or_frame.prelude.b = self.machine_st.b;
+ or_frame.prelude.bp = self.machine_st.p + offset;
+ or_frame.prelude.boip = 0;
+ or_frame.prelude.biip = 0;
+ or_frame.prelude.tr = self.machine_st.tr;
+ or_frame.prelude.h = self.machine_st.heap.len();
+ or_frame.prelude.b0 = self.machine_st.b0;
+ or_frame.prelude.attr_var_queue_len = self.machine_st.attr_var_init.attr_var_queue.len();
+
+ self.machine_st.b = b;
+
+ for i in 0..n {
+ or_frame[i] = self.machine_st.registers[i+1];
+ }
+
+ self.machine_st.hb = self.machine_st.heap.len();
+ }
+
+ self.machine_st.p += 1;
+ }
+
+ #[inline(always)]
+ pub(super) fn indexed_try(&mut self, offset: usize) {
+ if let Some(iip_offset) = self.next_inner_applicable_clause() {
+ let n = self.machine_st.num_of_args;
+ let b = self.machine_st.stack.allocate_or_frame(n);
+ let or_frame = self.machine_st.stack.index_or_frame_mut(b);
+
+ or_frame.prelude.num_cells = n;
+ or_frame.prelude.e = self.machine_st.e;
+ or_frame.prelude.cp = self.machine_st.cp;
+ or_frame.prelude.b = self.machine_st.b;
+ or_frame.prelude.bp = self.machine_st.p;
+ or_frame.prelude.boip = self.machine_st.oip;
+ or_frame.prelude.biip = self.machine_st.iip + iip_offset; // 1
+ or_frame.prelude.tr = self.machine_st.tr;
+ or_frame.prelude.h = self.machine_st.heap.len();
+ or_frame.prelude.b0 = self.machine_st.b0;
+ or_frame.prelude.attr_var_queue_len = self.machine_st.attr_var_init.attr_var_queue.len();
+
+ self.machine_st.b = b;
+
+ for i in 0..n {
+ or_frame[i] = self.machine_st.registers[i+1];
+ }
+
+ self.machine_st.hb = self.machine_st.heap.len();
+
+ self.machine_st.oip = 0;
+ self.machine_st.iip = 0;
+ }
+
+ self.machine_st.p += offset;
+ }
+
#[inline(always)]
fn retry_me_else(&mut self, offset: usize) {
let b = self.machine_st.b;
let or_frame = self.machine_st.stack.index_or_frame_mut(b);
let n = or_frame.prelude.num_cells;
+ let old_tr = or_frame.prelude.tr;
+ let curr_tr = self.machine_st.tr;
+
for i in 0..n {
self.machine_st.registers[i + 1] = or_frame[i];
}
- self.machine_st.num_of_args = n;
- self.machine_st.e = or_frame.prelude.e;
- self.machine_st.cp = or_frame.prelude.cp;
+ self.unwind_trail(old_tr, curr_tr);
- or_frame.prelude.bp = self.machine_st.p + offset;
+ if let Some(offset) = self.next_applicable_clause(offset) {
+ let or_frame = self.machine_st.stack.index_or_frame_mut(b);
- let old_tr = or_frame.prelude.tr;
- let curr_tr = self.machine_st.tr;
- let target_h = or_frame.prelude.h;
- let attr_var_queue_len = or_frame.prelude.attr_var_queue_len;
+ self.machine_st.num_of_args = n;
+ self.machine_st.e = or_frame.prelude.e;
+ self.machine_st.cp = or_frame.prelude.cp;
- self.machine_st.tr = or_frame.prelude.tr;
- self.reset_attr_var_state(attr_var_queue_len);
+ or_frame.prelude.bp = self.machine_st.p + offset;
- self.machine_st.hb = target_h;
+ let target_h = or_frame.prelude.h;
+ let attr_var_queue_len = or_frame.prelude.attr_var_queue_len;
- self.unwind_trail(old_tr, curr_tr);
+ self.machine_st.tr = or_frame.prelude.tr;
+ self.reset_attr_var_state(attr_var_queue_len);
- self.machine_st.trail.truncate(self.machine_st.tr);
- self.machine_st.heap.truncate(target_h);
+ self.machine_st.hb = target_h;
- self.machine_st.p += 1;
+ self.machine_st.trail.truncate(self.machine_st.tr);
+ self.machine_st.heap.truncate(target_h);
+
+ self.machine_st.p += 1;
+ } else {
+ self.trust_me_epilogue();
+ }
}
#[inline(always)]
let or_frame = self.machine_st.stack.index_or_frame_mut(b);
let n = or_frame.prelude.num_cells;
+ let old_tr = or_frame.prelude.tr;
+ let curr_tr = self.machine_st.tr;
+
for i in 0..n {
self.machine_st.registers[i+1] = or_frame[i];
}
- self.machine_st.num_of_args = n;
- self.machine_st.e = or_frame.prelude.e;
- self.machine_st.cp = or_frame.prelude.cp;
+ self.unwind_trail(old_tr, curr_tr);
- or_frame.prelude.biip += 1;
+ if let Some(iip_offset) = self.next_inner_applicable_clause() {
+ let or_frame = self.machine_st.stack.index_or_frame_mut(b);
- let old_tr = or_frame.prelude.tr;
- let curr_tr = self.machine_st.tr;
- let target_h = or_frame.prelude.h;
- let attr_var_queue_len = or_frame.prelude.attr_var_queue_len;
+ self.machine_st.num_of_args = n;
+ self.machine_st.e = or_frame.prelude.e;
+ self.machine_st.cp = or_frame.prelude.cp;
- self.machine_st.tr = or_frame.prelude.tr;
- self.reset_attr_var_state(attr_var_queue_len);
+ or_frame.prelude.biip += iip_offset;
- self.machine_st.hb = target_h;
- self.machine_st.p = self.machine_st.p + offset;
+ let target_h = or_frame.prelude.h;
+ let attr_var_queue_len = or_frame.prelude.attr_var_queue_len;
- self.unwind_trail(old_tr, curr_tr);
+ self.machine_st.tr = or_frame.prelude.tr;
+ self.machine_st.trail.truncate(self.machine_st.tr);
- self.machine_st.trail.truncate(self.machine_st.tr);
- self.machine_st.heap.truncate(target_h);
+ self.reset_attr_var_state(attr_var_queue_len);
- self.machine_st.oip = 0;
- self.machine_st.iip = 0;
+ self.machine_st.hb = target_h;
+ self.machine_st.p += offset;
+
+ self.machine_st.heap.truncate(target_h);
+
+ self.machine_st.oip = 0;
+ self.machine_st.iip = 0;
+ } else {
+ self.trust_epilogue(offset);
+ }
}
#[inline(always)]
let or_frame = self.machine_st.stack.index_or_frame(b);
let n = or_frame.prelude.num_cells;
+ let old_tr = or_frame.prelude.tr;
+ let curr_tr = self.machine_st.tr;
+
for i in 0..n {
self.machine_st.registers[i+1] = or_frame[i];
}
+ self.unwind_trail(old_tr, curr_tr);
+ self.trust_epilogue(offset);
+ }
+
+ #[inline(always)]
+ fn trust_epilogue(&mut self, offset: usize) {
+ let b = self.machine_st.b;
+ let or_frame = self.machine_st.stack.index_or_frame(b);
+ let n = or_frame.prelude.num_cells;
+
self.machine_st.num_of_args = n;
self.machine_st.e = or_frame.prelude.e;
self.machine_st.cp = or_frame.prelude.cp;
- let old_tr = or_frame.prelude.tr;
- let curr_tr = self.machine_st.tr;
let target_h = or_frame.prelude.h;
self.machine_st.tr = or_frame.prelude.tr;
+ self.machine_st.trail.truncate(self.machine_st.tr);
+
self.machine_st.b = or_frame.prelude.b;
self.reset_attr_var_state(or_frame.prelude.attr_var_queue_len);
self.machine_st.hb = target_h;
self.machine_st.p = self.machine_st.p + offset;
- self.unwind_trail(old_tr, curr_tr);
-
- self.machine_st.trail.truncate(self.machine_st.tr);
self.machine_st.stack.truncate(b);
self.machine_st.heap.truncate(target_h);
self.machine_st.registers[i+1] = or_frame[i];
}
+ let old_tr = or_frame.prelude.tr;
+ let curr_tr = self.machine_st.tr;
+
+ self.unwind_trail(old_tr, curr_tr);
+
+ self.trust_me_epilogue();
+ }
+
+ #[inline(always)]
+ fn trust_me_epilogue(&mut self) {
+ let b = self.machine_st.b;
+ let or_frame = self.machine_st.stack.index_or_frame(b);
+ let n = or_frame.prelude.num_cells;
+
self.machine_st.num_of_args = n;
self.machine_st.e = or_frame.prelude.e;
self.machine_st.cp = or_frame.prelude.cp;
- let old_tr = or_frame.prelude.tr;
- let curr_tr = self.machine_st.tr;
let target_h = or_frame.prelude.h;
self.machine_st.tr = or_frame.prelude.tr;
self.machine_st.hb = target_h;
self.machine_st.p += 1;
- self.unwind_trail(old_tr, curr_tr);
-
self.machine_st.trail.truncate(self.machine_st.tr);
self.machine_st.stack.truncate(b);
self.machine_st.heap.truncate(target_h);