[WIP] move towards lockless AtomTable
This commit is contained in:
@@ -70,12 +70,6 @@ pub struct F64Table {
|
|||||||
block: RawBlock<F64Table>,
|
block: RawBlock<F64Table>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for F64Table {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
self.block.deallocate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
fn set_f64_tbl_buf_base(ptr: *const u8) {
|
fn set_f64_tbl_buf_base(ptr: *const u8) {
|
||||||
F64_TABLE_BUF_BASE.with(|f64_table_buf_base| {
|
F64_TABLE_BUF_BASE.with(|f64_table_buf_base| {
|
||||||
|
|||||||
@@ -7,16 +7,16 @@ use std::hash::{Hash, Hasher};
|
|||||||
use std::mem;
|
use std::mem;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
|
use std::ptr::NonNull;
|
||||||
use std::slice;
|
use std::slice;
|
||||||
use std::str;
|
use std::str;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use std::sync::Mutex;
|
||||||
use std::sync::Weak;
|
use std::sync::Weak;
|
||||||
|
|
||||||
use indexmap::IndexSet;
|
use indexmap::IndexSet;
|
||||||
|
|
||||||
use modular_bitfield::prelude::*;
|
use modular_bitfield::prelude::*;
|
||||||
use tokio::runtime::Handle;
|
|
||||||
use tokio::sync::OwnedRwLockReadGuard;
|
|
||||||
use tokio::sync::RwLock;
|
use tokio::sync::RwLock;
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||||
@@ -46,45 +46,35 @@ impl From<bool> for Atom {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl indexmap::Equivalent<Atom> for LookupKey<'_, '_> {
|
impl indexmap::Equivalent<Atom> for str {
|
||||||
fn equivalent(&self, key: &Atom) -> bool {
|
fn equivalent(&self, key: &Atom) -> bool {
|
||||||
&*key.as_str_with_table(self.0) == self.1
|
&*key.as_str() == self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const ATOM_TABLE_INIT_SIZE: usize = 1 << 16;
|
const ATOM_TABLE_INIT_SIZE: usize = 1 << 16;
|
||||||
const ATOM_TABLE_ALIGN: usize = 8;
|
const ATOM_TABLE_ALIGN: usize = 8;
|
||||||
|
|
||||||
fn global_atom_table() -> &'static RwLock<Weak<RwLock<AtomTable>>> {
|
#[inline(always)]
|
||||||
|
fn global_atom_table() -> &'static RwLock<Weak<AtomTable>> {
|
||||||
#[cfg(feature = "rust_beta_channel")]
|
#[cfg(feature = "rust_beta_channel")]
|
||||||
{
|
{
|
||||||
// const Weak::new will be stabilized in 1.73 which is currently in beta,
|
// const Weak::new will be stabilized in 1.73 which is currently in beta,
|
||||||
// till then we need a OnceLock for initialization
|
// till then we need a OnceLock for initialization
|
||||||
static GLOBAL_ATOM_TABLE: RwLock<Weak<RwLock<AtomTable>>> = RwLock::const_new(Weak::new());
|
static GLOBAL_ATOM_TABLE: RwLock<Weak<AtomTable>> = RwLock::const_new(Weak::new());
|
||||||
&GLOBAL_ATOM_TABLE
|
&GLOBAL_ATOM_TABLE
|
||||||
}
|
}
|
||||||
#[cfg(not(feature = "rust_beta_channel"))]
|
#[cfg(not(feature = "rust_beta_channel"))]
|
||||||
{
|
{
|
||||||
use std::sync::OnceLock;
|
use std::sync::OnceLock;
|
||||||
static GLOBAL_ATOM_TABLE: OnceLock<RwLock<Weak<RwLock<AtomTable>>>> = OnceLock::new();
|
static GLOBAL_ATOM_TABLE: OnceLock<RwLock<Weak<AtomTable>>> = OnceLock::new();
|
||||||
GLOBAL_ATOM_TABLE.get_or_init(|| RwLock::new(Weak::new()))
|
GLOBAL_ATOM_TABLE.get_or_init(|| RwLock::new(Weak::new()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn owned_atom_table_read_guard() -> Option<OwnedRwLockReadGuard<AtomTable>> {
|
#[inline(always)]
|
||||||
let atom_table = global_atom_table().blocking_read().upgrade()?;
|
fn arc_atom_table() -> Option<Arc<AtomTable>> {
|
||||||
|
global_atom_table().blocking_read().upgrade()
|
||||||
let guard = {
|
|
||||||
// some test don't start a Runtime
|
|
||||||
if let Ok(handle) = Handle::try_current() {
|
|
||||||
handle.block_on(atom_table.read_owned())
|
|
||||||
} else {
|
|
||||||
tokio::runtime::Runtime::new()
|
|
||||||
.unwrap()
|
|
||||||
.block_on(atom_table.read_owned())
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Some(guard)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RawBlockTraits for AtomTable {
|
impl RawBlockTraits for AtomTable {
|
||||||
@@ -132,7 +122,7 @@ macro_rules! is_char {
|
|||||||
|
|
||||||
pub enum AtomString<'a> {
|
pub enum AtomString<'a> {
|
||||||
Static(&'a str),
|
Static(&'a str),
|
||||||
Dynamic(OwnedRwLockReadGuard<AtomTable, str>),
|
Dynamic(AtomTableRef<str>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AtomString<'_> {
|
impl AtomString<'_> {
|
||||||
@@ -142,7 +132,7 @@ impl AtomString<'_> {
|
|||||||
{
|
{
|
||||||
match self {
|
match self {
|
||||||
Self::Static(reference) => Self::Static(f(reference)),
|
Self::Static(reference) => Self::Static(f(reference)),
|
||||||
Self::Dynamic(guard) => Self::Dynamic(OwnedRwLockReadGuard::map(guard, f)),
|
Self::Dynamic(guard) => Self::Dynamic(AtomTableRef::map(guard, f)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -180,51 +170,28 @@ impl rustyline::completion::Candidate for AtomString<'_> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Atom {
|
impl Atom {
|
||||||
#[inline]
|
|
||||||
pub fn buf(self) -> Option<OwnedRwLockReadGuard<AtomTable, u8>> {
|
|
||||||
if let Some(guard) = self.as_ptr() {
|
|
||||||
Some(OwnedRwLockReadGuard::map(guard, |ptr| unsafe {
|
|
||||||
(ptr as *const u8)
|
|
||||||
.offset(mem::size_of::<AtomHeader>() as isize)
|
|
||||||
.as_ref()
|
|
||||||
.unwrap()
|
|
||||||
}))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn is_static(self) -> bool {
|
pub fn is_static(self) -> bool {
|
||||||
(self.index as usize) < STRINGS.len() << 3
|
(self.index as usize) < STRINGS.len() << 3
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn as_ptr_with_table<'at>(&self, atom_table: &'at AtomTable) -> Option<&'at u8> {
|
pub fn as_ptr(self) -> Option<AtomTableRef<u8>> {
|
||||||
if self.is_static() {
|
if self.is_static() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
|
let atom_table =
|
||||||
|
arc_atom_table().expect("We should only have an Atom while there is an AtomTable");
|
||||||
unsafe {
|
unsafe {
|
||||||
atom_table
|
AtomTableRef::try_map(atom_table.buf(), |buf| {
|
||||||
.buf()
|
(buf as *const u8)
|
||||||
.offset(((self.index as usize) - (STRINGS.len() << 3)) as isize)
|
.offset(((self.index as usize) - (STRINGS.len() << 3)) as isize)
|
||||||
.as_ref()
|
.as_ref()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
pub fn as_ptr(self) -> Option<OwnedRwLockReadGuard<AtomTable, u8>> {
|
|
||||||
if self.is_static() {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
let guard = owned_atom_table_read_guard()
|
|
||||||
.expect("We should only have an Atom while there is an AtomTable");
|
|
||||||
OwnedRwLockReadGuard::try_map(guard, |atom_table| self.as_ptr_with_table(atom_table))
|
|
||||||
.ok()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn from(index: u64) -> Self {
|
pub fn from(index: u64) -> Self {
|
||||||
Self { index }
|
Self { index }
|
||||||
@@ -260,35 +227,29 @@ impl Atom {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
pub fn as_str_with_table<'at>(&self, atom_table: &'at AtomTable) -> &'at str {
|
|
||||||
if let Some(ptr) = self.as_ptr_with_table(atom_table) {
|
|
||||||
let header = unsafe { ptr::read::<AtomHeader>(ptr as *const u8 as *const AtomHeader) };
|
|
||||||
let len = header.len() as usize;
|
|
||||||
let buf = (unsafe { (ptr as *const u8).offset(mem::size_of::<AtomHeader>() as isize) })
|
|
||||||
as *mut u8;
|
|
||||||
|
|
||||||
unsafe { str::from_utf8_unchecked(slice::from_raw_parts(buf, len)) }
|
|
||||||
} else {
|
|
||||||
&STRINGS[(self.index >> 3) as usize]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[track_caller]
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn as_str(&self) -> AtomString<'static> {
|
pub fn as_str(&self) -> AtomString<'static> {
|
||||||
if self.is_static() {
|
if self.is_static() {
|
||||||
AtomString::Static(STRINGS[(self.index >> 3) as usize])
|
AtomString::Static(STRINGS[(self.index >> 3) as usize])
|
||||||
} else {
|
} else {
|
||||||
let guard = owned_atom_table_read_guard()
|
if let Some(ptr) = self.as_ptr() {
|
||||||
.expect("We should only have an Atom while there is an AtomTable");
|
AtomString::Dynamic(AtomTableRef::map(ptr, |ptr| {
|
||||||
AtomString::Dynamic(OwnedRwLockReadGuard::map(guard, |atom_table| {
|
let header =
|
||||||
self.as_str_with_table(atom_table)
|
unsafe { ptr::read::<AtomHeader>(ptr as *const u8 as *const AtomHeader) };
|
||||||
|
let len = header.len() as usize;
|
||||||
|
let buf = (unsafe {
|
||||||
|
(ptr as *const u8).offset(mem::size_of::<AtomHeader>() as isize)
|
||||||
|
}) as *mut u8;
|
||||||
|
|
||||||
|
unsafe { str::from_utf8_unchecked(slice::from_raw_parts(buf, len)) }
|
||||||
}))
|
}))
|
||||||
|
} else {
|
||||||
|
AtomString::Static(&STRINGS[(self.index >> 3) as usize])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn defrock_brackets(&self, atom_tbl: &Arc<RwLock<AtomTable>>) -> Self {
|
pub fn defrock_brackets(&self, atom_tbl: &AtomTable) -> Self {
|
||||||
let s = self.as_str();
|
let s = self.as_str();
|
||||||
|
|
||||||
let sub_str = if s.starts_with('(') && s.ends_with(')') {
|
let sub_str = if s.starts_with('(') && s.ends_with(')') {
|
||||||
@@ -297,9 +258,7 @@ impl Atom {
|
|||||||
return *self;
|
return *self;
|
||||||
};
|
};
|
||||||
|
|
||||||
let val = sub_str.to_string();
|
AtomTable::build_with(&atom_tbl, &sub_str)
|
||||||
drop(s); // wee need to drop s as it holds a read lock on the AtomTable and build_with may need to acquire a write lock
|
|
||||||
AtomTable::build_with(&atom_tbl, &val)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -323,29 +282,80 @@ impl Ord for Atom {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct AtomTableRef<M>
|
||||||
|
where
|
||||||
|
M: ?Sized,
|
||||||
|
{
|
||||||
|
arc: Arc<InnerAtomTable>,
|
||||||
|
data: NonNull<M>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<M> Clone for AtomTableRef<M> {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
Self {
|
||||||
|
arc: Arc::clone(&self.arc),
|
||||||
|
data: self.data,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<M: ?Sized> AtomTableRef<M> {
|
||||||
|
pub fn map<N: ?Sized, F: for<'a> FnOnce(&'a M) -> &'a N>(
|
||||||
|
referece: Self,
|
||||||
|
f: F,
|
||||||
|
) -> AtomTableRef<N> {
|
||||||
|
AtomTableRef {
|
||||||
|
arc: referece.arc,
|
||||||
|
data: f(unsafe { referece.data.as_ref() }).into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn try_map<N, F: for<'a> FnOnce(&'a M) -> Option<&'a N>>(
|
||||||
|
referece: Self,
|
||||||
|
f: F,
|
||||||
|
) -> Option<AtomTableRef<N>> {
|
||||||
|
let val = f(unsafe { referece.data.as_ref() })?;
|
||||||
|
Some(AtomTableRef {
|
||||||
|
arc: Arc::clone(&referece.arc),
|
||||||
|
data: val.into(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<M: ?Sized> Deref for AtomTableRef<M> {
|
||||||
|
type Target = M;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
unsafe { self.data.as_ref() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct AtomTable {
|
pub struct InnerAtomTable {
|
||||||
block: RawBlock<AtomTable>,
|
block: RawBlock<AtomTable>,
|
||||||
pub table: RwLock<IndexSet<Atom>>,
|
pub table: RwLock<IndexSet<Atom>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for AtomTable {
|
#[derive(Debug)]
|
||||||
fn drop(&mut self) {
|
pub struct AtomTable {
|
||||||
self.block.deallocate();
|
inner: RwLock<Arc<InnerAtomTable>>,
|
||||||
}
|
// this lock is taking during resizing
|
||||||
|
update: Mutex<()>,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct LookupKey<'table, 'key>(&'table AtomTable, &'key str);
|
impl InnerAtomTable {
|
||||||
|
#[inline(always)]
|
||||||
impl Hash for LookupKey<'_, '_> {
|
fn lookup_str(self: &InnerAtomTable, string: &str) -> Option<Atom> {
|
||||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
STATIC_ATOMS_MAP
|
||||||
self.1.hash(state);
|
.get(string)
|
||||||
|
.cloned()
|
||||||
|
.or_else(|| self.table.blocking_read().get(string).cloned())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AtomTable {
|
impl AtomTable {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new() -> Arc<RwLock<Self>> {
|
pub fn new() -> Arc<Self> {
|
||||||
let upgraded = global_atom_table().blocking_read().upgrade();
|
let upgraded = global_atom_table().blocking_read().upgrade();
|
||||||
// don't inline upgraded, otherwise temporary will be dropped too late in case of None
|
// don't inline upgraded, otherwise temporary will be dropped too late in case of None
|
||||||
if let Some(atom_table) = upgraded {
|
if let Some(atom_table) = upgraded {
|
||||||
@@ -356,65 +366,76 @@ impl AtomTable {
|
|||||||
if let Some(atom_table) = guard.upgrade() {
|
if let Some(atom_table) = guard.upgrade() {
|
||||||
atom_table
|
atom_table
|
||||||
} else {
|
} else {
|
||||||
let atom_table = Arc::new(RwLock::new(Self {
|
let atom_table = Arc::new(Self {
|
||||||
|
inner: RwLock::new(Arc::new(InnerAtomTable {
|
||||||
block: RawBlock::new(),
|
block: RawBlock::new(),
|
||||||
table: RwLock::new(IndexSet::new()),
|
table: RwLock::new(IndexSet::new()),
|
||||||
}));
|
})),
|
||||||
|
update: Mutex::new(()),
|
||||||
|
});
|
||||||
*guard = Arc::downgrade(&atom_table);
|
*guard = Arc::downgrade(&atom_table);
|
||||||
atom_table
|
atom_table
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
pub fn active_epoch(&self) -> AtomTableRef<InnerAtomTable> {
|
||||||
pub fn buf(&self) -> *const u8 {
|
let arc = Arc::clone(&self.inner.blocking_read());
|
||||||
self.block.base as *const u8
|
AtomTableRef {
|
||||||
|
data: arc.deref().into(),
|
||||||
|
arc,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn top(&self) -> *const u8 {
|
pub fn buf(&self) -> AtomTableRef<u8> {
|
||||||
self.block.top
|
AtomTableRef::<InnerAtomTable>::map(self.active_epoch(), |inner| {
|
||||||
}
|
unsafe { inner.block.base.as_ref() }.unwrap()
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
fn lookup_str(self: &AtomTable, string: &str) -> Option<Atom> {
|
|
||||||
STATIC_ATOMS_MAP.get(string).cloned().or_else(|| {
|
|
||||||
self.table
|
|
||||||
.blocking_read()
|
|
||||||
.get(&LookupKey(self, string))
|
|
||||||
.cloned()
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build_with(atom_table: &RwLock<AtomTable>, string: &str) -> Atom {
|
pub fn build_with(atom_table: &AtomTable, string: &str) -> Atom {
|
||||||
let mut atom_table = loop {
|
loop {
|
||||||
// we can't just use blocking_write as tokio's RwLock is fair
|
let mut epoch = atom_table.active_epoch();
|
||||||
// and we can't block readers here as otherwise we will deadlock, see the guard downgrade below
|
let count = epoch.table.blocking_read().len();
|
||||||
if let Ok(guard) = atom_table.try_write() {
|
|
||||||
break guard;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(atom) = atom_table.lookup_str(string) {
|
if let Some(atom) = epoch.lookup_str(string) {
|
||||||
return atom;
|
return atom;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe {
|
let update_guard = atom_table.update.lock().unwrap();
|
||||||
|
|
||||||
|
let is_same_allocation = Arc::ptr_eq(&epoch.arc, &atom_table.active_epoch().arc);
|
||||||
|
let is_same_atom_count = count == epoch.table.blocking_read().len();
|
||||||
|
|
||||||
|
if !(is_same_allocation && is_same_atom_count) {
|
||||||
|
// some other thread raced us between our lookup and us aquring the update lock, try again
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
let size = mem::size_of::<AtomHeader>() + string.len();
|
let size = mem::size_of::<AtomHeader>() + string.len();
|
||||||
let align_offset = 8 * mem::align_of::<AtomHeader>();
|
let align_offset = 8 * mem::align_of::<AtomHeader>();
|
||||||
let size = (size & !(align_offset - 1)) + align_offset;
|
let size = (size & !(align_offset - 1)) + align_offset;
|
||||||
|
|
||||||
|
unsafe {
|
||||||
let len_ptr = loop {
|
let len_ptr = loop {
|
||||||
let ptr = atom_table.block.alloc(size);
|
let ptr = epoch.block.alloc(size);
|
||||||
|
|
||||||
if ptr.is_null() {
|
if ptr.is_null() {
|
||||||
atom_table.block.grow();
|
let new_block = epoch.block.grow_new().unwrap();
|
||||||
|
let new_table = RwLock::new(epoch.table.blocking_read().clone());
|
||||||
|
let new_alloc = Arc::new(InnerAtomTable {
|
||||||
|
block: new_block,
|
||||||
|
table: new_table,
|
||||||
|
});
|
||||||
|
*atom_table.inner.blocking_write() = new_alloc;
|
||||||
|
epoch = atom_table.active_epoch();
|
||||||
} else {
|
} else {
|
||||||
break ptr;
|
break ptr;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let ptr_base = atom_table.block.base as usize;
|
let ptr_base = epoch.block.base as usize;
|
||||||
|
|
||||||
write_to_ptr(string, len_ptr);
|
write_to_ptr(string, len_ptr);
|
||||||
|
|
||||||
@@ -422,18 +443,12 @@ impl AtomTable {
|
|||||||
index: ((STRINGS.len() << 3) + len_ptr as usize - ptr_base) as u64,
|
index: ((STRINGS.len() << 3) + len_ptr as usize - ptr_base) as u64,
|
||||||
};
|
};
|
||||||
|
|
||||||
// we need to downgrade to a read so that Atom::hash can read from the AtomTable,
|
epoch.table.blocking_write().insert(atom);
|
||||||
// so that it can calculate the hash for inserting the atom
|
|
||||||
// we can't just drop the guard as otherwise another thread could race us with another atom insertion
|
|
||||||
let atom_table = atom_table.downgrade();
|
|
||||||
|
|
||||||
// NOTE: there is no race between downgrade and blocking write as table is only accessed writable in this function
|
drop(update_guard);
|
||||||
// and only after the write lock is acquired as we have the guard and just convert it from a write to a read guard no writer can race us
|
|
||||||
atom_table.table.blocking_write().insert(atom);
|
|
||||||
|
|
||||||
drop(atom_table); // we need to keep the guard around till after the insert
|
return atom;
|
||||||
|
}
|
||||||
atom
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,8 +18,6 @@ use crate::machine::machine_errors::*;
|
|||||||
use fxhash::FxBuildHasher;
|
use fxhash::FxBuildHasher;
|
||||||
use indexmap::IndexSet;
|
use indexmap::IndexSet;
|
||||||
|
|
||||||
use tokio::sync::RwLock;
|
|
||||||
|
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
|
|
||||||
@@ -264,7 +262,7 @@ impl CodeGenSettings {
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) struct CodeGenerator<'a> {
|
pub(crate) struct CodeGenerator<'a> {
|
||||||
pub(crate) atom_tbl: &'a RwLock<AtomTable>,
|
pub(crate) atom_tbl: &'a AtomTable,
|
||||||
marker: DebrayAllocator,
|
marker: DebrayAllocator,
|
||||||
settings: CodeGenSettings,
|
settings: CodeGenSettings,
|
||||||
pub(crate) skeleton: PredicateSkeleton,
|
pub(crate) skeleton: PredicateSkeleton,
|
||||||
@@ -364,7 +362,7 @@ fn structure_cell(term: &Term) -> Option<&Cell<RegType>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'b> CodeGenerator<'b> {
|
impl<'b> CodeGenerator<'b> {
|
||||||
pub(crate) fn new(atom_tbl: &'b RwLock<AtomTable>, settings: CodeGenSettings) -> Self {
|
pub(crate) fn new(atom_tbl: &'b AtomTable, settings: CodeGenSettings) -> Self {
|
||||||
CodeGenerator {
|
CodeGenerator {
|
||||||
atom_tbl,
|
atom_tbl,
|
||||||
marker: DebrayAllocator::new(),
|
marker: DebrayAllocator::new(),
|
||||||
|
|||||||
@@ -16,8 +16,6 @@ use fxhash::FxBuildHasher;
|
|||||||
use indexmap::{IndexMap, IndexSet};
|
use indexmap::{IndexMap, IndexSet};
|
||||||
use ordered_float::OrderedFloat;
|
use ordered_float::OrderedFloat;
|
||||||
|
|
||||||
use tokio::sync::RwLock;
|
|
||||||
|
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
@@ -483,7 +481,7 @@ pub enum AtomOrString {
|
|||||||
|
|
||||||
impl AtomOrString {
|
impl AtomOrString {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn as_atom(&self, atom_tbl: &RwLock<AtomTable>) -> Atom {
|
pub fn as_atom(&self, atom_tbl: &AtomTable) -> Atom {
|
||||||
match self {
|
match self {
|
||||||
&AtomOrString::Atom(atom) => atom,
|
&AtomOrString::Atom(atom) => atom,
|
||||||
AtomOrString::String(string) => AtomTable::build_with(atom_tbl, &string),
|
AtomOrString::String(string) => AtomTable::build_with(atom_tbl, &string),
|
||||||
|
|||||||
@@ -24,8 +24,6 @@ use ordered_float::OrderedFloat;
|
|||||||
|
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
|
|
||||||
use tokio::sync::RwLock;
|
|
||||||
|
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
use std::iter::once;
|
use std::iter::once;
|
||||||
@@ -483,7 +481,7 @@ pub fn fmt_float(mut fl: f64) -> String {
|
|||||||
pub struct HCPrinter<'a, Outputter> {
|
pub struct HCPrinter<'a, Outputter> {
|
||||||
outputter: Outputter,
|
outputter: Outputter,
|
||||||
iter: StackfulPreOrderHeapIter<'a>,
|
iter: StackfulPreOrderHeapIter<'a>,
|
||||||
atom_tbl: Arc<RwLock<AtomTable>>,
|
atom_tbl: Arc<AtomTable>,
|
||||||
op_dir: &'a OpDir,
|
op_dir: &'a OpDir,
|
||||||
state_stack: Vec<TokenOrRedirect>,
|
state_stack: Vec<TokenOrRedirect>,
|
||||||
toplevel_spec: Option<DirectedOp>,
|
toplevel_spec: Option<DirectedOp>,
|
||||||
@@ -552,7 +550,7 @@ pub(crate) fn numbervar(offset: &Integer, addr: HeapCellValue) -> Option<String>
|
|||||||
impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
heap: &'a mut Heap,
|
heap: &'a mut Heap,
|
||||||
atom_tbl: Arc<RwLock<AtomTable>>,
|
atom_tbl: Arc<AtomTable>,
|
||||||
stack: &'a mut Stack,
|
stack: &'a mut Stack,
|
||||||
op_dir: &'a OpDir,
|
op_dir: &'a OpDir,
|
||||||
output: Outputter,
|
output: Outputter,
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ use crate::instructions::*;
|
|||||||
|
|
||||||
use fxhash::FxBuildHasher;
|
use fxhash::FxBuildHasher;
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use tokio::sync::RwLock;
|
|
||||||
|
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
@@ -1094,7 +1093,7 @@ fn uncap_choice_seq_with_try(prelude: &mut [IndexedChoiceInstruction]) {
|
|||||||
|
|
||||||
pub(crate) fn constant_key_alternatives(
|
pub(crate) fn constant_key_alternatives(
|
||||||
constant: Literal,
|
constant: Literal,
|
||||||
atom_tbl: &RwLock<AtomTable>,
|
atom_tbl: &AtomTable,
|
||||||
// arena: &mut Arena,
|
// arena: &mut Arena,
|
||||||
) -> Vec<Literal> {
|
) -> Vec<Literal> {
|
||||||
let mut constants = vec![];
|
let mut constants = vec![];
|
||||||
@@ -1455,7 +1454,7 @@ impl<I: Indexer> CodeOffsets<I> {
|
|||||||
|
|
||||||
fn index_constant(
|
fn index_constant(
|
||||||
&mut self,
|
&mut self,
|
||||||
atom_tbl: &RwLock<AtomTable>,
|
atom_tbl: &AtomTable,
|
||||||
constant: Literal,
|
constant: Literal,
|
||||||
index: usize,
|
index: usize,
|
||||||
) -> Vec<Literal> {
|
) -> Vec<Literal> {
|
||||||
@@ -1512,7 +1511,7 @@ impl<I: Indexer> CodeOffsets<I> {
|
|||||||
optimal_arg: &Term,
|
optimal_arg: &Term,
|
||||||
index: usize,
|
index: usize,
|
||||||
clause_index_info: &mut ClauseIndexInfo,
|
clause_index_info: &mut ClauseIndexInfo,
|
||||||
atom_tbl: &RwLock<AtomTable>,
|
atom_tbl: &AtomTable,
|
||||||
) {
|
) {
|
||||||
match optimal_arg {
|
match optimal_arg {
|
||||||
&Term::Clause(_, atom!("."), ref terms) if terms.len() == 2 => {
|
&Term::Clause(_, atom!("."), ref terms) if terms.len() == 2 => {
|
||||||
|
|||||||
@@ -3000,7 +3000,7 @@ impl Machine {
|
|||||||
HeapCellValueTag::StackVar |
|
HeapCellValueTag::StackVar |
|
||||||
HeapCellValueTag::Var) => {
|
HeapCellValueTag::Var) => {
|
||||||
let target_cell = self.machine_st.push_str_to_heap(
|
let target_cell = self.machine_st.push_str_to_heap(
|
||||||
string.as_str(),
|
&string.as_str(),
|
||||||
has_tail,
|
has_tail,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
use tokio::sync::RwLock;
|
|
||||||
|
|
||||||
use crate::arena::*;
|
use crate::arena::*;
|
||||||
use crate::atom_table::*;
|
use crate::atom_table::*;
|
||||||
use crate::forms::*;
|
use crate::forms::*;
|
||||||
@@ -132,11 +130,7 @@ pub fn print_heap_terms<'a, I: Iterator<Item = &'a HeapCellValue>>(heap: I, h: u
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(crate) fn put_complete_string(
|
pub(crate) fn put_complete_string(heap: &mut Heap, s: &str, atom_tbl: &AtomTable) -> HeapCellValue {
|
||||||
heap: &mut Heap,
|
|
||||||
s: &str,
|
|
||||||
atom_tbl: &RwLock<AtomTable>,
|
|
||||||
) -> HeapCellValue {
|
|
||||||
match allocate_pstr(heap, s, atom_tbl) {
|
match allocate_pstr(heap, s, atom_tbl) {
|
||||||
Some(h) => {
|
Some(h) => {
|
||||||
heap.pop(); // pop the trailing variable cell from the heap planted by allocate_pstr.
|
heap.pop(); // pop the trailing variable cell from the heap planted by allocate_pstr.
|
||||||
@@ -159,11 +153,7 @@ pub(crate) fn put_complete_string(
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(crate) fn put_partial_string(
|
pub(crate) fn put_partial_string(heap: &mut Heap, s: &str, atom_tbl: &AtomTable) -> HeapCellValue {
|
||||||
heap: &mut Heap,
|
|
||||||
s: &str,
|
|
||||||
atom_tbl: &RwLock<AtomTable>,
|
|
||||||
) -> HeapCellValue {
|
|
||||||
match allocate_pstr(heap, s, atom_tbl) {
|
match allocate_pstr(heap, s, atom_tbl) {
|
||||||
Some(h) => {
|
Some(h) => {
|
||||||
pstr_loc_as_cell!(h)
|
pstr_loc_as_cell!(h)
|
||||||
@@ -175,11 +165,7 @@ pub(crate) fn put_partial_string(
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(crate) fn allocate_pstr(
|
pub(crate) fn allocate_pstr(heap: &mut Heap, mut src: &str, atom_tbl: &AtomTable) -> Option<usize> {
|
||||||
heap: &mut Heap,
|
|
||||||
mut src: &str,
|
|
||||||
atom_tbl: &RwLock<AtomTable>,
|
|
||||||
) -> Option<usize> {
|
|
||||||
let orig_h = heap.len();
|
let orig_h = heap.len();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ use crate::types::*;
|
|||||||
use crate::parser::dashu::Integer;
|
use crate::parser::dashu::Integer;
|
||||||
|
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use tokio::sync::RwLock;
|
|
||||||
|
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
@@ -59,7 +58,7 @@ pub enum OnEOF {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct MachineState {
|
pub struct MachineState {
|
||||||
pub atom_tbl: Arc<RwLock<AtomTable>>,
|
pub atom_tbl: Arc<AtomTable>,
|
||||||
pub arena: Arena,
|
pub arena: Arena,
|
||||||
pub(super) pdl: Vec<HeapCellValue>,
|
pub(super) pdl: Vec<HeapCellValue>,
|
||||||
pub(super) s: HeapPtr,
|
pub(super) s: HeapPtr,
|
||||||
@@ -205,7 +204,7 @@ pub fn pstr_loc_and_offset(heap: &[HeapCellValue], index: usize) -> (usize, Fixn
|
|||||||
fn push_var_eq_functors<'a>(
|
fn push_var_eq_functors<'a>(
|
||||||
heap: &mut Heap,
|
heap: &mut Heap,
|
||||||
iter: impl Iterator<Item = (&'a VarKey, &'a HeapCellValue)>,
|
iter: impl Iterator<Item = (&'a VarKey, &'a HeapCellValue)>,
|
||||||
atom_tbl: &RwLock<AtomTable>,
|
atom_tbl: &AtomTable,
|
||||||
) -> Vec<HeapCellValue> {
|
) -> Vec<HeapCellValue> {
|
||||||
let mut list_of_var_eqs = vec![];
|
let mut list_of_var_eqs = vec![];
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
use tokio::sync::RwLock;
|
|
||||||
|
|
||||||
use crate::atom_table::*;
|
use crate::atom_table::*;
|
||||||
use crate::parser::ast::*;
|
use crate::parser::ast::*;
|
||||||
|
|
||||||
@@ -45,7 +43,7 @@ impl Into<Atom> for PartialString {
|
|||||||
|
|
||||||
impl PartialString {
|
impl PartialString {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(super) fn new<'a>(src: &'a str, atom_tbl: &RwLock<AtomTable>) -> Option<(Self, &'a str)> {
|
pub(super) fn new<'a>(src: &'a str, atom_tbl: &AtomTable) -> Option<(Self, &'a str)> {
|
||||||
let terminator_idx = scan_for_terminator(src.chars());
|
let terminator_idx = scan_for_terminator(src.chars());
|
||||||
let pstr = PartialString(AtomTable::build_with(&atom_tbl, &src[..terminator_idx]));
|
let pstr = PartialString(AtomTable::build_with(&atom_tbl, &src[..terminator_idx]));
|
||||||
Some(if terminator_idx < src.as_bytes().len() {
|
Some(if terminator_idx < src.as_bytes().len() {
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ use crate::machine::machine_errors::*;
|
|||||||
use crate::parser::ast::*;
|
use crate::parser::ast::*;
|
||||||
|
|
||||||
use indexmap::IndexSet;
|
use indexmap::IndexSet;
|
||||||
use tokio::sync::RwLock;
|
|
||||||
|
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
@@ -26,10 +25,7 @@ pub(crate) fn to_op_decl(prec: u16, spec: Atom, name: Atom) -> Result<OpDecl, Co
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup_op_decl(
|
fn setup_op_decl(mut terms: Vec<Term>, atom_tbl: &AtomTable) -> Result<OpDecl, CompilationError> {
|
||||||
mut terms: Vec<Term>,
|
|
||||||
atom_tbl: &RwLock<AtomTable>,
|
|
||||||
) -> Result<OpDecl, CompilationError> {
|
|
||||||
let name = match terms.pop().unwrap() {
|
let name = match terms.pop().unwrap() {
|
||||||
Term::Literal(_, Literal::Atom(name)) => name,
|
Term::Literal(_, Literal::Atom(name)) => name,
|
||||||
Term::Literal(_, Literal::Char(c)) => AtomTable::build_with(atom_tbl, &c.to_string()),
|
Term::Literal(_, Literal::Char(c)) => AtomTable::build_with(atom_tbl, &c.to_string()),
|
||||||
@@ -86,7 +82,7 @@ fn setup_predicate_indicator(term: &mut Term) -> Result<PredicateKey, Compilatio
|
|||||||
|
|
||||||
fn setup_module_export(
|
fn setup_module_export(
|
||||||
mut term: Term,
|
mut term: Term,
|
||||||
atom_tbl: &RwLock<AtomTable>,
|
atom_tbl: &AtomTable,
|
||||||
) -> Result<ModuleExport, CompilationError> {
|
) -> Result<ModuleExport, CompilationError> {
|
||||||
setup_predicate_indicator(&mut term)
|
setup_predicate_indicator(&mut term)
|
||||||
.map(ModuleExport::PredicateKey)
|
.map(ModuleExport::PredicateKey)
|
||||||
@@ -112,7 +108,7 @@ pub(crate) fn build_rule_body(vars: &[Term], body_term: Term) -> Term {
|
|||||||
|
|
||||||
pub(super) fn setup_module_export_list(
|
pub(super) fn setup_module_export_list(
|
||||||
mut export_list: Term,
|
mut export_list: Term,
|
||||||
atom_tbl: &RwLock<AtomTable>,
|
atom_tbl: &AtomTable,
|
||||||
) -> Result<Vec<ModuleExport>, CompilationError> {
|
) -> Result<Vec<ModuleExport>, CompilationError> {
|
||||||
let mut exports = vec![];
|
let mut exports = vec![];
|
||||||
|
|
||||||
@@ -132,7 +128,7 @@ pub(super) fn setup_module_export_list(
|
|||||||
|
|
||||||
fn setup_module_decl(
|
fn setup_module_decl(
|
||||||
mut terms: Vec<Term>,
|
mut terms: Vec<Term>,
|
||||||
atom_tbl: &RwLock<AtomTable>,
|
atom_tbl: &AtomTable,
|
||||||
) -> Result<ModuleDecl, CompilationError> {
|
) -> Result<ModuleDecl, CompilationError> {
|
||||||
let export_list = terms.pop().unwrap();
|
let export_list = terms.pop().unwrap();
|
||||||
let name = terms.pop().unwrap();
|
let name = terms.pop().unwrap();
|
||||||
@@ -165,7 +161,7 @@ type UseModuleExport = (ModuleSource, IndexSet<ModuleExport>);
|
|||||||
|
|
||||||
fn setup_qualified_import(
|
fn setup_qualified_import(
|
||||||
mut terms: Vec<Term>,
|
mut terms: Vec<Term>,
|
||||||
atom_tbl: &RwLock<AtomTable>,
|
atom_tbl: &AtomTable,
|
||||||
) -> Result<UseModuleExport, CompilationError> {
|
) -> Result<UseModuleExport, CompilationError> {
|
||||||
let mut export_list = terms.pop().unwrap();
|
let mut export_list = terms.pop().unwrap();
|
||||||
let module_src = match terms.pop().unwrap() {
|
let module_src = match terms.pop().unwrap() {
|
||||||
|
|||||||
@@ -30,12 +30,6 @@ pub struct Stack {
|
|||||||
_marker: PhantomData<HeapCellValue>,
|
_marker: PhantomData<HeapCellValue>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for Stack {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
self.buf.deallocate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) struct AndFramePrelude {
|
pub(crate) struct AndFramePrelude {
|
||||||
pub(crate) num_cells: usize,
|
pub(crate) num_cells: usize,
|
||||||
@@ -189,7 +183,7 @@ impl Stack {
|
|||||||
let frame_size = AndFrame::size_of(num_cells);
|
let frame_size = AndFrame::size_of(num_cells);
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let e = self.buf.ptr as usize - self.buf.base as usize;
|
let e = (*self.buf.ptr.get_mut()) as usize - self.buf.base as usize;
|
||||||
let new_ptr = self.alloc(frame_size);
|
let new_ptr = self.alloc(frame_size);
|
||||||
let mut offset = prelude_size::<AndFramePrelude>();
|
let mut offset = prelude_size::<AndFramePrelude>();
|
||||||
|
|
||||||
@@ -213,7 +207,7 @@ impl Stack {
|
|||||||
let frame_size = OrFrame::size_of(num_cells);
|
let frame_size = OrFrame::size_of(num_cells);
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let b = self.buf.ptr as usize - self.buf.base as usize;
|
let b = (*self.buf.ptr.get_mut()) as usize - self.buf.base as usize;
|
||||||
let new_ptr = self.alloc(frame_size);
|
let new_ptr = self.alloc(frame_size);
|
||||||
let mut offset = prelude_size::<OrFramePrelude>();
|
let mut offset = prelude_size::<OrFramePrelude>();
|
||||||
|
|
||||||
@@ -269,8 +263,8 @@ impl Stack {
|
|||||||
pub(crate) fn truncate(&mut self, b: usize) {
|
pub(crate) fn truncate(&mut self, b: usize) {
|
||||||
let base = self.buf.base as usize + b;
|
let base = self.buf.base as usize + b;
|
||||||
|
|
||||||
if base < self.buf.ptr as usize {
|
if base < (*self.buf.ptr.get_mut()) as usize {
|
||||||
self.buf.ptr = base as *mut _;
|
*self.buf.ptr.get_mut() = base as *mut _;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ use fxhash::FxBuildHasher;
|
|||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use modular_bitfield::error::OutOfBounds;
|
use modular_bitfield::error::OutOfBounds;
|
||||||
use modular_bitfield::prelude::*;
|
use modular_bitfield::prelude::*;
|
||||||
use tokio::sync::RwLock;
|
|
||||||
|
|
||||||
pub type Specifier = u32;
|
pub type Specifier = u32;
|
||||||
|
|
||||||
@@ -633,7 +632,7 @@ impl fmt::Display for Literal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Literal {
|
impl Literal {
|
||||||
pub fn to_atom(&self, atom_tbl: &Arc<RwLock<AtomTable>>) -> Option<Atom> {
|
pub fn to_atom(&self, atom_tbl: &Arc<AtomTable>) -> Option<Atom> {
|
||||||
match self {
|
match self {
|
||||||
Literal::Atom(atom) => Some(atom.defrock_brackets(atom_tbl)),
|
Literal::Atom(atom) => Some(atom.defrock_brackets(atom_tbl)),
|
||||||
_ => None,
|
_ => None,
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
use dashu::Integer;
|
use dashu::Integer;
|
||||||
use dashu::Rational;
|
use dashu::Rational;
|
||||||
use tokio::sync::RwLock;
|
|
||||||
|
|
||||||
use crate::arena::*;
|
use crate::arena::*;
|
||||||
use crate::atom_table::*;
|
use crate::atom_table::*;
|
||||||
@@ -286,14 +285,14 @@ fn read_tokens<R: CharRead>(lexer: &mut Lexer<R>) -> Result<Vec<Token>, ParserEr
|
|||||||
Ok(tokens)
|
Ok(tokens)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn atomize_term(atom_tbl: &RwLock<AtomTable>, term: &Term) -> Option<Atom> {
|
fn atomize_term(atom_tbl: &AtomTable, term: &Term) -> Option<Atom> {
|
||||||
match term {
|
match term {
|
||||||
Term::Literal(_, ref c) => atomize_constant(atom_tbl, *c),
|
Term::Literal(_, ref c) => atomize_constant(atom_tbl, *c),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn atomize_constant(atom_tbl: &RwLock<AtomTable>, c: Literal) -> Option<Atom> {
|
fn atomize_constant(atom_tbl: &AtomTable, c: Literal) -> Option<Atom> {
|
||||||
match c {
|
match c {
|
||||||
Literal::Atom(ref name) => Some(*name),
|
Literal::Atom(ref name) => Some(*name),
|
||||||
Literal::Char(c) => Some(AtomTable::build_with(atom_tbl, &c.to_string())),
|
Literal::Char(c) => Some(AtomTable::build_with(atom_tbl, &c.to_string())),
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
|
|
||||||
use std::alloc;
|
use std::alloc;
|
||||||
|
use std::cell::UnsafeCell;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
|
|
||||||
pub trait RawBlockTraits {
|
pub trait RawBlockTraits {
|
||||||
@@ -12,7 +13,7 @@ pub trait RawBlockTraits {
|
|||||||
pub struct RawBlock<T: RawBlockTraits> {
|
pub struct RawBlock<T: RawBlockTraits> {
|
||||||
pub base: *const u8,
|
pub base: *const u8,
|
||||||
pub top: *const u8,
|
pub top: *const u8,
|
||||||
pub ptr: *mut u8,
|
pub ptr: UnsafeCell<*mut u8>,
|
||||||
_marker: PhantomData<T>,
|
_marker: PhantomData<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -22,7 +23,7 @@ impl<T: RawBlockTraits> RawBlock<T> {
|
|||||||
RawBlock {
|
RawBlock {
|
||||||
base: ptr::null(),
|
base: ptr::null(),
|
||||||
top: ptr::null(),
|
top: ptr::null(),
|
||||||
ptr: ptr::null_mut(),
|
ptr: UnsafeCell::new(ptr::null_mut()),
|
||||||
_marker: PhantomData,
|
_marker: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -42,7 +43,7 @@ impl<T: RawBlockTraits> RawBlock<T> {
|
|||||||
|
|
||||||
self.base = alloc::alloc(layout) as *const _;
|
self.base = alloc::alloc(layout) as *const _;
|
||||||
self.top = (self.base as usize + cap) as *const _;
|
self.top = (self.base as usize + cap) as *const _;
|
||||||
self.ptr = self.base as *mut _;
|
*self.ptr.get_mut() = self.base as *mut _;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn grow(&mut self) {
|
pub unsafe fn grow(&mut self) {
|
||||||
@@ -54,7 +55,25 @@ impl<T: RawBlockTraits> RawBlock<T> {
|
|||||||
|
|
||||||
self.base = alloc::realloc(self.base as *mut _, layout, size * 2) as *const _;
|
self.base = alloc::realloc(self.base as *mut _, layout, size * 2) as *const _;
|
||||||
self.top = (self.base as usize + size * 2) as *const _;
|
self.top = (self.base as usize + size * 2) as *const _;
|
||||||
self.ptr = (self.base as usize + size) as *mut _;
|
*self.ptr.get_mut() = (self.base as usize + size) as *mut _;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn grow_new(&self) -> Option<Self> {
|
||||||
|
if self.base.is_null() {
|
||||||
|
Some(Self::new())
|
||||||
|
} else {
|
||||||
|
let mut new_block = Self::empty_block();
|
||||||
|
new_block.init_at_size(self.size() * 2);
|
||||||
|
if new_block.base.is_null() {
|
||||||
|
// allocation failed
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
let allocated = (*self.ptr.get()) as usize - self.base as usize;
|
||||||
|
self.base.copy_to(new_block.base.cast_mut(), allocated);
|
||||||
|
*new_block.ptr.get_mut() = new_block.base.offset(allocated as isize).cast_mut();
|
||||||
|
Some(new_block)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,35 +83,39 @@ impl<T: RawBlockTraits> RawBlock<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn free_space(&self) -> usize {
|
unsafe fn free_space(&self) -> usize {
|
||||||
debug_assert!(
|
debug_assert!(
|
||||||
self.ptr as *const _ >= self.base,
|
*self.ptr.get() as *const _ >= self.base,
|
||||||
"self.ptr = {:?} < {:?} = self.base",
|
"self.ptr = {:?} < {:?} = self.base",
|
||||||
self.ptr,
|
*self.ptr.get(),
|
||||||
self.base
|
self.base
|
||||||
);
|
);
|
||||||
|
|
||||||
self.top as usize - self.ptr as usize
|
self.top as usize - (*self.ptr.get()) as usize
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn alloc(&mut self, size: usize) -> *mut u8 {
|
pub unsafe fn alloc(&self, size: usize) -> *mut u8 {
|
||||||
if self.free_space() >= size {
|
if self.free_space() >= size {
|
||||||
let ptr = self.ptr;
|
let ptr = *self.ptr.get();
|
||||||
self.ptr = (self.ptr as usize + size) as *mut _;
|
*self.ptr.get() = (ptr as usize + size) as *mut _;
|
||||||
ptr
|
ptr
|
||||||
} else {
|
} else {
|
||||||
ptr::null_mut()
|
ptr::null_mut()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn deallocate(&mut self) {
|
impl<T: RawBlockTraits> Drop for RawBlock<T> {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
if !self.base.is_null() {
|
||||||
unsafe {
|
unsafe {
|
||||||
let layout = alloc::Layout::from_size_align_unchecked(self.size(), T::align());
|
let layout = alloc::Layout::from_size_align_unchecked(self.size(), T::align());
|
||||||
alloc::dealloc(self.base as *mut _, layout);
|
alloc::dealloc(self.base as *mut _, layout);
|
||||||
|
}
|
||||||
|
|
||||||
self.top = ptr::null();
|
self.top = ptr::null();
|
||||||
self.base = ptr::null();
|
self.base = ptr::null();
|
||||||
self.ptr = ptr::null_mut();
|
*self.ptr.get_mut() = ptr::null_mut();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
13
src/read.rs
13
src/read.rs
@@ -16,10 +16,6 @@ use crate::types::*;
|
|||||||
|
|
||||||
use fxhash::FxBuildHasher;
|
use fxhash::FxBuildHasher;
|
||||||
|
|
||||||
use tokio::sync::RwLock;
|
|
||||||
|
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
#[cfg(feature = "repl")]
|
#[cfg(feature = "repl")]
|
||||||
use rustyline::error::ReadlineError;
|
use rustyline::error::ReadlineError;
|
||||||
#[cfg(feature = "repl")]
|
#[cfg(feature = "repl")]
|
||||||
@@ -29,6 +25,7 @@ use rustyline::{Config, Editor};
|
|||||||
|
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::io::{Cursor, Error, ErrorKind, Read};
|
use std::io::{Cursor, Error, ErrorKind, Read};
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
type SubtermDeque = VecDeque<(usize, usize)>;
|
type SubtermDeque = VecDeque<(usize, usize)>;
|
||||||
|
|
||||||
@@ -148,7 +145,7 @@ impl ReadlineStream {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_atoms_for_completion(&mut self, atoms: &Arc<RwLock<AtomTable>>) {
|
pub fn set_atoms_for_completion(&mut self, atoms: &Arc<AtomTable>) {
|
||||||
#[cfg(feature = "repl")]
|
#[cfg(feature = "repl")]
|
||||||
{
|
{
|
||||||
let helper = self.rl.helper_mut().unwrap();
|
let helper = self.rl.helper_mut().unwrap();
|
||||||
@@ -291,7 +288,7 @@ impl CharRead for ReadlineStream {
|
|||||||
pub(crate) fn write_term_to_heap<'a, 'b>(
|
pub(crate) fn write_term_to_heap<'a, 'b>(
|
||||||
term: &'a Term,
|
term: &'a Term,
|
||||||
heap: &'b mut Heap,
|
heap: &'b mut Heap,
|
||||||
atom_tbl: &RwLock<AtomTable>,
|
atom_tbl: &AtomTable,
|
||||||
) -> Result<TermWriteResult, CompilationError> {
|
) -> Result<TermWriteResult, CompilationError> {
|
||||||
let term_writer = TermWriter::new(heap, atom_tbl);
|
let term_writer = TermWriter::new(heap, atom_tbl);
|
||||||
term_writer.write_term_to_heap(term)
|
term_writer.write_term_to_heap(term)
|
||||||
@@ -300,7 +297,7 @@ pub(crate) fn write_term_to_heap<'a, 'b>(
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct TermWriter<'a, 'b> {
|
struct TermWriter<'a, 'b> {
|
||||||
heap: &'a mut Heap,
|
heap: &'a mut Heap,
|
||||||
atom_tbl: &'b RwLock<AtomTable>,
|
atom_tbl: &'b AtomTable,
|
||||||
queue: SubtermDeque,
|
queue: SubtermDeque,
|
||||||
var_dict: HeapVarDict,
|
var_dict: HeapVarDict,
|
||||||
}
|
}
|
||||||
@@ -313,7 +310,7 @@ pub struct TermWriteResult {
|
|||||||
|
|
||||||
impl<'a, 'b> TermWriter<'a, 'b> {
|
impl<'a, 'b> TermWriter<'a, 'b> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn new(heap: &'a mut Heap, atom_tbl: &'b RwLock<AtomTable>) -> Self {
|
fn new(heap: &'a mut Heap, atom_tbl: &'b AtomTable) -> Self {
|
||||||
TermWriter {
|
TermWriter {
|
||||||
heap,
|
heap,
|
||||||
atom_tbl,
|
atom_tbl,
|
||||||
|
|||||||
@@ -4,8 +4,6 @@ use rustyline::hint::Hinter;
|
|||||||
use rustyline::validate::Validator;
|
use rustyline::validate::Validator;
|
||||||
use rustyline::{Context, Helper as RlHelper, Result};
|
use rustyline::{Context, Helper as RlHelper, Result};
|
||||||
|
|
||||||
use tokio::sync::RwLock;
|
|
||||||
|
|
||||||
use std::sync::Weak;
|
use std::sync::Weak;
|
||||||
|
|
||||||
use crate::atom_table::{AtomString, AtomTable, STATIC_ATOMS_MAP};
|
use crate::atom_table::{AtomString, AtomTable, STATIC_ATOMS_MAP};
|
||||||
@@ -13,7 +11,7 @@ use crate::atom_table::{AtomString, AtomTable, STATIC_ATOMS_MAP};
|
|||||||
// TODO: Maybe add validation to the helper
|
// TODO: Maybe add validation to the helper
|
||||||
pub struct Helper {
|
pub struct Helper {
|
||||||
highligher: MatchingBracketHighlighter,
|
highligher: MatchingBracketHighlighter,
|
||||||
pub atoms: Weak<RwLock<AtomTable>>,
|
pub atoms: Weak<AtomTable>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Helper {
|
impl Helper {
|
||||||
@@ -71,11 +69,10 @@ impl Completer for Helper {
|
|||||||
let sub_str = line.get(idx..pos).unwrap();
|
let sub_str = line.get(idx..pos).unwrap();
|
||||||
|
|
||||||
let atom_table = self.atoms.upgrade().unwrap();
|
let atom_table = self.atoms.upgrade().unwrap();
|
||||||
let guard = atom_table.blocking_read();
|
|
||||||
|
|
||||||
let mut matching = guard
|
let index_set = atom_table.active_epoch().table.blocking_read().clone();
|
||||||
.table
|
|
||||||
.blocking_read()
|
let mut matching = index_set
|
||||||
.iter()
|
.iter()
|
||||||
.chain(STATIC_ATOMS_MAP.values())
|
.chain(STATIC_ATOMS_MAP.values())
|
||||||
.map(|a| a.as_str())
|
.map(|a| a.as_str())
|
||||||
|
|||||||
Reference in New Issue
Block a user