layout add allocation_alignment_bytes

This commit is contained in:
Folkert 2021-09-03 23:56:42 +02:00
parent 63c488acd8
commit 97577c92cf
2 changed files with 71 additions and 2 deletions

View file

@ -158,12 +158,14 @@ impl<'ctx> PointerToRefcount<'ctx> {
} }
pub fn decrement<'a, 'env>(&self, env: &Env<'a, 'ctx, 'env>, layout: &Layout<'a>) { pub fn decrement<'a, 'env>(&self, env: &Env<'a, 'ctx, 'env>, layout: &Layout<'a>) {
let alignment = layout
.allocation_alignment_bytes(env.ptr_bytes)
.max(env.ptr_bytes);
let context = env.context; let context = env.context;
let block = env.builder.get_insert_block().expect("to be in a function"); let block = env.builder.get_insert_block().expect("to be in a function");
let di_location = env.builder.get_current_debug_location().unwrap(); let di_location = env.builder.get_current_debug_location().unwrap();
let alignment = layout.alignment_bytes(env.ptr_bytes).max(env.ptr_bytes);
let fn_name = &format!("decrement_refcounted_ptr_{}", alignment); let fn_name = &format!("decrement_refcounted_ptr_{}", alignment);
let function = match env.module.get_function(fn_name) { let function = match env.module.get_function(fn_name) {
@ -1142,6 +1144,10 @@ fn build_rec_union_help<'a, 'ctx, 'env>(
env.builder.position_at_end(should_recurse_block); env.builder.position_at_end(should_recurse_block);
// to increment/decrement the cons-cell itself
let refcount_ptr = PointerToRefcount::from_ptr_to_data(env, value_ptr);
let call_mode = mode_to_call_mode(fn_val, mode);
let layout = Layout::Union(union_layout); let layout = Layout::Union(union_layout);
match mode { match mode {

View file

@ -386,6 +386,32 @@ impl<'a> UnionLayout<'a> {
UnionLayout::NullableWrapped { .. } | UnionLayout::NullableUnwrapped { .. } => true, UnionLayout::NullableWrapped { .. } | UnionLayout::NullableUnwrapped { .. } => true,
} }
} }
fn tags_alignment_bytes(tags: &[&[Layout]], pointer_size: u32) -> u32 {
tags.iter()
.map(|fields| Layout::Struct(fields).alignment_bytes(pointer_size))
.max()
.unwrap_or(0)
}
pub fn allocation_alignment_bytes(&self, pointer_size: u32) -> u32 {
let allocation = match self {
UnionLayout::NonRecursive(_) => unreachable!("not heap-allocated"),
UnionLayout::Recursive(tags) => Self::tags_alignment_bytes(tags, pointer_size),
UnionLayout::NonNullableUnwrapped(fields) => {
Layout::Struct(fields).alignment_bytes(pointer_size)
}
UnionLayout::NullableWrapped { other_tags, .. } => {
Self::tags_alignment_bytes(other_tags, pointer_size)
}
UnionLayout::NullableUnwrapped { other_fields, .. } => {
Layout::Struct(other_fields).alignment_bytes(pointer_size)
}
};
// because we store a refcount, the alignment must be at least the size of a pointer
allocation.max(pointer_size)
}
} }
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
@ -898,6 +924,15 @@ impl<'a> Layout<'a> {
} }
} }
pub fn allocation_alignment_bytes(&self, pointer_size: u32) -> u32 {
match self {
Layout::Builtin(builtin) => builtin.allocation_alignment_bytes(pointer_size),
Layout::Struct(_) => unreachable!("not heap-allocated"),
Layout::Union(union_layout) => union_layout.allocation_alignment_bytes(pointer_size),
Layout::RecursivePointer => unreachable!("should be looked up to get an actual layout"),
}
}
pub fn is_refcounted(&self) -> bool { pub fn is_refcounted(&self) -> bool {
use self::Builtin::*; use self::Builtin::*;
use Layout::*; use Layout::*;
@ -1187,6 +1222,34 @@ impl<'a> Builtin<'a> {
.append(value_layout.to_doc(alloc, Parens::InTypeParam)), .append(value_layout.to_doc(alloc, Parens::InTypeParam)),
} }
} }
pub fn allocation_alignment_bytes(&self, pointer_size: u32) -> u32 {
let allocation = match self {
Builtin::Int128
| Builtin::Int64
| Builtin::Int32
| Builtin::Int16
| Builtin::Int8
| Builtin::Int1
| Builtin::Usize
| Builtin::Decimal
| Builtin::Float128
| Builtin::Float64
| Builtin::Float32
| Builtin::Float16 => unreachable!("not heap-allocated"),
Builtin::Str => pointer_size,
Builtin::Dict(k, v) => k
.alignment_bytes(pointer_size)
.max(v.alignment_bytes(pointer_size)),
Builtin::Set(k) => k.alignment_bytes(pointer_size),
Builtin::List(e) => e.alignment_bytes(pointer_size),
Builtin::EmptyStr | Builtin::EmptyList | Builtin::EmptyDict | Builtin::EmptySet => {
unreachable!("not heap-allocated")
}
};
allocation.max(pointer_size)
}
} }
fn layout_from_flat_type<'a>( fn layout_from_flat_type<'a>(