Merge pull request #2393 from mthom/unsafe_improvements
Improve use of unsafe Rust in arena.rs (#2391)
This commit is contained in:
1
.github/workflows/ci.yml
vendored
1
.github/workflows/ci.yml
vendored
@@ -47,7 +47,6 @@ jobs:
|
|||||||
# FIXME(issue #2138): run wasm tests, failing to run since https://github.com/mthom/scryer-prolog/pull/2137 removed wasm-pack
|
# FIXME(issue #2138): run wasm tests, failing to run since https://github.com/mthom/scryer-prolog/pull/2137 removed wasm-pack
|
||||||
- { os: ubuntu-22.04, rust-version: nightly, target: 'wasm32-unknown-unknown', publish: true, args: '--no-default-features' , test-args: '--no-run --no-default-features' }
|
- { os: ubuntu-22.04, rust-version: nightly, target: 'wasm32-unknown-unknown', publish: true, args: '--no-default-features' , test-args: '--no-run --no-default-features' }
|
||||||
# rust versions
|
# rust versions
|
||||||
- { os: ubuntu-22.04, rust-version: "1.70", target: 'x86_64-unknown-linux-gnu'}
|
|
||||||
- { os: ubuntu-22.04, rust-version: beta, target: 'x86_64-unknown-linux-gnu'}
|
- { os: ubuntu-22.04, rust-version: beta, target: 'x86_64-unknown-linux-gnu'}
|
||||||
- { os: ubuntu-22.04, rust-version: nightly, target: 'x86_64-unknown-linux-gnu'}
|
- { os: ubuntu-22.04, rust-version: nightly, target: 'x86_64-unknown-linux-gnu'}
|
||||||
defaults:
|
defaults:
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ license = "BSD-3-Clause"
|
|||||||
keywords = ["prolog", "prolog-interpreter", "prolog-system"]
|
keywords = ["prolog", "prolog-interpreter", "prolog-system"]
|
||||||
categories = ["command-line-utilities"]
|
categories = ["command-line-utilities"]
|
||||||
build = "build/main.rs"
|
build = "build/main.rs"
|
||||||
rust-version = "1.70"
|
rust-version = "1.77"
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
crate-type = ["cdylib", "rlib"]
|
crate-type = ["cdylib", "rlib"]
|
||||||
|
|||||||
313
src/arena.rs
313
src/arena.rs
@@ -11,7 +11,6 @@ use crate::read::*;
|
|||||||
use crate::parser::dashu::{Integer, Rational};
|
use crate::parser::dashu::{Integer, Rational};
|
||||||
use ordered_float::OrderedFloat;
|
use ordered_float::OrderedFloat;
|
||||||
|
|
||||||
use std::alloc;
|
|
||||||
use std::cell::UnsafeCell;
|
use std::cell::UnsafeCell;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::hash::{Hash, Hasher};
|
use std::hash::{Hash, Hasher};
|
||||||
@@ -25,10 +24,7 @@ use std::sync::RwLock;
|
|||||||
macro_rules! arena_alloc {
|
macro_rules! arena_alloc {
|
||||||
($e:expr, $arena:expr) => {{
|
($e:expr, $arena:expr) => {{
|
||||||
let result = $e;
|
let result = $e;
|
||||||
#[allow(unused_unsafe)]
|
|
||||||
unsafe {
|
|
||||||
ArenaAllocated::alloc($arena, result)
|
ArenaAllocated::alloc($arena, result)
|
||||||
}
|
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,13 +32,33 @@ macro_rules! arena_alloc {
|
|||||||
macro_rules! float_alloc {
|
macro_rules! float_alloc {
|
||||||
($e:expr, $arena:expr) => {{
|
($e:expr, $arena:expr) => {{
|
||||||
let result = $e;
|
let result = $e;
|
||||||
#[allow(unused_unsafe)]
|
unsafe { $arena.f64_tbl.build_with(result).as_ptr() }
|
||||||
unsafe {
|
|
||||||
$arena.f64_tbl.build_with(result).as_ptr()
|
|
||||||
}
|
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn header_offset_from_payload<Payload: Sized>() -> usize {
|
||||||
|
let payload_offset = mem::offset_of!(TypedAllocSlab<Payload>, payload);
|
||||||
|
let slab_offset = mem::offset_of!(TypedAllocSlab<Payload>, slab);
|
||||||
|
let header_offset = slab_offset + mem::offset_of!(AllocSlab, header);
|
||||||
|
|
||||||
|
debug_assert!(payload_offset > header_offset);
|
||||||
|
payload_offset - header_offset
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn ptr_to_allocated<Payload: ArenaAllocated>(slab: &mut AllocSlab) -> TypedArenaPtr<Payload> {
|
||||||
|
let typed_slab: &mut TypedAllocSlab<Payload> = unsafe { mem::transmute(slab) };
|
||||||
|
typed_slab.to_typed_arena_ptr()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! gen_ptr_to_allocated {
|
||||||
|
($payload: ty) => {
|
||||||
|
fn ptr_to_allocated(slab: &mut AllocSlab) -> TypedArenaPtr<$payload> {
|
||||||
|
ptr_to_allocated::<$payload>(slab)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
use std::sync::Weak;
|
use std::sync::Weak;
|
||||||
@@ -196,6 +212,7 @@ pub enum ArenaHeaderTag {
|
|||||||
#[bitfield]
|
#[bitfield]
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
pub struct ArenaHeader {
|
pub struct ArenaHeader {
|
||||||
|
#[allow(dead_code)]
|
||||||
size: B56,
|
size: B56,
|
||||||
m: bool,
|
m: bool,
|
||||||
tag: ArenaHeaderTag,
|
tag: ArenaHeaderTag,
|
||||||
@@ -291,16 +308,12 @@ impl<T: ?Sized + ArenaAllocated> TypedArenaPtr<T> {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn header_ptr(&self) -> *const ArenaHeader {
|
pub fn header_ptr(&self) -> *const ArenaHeader {
|
||||||
let mut ptr = self.as_ptr() as *const u8 as usize;
|
unsafe { self.as_ptr().byte_sub(T::header_offset_from_payload()) as *const _ }
|
||||||
ptr -= T::header_offset_from_payload(); // mem::size_of::<*const ArenaHeader>();
|
|
||||||
ptr as *const ArenaHeader
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn header_ptr_mut(&mut self) -> *mut ArenaHeader {
|
fn header_ptr_mut(&mut self) -> *mut ArenaHeader {
|
||||||
let mut ptr = self.as_ptr() as *const u8 as usize;
|
unsafe { self.as_ptr().byte_sub(T::header_offset_from_payload()) as *mut _ }
|
||||||
ptr -= T::header_offset_from_payload(); // mem::size_of::<*const ArenaHeader>();
|
|
||||||
ptr as *mut ArenaHeader
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@@ -339,35 +352,31 @@ pub trait ArenaAllocated: Sized {
|
|||||||
type PtrToAllocated;
|
type PtrToAllocated;
|
||||||
|
|
||||||
fn tag() -> ArenaHeaderTag;
|
fn tag() -> ArenaHeaderTag;
|
||||||
fn size(&self) -> usize;
|
fn ptr_to_allocated(slab: &mut AllocSlab) -> Self::PtrToAllocated;
|
||||||
fn copy_to_arena(self, dst: *mut Self) -> Self::PtrToAllocated;
|
|
||||||
|
|
||||||
fn header_offset_from_payload() -> usize {
|
fn header_offset_from_payload() -> usize {
|
||||||
mem::size_of::<ArenaHeader>()
|
header_offset_from_payload::<Self>()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::missing_safety_doc)]
|
#[allow(clippy::missing_safety_doc)]
|
||||||
unsafe fn alloc(arena: &mut Arena, value: Self) -> Self::PtrToAllocated {
|
fn alloc(arena: &mut Arena, value: Self) -> Self::PtrToAllocated {
|
||||||
let size = value.size() + mem::size_of::<AllocSlab>();
|
let size = mem::size_of::<TypedAllocSlab<Self>>();
|
||||||
|
let slab = Box::new(TypedAllocSlab {
|
||||||
|
slab: AllocSlab {
|
||||||
|
next: arena.base.take(),
|
||||||
#[cfg(target_pointer_width = "32")]
|
#[cfg(target_pointer_width = "32")]
|
||||||
let align = mem::align_of::<AllocSlab>() * 2;
|
_padding: 0,
|
||||||
|
header: ArenaHeader::build_with(size as u64, Self::tag()),
|
||||||
|
},
|
||||||
|
payload: value,
|
||||||
|
});
|
||||||
|
|
||||||
#[cfg(target_pointer_width = "64")]
|
let mut untyped_slab = unsafe { Box::from_raw(Box::into_raw(slab) as *mut AllocSlab) };
|
||||||
let align = mem::align_of::<AllocSlab>();
|
let allocated_ptr = Self::ptr_to_allocated(untyped_slab.as_mut());
|
||||||
let layout = alloc::Layout::from_size_align_unchecked(size, align);
|
|
||||||
|
|
||||||
let slab = alloc::alloc(layout) as *mut AllocSlab;
|
arena.base = Some(untyped_slab);
|
||||||
|
|
||||||
(*slab).next = arena.base;
|
allocated_ptr
|
||||||
(*slab).header = ArenaHeader::build_with(value.size() as u64, Self::tag());
|
|
||||||
|
|
||||||
let offset = (*slab).payload_offset();
|
|
||||||
let result = value.copy_to_arena(offset);
|
|
||||||
|
|
||||||
arena.base = slab;
|
|
||||||
|
|
||||||
result
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -505,141 +514,69 @@ impl fmt::Display for F64Offset {
|
|||||||
impl ArenaAllocated for Integer {
|
impl ArenaAllocated for Integer {
|
||||||
type PtrToAllocated = TypedArenaPtr<Integer>;
|
type PtrToAllocated = TypedArenaPtr<Integer>;
|
||||||
|
|
||||||
|
gen_ptr_to_allocated!(Integer);
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn tag() -> ArenaHeaderTag {
|
fn tag() -> ArenaHeaderTag {
|
||||||
ArenaHeaderTag::Integer
|
ArenaHeaderTag::Integer
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn size(&self) -> usize {
|
|
||||||
mem::size_of::<Self>()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(clippy::not_unsafe_ptr_arg_deref)]
|
|
||||||
#[inline]
|
|
||||||
fn copy_to_arena(self, dst: *mut Self) -> Self::PtrToAllocated {
|
|
||||||
unsafe {
|
|
||||||
ptr::write(dst, self);
|
|
||||||
TypedArenaPtr::new(dst)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ArenaAllocated for Rational {
|
impl ArenaAllocated for Rational {
|
||||||
type PtrToAllocated = TypedArenaPtr<Rational>;
|
type PtrToAllocated = TypedArenaPtr<Rational>;
|
||||||
|
|
||||||
|
gen_ptr_to_allocated!(Rational);
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn tag() -> ArenaHeaderTag {
|
fn tag() -> ArenaHeaderTag {
|
||||||
ArenaHeaderTag::Rational
|
ArenaHeaderTag::Rational
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn size(&self) -> usize {
|
|
||||||
mem::size_of::<Self>()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(clippy::not_unsafe_ptr_arg_deref)]
|
|
||||||
#[inline]
|
|
||||||
fn copy_to_arena(self, dst: *mut Self) -> Self::PtrToAllocated {
|
|
||||||
unsafe {
|
|
||||||
ptr::write(dst, self);
|
|
||||||
TypedArenaPtr::new(dst)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ArenaAllocated for LiveLoadState {
|
impl ArenaAllocated for LiveLoadState {
|
||||||
type PtrToAllocated = TypedArenaPtr<LiveLoadState>;
|
type PtrToAllocated = TypedArenaPtr<LiveLoadState>;
|
||||||
|
|
||||||
|
gen_ptr_to_allocated!(LiveLoadState);
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn tag() -> ArenaHeaderTag {
|
fn tag() -> ArenaHeaderTag {
|
||||||
ArenaHeaderTag::LiveLoadState
|
ArenaHeaderTag::LiveLoadState
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn size(&self) -> usize {
|
|
||||||
mem::size_of::<Self>()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(clippy::not_unsafe_ptr_arg_deref)]
|
|
||||||
#[inline]
|
|
||||||
fn copy_to_arena(self, dst: *mut Self) -> Self::PtrToAllocated {
|
|
||||||
unsafe {
|
|
||||||
ptr::write(dst, self);
|
|
||||||
TypedArenaPtr::new(dst)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ArenaAllocated for TcpListener {
|
impl ArenaAllocated for TcpListener {
|
||||||
type PtrToAllocated = TypedArenaPtr<TcpListener>;
|
type PtrToAllocated = TypedArenaPtr<TcpListener>;
|
||||||
|
|
||||||
|
gen_ptr_to_allocated!(TcpListener);
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn tag() -> ArenaHeaderTag {
|
fn tag() -> ArenaHeaderTag {
|
||||||
ArenaHeaderTag::TcpListener
|
ArenaHeaderTag::TcpListener
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn size(&self) -> usize {
|
|
||||||
mem::size_of::<Self>()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(clippy::not_unsafe_ptr_arg_deref)]
|
|
||||||
#[inline]
|
|
||||||
fn copy_to_arena(self, dst: *mut Self) -> Self::PtrToAllocated {
|
|
||||||
unsafe {
|
|
||||||
ptr::write(dst, self);
|
|
||||||
TypedArenaPtr::new(dst)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "http")]
|
#[cfg(feature = "http")]
|
||||||
impl ArenaAllocated for HttpListener {
|
impl ArenaAllocated for HttpListener {
|
||||||
type PtrToAllocated = TypedArenaPtr<HttpListener>;
|
type PtrToAllocated = TypedArenaPtr<HttpListener>;
|
||||||
|
|
||||||
|
gen_ptr_to_allocated!(HttpListener);
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn tag() -> ArenaHeaderTag {
|
fn tag() -> ArenaHeaderTag {
|
||||||
ArenaHeaderTag::HttpListener
|
ArenaHeaderTag::HttpListener
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn size(&self) -> usize {
|
|
||||||
mem::size_of::<Self>()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(clippy::not_unsafe_ptr_arg_deref)]
|
|
||||||
#[inline]
|
|
||||||
fn copy_to_arena(self, dst: *mut Self) -> Self::PtrToAllocated {
|
|
||||||
unsafe {
|
|
||||||
ptr::write(dst, self);
|
|
||||||
TypedArenaPtr::new(dst)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "http")]
|
#[cfg(feature = "http")]
|
||||||
impl ArenaAllocated for HttpResponse {
|
impl ArenaAllocated for HttpResponse {
|
||||||
type PtrToAllocated = TypedArenaPtr<HttpResponse>;
|
type PtrToAllocated = TypedArenaPtr<HttpResponse>;
|
||||||
|
|
||||||
|
gen_ptr_to_allocated!(HttpResponse);
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn tag() -> ArenaHeaderTag {
|
fn tag() -> ArenaHeaderTag {
|
||||||
ArenaHeaderTag::HttpResponse
|
ArenaHeaderTag::HttpResponse
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn size(&self) -> usize {
|
|
||||||
mem::size_of::<Self>()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(clippy::not_unsafe_ptr_arg_deref)]
|
|
||||||
#[inline]
|
|
||||||
fn copy_to_arena(self, dst: *mut Self) -> Self::PtrToAllocated {
|
|
||||||
unsafe {
|
|
||||||
ptr::write(dst, self);
|
|
||||||
TypedArenaPtr::new(dst)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ArenaAllocated for IndexPtr {
|
impl ArenaAllocated for IndexPtr {
|
||||||
@@ -651,17 +588,8 @@ impl ArenaAllocated for IndexPtr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn size(&self) -> usize {
|
fn ptr_to_allocated(slab: &mut AllocSlab) -> Self::PtrToAllocated {
|
||||||
mem::size_of::<Self>()
|
TypedArenaPtr::new(ptr::addr_of_mut!(slab.header) as *mut _)
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(clippy::not_unsafe_ptr_arg_deref)]
|
|
||||||
#[inline]
|
|
||||||
fn copy_to_arena(self, dst: *mut Self) -> Self::PtrToAllocated {
|
|
||||||
unsafe {
|
|
||||||
ptr::write(dst, self);
|
|
||||||
TypedArenaPtr::new(dst)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@@ -669,38 +597,48 @@ impl ArenaAllocated for IndexPtr {
|
|||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn alloc(arena: &mut Arena, value: Self) -> Self::PtrToAllocated {
|
#[inline]
|
||||||
let size = mem::size_of::<AllocSlab>();
|
fn alloc(arena: &mut Arena, value: Self) -> Self::PtrToAllocated {
|
||||||
|
let mut slab = Box::new(AllocSlab {
|
||||||
|
next: arena.base.take(),
|
||||||
|
#[cfg(target_pointer_width = "32")]
|
||||||
|
_padding: 0,
|
||||||
|
header: unsafe { mem::transmute(value) },
|
||||||
|
});
|
||||||
|
|
||||||
let align = mem::align_of::<AllocSlab>();
|
let allocated_ptr =
|
||||||
let layout = alloc::Layout::from_size_align_unchecked(size, align);
|
TypedArenaPtr::new(unsafe { mem::transmute(ptr::addr_of_mut!(slab.header)) });
|
||||||
|
arena.base = Some(slab);
|
||||||
let slab = alloc::alloc(layout) as *mut AllocSlab;
|
allocated_ptr
|
||||||
|
|
||||||
(*slab).next = arena.base;
|
|
||||||
|
|
||||||
let result = value.copy_to_arena(
|
|
||||||
&(*slab).header as *const crate::arena::ArenaHeader
|
|
||||||
as *mut crate::machine::machine_indices::IndexPtr,
|
|
||||||
);
|
|
||||||
arena.base = slab;
|
|
||||||
|
|
||||||
result
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
struct AllocSlab {
|
pub struct AllocSlab {
|
||||||
next: *mut AllocSlab,
|
next: Option<Box<AllocSlab>>,
|
||||||
#[cfg(target_pointer_width = "32")]
|
#[cfg(target_pointer_width = "32")]
|
||||||
_padding: u32,
|
_padding: u32,
|
||||||
header: ArenaHeader,
|
header: ArenaHeader,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct TypedAllocSlab<Payload> {
|
||||||
|
slab: AllocSlab,
|
||||||
|
payload: Payload,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<Payload: ArenaAllocated> TypedAllocSlab<Payload> {
|
||||||
|
#[inline]
|
||||||
|
pub fn to_typed_arena_ptr(&mut self) -> TypedArenaPtr<Payload> {
|
||||||
|
TypedArenaPtr::new(&mut self.payload as *mut _)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Arena {
|
pub struct Arena {
|
||||||
base: *mut AllocSlab,
|
base: Option<Box<AllocSlab>>,
|
||||||
pub f64_tbl: Arc<F64Table>,
|
pub f64_tbl: Arc<F64Table>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -712,72 +650,77 @@ impl Arena {
|
|||||||
#[inline]
|
#[inline]
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Arena {
|
Arena {
|
||||||
base: ptr::null_mut(),
|
base: None,
|
||||||
f64_tbl: F64Table::new(),
|
f64_tbl: F64Table::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn drop_slab_in_place(value: &mut AllocSlab) {
|
unsafe fn drop_slab_in_place(value: &mut AllocSlab) {
|
||||||
use crate::parser::char_reader::CharReader;
|
macro_rules! drop_typed_slab_in_place {
|
||||||
|
($payload: ty, $value: expr) => {
|
||||||
|
let slab: &mut TypedAllocSlab<$payload> = mem::transmute($value);
|
||||||
|
ptr::drop_in_place(&mut slab.payload);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
match value.header.tag() {
|
match value.header.tag() {
|
||||||
ArenaHeaderTag::Integer => {
|
ArenaHeaderTag::Integer => {
|
||||||
ptr::drop_in_place(value.payload_offset::<Integer>());
|
drop_typed_slab_in_place!(Integer, value);
|
||||||
}
|
}
|
||||||
ArenaHeaderTag::Rational => {
|
ArenaHeaderTag::Rational => {
|
||||||
ptr::drop_in_place(value.payload_offset::<Rational>());
|
drop_typed_slab_in_place!(Rational, value);
|
||||||
}
|
}
|
||||||
ArenaHeaderTag::InputFileStream => {
|
ArenaHeaderTag::InputFileStream => {
|
||||||
ptr::drop_in_place(value.payload_offset::<StreamLayout<CharReader<InputFileStream>>>());
|
drop_typed_slab_in_place!(InputFileStream, value);
|
||||||
}
|
}
|
||||||
ArenaHeaderTag::OutputFileStream => {
|
ArenaHeaderTag::OutputFileStream => {
|
||||||
ptr::drop_in_place(value.payload_offset::<StreamLayout<OutputFileStream>>());
|
drop_typed_slab_in_place!(OutputFileStream, value);
|
||||||
}
|
}
|
||||||
ArenaHeaderTag::NamedTcpStream => {
|
ArenaHeaderTag::NamedTcpStream => {
|
||||||
ptr::drop_in_place(value.payload_offset::<StreamLayout<CharReader<NamedTcpStream>>>());
|
drop_typed_slab_in_place!(NamedTcpStream, value);
|
||||||
}
|
}
|
||||||
ArenaHeaderTag::NamedTlsStream => {
|
ArenaHeaderTag::NamedTlsStream => {
|
||||||
#[cfg(feature = "tls")]
|
#[cfg(feature = "tls")]
|
||||||
ptr::drop_in_place(value.payload_offset::<StreamLayout<CharReader<NamedTlsStream>>>());
|
drop_typed_slab_in_place!(NamedTlsStream, value);
|
||||||
}
|
}
|
||||||
ArenaHeaderTag::HttpReadStream => {
|
ArenaHeaderTag::HttpReadStream => {
|
||||||
#[cfg(feature = "http")]
|
#[cfg(feature = "http")]
|
||||||
ptr::drop_in_place(value.payload_offset::<StreamLayout<CharReader<HttpReadStream>>>());
|
drop_typed_slab_in_place!(HttpReadStream, value);
|
||||||
}
|
}
|
||||||
ArenaHeaderTag::HttpWriteStream => {
|
ArenaHeaderTag::HttpWriteStream => {
|
||||||
#[cfg(feature = "http")]
|
#[cfg(feature = "http")]
|
||||||
ptr::drop_in_place(value.payload_offset::<StreamLayout<CharReader<HttpWriteStream>>>());
|
drop_typed_slab_in_place!(HttpWriteStream, value);
|
||||||
}
|
}
|
||||||
ArenaHeaderTag::ReadlineStream => {
|
ArenaHeaderTag::ReadlineStream => {
|
||||||
ptr::drop_in_place(value.payload_offset::<StreamLayout<ReadlineStream>>());
|
drop_typed_slab_in_place!(ReadlineStream, value);
|
||||||
}
|
}
|
||||||
ArenaHeaderTag::StaticStringStream => {
|
ArenaHeaderTag::StaticStringStream => {
|
||||||
ptr::drop_in_place(value.payload_offset::<StreamLayout<StaticStringStream>>());
|
drop_typed_slab_in_place!(StaticStringStream, value);
|
||||||
}
|
}
|
||||||
ArenaHeaderTag::ByteStream => {
|
ArenaHeaderTag::ByteStream => {
|
||||||
ptr::drop_in_place(value.payload_offset::<StreamLayout<CharReader<ByteStream>>>());
|
drop_typed_slab_in_place!(ByteStream, value);
|
||||||
}
|
}
|
||||||
ArenaHeaderTag::LiveLoadState | ArenaHeaderTag::InactiveLoadState => {
|
ArenaHeaderTag::LiveLoadState | ArenaHeaderTag::InactiveLoadState => {
|
||||||
ptr::drop_in_place(value.payload_offset::<LiveLoadState>());
|
drop_typed_slab_in_place!(LiveLoadState, value);
|
||||||
}
|
}
|
||||||
ArenaHeaderTag::Dropped => {}
|
ArenaHeaderTag::Dropped => {}
|
||||||
ArenaHeaderTag::TcpListener => {
|
ArenaHeaderTag::TcpListener => {
|
||||||
ptr::drop_in_place(value.payload_offset::<TcpListener>());
|
drop_typed_slab_in_place!(TcpListener, value);
|
||||||
}
|
}
|
||||||
ArenaHeaderTag::HttpListener => {
|
ArenaHeaderTag::HttpListener => {
|
||||||
#[cfg(feature = "http")]
|
#[cfg(feature = "http")]
|
||||||
ptr::drop_in_place(value.payload_offset::<HttpListener>());
|
drop_typed_slab_in_place!(HttpListener, value);
|
||||||
}
|
}
|
||||||
ArenaHeaderTag::HttpResponse => {
|
ArenaHeaderTag::HttpResponse => {
|
||||||
#[cfg(feature = "http")]
|
#[cfg(feature = "http")]
|
||||||
ptr::drop_in_place(value.payload_offset::<HttpResponse>());
|
drop_typed_slab_in_place!(HttpResponse, value);
|
||||||
}
|
}
|
||||||
ArenaHeaderTag::StandardOutputStream => {
|
ArenaHeaderTag::StandardOutputStream => {
|
||||||
ptr::drop_in_place(value.payload_offset::<StreamLayout<StandardOutputStream>>());
|
drop_typed_slab_in_place!(StandardOutputStream, value);
|
||||||
}
|
}
|
||||||
ArenaHeaderTag::StandardErrorStream => {
|
ArenaHeaderTag::StandardErrorStream => {
|
||||||
ptr::drop_in_place(value.payload_offset::<StreamLayout<StandardErrorStream>>());
|
drop_typed_slab_in_place!(StandardErrorStream, value);
|
||||||
}
|
}
|
||||||
ArenaHeaderTag::NullStream
|
ArenaHeaderTag::NullStream
|
||||||
| ArenaHeaderTag::IndexPtrUndefined
|
| ArenaHeaderTag::IndexPtrUndefined
|
||||||
@@ -789,44 +732,18 @@ unsafe fn drop_slab_in_place(value: &mut AllocSlab) {
|
|||||||
|
|
||||||
impl Drop for Arena {
|
impl Drop for Arena {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
let mut ptr = self.base;
|
let mut ptr = self.base.take();
|
||||||
|
|
||||||
while !ptr.is_null() {
|
while let Some(mut slab) = ptr {
|
||||||
unsafe {
|
unsafe {
|
||||||
let ptr_r = &*ptr;
|
drop_slab_in_place(&mut slab);
|
||||||
|
ptr = slab.next;
|
||||||
let layout = alloc::Layout::from_size_align_unchecked(
|
|
||||||
ptr_r.slab_size(),
|
|
||||||
mem::align_of::<AllocSlab>(),
|
|
||||||
);
|
|
||||||
|
|
||||||
drop_slab_in_place(&mut *ptr);
|
|
||||||
|
|
||||||
let next_ptr = ptr_r.next;
|
|
||||||
alloc::dealloc(ptr as *mut u8, layout);
|
|
||||||
ptr = next_ptr;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.base = ptr::null_mut();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const_assert!(mem::size_of::<AllocSlab>() == 16);
|
const_assert!(mem::size_of::<AllocSlab>() == 16);
|
||||||
|
|
||||||
impl AllocSlab {
|
|
||||||
#[inline]
|
|
||||||
fn slab_size(&self) -> usize {
|
|
||||||
self.header.size() as usize + mem::size_of::<AllocSlab>()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn payload_offset<T>(&self) -> *mut T {
|
|
||||||
// This looks really scary, should this method be marked as unsafe?
|
|
||||||
// Also, this seems to cause UB.
|
|
||||||
unsafe { (self as *const AllocSlab).add(1) as *mut T }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const_assert!(mem::size_of::<OrderedFloat<f64>>() == 8);
|
const_assert!(mem::size_of::<OrderedFloat<f64>>() == 8);
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
@@ -298,9 +298,11 @@ impl IndexStore {
|
|||||||
_ => self
|
_ => self
|
||||||
.get_meta_predicate_spec(key.0, key.1, &compilation_target)
|
.get_meta_predicate_spec(key.0, key.1, &compilation_target)
|
||||||
.map(|meta_specs| {
|
.map(|meta_specs| {
|
||||||
meta_specs.iter().find(|meta_spec| match meta_spec {
|
meta_specs.iter().find(|meta_spec| {
|
||||||
MetaSpec::Colon | MetaSpec::RequiresExpansionWithArgument(_) => true,
|
matches!(
|
||||||
_ => false,
|
meta_spec,
|
||||||
|
MetaSpec::Colon | MetaSpec::RequiresExpansionWithArgument(_)
|
||||||
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.map(|meta_spec_opt| meta_spec_opt.is_some())
|
.map(|meta_spec_opt| meta_spec_opt.is_some())
|
||||||
|
|||||||
@@ -455,25 +455,12 @@ macro_rules! arena_allocated_impl_for_stream {
|
|||||||
impl ArenaAllocated for StreamLayout<$stream_type> {
|
impl ArenaAllocated for StreamLayout<$stream_type> {
|
||||||
type PtrToAllocated = TypedArenaPtr<StreamLayout<$stream_type>>;
|
type PtrToAllocated = TypedArenaPtr<StreamLayout<$stream_type>>;
|
||||||
|
|
||||||
|
gen_ptr_to_allocated!(StreamLayout<$stream_type>);
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn tag() -> ArenaHeaderTag {
|
fn tag() -> ArenaHeaderTag {
|
||||||
ArenaHeaderTag::$stream_tag
|
ArenaHeaderTag::$stream_tag
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn size(&self) -> usize {
|
|
||||||
mem::size_of::<StreamLayout<$stream_type>>()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(clippy::not_unsafe_ptr_arg_deref)]
|
|
||||||
#[inline]
|
|
||||||
fn copy_to_arena(self, dst: *mut Self) -> Self::PtrToAllocated {
|
|
||||||
unsafe {
|
|
||||||
// Miri seems to hit this a lot
|
|
||||||
ptr::write(dst, self);
|
|
||||||
TypedArenaPtr::new(dst as *mut Self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -428,16 +428,14 @@ impl BrentAlgState {
|
|||||||
|
|
||||||
pstr_chars = pstr.as_str_from(n).chars().count() - 1;
|
pstr_chars = pstr.as_str_from(n).chars().count() - 1;
|
||||||
|
|
||||||
if heap[h].get_tag() == HeapCellValueTag::PStrOffset {
|
if heap[h].get_tag() == HeapCellValueTag::PStrOffset && heap[h_offset].get_tag() == HeapCellValueTag::CStr {
|
||||||
if heap[h_offset].get_tag() == HeapCellValueTag::CStr {
|
|
||||||
return if pstr_chars < max_steps {
|
return if pstr_chars < max_steps {
|
||||||
CycleSearchResult::ProperList(pstr_chars + 1)
|
CycleSearchResult::ProperList(pstr_chars + 1)
|
||||||
} else {
|
} else {
|
||||||
let offset = max_steps as usize + n;
|
let offset = max_steps + n;
|
||||||
CycleSearchResult::PStrLocation(max_steps, h_offset, offset)
|
CycleSearchResult::PStrLocation(max_steps, h_offset, offset)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if pstr_chars + 1 > max_steps {
|
if pstr_chars + 1 > max_steps {
|
||||||
return CycleSearchResult::PStrLocation(max_steps, h_offset, max_steps);
|
return CycleSearchResult::PStrLocation(max_steps, h_offset, max_steps);
|
||||||
|
|||||||
@@ -327,12 +327,11 @@ impl<R: Read> Read for CharReader<R> {
|
|||||||
return self.inner.read_vectored(bufs);
|
return self.inner.read_vectored(bufs);
|
||||||
}
|
}
|
||||||
|
|
||||||
let nread = {
|
|
||||||
self.refresh_buffer()?;
|
self.refresh_buffer()?;
|
||||||
(&self.buf[self.pos..]).read_vectored(bufs)?
|
|
||||||
};
|
|
||||||
|
|
||||||
|
let nread = (&self.buf[self.pos..]).read_vectored(bufs)?;
|
||||||
self.consume(nread);
|
self.consume(nread);
|
||||||
|
|
||||||
Ok(nread)
|
Ok(nread)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user