add s pointers for strings and partial strings, put_unsafe_value calls store earlier to avoid unnecessary heap writes (#273)
This commit is contained in:
@@ -18,6 +18,7 @@ use std::cmp::Ordering;
|
|||||||
use std::io::{stdout, Write};
|
use std::io::{stdout, Write};
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::ops::{Index, IndexMut};
|
use std::ops::{Index, IndexMut};
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
pub struct Ball {
|
pub struct Ball {
|
||||||
pub(super) boundary: usize,
|
pub(super) boundary: usize,
|
||||||
@@ -245,8 +246,33 @@ pub(super) enum MachineMode {
|
|||||||
Write,
|
Write,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub(super) enum HeapPtr {
|
||||||
|
HeapCell(usize),
|
||||||
|
PStrLocation(usize, usize),
|
||||||
|
String(usize, Rc<String>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl HeapPtr {
|
||||||
|
#[inline]
|
||||||
|
pub(super)
|
||||||
|
fn as_addr(&self) -> Addr {
|
||||||
|
match self {
|
||||||
|
&HeapPtr::HeapCell(h) => Addr::HeapCell(h),
|
||||||
|
&HeapPtr::PStrLocation(h, n) => Addr::PStrLocation(h, n),
|
||||||
|
&HeapPtr::String(n, ref s) => Addr::Con(Constant::String(n, s.clone())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for HeapPtr {
|
||||||
|
fn default() -> Self {
|
||||||
|
HeapPtr::HeapCell(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct MachineState {
|
pub struct MachineState {
|
||||||
pub(super) s: usize,
|
pub(super) s: HeapPtr,
|
||||||
pub(super) p: CodePtr,
|
pub(super) p: CodePtr,
|
||||||
pub(super) b: usize,
|
pub(super) b: usize,
|
||||||
pub(super) b0: usize,
|
pub(super) b0: usize,
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ impl MachineState {
|
|||||||
pub(crate)
|
pub(crate)
|
||||||
fn new() -> Self {
|
fn new() -> Self {
|
||||||
MachineState {
|
MachineState {
|
||||||
s: 0,
|
s: HeapPtr::default(),
|
||||||
p: CodePtr::default(),
|
p: CodePtr::default(),
|
||||||
b: 0,
|
b: 0,
|
||||||
b0: 0,
|
b0: 0,
|
||||||
@@ -82,7 +82,7 @@ impl MachineState {
|
|||||||
pub(crate)
|
pub(crate)
|
||||||
fn with_small_heap() -> Self {
|
fn with_small_heap() -> Self {
|
||||||
MachineState {
|
MachineState {
|
||||||
s: 0,
|
s: HeapPtr::default(),
|
||||||
p: CodePtr::default(),
|
p: CodePtr::default(),
|
||||||
b: 0,
|
b: 0,
|
||||||
b0: 0,
|
b0: 0,
|
||||||
@@ -645,6 +645,33 @@ impl MachineState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn increment_s_ptr(&mut self, rhs: usize) {
|
||||||
|
match &mut self.s {
|
||||||
|
HeapPtr::HeapCell(ref mut h) => {
|
||||||
|
*h += rhs;
|
||||||
|
}
|
||||||
|
HeapPtr::PStrLocation(h, n) => {
|
||||||
|
match &self.heap[*h] {
|
||||||
|
HeapCellValue::PartialString(ref pstr) => {
|
||||||
|
let s = pstr.block_as_str();
|
||||||
|
|
||||||
|
for c in s[*n ..].chars().take(rhs) {
|
||||||
|
*n += c.len_utf8();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
HeapPtr::String(ref mut n, ref s) => {
|
||||||
|
for c in s[*n ..].chars().take(rhs) {
|
||||||
|
*n += c.len_utf8();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(super)
|
pub(super)
|
||||||
fn unwind_trail(&mut self, a1: usize, a2: usize) {
|
fn unwind_trail(&mut self, a1: usize, a2: usize) {
|
||||||
// the sequence is reversed to respect the chronology of trail
|
// the sequence is reversed to respect the chronology of trail
|
||||||
@@ -1564,45 +1591,6 @@ impl MachineState {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_char_list(&mut self, offset: usize, s: Rc<String>)
|
|
||||||
{
|
|
||||||
if let Some(c) = s[offset ..].chars().next() {
|
|
||||||
let h = self.heap.h();
|
|
||||||
|
|
||||||
self.heap.push(HeapCellValue::Addr(Addr::Con(Constant::Char(c))));
|
|
||||||
self.heap.push(HeapCellValue::Addr(Addr::Con(Constant::String(
|
|
||||||
offset + c.len_utf8(),
|
|
||||||
s,
|
|
||||||
))));
|
|
||||||
|
|
||||||
self.s = h;
|
|
||||||
self.mode = MachineMode::Read;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_partial_string_list(&mut self, pstr_h: usize, offset: usize)
|
|
||||||
{
|
|
||||||
let (c, pstr_tail) =
|
|
||||||
if let HeapCellValue::PartialString(ref pstr) = &self.heap[pstr_h] {
|
|
||||||
let s = pstr.block_as_str();
|
|
||||||
|
|
||||||
if let Some(c) = s[offset ..].chars().next() {
|
|
||||||
(c, Addr::PStrTail(pstr_h, offset + c.len_utf8()))
|
|
||||||
} else {
|
|
||||||
unreachable!()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
unreachable!()
|
|
||||||
};
|
|
||||||
|
|
||||||
self.s = self.heap.h();
|
|
||||||
|
|
||||||
self.heap.push(HeapCellValue::Addr(Addr::Con(Constant::Char(c))));
|
|
||||||
self.heap.push(HeapCellValue::Addr(pstr_tail));
|
|
||||||
|
|
||||||
self.mode = MachineMode::Read;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(super)
|
pub(super)
|
||||||
fn execute_fact_instr(&mut self, instr: &FactInstruction) {
|
fn execute_fact_instr(&mut self, instr: &FactInstruction) {
|
||||||
match instr {
|
match instr {
|
||||||
@@ -1618,14 +1606,16 @@ impl MachineState {
|
|||||||
match self.flags.double_quotes {
|
match self.flags.double_quotes {
|
||||||
DoubleQuotes::Chars | DoubleQuotes::Codes
|
DoubleQuotes::Chars | DoubleQuotes::Codes
|
||||||
if s.len() > n => {
|
if s.len() > n => {
|
||||||
self.get_char_list(n, s)
|
self.s = HeapPtr::String(n, s);
|
||||||
|
self.mode = MachineMode::Read;
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
self.fail = true
|
self.fail = true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Addr::PStrLocation(h, n) => {
|
Addr::PStrLocation(h, n) => {
|
||||||
self.get_partial_string_list(h, n)
|
self.s = HeapPtr::PStrLocation(h, n);
|
||||||
|
self.mode = MachineMode::Read;
|
||||||
}
|
}
|
||||||
addr @ Addr::AttrVar(_)
|
addr @ Addr::AttrVar(_)
|
||||||
| addr @ Addr::StackCell(..)
|
| addr @ Addr::StackCell(..)
|
||||||
@@ -1639,7 +1629,7 @@ impl MachineState {
|
|||||||
self.mode = MachineMode::Write;
|
self.mode = MachineMode::Write;
|
||||||
}
|
}
|
||||||
Addr::Lis(a) => {
|
Addr::Lis(a) => {
|
||||||
self.s = a;
|
self.s = HeapPtr::HeapCell(a);
|
||||||
self.mode = MachineMode::Read;
|
self.mode = MachineMode::Read;
|
||||||
}
|
}
|
||||||
_ => self.fail = true,
|
_ => self.fail = true,
|
||||||
@@ -1654,7 +1644,7 @@ impl MachineState {
|
|||||||
|
|
||||||
if let &HeapCellValue::NamedStr(narity, ref s, _) = result {
|
if let &HeapCellValue::NamedStr(narity, ref s, _) = result {
|
||||||
if narity == arity && ct.name() == *s {
|
if narity == arity && ct.name() == *s {
|
||||||
self.s = a + 1;
|
self.s = HeapPtr::HeapCell(a + 1);
|
||||||
self.mode = MachineMode::Read;
|
self.mode = MachineMode::Read;
|
||||||
} else {
|
} else {
|
||||||
self.fail = true;
|
self.fail = true;
|
||||||
@@ -1685,7 +1675,7 @@ impl MachineState {
|
|||||||
&FactInstruction::UnifyConstant(ref c) => {
|
&FactInstruction::UnifyConstant(ref c) => {
|
||||||
match self.mode {
|
match self.mode {
|
||||||
MachineMode::Read => {
|
MachineMode::Read => {
|
||||||
let addr = Addr::HeapCell(self.s);
|
let addr = self.s.as_addr();
|
||||||
self.write_constant_to_var(addr, c.clone());
|
self.write_constant_to_var(addr, c.clone());
|
||||||
}
|
}
|
||||||
MachineMode::Write => {
|
MachineMode::Write => {
|
||||||
@@ -1693,11 +1683,11 @@ impl MachineState {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
self.s += 1;
|
self.increment_s_ptr(1);
|
||||||
}
|
}
|
||||||
&FactInstruction::UnifyVariable(reg) => {
|
&FactInstruction::UnifyVariable(reg) => {
|
||||||
match self.mode {
|
match self.mode {
|
||||||
MachineMode::Read => self[reg] = self.heap[self.s].as_addr(self.s),
|
MachineMode::Read => self[reg] = self.s.as_addr(),
|
||||||
MachineMode::Write => {
|
MachineMode::Write => {
|
||||||
let h = self.heap.h();
|
let h = self.heap.h();
|
||||||
|
|
||||||
@@ -1706,15 +1696,13 @@ impl MachineState {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
self.s += 1;
|
self.increment_s_ptr(1);
|
||||||
}
|
}
|
||||||
&FactInstruction::UnifyLocalValue(reg) => {
|
&FactInstruction::UnifyLocalValue(reg) => {
|
||||||
let s = self.s;
|
|
||||||
|
|
||||||
match self.mode {
|
match self.mode {
|
||||||
MachineMode::Read => {
|
MachineMode::Read => {
|
||||||
let reg_addr = self[reg].clone();
|
let reg_addr = self[reg].clone();
|
||||||
self.unify(reg_addr, Addr::HeapCell(s));
|
self.unify(reg_addr, self.s.as_addr());
|
||||||
}
|
}
|
||||||
MachineMode::Write => {
|
MachineMode::Write => {
|
||||||
let addr = self.deref(self[reg].clone());
|
let addr = self.deref(self[reg].clone());
|
||||||
@@ -1725,7 +1713,7 @@ impl MachineState {
|
|||||||
let val = self.heap[hc].clone();
|
let val = self.heap[hc].clone();
|
||||||
|
|
||||||
self.heap.push(val);
|
self.heap.push(val);
|
||||||
self.s += 1;
|
self.increment_s_ptr(1);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1736,15 +1724,13 @@ impl MachineState {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
self.s += 1;
|
self.increment_s_ptr(1);
|
||||||
}
|
}
|
||||||
&FactInstruction::UnifyValue(reg) => {
|
&FactInstruction::UnifyValue(reg) => {
|
||||||
let s = self.s;
|
|
||||||
|
|
||||||
match self.mode {
|
match self.mode {
|
||||||
MachineMode::Read => {
|
MachineMode::Read => {
|
||||||
let reg_addr = self[reg].clone();
|
let reg_addr = self[reg].clone();
|
||||||
self.unify(reg_addr, Addr::HeapCell(s));
|
self.unify(reg_addr, self.s.as_addr());
|
||||||
}
|
}
|
||||||
MachineMode::Write => {
|
MachineMode::Write => {
|
||||||
let heap_val = self.store(self[reg].clone());
|
let heap_val = self.store(self[reg].clone());
|
||||||
@@ -1752,11 +1738,11 @@ impl MachineState {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
self.s += 1;
|
self.increment_s_ptr(1);
|
||||||
}
|
}
|
||||||
&FactInstruction::UnifyVoid(n) => {
|
&FactInstruction::UnifyVoid(n) => {
|
||||||
match self.mode {
|
match self.mode {
|
||||||
MachineMode::Read => self.s += n,
|
MachineMode::Read => self.increment_s_ptr(n),
|
||||||
MachineMode::Write => {
|
MachineMode::Write => {
|
||||||
let h = self.heap.h();
|
let h = self.heap.h();
|
||||||
|
|
||||||
@@ -1865,16 +1851,15 @@ impl MachineState {
|
|||||||
&QueryInstruction::PutStructure(ref ct, arity, reg) => {
|
&QueryInstruction::PutStructure(ref ct, arity, reg) => {
|
||||||
let h = self.heap.h();
|
let h = self.heap.h();
|
||||||
|
|
||||||
self.heap
|
self.heap.push(HeapCellValue::NamedStr(arity, ct.name(), ct.spec()));
|
||||||
.push(HeapCellValue::NamedStr(arity, ct.name(), ct.spec()));
|
|
||||||
self[reg] = Addr::Str(h);
|
self[reg] = Addr::Str(h);
|
||||||
}
|
}
|
||||||
&QueryInstruction::PutUnsafeValue(n, arg) => {
|
&QueryInstruction::PutUnsafeValue(n, arg) => {
|
||||||
let e = self.e;
|
let e = self.e;
|
||||||
let addr = self.deref(Addr::StackCell(e, n));
|
let addr = self.store(self.deref(Addr::StackCell(e, n)));
|
||||||
|
|
||||||
if addr.is_protected(e) {
|
if addr.is_protected(e) {
|
||||||
self.registers[arg] = self.store(addr);
|
self.registers[arg] = addr;
|
||||||
} else {
|
} else {
|
||||||
let h = self.heap.h();
|
let h = self.heap.h();
|
||||||
|
|
||||||
@@ -3454,7 +3439,7 @@ impl MachineState {
|
|||||||
self.e = 0;
|
self.e = 0;
|
||||||
self.b = 0;
|
self.b = 0;
|
||||||
self.b0 = 0;
|
self.b0 = 0;
|
||||||
self.s = 0;
|
self.s = HeapPtr::default();
|
||||||
self.tr = 0;
|
self.tr = 0;
|
||||||
self.p = CodePtr::default();
|
self.p = CodePtr::default();
|
||||||
self.cp = LocalCodePtr::default();
|
self.cp = LocalCodePtr::default();
|
||||||
|
|||||||
@@ -699,7 +699,7 @@ impl Machine {
|
|||||||
snapshot.e = self.machine_st.e;
|
snapshot.e = self.machine_st.e;
|
||||||
snapshot.b = self.machine_st.b;
|
snapshot.b = self.machine_st.b;
|
||||||
snapshot.b0 = self.machine_st.b0;
|
snapshot.b0 = self.machine_st.b0;
|
||||||
snapshot.s = self.machine_st.s;
|
snapshot.s = self.machine_st.s.clone();
|
||||||
snapshot.tr = self.machine_st.tr;
|
snapshot.tr = self.machine_st.tr;
|
||||||
snapshot.num_of_args = self.machine_st.num_of_args;
|
snapshot.num_of_args = self.machine_st.num_of_args;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user