Skip to content

Commit

Permalink
refactor(memory): simplify and rename TypeLayout trait
Browse files Browse the repository at this point in the history
  • Loading branch information
Wodann committed May 13, 2020
1 parent e403130 commit b7fcf06
Show file tree
Hide file tree
Showing 8 changed files with 60 additions and 57 deletions.
4 changes: 2 additions & 2 deletions crates/mun_memory/src/gc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ mod mark_sweep;
mod ptr;
mod root_ptr;

use crate::TypeLayout;
use crate::TypeMemory;
use std::marker::PhantomData;

pub use mark_sweep::MarkSweep;
Expand All @@ -24,7 +24,7 @@ pub trait TypeTrace: Send + Sync {
}

/// An object that can be used to allocate and collect memory.
pub trait GcRuntime<T: TypeLayout + TypeTrace>: Send + Sync {
pub trait GcRuntime<T: TypeMemory + TypeTrace>: Send + Sync {
/// Allocates an object of the given type returning a GcPtr
fn alloc(&self, ty: T) -> GcPtr;

Expand Down
46 changes: 22 additions & 24 deletions crates/mun_memory/src/gc/mark_sweep.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::{
cast,
gc::{Event, GcPtr, GcRuntime, Observer, RawGcPtr, Stats, TypeTrace},
mapping::{self, FieldMapping, MemoryMapper},
TypeDesc, TypeLayout,
TypeDesc, TypeMemory,
};
use mapping::{Conversion, Mapping};
use parking_lot::RwLock;
Expand All @@ -18,7 +18,7 @@ use std::{
#[derive(Debug)]
pub struct MarkSweep<T, O>
where
T: TypeLayout + TypeTrace + Clone,
T: TypeMemory + TypeTrace + Clone,
O: Observer<Event = Event>,
{
objects: RwLock<HashMap<GcPtr, Pin<Box<ObjectInfo<T>>>>>,
Expand All @@ -28,7 +28,7 @@ where

impl<T, O> Default for MarkSweep<T, O>
where
T: TypeLayout + TypeTrace + Clone,
T: TypeMemory + TypeTrace + Clone,
O: Observer<Event = Event> + Default,
{
fn default() -> Self {
Expand All @@ -42,7 +42,7 @@ where

impl<T, O> MarkSweep<T, O>
where
T: TypeLayout + TypeTrace + Clone,
T: TypeMemory + TypeTrace + Clone,
O: Observer<Event = Event>,
{
/// Creates a `MarkSweep` memory collector with the specified `Observer`.
Expand Down Expand Up @@ -70,7 +70,7 @@ where
}
}

fn alloc_obj<T: Clone + TypeLayout + TypeTrace>(ty: T) -> Pin<Box<ObjectInfo<T>>> {
fn alloc_obj<T: Clone + TypeMemory + TypeTrace>(ty: T) -> Pin<Box<ObjectInfo<T>>> {
let ptr = unsafe { std::alloc::alloc(ty.layout()) };
Box::pin(ObjectInfo {
ptr,
Expand All @@ -82,7 +82,7 @@ fn alloc_obj<T: Clone + TypeLayout + TypeTrace>(ty: T) -> Pin<Box<ObjectInfo<T>>

impl<T, O> GcRuntime<T> for MarkSweep<T, O>
where
T: TypeLayout + TypeTrace + Clone,
T: TypeMemory + TypeTrace + Clone,
O: Observer<Event = Event>,
{
fn alloc(&self, ty: T) -> GcPtr {
Expand Down Expand Up @@ -135,7 +135,7 @@ where

impl<T, O> MarkSweep<T, O>
where
T: TypeLayout + TypeTrace + Clone,
T: TypeMemory + TypeTrace + Clone,
O: Observer<Event = Event>,
{
/// Collects all memory that is no longer referenced by rooted objects. Returns `true` if memory
Expand Down Expand Up @@ -207,7 +207,7 @@ where

impl<T, O> MemoryMapper<T> for MarkSweep<T, O>
where
T: TypeDesc + TypeLayout + TypeTrace + Clone + Eq + Hash,
T: TypeDesc + TypeMemory + TypeTrace + Clone + Eq + Hash,
O: Observer<Event = Event>,
{
fn map_memory(&self, mapping: Mapping<T, T>) -> Vec<GcPtr> {
Expand Down Expand Up @@ -292,7 +292,7 @@ where
src: NonNull<u8>,
dest: NonNull<u8>,
) where
T: TypeDesc + TypeLayout + TypeTrace + Clone + Eq + Hash,
T: TypeDesc + TypeMemory + TypeTrace + Clone + Eq + Hash,
O: Observer<Event = Event>,
{
for FieldMapping {
Expand All @@ -315,10 +315,8 @@ where
src as *mut u8
};

if let Some(old_memory_kind) = old_ty.memory_kind() {
let new_memory_kind = new_ty.memory_kind().expect(
"We are dealing with a struct and we do not directly compare fundamental types and struct type, so its counterpart must also be a struct.",
);
if old_ty.group().is_struct() {
debug_assert!(new_ty.group().is_struct());

// When the name is the same, we are dealing with the same struct,
// but different internals
Expand All @@ -327,8 +325,8 @@ where
// If the same struct changed, there must also be a conversion
let conversion = conversions.get(old_ty);

if old_memory_kind == abi::StructMemoryKind::Value {
if new_memory_kind == abi::StructMemoryKind::Value {
if old_ty.is_stack_allocated() {
if new_ty.is_stack_allocated() {
// struct(value) -> struct(value)
if is_same_struct {
// Map in-memory struct to in-memory struct
Expand Down Expand Up @@ -378,7 +376,7 @@ where

new_allocations.push(object);
}
} else if new_memory_kind == abi::StructMemoryKind::GC {
} else if !new_ty.is_stack_allocated() {
// struct(gc) -> struct(gc)
let field_src = field_src.cast::<GcPtr>();
let field_dest = field_dest.cast::<GcPtr>();
Expand Down Expand Up @@ -472,7 +470,7 @@ where
};
}
mapping::Action::Insert => {
if let Some(abi::StructMemoryKind::GC) = new_ty.memory_kind() {
if !new_ty.is_stack_allocated() {
let object = alloc_obj(new_ty.clone());

// We want to return a pointer to the `ObjectInfo`, to be used as
Expand Down Expand Up @@ -516,36 +514,36 @@ enum Color {
/// meta information.
#[derive(Debug)]
#[repr(C)]
struct ObjectInfo<T: TypeLayout + TypeTrace + Clone> {
struct ObjectInfo<T: TypeMemory + TypeTrace + Clone> {
pub ptr: *mut u8,
pub roots: u32,
pub color: Color,
pub ty: T,
}

/// An `ObjectInfo` is thread-safe.
unsafe impl<T: TypeLayout + TypeTrace + Clone> Send for ObjectInfo<T> {}
unsafe impl<T: TypeLayout + TypeTrace + Clone> Sync for ObjectInfo<T> {}
unsafe impl<T: TypeMemory + TypeTrace + Clone> Send for ObjectInfo<T> {}
unsafe impl<T: TypeMemory + TypeTrace + Clone> Sync for ObjectInfo<T> {}

impl<T: TypeLayout + TypeTrace + Clone> Into<*const ObjectInfo<T>> for GcPtr {
impl<T: TypeMemory + TypeTrace + Clone> Into<*const ObjectInfo<T>> for GcPtr {
fn into(self) -> *const ObjectInfo<T> {
self.as_ptr() as *const ObjectInfo<T>
}
}

impl<T: TypeLayout + TypeTrace + Clone> Into<*mut ObjectInfo<T>> for GcPtr {
impl<T: TypeMemory + TypeTrace + Clone> Into<*mut ObjectInfo<T>> for GcPtr {
fn into(self) -> *mut ObjectInfo<T> {
self.as_ptr() as *mut ObjectInfo<T>
}
}

impl<T: TypeLayout + TypeTrace + Clone> Into<GcPtr> for *const ObjectInfo<T> {
impl<T: TypeMemory + TypeTrace + Clone> Into<GcPtr> for *const ObjectInfo<T> {
fn into(self) -> GcPtr {
(self as RawGcPtr).into()
}
}

impl<T: TypeLayout + TypeTrace + Clone> Into<GcPtr> for *mut ObjectInfo<T> {
impl<T: TypeMemory + TypeTrace + Clone> Into<GcPtr> for *mut ObjectInfo<T> {
fn into(self) -> GcPtr {
(self as RawGcPtr).into()
}
Expand Down
14 changes: 7 additions & 7 deletions crates/mun_memory/src/gc/root_ptr.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
use crate::{
gc::{GcPtr, GcRuntime, HasIndirectionPtr, TypeTrace},
TypeLayout,
TypeMemory,
};
use std::marker::PhantomData;
use std::sync::{Arc, Weak};

/// A `GcPtr` that automatically roots and unroots its internal `GcPtr`.
pub struct GcRootPtr<T: TypeLayout + TypeTrace, G: GcRuntime<T>> {
pub struct GcRootPtr<T: TypeMemory + TypeTrace, G: GcRuntime<T>> {
handle: GcPtr,
runtime: Weak<G>,
ty: PhantomData<T>,
}

impl<T: TypeLayout + TypeTrace, G: GcRuntime<T>> Clone for GcRootPtr<T, G> {
impl<T: TypeMemory + TypeTrace, G: GcRuntime<T>> Clone for GcRootPtr<T, G> {
fn clone(&self) -> Self {
if let Some(runtime) = self.runtime.upgrade() {
runtime.root(self.handle)
Expand All @@ -25,7 +25,7 @@ impl<T: TypeLayout + TypeTrace, G: GcRuntime<T>> Clone for GcRootPtr<T, G> {
}
}

impl<T: TypeLayout + TypeTrace, G: GcRuntime<T>> GcRootPtr<T, G> {
impl<T: TypeMemory + TypeTrace, G: GcRuntime<T>> GcRootPtr<T, G> {
/// Constructs a new GCRootHandle from a runtime and a handle
pub fn new(runtime: &Arc<G>, handle: GcPtr) -> Self {
runtime.root(handle);
Expand All @@ -47,21 +47,21 @@ impl<T: TypeLayout + TypeTrace, G: GcRuntime<T>> GcRootPtr<T, G> {
}
}

impl<T: TypeLayout + TypeTrace, G: GcRuntime<T>> Into<GcPtr> for GcRootPtr<T, G> {
impl<T: TypeMemory + TypeTrace, G: GcRuntime<T>> Into<GcPtr> for GcRootPtr<T, G> {
fn into(self) -> GcPtr {
self.handle
}
}

impl<T: TypeLayout + TypeTrace, G: GcRuntime<T>> Drop for GcRootPtr<T, G> {
impl<T: TypeMemory + TypeTrace, G: GcRuntime<T>> Drop for GcRootPtr<T, G> {
fn drop(&mut self) {
if let Some(runtime) = self.runtime.upgrade() {
runtime.unroot(self.handle)
}
}
}

impl<T: TypeLayout + TypeTrace, G: GcRuntime<T>> HasIndirectionPtr for GcRootPtr<T, G> {
impl<T: TypeMemory + TypeTrace, G: GcRuntime<T>> HasIndirectionPtr for GcRootPtr<T, G> {
unsafe fn deref<R: Sized>(&self) -> *const R {
self.handle.deref()
}
Expand Down
8 changes: 4 additions & 4 deletions crates/mun_memory/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@ pub trait TypeDesc: Send + Sync {
fn group(&self) -> abi::TypeGroup;
}

/// A trait used to obtain a type's memory layout.
pub trait TypeLayout: Send + Sync {
/// A trait used to obtain a type's memory description.
pub trait TypeMemory: Send + Sync {
/// Returns the memory layout of this type.
fn layout(&self) -> Layout;
/// Returns the memory kind of this type, if it is a struct.
fn memory_kind(&self) -> Option<abi::StructMemoryKind>;
/// Returns whether the memory is stack-allocated.
fn is_stack_allocated(&self) -> bool;
}

/// A trait used to obtain a type's fields.
Expand Down
20 changes: 10 additions & 10 deletions crates/mun_memory/src/mapping.rs
Original file line number Diff line number Diff line change
@@ -1,43 +1,43 @@
use crate::{
diff::{diff, Diff, FieldDiff, FieldEditKind},
gc::GcPtr,
TypeDesc, TypeFields, TypeLayout,
TypeDesc, TypeFields, TypeMemory,
};
use std::{
collections::{HashMap, HashSet},
hash::Hash,
};

pub struct Mapping<T: Eq + Hash, U: TypeDesc + TypeLayout> {
pub struct Mapping<T: Eq + Hash, U: TypeDesc + TypeMemory> {
pub deletions: HashSet<T>,
pub conversions: HashMap<T, Conversion<U>>,
pub identical: Vec<(T, T)>,
}

pub struct Conversion<T: TypeDesc + TypeLayout> {
pub struct Conversion<T: TypeDesc + TypeMemory> {
pub field_mapping: Vec<FieldMapping<T>>,
pub new_ty: T,
}

/// Description of the mapping of a single field. When stored together with the new index, this
/// provides all information necessary for a mapping function.
pub struct FieldMapping<T: TypeDesc + TypeLayout> {
pub struct FieldMapping<T: TypeDesc + TypeMemory> {
pub new_ty: T,
pub new_offset: usize,
pub action: Action<T>,
}

/// The `Action` to take when mapping memory from A to B.
#[derive(Eq, PartialEq)]
pub enum Action<T: TypeDesc + TypeLayout> {
pub enum Action<T: TypeDesc + TypeMemory> {
Cast { old_offset: usize, old_ty: T },
Copy { old_offset: usize },
Insert,
}

impl<T> Mapping<T, T>
where
T: TypeDesc + TypeFields<T> + TypeLayout + Copy + Eq + Hash,
T: TypeDesc + TypeFields<T> + TypeMemory + Copy + Eq + Hash,
{
///
pub fn new(old: &[T], new: &[T]) -> Self {
Expand Down Expand Up @@ -83,7 +83,7 @@ where
let mut new_candidates: HashSet<T> = new
.iter()
// Filter non-struct types
.filter(|ty| ty.memory_kind().is_some())
.filter(|ty| ty.group().is_struct())
// Filter inserted structs
.filter(|ty| !insertions.contains(*ty))
.cloned()
Expand All @@ -92,7 +92,7 @@ where
let mut old_candidates: HashSet<T> = old
.iter()
// Filter non-struct types
.filter(|ty| ty.memory_kind().is_some())
.filter(|ty| ty.group().is_struct())
// Filter deleted structs
.filter(|ty| !deletions.contains(*ty))
// Filter edited types
Expand Down Expand Up @@ -139,7 +139,7 @@ where
/// # Safety
///
/// Expects the `diff` to be based on `old_ty` and `new_ty`. If not, it causes undefined behavior.
pub unsafe fn field_mapping<T: Clone + TypeDesc + TypeFields<T> + TypeLayout>(
pub unsafe fn field_mapping<T: Clone + TypeDesc + TypeFields<T> + TypeMemory>(
old_ty: T,
new_ty: T,
diff: &[FieldDiff],
Expand Down Expand Up @@ -265,7 +265,7 @@ pub unsafe fn field_mapping<T: Clone + TypeDesc + TypeFields<T> + TypeLayout>(
}

/// A trait used to map allocated memory using type differences.
pub trait MemoryMapper<T: Eq + Hash + TypeDesc + TypeLayout> {
pub trait MemoryMapper<T: Eq + Hash + TypeDesc + TypeMemory> {
/// Maps its allocated memory using the provided `mapping`.
///
/// A `Vec<GcPtr>` is returned containing all objects of types that were deleted. The
Expand Down
8 changes: 4 additions & 4 deletions crates/mun_memory/tests/diff/util.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#![allow(dead_code)]
use mun_memory::{
diff::{myers, Diff, FieldDiff, FieldEditKind},
TypeDesc, TypeFields, TypeLayout,
TypeDesc, TypeFields, TypeMemory,
};
use std::alloc::Layout;

Expand Down Expand Up @@ -106,14 +106,14 @@ impl TypeDesc for &TypeInfo {
}
}

impl TypeLayout for &TypeInfo {
impl TypeMemory for &TypeInfo {
fn layout(&self) -> Layout {
self.layout
}

fn memory_kind(&self) -> Option<abi::StructMemoryKind> {
fn is_stack_allocated(&self) -> bool {
// NOTE: This contrived test does not support structs
None
true
}
}

Expand Down
6 changes: 3 additions & 3 deletions crates/mun_memory/tests/gc/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,15 +72,15 @@ macro_rules! impl_struct_ty {

impl_primitive_types!(i8, i16, i32, i64, u8, u16, u32, u64, f32, f64, bool);

impl mun_memory::TypeLayout for &'static TypeInfo {
impl mun_memory::TypeMemory for &'static TypeInfo {
fn layout(&self) -> Layout {
Layout::from_size_align(self.size as usize, self.alignment as usize)
.expect("invalid layout specified by TypeInfo")
}

fn memory_kind(&self) -> Option<abi::StructMemoryKind> {
fn is_stack_allocated(&self) -> bool {
// NOTE: This contrived test does not support structs
None
true
}
}

Expand Down
Loading

0 comments on commit b7fcf06

Please sign in to comment.