From 78ef78143b01029c4144712195abaa579ea26a12 Mon Sep 17 00:00:00 2001 From: Aster Date: Wed, 27 Mar 2019 11:12:33 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=94=AE=20Create=20gc=20managed=20object?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- projects/zero-gc/Cargo.toml | 6 +- projects/zero-gc/src/barrier/mod.rs | 114 +++++++++++++++++++--------- projects/zero-gc/src/errors.rs | 6 -- projects/zero-gc/src/errors/mod.rs | 11 +++ projects/zero-gc/src/gc_head/mod.rs | 78 ++++++------------- projects/zero-gc/src/lib.rs | 8 +- projects/zero-gc/tests/main.rs | 31 ++++++++ 7 files changed, 152 insertions(+), 102 deletions(-) delete mode 100644 projects/zero-gc/src/errors.rs create mode 100644 projects/zero-gc/src/errors/mod.rs diff --git a/projects/zero-gc/Cargo.toml b/projects/zero-gc/Cargo.toml index 14afa96..4ec1c43 100644 --- a/projects/zero-gc/Cargo.toml +++ b/projects/zero-gc/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "zgc" -version = "0.0.0" +version = "0.0.1" authors = ["Aster <192607617@qq.com>"] -description = "Concurrent GC in Rust" +description = "Pauseless GC in Rust" repository = "https://github.com/nyar-vm/zero-gc" documentation = "https://docs.rs/zgc" readme = "Readme.md" @@ -11,7 +11,7 @@ edition = "2021" exclude = ["package.json", "tests/**"] [dependencies] -bitflags = "2.3.1" +#bitflags = "2.3.1" [dev-dependencies] diff --git a/projects/zero-gc/src/barrier/mod.rs b/projects/zero-gc/src/barrier/mod.rs index ff23571..d29f03f 100644 --- a/projects/zero-gc/src/barrier/mod.rs +++ b/projects/zero-gc/src/barrier/mod.rs @@ -9,15 +9,27 @@ // } use std::fmt::{Debug, Formatter, Pointer}; +use std::ptr::from_raw_parts; -pub struct LoadBarrier { +/// A gc pointer. +#[repr(C)] +#[derive(Clone, Copy)] +pub struct GcPointer { raw: usize, } -impl Debug for LoadBarrier { +/// A untyped gc object. +#[repr(C)] +#[derive(Clone, Copy)] +pub struct GcObject { + head: GcPointer, + size: usize, +} + +impl Debug for GcPointer { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - f.debug_struct("GcPointer") - .field("raw", &format_args!("0x{:0x}", self.raw)) + f.debug_struct("Pointer") + .field("raw", &format_args!("0x{:016x}", self.raw)) .field("pointer", &format_args!("{:p}", self.as_pointer())) .field("finalize", &self.is_finalizable()) .field("remapped", &self.is_remapped()) @@ -27,89 +39,119 @@ impl Debug for LoadBarrier { } } -impl Pointer for LoadBarrier { +impl Debug for GcObject { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + f.debug_struct("Object") + .field("head", &self.head) + .field("size", &self.size) + .finish() + } +} + +impl Pointer for GcPointer { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { write!(f, "0x{:0x}", self.raw) } } -impl LoadBarrier { - /// Create a new pointer from a usize. - pub unsafe fn new(address: *const usize) -> Self { +impl GcPointer { + /// Create a new gc pointer from a raw pointer. + pub unsafe fn new(address: *const ()) -> Self { Self { raw: address as usize, } } - pub fn make(value: T) -> Self { + /// Create a new gc pointer from the data + pub fn make(value: &T) -> Self { Self { - raw: &value as *const T as usize, + raw: value as *const T as usize, } } - /// Get the pointer as a usize. + /// Get the last 42 bits of the pointer. pub fn as_pointer(&self) -> *const usize { - let masked = self.raw & 0x0000_0000_ffff_ffff; + let masked = self.raw & 0x0000_02ff_ffff_ffff; masked as *const usize } /// Cast the pointer to a specific type. pub unsafe fn cast(&self) -> &mut T { &mut *(self.as_pointer() as *mut T) } + /// The 19th bit of the pointer is used to indicate whether the object is finalizable. pub fn is_finalizable(&self) -> bool { - self.raw & 0x80000 != 0 + self.raw & 0x0000_0400_0000_0000 != 0 } + /// The 19th bit of the pointer is used to indicate whether the object is finalizable. pub fn set_finalize(&mut self, finalize: bool) { if finalize { - self.raw |= 0x80000; + self.raw |= 0x0000_0400_0000_0000; } else { - self.raw &= !0x80000; + self.raw &= 0xffff_fbff_ffff_ffff; } } /// The 20th bit of the pointer is used to indicate whether the object is remapped. pub fn is_remapped(&self) -> bool { - self.raw & 0x40000 != 0 + self.raw & 0x0000_0800_0000_0000 != 0 } + /// The 20th bit of the pointer is used to indicate whether the object is remapped. pub fn set_remapped(&mut self, remapped: bool) { if remapped { - self.raw |= 0x40000; + self.raw |= 0x0000_0800_0000_0000; } else { - self.raw &= !0x40000; + self.raw &= 0xffff_f7ff_ffff_ffff; } } /// The 21th bit of the pointer is used to indicate whether the object is marked. pub fn is_marked1(&self) -> bool { - self.raw & 0x20000 != 0 + self.raw & 0x0000_1000_0000_0000 != 0 } + /// The 21th bit of the pointer is used to indicate whether the object is marked. pub fn set_marked1(&mut self, marked: bool) { if marked { - self.raw |= 0x20000; + self.raw |= 0x0000_1000_0000_0000; } else { - self.raw &= !0x20000; + self.raw &= 0xffff_efff_ffff_ffff; } } /// The 22th bit of the pointer is used to indicate whether the object is marked. pub fn is_marked0(&self) -> bool { - self.raw & 0x10000 != 0 + self.raw & 0x0000_2000_0000_0000 != 0 } + /// The 22th bit of the pointer is used to indicate whether the object is marked. pub fn set_marked0(&mut self, marked0: bool) { if marked0 { - self.raw |= 0x10000; + self.raw |= 0x0000_2000_0000_0000; } else { - self.raw &= !0x10000; + self.raw &= 0xffff_dfff_ffff_ffff; } } } -#[test] -pub fn test() { - let a: i64 = -2333; - println!("{:p}", &a); - let mut ptr = LoadBarrier::make(a); - ptr.set_marked0(true); - ptr.set_marked1(true); - ptr.set_remapped(true); - ptr.set_finalize(true); - println!("{:#?}", ptr); - let d = unsafe { ptr.cast::() }; - println!("{:?}", d) +impl GcObject { + /// Make an owned object to gc object. + pub fn make(value: T) -> Self { + let header = GcPointer::make(&value); + let size = std::mem::size_of::(); + Self { + head: header, + size, + } + } + /// Get the last 42 bits of the pointer. + pub fn as_pointer(&self) -> *const usize { + self.head.as_pointer() + } + /// Get the size of the object. + pub fn as_bytes(&self) -> &[u8] { + unsafe { + let ptr = from_raw_parts(self.as_pointer() as *const (), self.size); + &*ptr + } + } + /// Cast the pointer to a specific type. + pub unsafe fn cast(self) -> T { + debug_assert!(self.size == std::mem::size_of::()); + let ptr = self.head.as_pointer() as *const T; + ptr.read() + } } diff --git a/projects/zero-gc/src/errors.rs b/projects/zero-gc/src/errors.rs deleted file mode 100644 index 982023b..0000000 --- a/projects/zero-gc/src/errors.rs +++ /dev/null @@ -1,6 +0,0 @@ -#[derive(Debug, Copy, Clone)] -pub enum Error { - UnknownError -} - -pub type Result = std::result::Result; diff --git a/projects/zero-gc/src/errors/mod.rs b/projects/zero-gc/src/errors/mod.rs new file mode 100644 index 0000000..048bf3a --- /dev/null +++ b/projects/zero-gc/src/errors/mod.rs @@ -0,0 +1,11 @@ +/// Result type of gc +pub type GcResult = std::result::Result; + +/// Error type for the GC +#[derive(Debug, Copy, Clone)] +pub enum GcError { + /// The object is not a valid gc object. + UnknownError +} + + diff --git a/projects/zero-gc/src/gc_head/mod.rs b/projects/zero-gc/src/gc_head/mod.rs index 36cd284..3bd7be0 100644 --- a/projects/zero-gc/src/gc_head/mod.rs +++ b/projects/zero-gc/src/gc_head/mod.rs @@ -1,70 +1,38 @@ -use std::alloc::{Allocator, AllocError, Layout}; use std::marker::PhantomData; -use std::ptr::NonNull; -/// Gc pointer + +use crate::GcPointer; + +/// A typed gc object. +#[repr(C)] +#[derive(Copy, Clone, Debug)] pub struct Gc { /// Pointer to the head - ptr: *mut u64, + head: GcPointer, /// Pointer to the data - bytes: *mut u8, + size: usize, /// Phantom data typing: PhantomData, } - -pub trait Region { - fn allocate(&mut self, size: usize) -> *mut u8; - fn free(&mut self, ptr: *mut u8); -} - -impl Region for SmallRegion { - fn allocate(&mut self, size: usize) -> *mut u8 { - todo!() - } - - fn free(&mut self, ptr: *mut u8) { - todo!() +impl Gc { + /// Create a new gc object from the data + pub fn new(value: T) -> Self { + Self { + head: GcPointer::make(&value), + size: std::mem::size_of::(), + typing: PhantomData::default(), + } } } +/// The world. +#[derive(Copy, Clone, Debug)] pub struct TheWorld {} -#[derive(Copy, Clone)] -pub union TheRegion { - small: SmallRegion, - medium: MediumRegion, -} - -unsafe impl Allocator for TheWorld { - fn allocate(&self, layout: Layout) -> Result, AllocError> { - todo!() - } - - unsafe fn deallocate(&self, ptr: NonNull, layout: Layout) { - todo!() - } -} -// 小型Region(Small Region):容量固定为2MB,用于放置小于256KB的小对象。 -// 中型Region(Medium Region):容量固定为32MB,用于放置大于等于256KB但小于4MB的对象。 -// 大型Region(Large Region):容量不固定,可以动态变化,但必须为2MB的整数倍,用于放置4MB或以上的大对象。每个大型Region中只会存放一个大对象,这也预示着虽然名字叫作“大型Region”,但它的实际容量完全有可能小于中型Region,最小容量可低至4MB。大型Region在ZGC的实现中是不会被重分配的,因为复制一个大对象的代价非常高昂。 - -/// 容量固定为1MB,用于放置小于128KB的小对象。 -#[derive(Copy, Clone)] -pub struct SmallRegion { - bytes: [u8; 1 * 1024 * 1024], -} - -/// 容量固定为 32MB,用于放置小于4MB的中等对象。 -#[derive(Copy, Clone)] -pub struct MediumRegion { - bytes: [u8; 32 * 1024 * 1024], -} - -pub struct OwnedRegion { - bytes: Vec, -} - -pub struct WorldControl { - initiating_heap_occupancy_percent: u8, +/// The world control. +#[derive(Copy, Clone, Debug)] +pub struct TheWorldControl { + /// The world + pub initiating_heap_occupancy_percent: u8, } \ No newline at end of file diff --git a/projects/zero-gc/src/lib.rs b/projects/zero-gc/src/lib.rs index 3373d0a..bd70c39 100644 --- a/projects/zero-gc/src/lib.rs +++ b/projects/zero-gc/src/lib.rs @@ -1,4 +1,5 @@ -#![feature(allocator_api)] +#![feature(allocator_api, slice_from_ptr_range)] +#![feature(ptr_metadata)] #![deny(missing_debug_implementations, missing_copy_implementations)] #![warn(missing_docs, rustdoc::missing_crate_level_docs)] #![doc = include_str!("../readme.md")] @@ -9,4 +10,7 @@ mod errors; mod gc_head; mod barrier; -pub use crate::errors::{Error, Result}; +pub use crate::errors::{GcError, GcResult}; + +pub use crate::barrier::{GcObject, GcPointer}; +pub use crate::gc_head::{Gc, TheWorld, TheWorldControl}; \ No newline at end of file diff --git a/projects/zero-gc/tests/main.rs b/projects/zero-gc/tests/main.rs index cf5bed2..79dfd82 100644 --- a/projects/zero-gc/tests/main.rs +++ b/projects/zero-gc/tests/main.rs @@ -1,4 +1,35 @@ +#[allow(unused, dead_code)] +use zgc::{GcObject, GcPointer}; + #[test] fn ready() { println!("it works!") } + + +// #[test] +// pub fn test() { +// let a: i32 = -2333; +// println!("{} at {:p}", a, &a); +// let mut ptr = GcPointer::make(&a); +// ptr.set_marked0(true); +// ptr.set_marked1(false); +// ptr.set_remapped(true); +// ptr.set_finalize(false); +// println!("{:#?}", ptr); +// // println!("{:p}", ptr.as_pointer()); +// let d = *unsafe { ptr.cast::() }; +// println!("value: {}", d); +// } + + +// #[test] +// pub fn test2() { +// let a: [i32; 4] = [2, -3, -5, -7]; +// println!("{:?} at {:p}", a, &a); +// let obj = GcObject::make(a); +// println!("{:#?}", obj); +// println!("{:?}", obj.as_bytes()); +// let d = unsafe { obj.cast::<[u32; 4]>() }; +// println!("value: {:?}", d); +// } \ No newline at end of file