Skip to content

Commit

Permalink
🔮 Create gc managed object
Browse files Browse the repository at this point in the history
  • Loading branch information
oovm committed Mar 27, 2019
1 parent 816dca0 commit 78ef781
Show file tree
Hide file tree
Showing 7 changed files with 152 additions and 102 deletions.
6 changes: 3 additions & 3 deletions projects/zero-gc/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
[package]
name = "zgc"
version = "0.0.0"
version = "0.0.1"
authors = ["Aster <[email protected]>"]
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"
Expand All @@ -11,7 +11,7 @@ edition = "2021"
exclude = ["package.json", "tests/**"]

[dependencies]
bitflags = "2.3.1"
#bitflags = "2.3.1"

[dev-dependencies]

Expand Down
114 changes: 78 additions & 36 deletions projects/zero-gc/src/barrier/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand All @@ -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<T>(value: T) -> Self {
/// Create a new gc pointer from the data
pub fn make<T>(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<T>(&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::<i64>() };
println!("{:?}", d)
impl GcObject {
/// Make an owned object to gc object.
pub fn make<T>(value: T) -> Self {
let header = GcPointer::make(&value);
let size = std::mem::size_of::<T>();
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<T>(self) -> T {
debug_assert!(self.size == std::mem::size_of::<T>());
let ptr = self.head.as_pointer() as *const T;
ptr.read()
}
}
6 changes: 0 additions & 6 deletions projects/zero-gc/src/errors.rs

This file was deleted.

11 changes: 11 additions & 0 deletions projects/zero-gc/src/errors/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/// Result type of gc
pub type GcResult<T> = std::result::Result<T, GcError>;

/// Error type for the GC
#[derive(Debug, Copy, Clone)]
pub enum GcError {
/// The object is not a valid gc object.
UnknownError
}


78 changes: 23 additions & 55 deletions projects/zero-gc/src/gc_head/mod.rs
Original file line number Diff line number Diff line change
@@ -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<T> {
/// Pointer to the head
ptr: *mut u64,
head: GcPointer,
/// Pointer to the data
bytes: *mut u8,
size: usize,
/// Phantom data
typing: PhantomData<T>,
}


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<T> Gc<T> {
/// Create a new gc object from the data
pub fn new(value: T) -> Self {
Self {
head: GcPointer::make(&value),
size: std::mem::size_of::<T>(),
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<NonNull<[u8]>, AllocError> {
todo!()
}

unsafe fn deallocate(&self, ptr: NonNull<u8>, 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<u8>,
}

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,
}
8 changes: 6 additions & 2 deletions projects/zero-gc/src/lib.rs
Original file line number Diff line number Diff line change
@@ -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")]
Expand All @@ -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};
31 changes: 31 additions & 0 deletions projects/zero-gc/tests/main.rs
Original file line number Diff line number Diff line change
@@ -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::<i32>() };
// 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);
// }

0 comments on commit 78ef781

Please sign in to comment.