fix '$get_clause_p' whose old implementation was broken by the introduction

of lookahead indexing
This commit is contained in:
Mark
2023-12-18 09:52:46 -07:00
parent 30f3818c66
commit b943afb7c7
2 changed files with 68 additions and 102 deletions

View File

@@ -925,8 +925,8 @@ impl Machine {
self.machine_st.hb = self.machine_st.heap.len(); self.machine_st.hb = self.machine_st.heap.len();
self.machine_st.oip = 0; // self.machine_st.oip = 0;
self.machine_st.iip = 0; // self.machine_st.iip = 0;
} }
self.machine_st.p += offset; self.machine_st.p += offset;
@@ -1010,8 +1010,8 @@ impl Machine {
self.machine_st.heap.truncate(target_h); self.machine_st.heap.truncate(target_h);
self.machine_st.oip = 0; // self.machine_st.oip = 0;
self.machine_st.iip = 0; // self.machine_st.iip = 0;
} else { } else {
self.trust_epilogue(offset); self.trust_epilogue(offset);
} }
@@ -1059,8 +1059,13 @@ impl Machine {
self.machine_st.stack.truncate(b); self.machine_st.stack.truncate(b);
self.machine_st.heap.truncate(target_h); self.machine_st.heap.truncate(target_h);
self.machine_st.oip = 0; // these registers don't need to be reset here and MUST NOT be
self.machine_st.iip = 0; // (nor in indexed_try to trust_epilogue)! oip could be reset
// without any adverse effects but iip is needed by
// get_clause_p to find the last executed clause/2 clause.
// self.machine_st.oip = 0;
// self.machine_st.iip = 0;
} }
#[inline(always)] #[inline(always)]

View File

@@ -1171,112 +1171,73 @@ impl Machine {
.get_predicate_skeleton(&compilation_target, &key) .get_predicate_skeleton(&compilation_target, &key)
.unwrap(); .unwrap();
if self.machine_st.b > self.machine_st.e { let module_name = match compilation_target {
let or_frame = self.machine_st.stack.index_or_frame(self.machine_st.b); CompilationTarget::User => atom!("builtins"),
let bp = or_frame.prelude.bp; CompilationTarget::Module(target) => target,
};
match &self.code[bp] { let bp = self
Instruction::IndexingCode(ref indexing_code) => { .indices
match &indexing_code[or_frame.prelude.boip as usize] { .get_predicate_code_index(atom!("$clause"), 2, module_name)
IndexingLine::IndexedChoice(ref indexed_choice) => { .and_then(|idx| idx.local())
let p = or_frame.prelude.biip as usize - 1; .unwrap();
match &indexed_choice[p] { let p = self.machine_st.iip as usize;
&IndexedChoiceInstruction::Try(offset)
| &IndexedChoiceInstruction::Retry(offset) macro_rules! extract_ptr {
| &IndexedChoiceInstruction::DefaultRetry(offset) => { ($ptr: expr) => {
let clause_clause_loc = skeleton.core.clause_clause_locs[p]; match $ptr {
(clause_clause_loc, bp + offset) IndexingCodePtr::External(p) => {
} return (
&IndexedChoiceInstruction::Trust(_) skeleton.core.clause_clause_locs.back().cloned().unwrap(),
| &IndexedChoiceInstruction::DefaultTrust(_) => { bp + p,
unreachable!() )
} }
} IndexingCodePtr::Internal(boip) => boip,
} _ => unreachable!(),
_ => { }
unreachable!() };
}
match &self.code[bp] {
Instruction::IndexingCode(ref indexing_code) => {
let indexing_code_ptr = match &indexing_code[0] {
&IndexingLine::Indexing(IndexingInstruction::SwitchOnTerm(_, _, c, _, s)) => {
if key.1 > 0 {
s
} else {
c
} }
} }
} _ => {
_ => unreachable!(), unreachable!()
}
} else {
let module_name = match compilation_target {
CompilationTarget::User => atom!("builtins"),
CompilationTarget::Module(target) => target,
};
let bp = self
.indices
.get_predicate_code_index(atom!("$clause"), 2, module_name)
.and_then(|idx| idx.local())
.unwrap();
macro_rules! extract_ptr {
($ptr: expr) => {
match $ptr {
IndexingCodePtr::External(p) => {
return (
skeleton.core.clause_clause_locs.back().cloned().unwrap(),
bp + p,
)
}
IndexingCodePtr::Internal(boip) => boip,
_ => unreachable!(),
} }
}; };
}
match &self.code[bp] { let boip = extract_ptr!(indexing_code_ptr);
Instruction::IndexingCode(ref indexing_code) => {
let indexing_code_ptr = match &indexing_code[0] {
&IndexingLine::Indexing(IndexingInstruction::SwitchOnTerm(
_,
_,
c,
_,
s,
)) => {
if key.1 > 0 {
s
} else {
c
}
}
_ => {
unreachable!()
}
};
let boip = extract_ptr!(indexing_code_ptr); let boip = match &indexing_code[boip] {
IndexingLine::Indexing(IndexingInstruction::SwitchOnStructure(ref hm)) => {
let boip = match &indexing_code[boip] { boip + extract_ptr!(hm.get(&key).cloned().unwrap())
IndexingLine::Indexing(IndexingInstruction::SwitchOnStructure(ref hm)) => {
boip + extract_ptr!(hm.get(&key).cloned().unwrap())
}
IndexingLine::Indexing(IndexingInstruction::SwitchOnConstant(ref hm)) => {
boip + extract_ptr!(hm.get(&Literal::Atom(key.0)).cloned().unwrap())
}
_ => boip,
};
match &indexing_code[boip] {
IndexingLine::IndexedChoice(indexed_choice) => {
return (
skeleton.core.clause_clause_locs.back().cloned().unwrap(),
bp + indexed_choice.back().unwrap().offset(),
);
}
_ => unreachable!(),
} }
IndexingLine::Indexing(IndexingInstruction::SwitchOnConstant(ref hm)) => {
boip + extract_ptr!(hm.get(&Literal::Atom(key.0)).cloned().unwrap())
}
_ => boip,
};
match &indexing_code[boip] {
IndexingLine::IndexedChoice(indexed_choice) => {
return (
skeleton.core.clause_clause_locs[p],
bp + indexed_choice[p].offset(),
);
}
_ => unreachable!(),
} }
_ => { }
return ( _ => {
skeleton.core.clause_clause_locs.back().cloned().unwrap(), return (skeleton.core.clause_clause_locs[p], bp);
bp,
);
}
} }
} }
} }