use granular hierarchical locks in offset_table.rs
This commit is contained in:
13
Cargo.lock
generated
13
Cargo.lock
generated
@@ -1673,9 +1673,9 @@ checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lock_api"
|
name = "lock_api"
|
||||||
version = "0.4.12"
|
version = "0.4.13"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17"
|
checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg",
|
"autocfg",
|
||||||
"scopeguard",
|
"scopeguard",
|
||||||
@@ -2011,9 +2011,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "parking_lot"
|
name = "parking_lot"
|
||||||
version = "0.12.3"
|
version = "0.12.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27"
|
checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"lock_api",
|
"lock_api",
|
||||||
"parking_lot_core",
|
"parking_lot_core",
|
||||||
@@ -2021,9 +2021,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "parking_lot_core"
|
name = "parking_lot_core"
|
||||||
version = "0.9.10"
|
version = "0.9.11"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
|
checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"libc",
|
"libc",
|
||||||
@@ -2712,6 +2712,7 @@ dependencies = [
|
|||||||
"num-order",
|
"num-order",
|
||||||
"ordered-float",
|
"ordered-float",
|
||||||
"ouroboros",
|
"ouroboros",
|
||||||
|
"parking_lot",
|
||||||
"phf",
|
"phf",
|
||||||
"pprof",
|
"pprof",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
|
|||||||
@@ -79,6 +79,7 @@ ego-tree = "0.10.0"
|
|||||||
|
|
||||||
serde_json = "1.0.122"
|
serde_json = "1.0.122"
|
||||||
serde = "1.0.204"
|
serde = "1.0.204"
|
||||||
|
parking_lot = "0.12.4"
|
||||||
|
|
||||||
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
||||||
crossterm = { version = "0.28.1", optional = true }
|
crossterm = { version = "0.28.1", optional = true }
|
||||||
|
|||||||
11
src/arena.rs
11
src/arena.rs
@@ -570,8 +570,6 @@ const_assert!(mem::size_of::<OrderedFloat<f64>>() == 8);
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use std::ops::Deref;
|
|
||||||
|
|
||||||
use crate::arena::*;
|
use crate::arena::*;
|
||||||
use crate::atom_table::*;
|
use crate::atom_table::*;
|
||||||
use crate::machine::mock_wam::*;
|
use crate::machine::mock_wam::*;
|
||||||
@@ -590,10 +588,7 @@ mod tests {
|
|||||||
|
|
||||||
assert_eq!(cell.get_tag(), HeapCellValueTag::F64Offset);
|
assert_eq!(cell.get_tag(), HeapCellValueTag::F64Offset);
|
||||||
assert!(!cell.get_mark_bit());
|
assert!(!cell.get_mark_bit());
|
||||||
assert_eq!(
|
assert_eq!(wam.machine_st.arena.f64_tbl.get_entry(fp), OrderedFloat(f));
|
||||||
wam.machine_st.arena.f64_tbl.lookup(fp).deref(),
|
|
||||||
&OrderedFloat(f)
|
|
||||||
);
|
|
||||||
|
|
||||||
cell.set_mark_bit(true);
|
cell.set_mark_bit(true);
|
||||||
|
|
||||||
@@ -601,8 +596,8 @@ mod tests {
|
|||||||
|
|
||||||
read_heap_cell!(cell,
|
read_heap_cell!(cell,
|
||||||
(HeapCellValueTag::F64Offset, offset) => {
|
(HeapCellValueTag::F64Offset, offset) => {
|
||||||
let fp = wam.machine_st.arena.f64_tbl.lookup(offset.into());
|
let fp = wam.machine_st.arena.f64_tbl.get_entry(offset);
|
||||||
assert_eq!(*fp, OrderedFloat(0f64))
|
assert_eq!(fp, OrderedFloat(0f64))
|
||||||
}
|
}
|
||||||
_ => { unreachable!() }
|
_ => { unreachable!() }
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -166,7 +166,7 @@ fn push_literal(
|
|||||||
Literal::Fixnum(n) => interm.push(ArithmeticTerm::Number(Number::Fixnum(*n))),
|
Literal::Fixnum(n) => interm.push(ArithmeticTerm::Number(Number::Fixnum(*n))),
|
||||||
Literal::Integer(n) => interm.push(ArithmeticTerm::Number(Number::Integer(*n))),
|
Literal::Integer(n) => interm.push(ArithmeticTerm::Number(Number::Integer(*n))),
|
||||||
&Literal::F64Offset(offset) => {
|
&Literal::F64Offset(offset) => {
|
||||||
let n = *f64_tbl.lookup(offset);
|
let n = f64_tbl.get_entry(offset);
|
||||||
interm.push(ArithmeticTerm::Number(Number::Float(n)));
|
interm.push(ArithmeticTerm::Number(Number::Float(n)));
|
||||||
}
|
}
|
||||||
Literal::Rational(n) => interm.push(ArithmeticTerm::Number(Number::Rational(*n))),
|
Literal::Rational(n) => interm.push(ArithmeticTerm::Number(Number::Rational(*n))),
|
||||||
@@ -685,7 +685,7 @@ impl TryFrom<(HeapCellValue, &'_ F64Table)> for Number {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
(HeapCellValueTag::F64Offset, offset) => {
|
(HeapCellValueTag::F64Offset, offset) => {
|
||||||
let n = *f64_tbl.lookup(offset.into());
|
let n = f64_tbl.get_entry(offset);
|
||||||
Ok(Number::Float(n))
|
Ok(Number::Float(n))
|
||||||
}
|
}
|
||||||
(HeapCellValueTag::Fixnum | HeapCellValueTag::CutPoint, n) => {
|
(HeapCellValueTag::Fixnum | HeapCellValueTag::CutPoint, n) => {
|
||||||
|
|||||||
@@ -1544,7 +1544,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
|||||||
self.state_stack.pop();
|
self.state_stack.pop();
|
||||||
self.state_stack.pop();
|
self.state_stack.pop();
|
||||||
|
|
||||||
let idx_ptr = self.arena.code_index_tbl.lookup(idx);
|
let idx_ptr = self.arena.code_index_tbl.get_entry(idx);
|
||||||
|
|
||||||
let offset = if idx_ptr.is_undefined() || idx_ptr.is_dynamic_undefined() {
|
let offset = if idx_ptr.is_undefined() || idx_ptr.is_dynamic_undefined() {
|
||||||
TokenOrRedirect::Atom(atom!("undefined"))
|
TokenOrRedirect::Atom(atom!("undefined"))
|
||||||
@@ -1749,7 +1749,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
|
|||||||
self.print_number(max_depth, NumberFocus::Unfocused(Number::Fixnum(n)), &op);
|
self.print_number(max_depth, NumberFocus::Unfocused(Number::Fixnum(n)), &op);
|
||||||
}
|
}
|
||||||
(HeapCellValueTag::F64Offset, offset) => {
|
(HeapCellValueTag::F64Offset, offset) => {
|
||||||
let f = *self.arena.f64_tbl.lookup(offset.into());
|
let f = self.arena.f64_tbl.get_entry(offset);
|
||||||
self.print_number(max_depth, NumberFocus::Unfocused(Number::Float(f)), &op);
|
self.print_number(max_depth, NumberFocus::Unfocused(Number::Float(f)), &op);
|
||||||
}
|
}
|
||||||
(HeapCellValueTag::PStrLoc) => {
|
(HeapCellValueTag::PStrLoc) => {
|
||||||
|
|||||||
@@ -1389,8 +1389,8 @@ impl MachineState {
|
|||||||
self.interms.push(Number::Fixnum(n));
|
self.interms.push(Number::Fixnum(n));
|
||||||
}
|
}
|
||||||
(HeapCellValueTag::F64Offset, offset) => {
|
(HeapCellValueTag::F64Offset, offset) => {
|
||||||
let fl = self.arena.f64_tbl.lookup(offset);
|
let fl = self.arena.f64_tbl.get_entry(offset);
|
||||||
self.interms.push(Number::Float(*fl));
|
self.interms.push(Number::Float(fl));
|
||||||
}
|
}
|
||||||
(HeapCellValueTag::Cons, ptr) => {
|
(HeapCellValueTag::Cons, ptr) => {
|
||||||
match_untyped_arena_ptr!(ptr,
|
match_untyped_arena_ptr!(ptr,
|
||||||
|
|||||||
@@ -1328,17 +1328,15 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
|
|||||||
let index_ptr = LS::machine_st(&mut self.payload)
|
let index_ptr = LS::machine_st(&mut self.payload)
|
||||||
.arena
|
.arena
|
||||||
.code_index_tbl
|
.code_index_tbl
|
||||||
.lookup(code_idx.into());
|
.get_entry(code_idx.into());
|
||||||
|
|
||||||
print_overwrite_warning(
|
print_overwrite_warning(
|
||||||
&predicates.compilation_target,
|
&predicates.compilation_target,
|
||||||
*index_ptr,
|
index_ptr,
|
||||||
key,
|
key,
|
||||||
settings.is_dynamic(),
|
settings.is_dynamic(),
|
||||||
);
|
);
|
||||||
|
|
||||||
drop(index_ptr);
|
|
||||||
|
|
||||||
let index_ptr = if settings.is_dynamic() {
|
let index_ptr = if settings.is_dynamic() {
|
||||||
IndexPtr::dynamic_index(code_ptr)
|
IndexPtr::dynamic_index(code_ptr)
|
||||||
} else {
|
} else {
|
||||||
@@ -2231,10 +2229,10 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
|
|||||||
|
|
||||||
if let Some(filename) = self.listing_src_file_name() {
|
if let Some(filename) = self.listing_src_file_name() {
|
||||||
if let Some(ref mut module) = self.wam_prelude.indices.modules.get_mut(&filename) {
|
if let Some(ref mut module) = self.wam_prelude.indices.modules.get_mut(&filename) {
|
||||||
let index_ptr = *LS::machine_st(&mut self.payload)
|
let index_ptr = LS::machine_st(&mut self.payload)
|
||||||
.arena
|
.arena
|
||||||
.code_index_tbl
|
.code_index_tbl
|
||||||
.lookup_mut(offset.into());
|
.get_entry(offset.into());
|
||||||
|
|
||||||
let offset = *module.code_dir.entry(key).or_insert(offset);
|
let offset = *module.code_dir.entry(key).or_insert(offset);
|
||||||
|
|
||||||
|
|||||||
@@ -547,8 +547,8 @@ impl Machine {
|
|||||||
|
|
||||||
// Find the boundaries of the current predicate
|
// Find the boundaries of the current predicate
|
||||||
self.indices.code_dir.sort_by(|_, a, _, b| {
|
self.indices.code_dir.sort_by(|_, a, _, b| {
|
||||||
let a = *self.machine_st.arena.code_index_tbl.lookup((*a).into());
|
let a = self.machine_st.arena.code_index_tbl.get_entry((*a).into());
|
||||||
let b = *self.machine_st.arena.code_index_tbl.lookup((*b).into());
|
let b = self.machine_st.arena.code_index_tbl.get_entry((*b).into());
|
||||||
|
|
||||||
a.cmp(&b)
|
a.cmp(&b)
|
||||||
});
|
});
|
||||||
@@ -557,8 +557,11 @@ impl Machine {
|
|||||||
.indices
|
.indices
|
||||||
.code_dir
|
.code_dir
|
||||||
.binary_search_by_key(&p, |_, x| -> usize {
|
.binary_search_by_key(&p, |_, x| -> usize {
|
||||||
self.machine_st.arena.code_index_tbl.lookup((*x).into()).p()
|
self.machine_st
|
||||||
as usize
|
.arena
|
||||||
|
.code_index_tbl
|
||||||
|
.get_entry((*x).into())
|
||||||
|
.p() as usize
|
||||||
})
|
})
|
||||||
.unwrap_or_else(|x| x - 1);
|
.unwrap_or_else(|x| x - 1);
|
||||||
|
|
||||||
@@ -570,7 +573,7 @@ impl Machine {
|
|||||||
self.machine_st
|
self.machine_st
|
||||||
.arena
|
.arena
|
||||||
.code_index_tbl
|
.code_index_tbl
|
||||||
.lookup((*idx.1).into())
|
.get_entry((*idx.1).into())
|
||||||
.p() as usize
|
.p() as usize
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@@ -585,7 +588,7 @@ impl Machine {
|
|||||||
self.machine_st
|
self.machine_st
|
||||||
.arena
|
.arena
|
||||||
.code_index_tbl
|
.code_index_tbl
|
||||||
.lookup((*idx.1).into())
|
.get_entry((*idx.1).into())
|
||||||
.p() as usize
|
.p() as usize
|
||||||
})
|
})
|
||||||
.unwrap_or(self.code.len());
|
.unwrap_or(self.code.len());
|
||||||
@@ -2696,7 +2699,7 @@ impl Machine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
&Instruction::CallNamed(arity, name, idx) => {
|
&Instruction::CallNamed(arity, name, idx) => {
|
||||||
let idx = *self.machine_st.arena.code_index_tbl.lookup(idx.into());
|
let idx = self.machine_st.arena.code_index_tbl.get_entry(idx.into());
|
||||||
|
|
||||||
try_or_throw!(self.machine_st, self.try_call(name, arity, idx));
|
try_or_throw!(self.machine_st, self.try_call(name, arity, idx));
|
||||||
|
|
||||||
@@ -2707,7 +2710,7 @@ impl Machine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
&Instruction::ExecuteNamed(arity, name, idx) => {
|
&Instruction::ExecuteNamed(arity, name, idx) => {
|
||||||
let idx = *self.machine_st.arena.code_index_tbl.lookup(idx.into());
|
let idx = self.machine_st.arena.code_index_tbl.get_entry(idx.into());
|
||||||
|
|
||||||
try_or_throw!(self.machine_st, self.try_execute(name, arity, idx));
|
try_or_throw!(self.machine_st, self.try_execute(name, arity, idx));
|
||||||
|
|
||||||
@@ -2718,7 +2721,7 @@ impl Machine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
&Instruction::DefaultCallNamed(arity, name, idx) => {
|
&Instruction::DefaultCallNamed(arity, name, idx) => {
|
||||||
let idx = *self.machine_st.arena.code_index_tbl.lookup(idx.into());
|
let idx = self.machine_st.arena.code_index_tbl.get_entry(idx.into());
|
||||||
|
|
||||||
try_or_throw!(self.machine_st, self.try_call(name, arity, idx));
|
try_or_throw!(self.machine_st, self.try_call(name, arity, idx));
|
||||||
|
|
||||||
@@ -2727,7 +2730,7 @@ impl Machine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
&Instruction::DefaultExecuteNamed(arity, name, idx) => {
|
&Instruction::DefaultExecuteNamed(arity, name, idx) => {
|
||||||
let idx = *self.machine_st.arena.code_index_tbl.lookup(idx.into());
|
let idx = self.machine_st.arena.code_index_tbl.get_entry(idx.into());
|
||||||
|
|
||||||
try_or_throw!(self.machine_st, self.try_execute(name, arity, idx));
|
try_or_throw!(self.machine_st, self.try_execute(name, arity, idx));
|
||||||
|
|
||||||
|
|||||||
@@ -278,7 +278,7 @@ impl Term {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
(HeapCellValueTag::F64Offset, offset) => {
|
(HeapCellValueTag::F64Offset, offset) => {
|
||||||
let f = *machine.machine_st.arena.f64_tbl.lookup(offset);
|
let f = machine.machine_st.arena.f64_tbl.get_entry(offset);
|
||||||
term_stack.push(Term::Float(f.into()));
|
term_stack.push(Term::Float(f.into()));
|
||||||
}
|
}
|
||||||
(HeapCellValueTag::Fixnum, n) => {
|
(HeapCellValueTag::Fixnum, n) => {
|
||||||
@@ -602,7 +602,7 @@ impl Machine {
|
|||||||
self.machine_st
|
self.machine_st
|
||||||
.arena
|
.arena
|
||||||
.code_index_tbl
|
.code_index_tbl
|
||||||
.lookup(offset.into())
|
.get_entry(offset.into())
|
||||||
.p() as usize
|
.p() as usize
|
||||||
})
|
})
|
||||||
.expect("couldn't get code index");
|
.expect("couldn't get code index");
|
||||||
|
|||||||
@@ -22,33 +22,30 @@ pub(super) fn set_code_index<'a, LS: LoadState<'a>>(
|
|||||||
code_idx: CodeIndex,
|
code_idx: CodeIndex,
|
||||||
code_ptr: IndexPtr,
|
code_ptr: IndexPtr,
|
||||||
) {
|
) {
|
||||||
let mut code_idx_ptr = LS::machine_st(payload)
|
let record = LS::machine_st(payload).arena.code_index_tbl.with_entry_mut(
|
||||||
.arena
|
code_idx.into(),
|
||||||
.code_index_tbl
|
|code_idx_ptr| match compilation_target {
|
||||||
.lookup_mut(code_idx.into());
|
|
||||||
|
|
||||||
let record = match compilation_target {
|
|
||||||
CompilationTarget::User => {
|
CompilationTarget::User => {
|
||||||
if IndexPtrTag::Undefined == code_idx_ptr.tag() {
|
if IndexPtrTag::Undefined == code_idx_ptr.tag() {
|
||||||
code_idx_ptr.set(code_ptr);
|
*code_idx_ptr = code_ptr;
|
||||||
RetractionRecord::AddedUserPredicate(key)
|
RetractionRecord::AddedUserPredicate(key)
|
||||||
} else {
|
} else {
|
||||||
let replaced = code_idx_ptr.replace(code_ptr);
|
let replaced = mem::replace(code_idx_ptr, code_ptr);
|
||||||
RetractionRecord::ReplacedUserPredicate(key, replaced)
|
RetractionRecord::ReplacedUserPredicate(key, replaced)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CompilationTarget::Module(ref module_name) => {
|
CompilationTarget::Module(ref module_name) => {
|
||||||
if IndexPtrTag::Undefined == code_idx_ptr.tag() {
|
if IndexPtrTag::Undefined == code_idx_ptr.tag() {
|
||||||
code_idx_ptr.set(code_ptr);
|
*code_idx_ptr = code_ptr;
|
||||||
RetractionRecord::AddedModulePredicate(*module_name, key)
|
RetractionRecord::AddedModulePredicate(*module_name, key)
|
||||||
} else {
|
} else {
|
||||||
let replaced = code_idx_ptr.replace(code_ptr);
|
let replaced = mem::replace(code_idx_ptr, code_ptr);
|
||||||
RetractionRecord::ReplacedModulePredicate(*module_name, key, replaced)
|
RetractionRecord::ReplacedModulePredicate(*module_name, key, replaced)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
},
|
||||||
|
);
|
||||||
|
|
||||||
drop(code_idx_ptr);
|
|
||||||
payload.retraction_info.push_record(record);
|
payload.retraction_info.push_record(record);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -145,7 +142,7 @@ pub(super) fn import_module_exports<'a, LS: LoadState<'a>>(
|
|||||||
.entry(key)
|
.entry(key)
|
||||||
.or_insert_with(|| CodeIndex::default(code_idx_tbl));
|
.or_insert_with(|| CodeIndex::default(code_idx_tbl));
|
||||||
|
|
||||||
let src_code_index_ptr = *code_idx_tbl.lookup(src_code_index.into());
|
let src_code_index_ptr = code_idx_tbl.get_entry(src_code_index.into());
|
||||||
|
|
||||||
set_code_index::<LS>(
|
set_code_index::<LS>(
|
||||||
payload,
|
payload,
|
||||||
@@ -158,7 +155,7 @@ pub(super) fn import_module_exports<'a, LS: LoadState<'a>>(
|
|||||||
if LS::machine_st(payload)
|
if LS::machine_st(payload)
|
||||||
.arena
|
.arena
|
||||||
.code_index_tbl
|
.code_index_tbl
|
||||||
.lookup(src_code_index.into())
|
.get_entry(src_code_index.into())
|
||||||
.is_dynamic_undefined()
|
.is_dynamic_undefined()
|
||||||
{
|
{
|
||||||
code_dir.insert(key, src_code_index);
|
code_dir.insert(key, src_code_index);
|
||||||
@@ -205,7 +202,7 @@ fn import_module_exports_into_module<'a, LS: LoadState<'a>>(
|
|||||||
if let Some(src_code_index) = imported_module.code_dir.get(&key).cloned() {
|
if let Some(src_code_index) = imported_module.code_dir.get(&key).cloned() {
|
||||||
let code_index_tbl = &mut LS::machine_st(payload).arena.code_index_tbl;
|
let code_index_tbl = &mut LS::machine_st(payload).arena.code_index_tbl;
|
||||||
|
|
||||||
let src_code_ptr = *code_index_tbl.lookup(src_code_index.into());
|
let src_code_ptr = code_index_tbl.get_entry(src_code_index.into());
|
||||||
let target_code_index = *code_dir
|
let target_code_index = *code_dir
|
||||||
.entry(key)
|
.entry(key)
|
||||||
.or_insert_with(|| CodeIndex::default(code_index_tbl));
|
.or_insert_with(|| CodeIndex::default(code_index_tbl));
|
||||||
@@ -259,7 +256,7 @@ fn import_qualified_module_exports<'a, LS: LoadState<'a>>(
|
|||||||
if let Some(src_code_index) = imported_module.code_dir.get(&key).cloned() {
|
if let Some(src_code_index) = imported_module.code_dir.get(&key).cloned() {
|
||||||
let code_index_tbl = &mut LS::machine_st(payload).arena.code_index_tbl;
|
let code_index_tbl = &mut LS::machine_st(payload).arena.code_index_tbl;
|
||||||
|
|
||||||
let src_code_ptr = *code_index_tbl.lookup(src_code_index.into());
|
let src_code_ptr = code_index_tbl.get_entry(src_code_index.into());
|
||||||
let target_code_index =
|
let target_code_index =
|
||||||
*wam_prelude.indices.code_dir.entry(key).or_insert_with(|| {
|
*wam_prelude.indices.code_dir.entry(key).or_insert_with(|| {
|
||||||
CodeIndex::new(IndexPtr::undefined(), code_index_tbl)
|
CodeIndex::new(IndexPtr::undefined(), code_index_tbl)
|
||||||
@@ -320,7 +317,7 @@ fn import_qualified_module_exports_into_module<'a, LS: LoadState<'a>>(
|
|||||||
if let Some(src_code_index) = imported_module.code_dir.get(&key).cloned() {
|
if let Some(src_code_index) = imported_module.code_dir.get(&key).cloned() {
|
||||||
let code_index_tbl = &mut LS::machine_st(payload).arena.code_index_tbl;
|
let code_index_tbl = &mut LS::machine_st(payload).arena.code_index_tbl;
|
||||||
|
|
||||||
let src_code_ptr = *code_index_tbl.lookup(src_code_index.into());
|
let src_code_ptr = code_index_tbl.get_entry(src_code_index.into());
|
||||||
let target_code_index = *code_dir
|
let target_code_index = *code_dir
|
||||||
.entry(key)
|
.entry(key)
|
||||||
.or_insert_with(|| CodeIndex::new(IndexPtr::undefined(), code_index_tbl));
|
.or_insert_with(|| CodeIndex::new(IndexPtr::undefined(), code_index_tbl));
|
||||||
@@ -505,10 +502,9 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let code_index_tbl = &mut LS::machine_st(&mut self.payload).arena.code_index_tbl;
|
let code_index_tbl = &mut LS::machine_st(&mut self.payload).arena.code_index_tbl;
|
||||||
let code_ptr = code_index_tbl.lookup((*code_index).into());
|
let code_ptr = code_index_tbl.get_entry((*code_index).into());
|
||||||
|
|
||||||
if !code_ptr.is_undefined() && !code_ptr.is_dynamic_undefined() {
|
if !code_ptr.is_undefined() && !code_ptr.is_dynamic_undefined() {
|
||||||
drop(code_ptr);
|
|
||||||
let old_index_ptr = code_index.replace(code_index_tbl, IndexPtr::undefined());
|
let old_index_ptr = code_index.replace(code_index_tbl, IndexPtr::undefined());
|
||||||
|
|
||||||
self.payload.retraction_info.push_record(
|
self.payload.retraction_info.push_record(
|
||||||
@@ -557,13 +553,12 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
|
|||||||
(Some(module_code_idx), Some(target_code_idx)) => {
|
(Some(module_code_idx), Some(target_code_idx)) => {
|
||||||
let code_index_tbl =
|
let code_index_tbl =
|
||||||
&mut LS::machine_st(payload).arena.code_index_tbl;
|
&mut LS::machine_st(payload).arena.code_index_tbl;
|
||||||
let module_code_ptr = code_index_tbl.lookup(module_code_idx.into());
|
let module_code_ptr =
|
||||||
let target_code_ptr = code_index_tbl.lookup(target_code_idx.into());
|
code_index_tbl.get_entry(module_code_idx.into());
|
||||||
|
let target_code_ptr =
|
||||||
|
code_index_tbl.get_entry(target_code_idx.into());
|
||||||
|
|
||||||
if module_code_ptr == target_code_ptr {
|
if module_code_ptr == target_code_ptr {
|
||||||
drop(module_code_ptr);
|
|
||||||
drop(target_code_ptr);
|
|
||||||
|
|
||||||
let old_index_ptr = target_code_idx
|
let old_index_ptr = target_code_idx
|
||||||
.replace(code_index_tbl, IndexPtr::undefined());
|
.replace(code_index_tbl, IndexPtr::undefined());
|
||||||
payload
|
payload
|
||||||
|
|||||||
@@ -1225,11 +1225,9 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> {
|
|||||||
let code_idx_ptr = LS::machine_st(&mut self.payload)
|
let code_idx_ptr = LS::machine_st(&mut self.payload)
|
||||||
.arena
|
.arena
|
||||||
.code_index_tbl
|
.code_index_tbl
|
||||||
.lookup_mut(offset.into());
|
.get_entry(offset.into());
|
||||||
|
|
||||||
if code_idx_ptr.is_undefined() {
|
if code_idx_ptr.is_undefined() {
|
||||||
drop(code_idx_ptr);
|
|
||||||
|
|
||||||
set_code_index::<LS>(
|
set_code_index::<LS>(
|
||||||
&mut self.payload,
|
&mut self.payload,
|
||||||
&compilation_target,
|
&compilation_target,
|
||||||
@@ -2015,8 +2013,7 @@ impl Machine {
|
|||||||
.machine_st
|
.machine_st
|
||||||
.arena
|
.arena
|
||||||
.code_index_tbl
|
.code_index_tbl
|
||||||
.lookup(offset.into())
|
.with_entry(offset.into(), |idx| idx.tag())
|
||||||
.tag()
|
|
||||||
})
|
})
|
||||||
.unwrap_or(IndexPtrTag::DynamicUndefined);
|
.unwrap_or(IndexPtrTag::DynamicUndefined);
|
||||||
|
|
||||||
@@ -2162,16 +2159,14 @@ impl Machine {
|
|||||||
|
|
||||||
let offset = loader.get_or_insert_code_index(key, compilation_target);
|
let offset = loader.get_or_insert_code_index(key, compilation_target);
|
||||||
|
|
||||||
let mut code_idx = loader
|
loader
|
||||||
.payload
|
.payload
|
||||||
.machine_st
|
.machine_st
|
||||||
.arena
|
.arena
|
||||||
.code_index_tbl
|
.code_index_tbl
|
||||||
.lookup_mut(offset.into());
|
.with_entry_mut(offset.into(), |code_idx| {
|
||||||
|
*code_idx = IndexPtr::undefined();
|
||||||
code_idx.set(IndexPtr::undefined());
|
});
|
||||||
|
|
||||||
drop(code_idx);
|
|
||||||
|
|
||||||
loader.payload.compilation_target = clause_clause_compilation_target;
|
loader.payload.compilation_target = clause_clause_compilation_target;
|
||||||
|
|
||||||
|
|||||||
@@ -186,12 +186,12 @@ impl CodeIndex {
|
|||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn set(&self, code_index_tbl: &mut CodeIndexTable, value: IndexPtr) {
|
pub(crate) fn set(&self, code_index_tbl: &mut CodeIndexTable, value: IndexPtr) {
|
||||||
code_index_tbl.lookup_mut(self.0).set(value);
|
code_index_tbl.with_entry_mut(self.0, |idx| *idx = value);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn replace(&self, code_index_tbl: &mut CodeIndexTable, value: IndexPtr) -> IndexPtr {
|
pub(crate) fn replace(&self, code_index_tbl: &mut CodeIndexTable, value: IndexPtr) -> IndexPtr {
|
||||||
code_index_tbl.lookup_mut(self.0).replace(value)
|
code_index_tbl.with_entry_mut(self.0, |idx| std::mem::replace(idx, value))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -412,8 +412,8 @@ impl MachineState {
|
|||||||
let v1 = cell_as_f64_offset!(v1);
|
let v1 = cell_as_f64_offset!(v1);
|
||||||
let v2 = cell_as_f64_offset!(v2);
|
let v2 = cell_as_f64_offset!(v2);
|
||||||
|
|
||||||
let v1 = self.arena.f64_tbl.lookup(v1);
|
let v1 = self.arena.f64_tbl.get_entry(v1);
|
||||||
let v2 = self.arena.f64_tbl.lookup(v2);
|
let v2 = self.arena.f64_tbl.get_entry(v2);
|
||||||
|
|
||||||
if v1 != v2 {
|
if v1 != v2 {
|
||||||
self.pdl.clear();
|
self.pdl.clear();
|
||||||
|
|||||||
@@ -253,7 +253,11 @@ impl Machine {
|
|||||||
) -> std::process::ExitCode {
|
) -> std::process::ExitCode {
|
||||||
if let Some(module) = self.indices.modules.get(&module_name) {
|
if let Some(module) = self.indices.modules.get(&module_name) {
|
||||||
if let Some(code_idx) = module.code_dir.get(&key) {
|
if let Some(code_idx) = module.code_dir.get(&key) {
|
||||||
let index_ptr = *self.machine_st.arena.code_index_tbl.lookup(code_idx.into());
|
let index_ptr = self
|
||||||
|
.machine_st
|
||||||
|
.arena
|
||||||
|
.code_index_tbl
|
||||||
|
.get_entry(code_idx.into());
|
||||||
let p = index_ptr.local().unwrap();
|
let p = index_ptr.local().unwrap();
|
||||||
|
|
||||||
// Leave a halting choice point to backtrack to in case the predicate fails or throws.
|
// Leave a halting choice point to backtrack to in case the predicate fails or throws.
|
||||||
@@ -327,7 +331,11 @@ impl Machine {
|
|||||||
|
|
||||||
if let Some(module) = self.indices.modules.get(&atom!("$atts")) {
|
if let Some(module) = self.indices.modules.get(&atom!("$atts")) {
|
||||||
if let Some(code_idx) = module.code_dir.get(&(atom!("driver"), 2)) {
|
if let Some(code_idx) = module.code_dir.get(&(atom!("driver"), 2)) {
|
||||||
let index_ptr = *self.machine_st.arena.code_index_tbl.lookup(code_idx.into());
|
let index_ptr = self
|
||||||
|
.machine_st
|
||||||
|
.arena
|
||||||
|
.code_index_tbl
|
||||||
|
.get_entry(code_idx.into());
|
||||||
self.machine_st.attr_var_init.verify_attrs_loc = index_ptr.local().unwrap();
|
self.machine_st.attr_var_init.verify_attrs_loc = index_ptr.local().unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -350,7 +358,7 @@ impl Machine {
|
|||||||
CodeIndex::new(IndexPtr::undefined(), code_index_tbl)
|
CodeIndex::new(IndexPtr::undefined(), code_index_tbl)
|
||||||
});
|
});
|
||||||
|
|
||||||
let src_code_ptr = *code_index_tbl.lookup(src_code_index.into());
|
let src_code_ptr = code_index_tbl.get_entry(src_code_index.into());
|
||||||
target_code_index.set(code_index_tbl, src_code_ptr);
|
target_code_index.set(code_index_tbl, src_code_ptr);
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
@@ -1045,14 +1053,14 @@ impl Machine {
|
|||||||
|
|
||||||
if module_name == atom!("user") {
|
if module_name == atom!("user") {
|
||||||
if let Some(idx) = self.indices.code_dir.get(&(name, arity)).cloned() {
|
if let Some(idx) = self.indices.code_dir.get(&(name, arity)).cloned() {
|
||||||
let index_ptr = *self.machine_st.arena.code_index_tbl.lookup(idx.into());
|
let index_ptr = self.machine_st.arena.code_index_tbl.get_entry(idx.into());
|
||||||
self.try_call(name, arity, index_ptr)
|
self.try_call(name, arity, index_ptr)
|
||||||
} else {
|
} else {
|
||||||
Err(self.machine_st.throw_undefined_error(name, arity))
|
Err(self.machine_st.throw_undefined_error(name, arity))
|
||||||
}
|
}
|
||||||
} else if let Some(module) = self.indices.modules.get(&module_name) {
|
} else if let Some(module) = self.indices.modules.get(&module_name) {
|
||||||
if let Some(idx) = module.code_dir.get(&(name, arity)).cloned() {
|
if let Some(idx) = module.code_dir.get(&(name, arity)).cloned() {
|
||||||
let index_ptr = *self.machine_st.arena.code_index_tbl.lookup(idx.into());
|
let index_ptr = self.machine_st.arena.code_index_tbl.get_entry(idx.into());
|
||||||
self.try_call(name, arity, index_ptr)
|
self.try_call(name, arity, index_ptr)
|
||||||
} else {
|
} else {
|
||||||
self.undefined_procedure(name, arity)
|
self.undefined_procedure(name, arity)
|
||||||
@@ -1076,15 +1084,23 @@ impl Machine {
|
|||||||
let (name, arity) = key;
|
let (name, arity) = key;
|
||||||
|
|
||||||
if module_name == atom!("user") {
|
if module_name == atom!("user") {
|
||||||
if let Some(idx) = self.indices.code_dir.get(&(name, arity)).cloned() {
|
if let Some(offset) = self.indices.code_dir.get(&(name, arity)).cloned() {
|
||||||
let index_ptr = *self.machine_st.arena.code_index_tbl.lookup(idx.into());
|
let index_ptr = self
|
||||||
|
.machine_st
|
||||||
|
.arena
|
||||||
|
.code_index_tbl
|
||||||
|
.get_entry(offset.into());
|
||||||
self.try_execute(name, arity, index_ptr)
|
self.try_execute(name, arity, index_ptr)
|
||||||
} else {
|
} else {
|
||||||
self.undefined_procedure(name, arity)
|
self.undefined_procedure(name, arity)
|
||||||
}
|
}
|
||||||
} else if let Some(module) = self.indices.modules.get(&module_name) {
|
} else if let Some(module) = self.indices.modules.get(&module_name) {
|
||||||
if let Some(idx) = module.code_dir.get(&(name, arity)).cloned() {
|
if let Some(offset) = module.code_dir.get(&(name, arity)).cloned() {
|
||||||
let index_ptr = *self.machine_st.arena.code_index_tbl.lookup(idx.into());
|
let index_ptr = self
|
||||||
|
.machine_st
|
||||||
|
.arena
|
||||||
|
.code_index_tbl
|
||||||
|
.get_entry(offset.into());
|
||||||
self.try_execute(name, arity, index_ptr)
|
self.try_execute(name, arity, index_ptr)
|
||||||
} else {
|
} else {
|
||||||
self.undefined_procedure(name, arity)
|
self.undefined_procedure(name, arity)
|
||||||
@@ -1131,7 +1147,7 @@ impl Machine {
|
|||||||
self.machine_st
|
self.machine_st
|
||||||
.arena
|
.arena
|
||||||
.code_index_tbl
|
.code_index_tbl
|
||||||
.lookup(code_idx.into())
|
.get_entry(code_idx.into())
|
||||||
.local()
|
.local()
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@@ -1142,7 +1158,7 @@ impl Machine {
|
|||||||
self.machine_st
|
self.machine_st
|
||||||
.arena
|
.arena
|
||||||
.code_index_tbl
|
.code_index_tbl
|
||||||
.lookup(code_idx.into())
|
.get_entry(code_idx.into())
|
||||||
.local()
|
.local()
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|||||||
@@ -1246,7 +1246,7 @@ impl Machine {
|
|||||||
self.machine_st
|
self.machine_st
|
||||||
.arena
|
.arena
|
||||||
.code_index_tbl
|
.code_index_tbl
|
||||||
.lookup(idx.into())
|
.get_entry(idx.into())
|
||||||
.local()
|
.local()
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@@ -1477,7 +1477,11 @@ impl Machine {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if let Some(code_idx) = index_cell_opt {
|
if let Some(code_idx) = index_cell_opt {
|
||||||
let index_ptr = *self.machine_st.arena.code_index_tbl.lookup(code_idx.into());
|
let index_ptr = self
|
||||||
|
.machine_st
|
||||||
|
.arena
|
||||||
|
.code_index_tbl
|
||||||
|
.get_entry(code_idx.into());
|
||||||
|
|
||||||
if !index_ptr.is_undefined() {
|
if !index_ptr.is_undefined() {
|
||||||
load_registers(&mut self.machine_st, goal, goal_arity);
|
load_registers(&mut self.machine_st, goal, goal_arity);
|
||||||
@@ -6005,7 +6009,7 @@ impl Machine {
|
|||||||
self.machine_st
|
self.machine_st
|
||||||
.arena
|
.arena
|
||||||
.code_index_tbl
|
.code_index_tbl
|
||||||
.lookup(idx.into())
|
.get_entry(idx.into())
|
||||||
.local()
|
.local()
|
||||||
.is_some()
|
.is_some()
|
||||||
})
|
})
|
||||||
@@ -6030,10 +6034,10 @@ impl Machine {
|
|||||||
arity,
|
arity,
|
||||||
module_name,
|
module_name,
|
||||||
)
|
)
|
||||||
.map(|idx| *self.machine_st
|
.map(|idx| self.machine_st
|
||||||
.arena
|
.arena
|
||||||
.code_index_tbl
|
.code_index_tbl
|
||||||
.lookup(idx.into()))
|
.get_entry(idx.into()))
|
||||||
.unwrap_or(IndexPtr::dynamic_undefined());
|
.unwrap_or(IndexPtr::dynamic_undefined());
|
||||||
|
|
||||||
!matches!(index.tag(), IndexPtrTag::DynamicUndefined | IndexPtrTag::Undefined)
|
!matches!(index.tag(), IndexPtrTag::DynamicUndefined | IndexPtrTag::Undefined)
|
||||||
@@ -6050,10 +6054,10 @@ impl Machine {
|
|||||||
0,
|
0,
|
||||||
module_name,
|
module_name,
|
||||||
)
|
)
|
||||||
.map(|idx| *self.machine_st
|
.map(|idx| self.machine_st
|
||||||
.arena
|
.arena
|
||||||
.code_index_tbl
|
.code_index_tbl
|
||||||
.lookup(idx.into()))
|
.get_entry(idx.into()))
|
||||||
.unwrap_or(IndexPtr::dynamic_undefined());
|
.unwrap_or(IndexPtr::dynamic_undefined());
|
||||||
|
|
||||||
!matches!(index.tag(), IndexPtrTag::DynamicUndefined)
|
!matches!(index.tag(), IndexPtrTag::DynamicUndefined)
|
||||||
@@ -7480,7 +7484,7 @@ impl Machine {
|
|||||||
self.machine_st
|
self.machine_st
|
||||||
.arena
|
.arena
|
||||||
.code_index_tbl
|
.code_index_tbl
|
||||||
.lookup(first_idx.into())
|
.get_entry(first_idx.into())
|
||||||
.local()
|
.local()
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -289,10 +289,10 @@ pub(crate) trait Unifier: DerefMut<Target = MachineState> {
|
|||||||
(HeapCellValueTag::F64Offset, f2) => {
|
(HeapCellValueTag::F64Offset, f2) => {
|
||||||
let machine_st = self.deref_mut();
|
let machine_st = self.deref_mut();
|
||||||
|
|
||||||
let f1 = *machine_st.arena.f64_tbl.lookup(f1);
|
let f1 = machine_st.arena.f64_tbl.get_entry(f1);
|
||||||
let f2 = *machine_st.arena.f64_tbl.lookup(f2.into());
|
let f2 = machine_st.arena.f64_tbl.get_entry(f2.into());
|
||||||
|
|
||||||
self.fail = *f1 != *f2;
|
self.fail = f1 != f2;
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
self.fail = true;
|
self.fail = true;
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
use std::cell::UnsafeCell;
|
use std::cell::UnsafeCell;
|
||||||
use std::hash::{Hash, Hasher};
|
use std::sync::Arc;
|
||||||
use std::ops::{Deref, DerefMut};
|
|
||||||
use std::sync::{Arc, RwLock, RwLockReadGuard};
|
|
||||||
use std::{fmt, mem, ptr};
|
use std::{fmt, mem, ptr};
|
||||||
|
|
||||||
use arcu::atomic::Arcu;
|
use arcu::atomic::Arcu;
|
||||||
use arcu::epoch_counters::GlobalEpochCounterPool;
|
use arcu::epoch_counters::GlobalEpochCounterPool;
|
||||||
use arcu::rcu_ref::RcuRef;
|
use arcu::rcu_ref::RcuRef;
|
||||||
use arcu::Rcu;
|
use arcu::Rcu;
|
||||||
|
use parking_lot::RwLock;
|
||||||
|
|
||||||
use crate::machine::machine_indices::IndexPtr;
|
use crate::machine::machine_indices::IndexPtr;
|
||||||
use crate::raw_block::RawBlock;
|
use crate::raw_block::RawBlock;
|
||||||
@@ -55,7 +54,7 @@ impl<T: RawBlockTraits> From<Arc<ConcurrentOffsetTable<T>>> for OffsetTableImpl<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: RawBlockTraits> OffsetTableImpl<T> {
|
impl<T: fmt::Debug + RawBlockTraits> OffsetTableImpl<T> {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self(InnerOffsetTableImpl::Serial(SerialOffsetTable::new()))
|
Self(InnerOffsetTableImpl::Serial(SerialOffsetTable::new()))
|
||||||
@@ -70,10 +69,17 @@ impl<T: RawBlockTraits> OffsetTableImpl<T> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let serial_tbl = mem::replace(serial_tbl, empty_serial_tbl);
|
let serial_tbl = mem::replace(serial_tbl, empty_serial_tbl);
|
||||||
|
let num_tbl_entries = serial_tbl.block.size() / size_of::<T>();
|
||||||
let block = Arcu::new(serial_tbl.block, GlobalEpochCounterPool);
|
let block = Arcu::new(serial_tbl.block, GlobalEpochCounterPool);
|
||||||
|
|
||||||
let growth_lock = RwLock::new(());
|
let offset_locks: Vec<RwLock<()>> =
|
||||||
let concurrent_tbl = Arc::new(ConcurrentOffsetTable { block, growth_lock });
|
(0..num_tbl_entries).map(|_| RwLock::new(())).collect();
|
||||||
|
|
||||||
|
let concurrent_tbl = Arc::new(ConcurrentOffsetTable {
|
||||||
|
block,
|
||||||
|
growth_lock: RwLock::new(()),
|
||||||
|
offset_locks: RwLock::new(offset_locks),
|
||||||
|
});
|
||||||
|
|
||||||
self.0 = InnerOffsetTableImpl::Concurrent(concurrent_tbl.clone());
|
self.0 = InnerOffsetTableImpl::Concurrent(concurrent_tbl.clone());
|
||||||
|
|
||||||
@@ -88,23 +94,48 @@ impl<T: RawBlockTraits> OffsetTableImpl<T> {
|
|||||||
match &mut self.0 {
|
match &mut self.0 {
|
||||||
InnerOffsetTableImpl::Serial(_serial_tbl) => Ok(()),
|
InnerOffsetTableImpl::Serial(_serial_tbl) => Ok(()),
|
||||||
InnerOffsetTableImpl::Concurrent(concurrent_tbl) => {
|
InnerOffsetTableImpl::Concurrent(concurrent_tbl) => {
|
||||||
let lock_guard = concurrent_tbl.growth_lock.write().unwrap();
|
let table_arc = std::mem::replace(
|
||||||
let raw_block = concurrent_tbl.block.replace(RawBlock::empty_block());
|
concurrent_tbl,
|
||||||
|
Arc::new(ConcurrentOffsetTable {
|
||||||
|
block: Arcu::new(RawBlock::empty_block(), GlobalEpochCounterPool),
|
||||||
|
growth_lock: RwLock::new(()),
|
||||||
|
offset_locks: RwLock::new(vec![]),
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
match Arc::try_unwrap(raw_block) {
|
match Arc::try_unwrap(table_arc) {
|
||||||
Ok(block) => {
|
Ok(table) => {
|
||||||
drop(lock_guard);
|
// this was the only instance of the concurrent table, as such
|
||||||
self.0 = InnerOffsetTableImpl::Serial(SerialOffsetTable { block });
|
// at this point no build_with/with_entry{_mut} call can be in-progress/made
|
||||||
|
|
||||||
|
// this shouldn't be able to fail
|
||||||
|
let raw_block =
|
||||||
|
Arc::try_unwrap(table.block.replace(RawBlock::empty_block())).unwrap();
|
||||||
|
self.0 =
|
||||||
|
InnerOffsetTableImpl::Serial(SerialOffsetTable { block: raw_block });
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Err(_) => Err(()),
|
Err(table_arc) => {
|
||||||
|
// restore the concurrent_tbl
|
||||||
|
*concurrent_tbl = table_arc;
|
||||||
|
Err(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: RawBlockTraits> Default for OffsetTableImpl<T> {
|
#[inline]
|
||||||
|
pub fn get_entry(&self, offset: <Self as OffsetTable<T>>::Offset) -> T
|
||||||
|
where
|
||||||
|
Self: OffsetTable<T>,
|
||||||
|
T: Copy,
|
||||||
|
{
|
||||||
|
self.with_entry(offset, |value| *value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: fmt::Debug + RawBlockTraits> Default for OffsetTableImpl<T> {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self::new()
|
Self::new()
|
||||||
}
|
}
|
||||||
@@ -119,6 +150,7 @@ struct SerialOffsetTable<T: RawBlockTraits> {
|
|||||||
pub struct ConcurrentOffsetTable<T: RawBlockTraits> {
|
pub struct ConcurrentOffsetTable<T: RawBlockTraits> {
|
||||||
block: Arcu<RawBlock<T>, GlobalEpochCounterPool>,
|
block: Arcu<RawBlock<T>, GlobalEpochCounterPool>,
|
||||||
growth_lock: RwLock<()>,
|
growth_lock: RwLock<()>,
|
||||||
|
offset_locks: RwLock<Vec<RwLock<()>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -132,42 +164,24 @@ impl<T: RawBlockTraits> InnerOffsetTableImpl<T> {
|
|||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn build_with(&mut self, value: T) -> usize {
|
fn build_with(&mut self, value: T) -> usize {
|
||||||
match self {
|
match self {
|
||||||
Self::Concurrent(concurrent_tbl) => unsafe { concurrent_tbl.build_with(value) },
|
Self::Concurrent(concurrent_tbl) => concurrent_tbl.build_with(value),
|
||||||
Self::Serial(serial_tbl) => unsafe { serial_tbl.build_with(value) },
|
Self::Serial(serial_tbl) => unsafe { serial_tbl.build_with(value) },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn lookup<'a>(&'a self, offset: usize) -> TablePtr<'a, T> {
|
fn with_entry<R, F: FnOnce(&T) -> R>(&self, offset: usize, f: F) -> R {
|
||||||
match self {
|
match self {
|
||||||
Self::Concurrent(concurrent_tbl) => TablePtr({
|
Self::Concurrent(concurrent_tbl) => concurrent_tbl.with_entry(offset, f),
|
||||||
let (rcu_ref, guard_lock) = concurrent_tbl.lookup(offset);
|
Self::Serial(serial_tbl) => f(unsafe { serial_tbl.lookup(offset) }),
|
||||||
InnerTablePtr::Concurrent {
|
|
||||||
rcu_ref,
|
|
||||||
guard_lock,
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
Self::Serial(serial_tbl) => unsafe {
|
|
||||||
TablePtr(InnerTablePtr::Serial(serial_tbl.lookup(offset)))
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn lookup_mut<'a>(&'a mut self, offset: usize) -> TablePtrMut<'a, T> {
|
fn with_entry_mut<R, F: FnOnce(&mut T) -> R>(&mut self, offset: usize, f: F) -> R {
|
||||||
match self {
|
match self {
|
||||||
InnerOffsetTableImpl::Concurrent(concurrent_tbl) => TablePtrMut({
|
Self::Concurrent(concurrent_tbl) => concurrent_tbl.with_entry_mut(offset, f),
|
||||||
let (rcu_ref, guard_lock) = concurrent_tbl.lookup_mut(offset);
|
Self::Serial(serial_tbl) => f(unsafe { serial_tbl.lookup_mut(offset) }),
|
||||||
InnerTablePtrMut::Concurrent {
|
|
||||||
rcu_ref,
|
|
||||||
guard_lock,
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
InnerOffsetTableImpl::Serial(serial_tbl) => {
|
|
||||||
TablePtrMut(InnerTablePtrMut::Serial(unsafe {
|
|
||||||
serial_tbl.lookup_mut(offset)
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -176,8 +190,9 @@ pub trait OffsetTable<T: RawBlockTraits> {
|
|||||||
type Offset: Copy + Into<usize>;
|
type Offset: Copy + Into<usize>;
|
||||||
|
|
||||||
fn build_with(&mut self, value: T) -> Self::Offset;
|
fn build_with(&mut self, value: T) -> Self::Offset;
|
||||||
fn lookup<'a>(&'a self, offset: Self::Offset) -> TablePtr<'a, T>;
|
|
||||||
fn lookup_mut<'a>(&'a mut self, offset: Self::Offset) -> TablePtrMut<'a, T>;
|
fn with_entry<R, F: FnOnce(&T) -> R>(&self, offset: Self::Offset, f: F) -> R;
|
||||||
|
fn with_entry_mut<R, F: FnOnce(&mut T) -> R>(&mut self, offset: Self::Offset, f: F) -> R;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl OffsetTable<OrderedFloat<f64>> for OffsetTableImpl<OrderedFloat<f64>> {
|
impl OffsetTable<OrderedFloat<f64>> for OffsetTableImpl<OrderedFloat<f64>> {
|
||||||
@@ -187,12 +202,18 @@ impl OffsetTable<OrderedFloat<f64>> for OffsetTableImpl<OrderedFloat<f64>> {
|
|||||||
F64Offset(self.0.build_with(value))
|
F64Offset(self.0.build_with(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lookup<'a>(&'a self, offset: F64Offset) -> TablePtr<'a, OrderedFloat<f64>> {
|
#[inline]
|
||||||
self.0.lookup(offset.into())
|
fn with_entry<R, F: FnOnce(&OrderedFloat<f64>) -> R>(&self, offset: F64Offset, f: F) -> R {
|
||||||
|
self.0.with_entry(offset.into(), f)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lookup_mut<'a>(&'a mut self, offset: F64Offset) -> TablePtrMut<'a, OrderedFloat<f64>> {
|
#[inline]
|
||||||
self.0.lookup_mut(offset.into())
|
fn with_entry_mut<R, F: FnOnce(&mut OrderedFloat<f64>) -> R>(
|
||||||
|
&mut self,
|
||||||
|
offset: F64Offset,
|
||||||
|
f: F,
|
||||||
|
) -> R {
|
||||||
|
self.0.with_entry_mut(offset.into(), f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -203,12 +224,18 @@ impl OffsetTable<IndexPtr> for OffsetTableImpl<IndexPtr> {
|
|||||||
CodeIndexOffset(self.0.build_with(value))
|
CodeIndexOffset(self.0.build_with(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lookup<'a>(&'a self, offset: CodeIndexOffset) -> TablePtr<'a, IndexPtr> {
|
#[inline]
|
||||||
self.0.lookup(offset.into())
|
fn with_entry<R, F: FnOnce(&IndexPtr) -> R>(&self, offset: CodeIndexOffset, f: F) -> R {
|
||||||
|
self.0.with_entry(offset.into(), f)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lookup_mut<'a>(&'a mut self, offset: CodeIndexOffset) -> TablePtrMut<'a, IndexPtr> {
|
#[inline]
|
||||||
self.0.lookup_mut(offset.into())
|
fn with_entry_mut<R, F: FnOnce(&mut IndexPtr) -> R>(
|
||||||
|
&mut self,
|
||||||
|
offset: CodeIndexOffset,
|
||||||
|
f: F,
|
||||||
|
) -> R {
|
||||||
|
self.0.with_entry_mut(offset.into(), f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -251,8 +278,8 @@ impl<T: RawBlockTraits> SerialOffsetTable<T> {
|
|||||||
|
|
||||||
impl<T: RawBlockTraits> ConcurrentOffsetTable<T> {
|
impl<T: RawBlockTraits> ConcurrentOffsetTable<T> {
|
||||||
#[allow(clippy::missing_safety_doc)]
|
#[allow(clippy::missing_safety_doc)]
|
||||||
unsafe fn build_with(&self, value: T) -> usize {
|
fn build_with(&self, value: T) -> usize {
|
||||||
let update_guard = self.growth_lock.write().unwrap();
|
let growth_lock = self.growth_lock.write();
|
||||||
|
|
||||||
// we don't have an index table for lookups as AtomTable does so
|
// we don't have an index table for lookups as AtomTable does so
|
||||||
// just get the epoch after we take the upgrade lock
|
// just get the epoch after we take the upgrade lock
|
||||||
@@ -260,10 +287,10 @@ impl<T: RawBlockTraits> ConcurrentOffsetTable<T> {
|
|||||||
let mut ptr;
|
let mut ptr;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
ptr = block_epoch.alloc(mem::size_of::<T>());
|
ptr = unsafe { block_epoch.alloc(mem::size_of::<T>()) };
|
||||||
|
|
||||||
if ptr.is_null() {
|
if ptr.is_null() {
|
||||||
let new_block = block_epoch.grow_new().unwrap();
|
let new_block = unsafe { block_epoch.grow_new().unwrap() };
|
||||||
self.block.replace(new_block);
|
self.block.replace(new_block);
|
||||||
block_epoch = self.block.read();
|
block_epoch = self.block.read();
|
||||||
} else {
|
} else {
|
||||||
@@ -271,35 +298,46 @@ impl<T: RawBlockTraits> ConcurrentOffsetTable<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let new_tbl_sz = block_epoch.size() / size_of::<T>();
|
||||||
|
let mut offset_locks = self.offset_locks.write();
|
||||||
|
|
||||||
|
offset_locks.resize_with(new_tbl_sz, || RwLock::new(()));
|
||||||
|
|
||||||
|
unsafe {
|
||||||
ptr::write(ptr as *mut T, value);
|
ptr::write(ptr as *mut T, value);
|
||||||
|
}
|
||||||
|
|
||||||
let value = ptr.addr() - block_epoch.base.addr();
|
let value = ptr.addr() - block_epoch.base.addr();
|
||||||
|
|
||||||
// AtomTable would have to update the index table at this point
|
// AtomTable would have to update the index table at this point
|
||||||
// explicit drop to ensure we don't accidentally drop it early
|
// explicit drop to ensure we don't accidentally drop it early
|
||||||
drop(update_guard);
|
drop(offset_locks);
|
||||||
|
drop(growth_lock);
|
||||||
|
|
||||||
value
|
value
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
fn with_entry<R, F: FnOnce(&T) -> R>(&self, offset: usize, f: F) -> R {
|
||||||
fn lookup<'a>(&'a self, offset: usize) -> (RcuRef<RawBlock<T>, T>, RwLockReadGuard<'a, ()>) {
|
let outer_offset_lock = self.offset_locks.read();
|
||||||
let growth_lock_guard = self.growth_lock.read().unwrap();
|
let inner_offset_lock = outer_offset_lock[offset / size_of::<T>()].read();
|
||||||
|
|
||||||
let rcu_ref = RcuRef::try_map(self.block.read(), |raw_block| unsafe {
|
let rcu_ref = RcuRef::try_map(self.block.read(), |raw_block| unsafe {
|
||||||
raw_block.base.add(offset).cast::<T>().as_ref()
|
raw_block.base.add(offset).cast::<T>().as_ref()
|
||||||
})
|
})
|
||||||
.expect("The offset should result in a non-null pointer");
|
.expect("offset valid");
|
||||||
|
|
||||||
(rcu_ref, growth_lock_guard)
|
let result = f(&*rcu_ref);
|
||||||
|
|
||||||
|
drop(inner_offset_lock);
|
||||||
|
drop(outer_offset_lock);
|
||||||
|
|
||||||
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
fn with_entry_mut<R, F: FnOnce(&mut T) -> R>(&self, offset: usize, f: F) -> R {
|
||||||
fn lookup_mut<'a>(
|
let growth_lock = self.growth_lock.read();
|
||||||
&'a self,
|
let outer_offset_lock = self.offset_locks.read();
|
||||||
offset: usize,
|
let inner_offset_lock = outer_offset_lock[offset / size_of::<T>()].write();
|
||||||
) -> (RcuRef<RawBlock<T>, UnsafeCell<T>>, RwLockReadGuard<'a, ()>) {
|
|
||||||
let growth_lock_guard = self.growth_lock.read().unwrap();
|
|
||||||
|
|
||||||
let rcu_ref = RcuRef::try_map(self.block.read(), |raw_block| unsafe {
|
let rcu_ref = RcuRef::try_map(self.block.read(), |raw_block| unsafe {
|
||||||
raw_block
|
raw_block
|
||||||
@@ -309,9 +347,15 @@ impl<T: RawBlockTraits> ConcurrentOffsetTable<T> {
|
|||||||
.cast::<UnsafeCell<T>>()
|
.cast::<UnsafeCell<T>>()
|
||||||
.as_ref()
|
.as_ref()
|
||||||
})
|
})
|
||||||
.expect("The offset should result in a non-null pointer");
|
.expect("offset valid");
|
||||||
|
|
||||||
(rcu_ref, growth_lock_guard)
|
let result = f(unsafe { &mut *rcu_ref.get().as_mut().unwrap() });
|
||||||
|
|
||||||
|
drop(inner_offset_lock);
|
||||||
|
drop(outer_offset_lock);
|
||||||
|
drop(growth_lock);
|
||||||
|
|
||||||
|
result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -358,64 +402,6 @@ impl CodeIndexOffset {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct TablePtr<'a, T: RawBlockTraits>(InnerTablePtr<'a, T>);
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
enum InnerTablePtr<'a, T: RawBlockTraits> {
|
|
||||||
Concurrent {
|
|
||||||
rcu_ref: RcuRef<RawBlock<T>, T>,
|
|
||||||
#[allow(dead_code)]
|
|
||||||
guard_lock: RwLockReadGuard<'a, ()>,
|
|
||||||
},
|
|
||||||
Serial(&'a T),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: PartialEq + RawBlockTraits> PartialEq for TablePtr<'_, T> {
|
|
||||||
fn eq(&self, other: &TablePtr<'_, T>) -> bool {
|
|
||||||
self.deref() == other.deref()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Eq + RawBlockTraits> Eq for TablePtr<'_, T> {}
|
|
||||||
|
|
||||||
impl<T: PartialOrd + Ord + RawBlockTraits> PartialOrd for TablePtr<'_, T> {
|
|
||||||
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
|
||||||
Some(self.cmp(other))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Ord + RawBlockTraits> Ord for TablePtr<'_, T> {
|
|
||||||
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
|
|
||||||
(**self).cmp(&**other)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Hash + RawBlockTraits> Hash for TablePtr<'_, T> {
|
|
||||||
#[inline(always)]
|
|
||||||
fn hash<H: Hasher>(&self, hasher: &mut H) {
|
|
||||||
(self as &T).hash(hasher)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: fmt::Display + RawBlockTraits> fmt::Display for TablePtr<'_, T> {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
write!(f, "{}", self as &T)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: RawBlockTraits> Deref for TablePtr<'_, T> {
|
|
||||||
type Target = T;
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn deref(&self) -> &Self::Target {
|
|
||||||
match &self.0 {
|
|
||||||
InnerTablePtr::Concurrent { rcu_ref, .. } => rcu_ref,
|
|
||||||
InnerTablePtr::Serial(ref_mut) => ref_mut,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for CodeIndexOffset {
|
impl fmt::Display for CodeIndexOffset {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(f, "CodeIndexOffset({})", self.0)
|
write!(f, "CodeIndexOffset({})", self.0)
|
||||||
@@ -434,97 +420,3 @@ impl fmt::Display for F64Offset {
|
|||||||
write!(f, "F64Offset({})", self.0)
|
write!(f, "F64Offset({})", self.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct TablePtrMut<'a, T: RawBlockTraits>(InnerTablePtrMut<'a, T>);
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
enum InnerTablePtrMut<'a, T: RawBlockTraits> {
|
|
||||||
Concurrent {
|
|
||||||
rcu_ref: RcuRef<RawBlock<T>, UnsafeCell<T>>,
|
|
||||||
#[allow(dead_code)]
|
|
||||||
guard_lock: RwLockReadGuard<'a, ()>,
|
|
||||||
},
|
|
||||||
Serial(&'a mut T),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: PartialEq + RawBlockTraits> PartialEq for TablePtrMut<'_, T> {
|
|
||||||
fn eq(&self, other: &TablePtrMut<'_, T>) -> bool {
|
|
||||||
self.deref() == other.deref()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Eq + RawBlockTraits> Eq for TablePtrMut<'_, T> {}
|
|
||||||
|
|
||||||
impl<T: PartialOrd + Ord + RawBlockTraits> PartialOrd for TablePtrMut<'_, T> {
|
|
||||||
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
|
||||||
Some(self.cmp(other))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Ord + RawBlockTraits> Ord for TablePtrMut<'_, T> {
|
|
||||||
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
|
|
||||||
(**self).cmp(&**other)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Hash + RawBlockTraits> Hash for TablePtrMut<'_, T> {
|
|
||||||
#[inline(always)]
|
|
||||||
fn hash<H: Hasher>(&self, hasher: &mut H) {
|
|
||||||
(self as &T).hash(hasher)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: fmt::Display + RawBlockTraits> fmt::Display for TablePtrMut<'_, T> {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
write!(f, "{}", self as &T)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: RawBlockTraits> Deref for TablePtrMut<'_, T> {
|
|
||||||
type Target = T;
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn deref(&self) -> &Self::Target {
|
|
||||||
match &self.0 {
|
|
||||||
InnerTablePtrMut::Concurrent { rcu_ref, .. } => unsafe {
|
|
||||||
rcu_ref.get().as_ref().unwrap()
|
|
||||||
},
|
|
||||||
InnerTablePtrMut::Serial(ref_mut) => ref_mut,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: RawBlockTraits> DerefMut for TablePtrMut<'_, T> {
|
|
||||||
#[inline]
|
|
||||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
|
||||||
match &mut self.0 {
|
|
||||||
InnerTablePtrMut::Concurrent { rcu_ref, .. } => unsafe {
|
|
||||||
&mut *rcu_ref.get().as_mut().unwrap()
|
|
||||||
},
|
|
||||||
InnerTablePtrMut::Serial(ref_mut) => ref_mut,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TablePtrMut<'_, IndexPtr> {
|
|
||||||
#[inline]
|
|
||||||
pub fn set(&mut self, val: IndexPtr) {
|
|
||||||
match &mut self.0 {
|
|
||||||
InnerTablePtrMut::Concurrent { rcu_ref, .. } => unsafe {
|
|
||||||
*rcu_ref.get() = val;
|
|
||||||
},
|
|
||||||
InnerTablePtrMut::Serial(ref_mut) => {
|
|
||||||
**ref_mut = val;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn replace(&mut self, val: IndexPtr) -> IndexPtr {
|
|
||||||
match &mut self.0 {
|
|
||||||
InnerTablePtrMut::Concurrent { rcu_ref, .. } => unsafe { rcu_ref.get().replace(val) },
|
|
||||||
InnerTablePtrMut::Serial(ref_mut) => mem::replace(*ref_mut, val),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -962,14 +962,14 @@ impl<'a, R: CharRead> Parser<'a, R> {
|
|||||||
Token::Literal(Literal::Rational(n)) => {
|
Token::Literal(Literal::Rational(n)) => {
|
||||||
self.negate_number(n, negate_rat_rc, |r, _| Literal::Rational(r))
|
self.negate_number(n, negate_rat_rc, |r, _| Literal::Rational(r))
|
||||||
}
|
}
|
||||||
Token::Literal(Literal::F64Offset(n)) if self.lexer.machine_st.arena.f64_tbl.lookup(n).is_infinite() => {
|
Token::Literal(Literal::F64Offset(n)) if self.lexer.machine_st.arena.f64_tbl.get_entry(n).is_infinite() => {
|
||||||
return Err(ParserError::InfiniteFloat(
|
return Err(ParserError::InfiniteFloat(
|
||||||
self.lexer.line_num,
|
self.lexer.line_num,
|
||||||
self.lexer.col_num,
|
self.lexer.col_num,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
Token::Literal(Literal::F64Offset(n)) => {
|
Token::Literal(Literal::F64Offset(n)) => {
|
||||||
let n = *self.lexer.machine_st.arena.f64_tbl.lookup(n);
|
let n = self.lexer.machine_st.arena.f64_tbl.get_entry(n);
|
||||||
|
|
||||||
self.negate_number(
|
self.negate_number(
|
||||||
n,
|
n,
|
||||||
|
|||||||
Reference in New Issue
Block a user