mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-01 07:41:12 +00:00
use the WhenRecursive trick in refcounting
This commit is contained in:
parent
ff20ab76ce
commit
a850ccb94a
1 changed files with 152 additions and 11 deletions
|
@ -285,6 +285,7 @@ fn modify_refcount_struct<'a, 'ctx, 'env>(
|
||||||
value: BasicValueEnum<'ctx>,
|
value: BasicValueEnum<'ctx>,
|
||||||
layouts: &[Layout<'a>],
|
layouts: &[Layout<'a>],
|
||||||
mode: Mode,
|
mode: Mode,
|
||||||
|
when_recursive: &WhenRecursive<'a>,
|
||||||
) {
|
) {
|
||||||
let wrapper_struct = value.into_struct_value();
|
let wrapper_struct = value.into_struct_value();
|
||||||
|
|
||||||
|
@ -295,7 +296,15 @@ fn modify_refcount_struct<'a, 'ctx, 'env>(
|
||||||
.build_extract_value(wrapper_struct, i as u32, "decrement_struct_field")
|
.build_extract_value(wrapper_struct, i as u32, "decrement_struct_field")
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
modify_refcount_layout(env, parent, layout_ids, mode, field_ptr, field_layout);
|
modify_refcount_layout_help(
|
||||||
|
env,
|
||||||
|
parent,
|
||||||
|
layout_ids,
|
||||||
|
mode,
|
||||||
|
when_recursive,
|
||||||
|
field_ptr,
|
||||||
|
field_layout,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -332,6 +341,7 @@ fn modify_refcount_builtin<'a, 'ctx, 'env>(
|
||||||
env: &Env<'a, 'ctx, 'env>,
|
env: &Env<'a, 'ctx, 'env>,
|
||||||
layout_ids: &mut LayoutIds<'a>,
|
layout_ids: &mut LayoutIds<'a>,
|
||||||
mode: Mode,
|
mode: Mode,
|
||||||
|
when_recursive: &WhenRecursive<'a>,
|
||||||
value: BasicValueEnum<'ctx>,
|
value: BasicValueEnum<'ctx>,
|
||||||
layout: &Layout<'a>,
|
layout: &Layout<'a>,
|
||||||
builtin: &Builtin<'a>,
|
builtin: &Builtin<'a>,
|
||||||
|
@ -347,6 +357,7 @@ fn modify_refcount_builtin<'a, 'ctx, 'env>(
|
||||||
env,
|
env,
|
||||||
layout_ids,
|
layout_ids,
|
||||||
mode,
|
mode,
|
||||||
|
when_recursive,
|
||||||
layout,
|
layout,
|
||||||
element_layout,
|
element_layout,
|
||||||
wrapper_struct,
|
wrapper_struct,
|
||||||
|
@ -365,6 +376,7 @@ fn modify_refcount_builtin<'a, 'ctx, 'env>(
|
||||||
env,
|
env,
|
||||||
layout_ids,
|
layout_ids,
|
||||||
mode,
|
mode,
|
||||||
|
when_recursive,
|
||||||
layout,
|
layout,
|
||||||
key_layout,
|
key_layout,
|
||||||
value_layout,
|
value_layout,
|
||||||
|
@ -389,11 +401,45 @@ fn modify_refcount_layout<'a, 'ctx, 'env>(
|
||||||
mode: Mode,
|
mode: Mode,
|
||||||
value: BasicValueEnum<'ctx>,
|
value: BasicValueEnum<'ctx>,
|
||||||
layout: &Layout<'a>,
|
layout: &Layout<'a>,
|
||||||
|
) {
|
||||||
|
modify_refcount_layout_help(
|
||||||
|
env,
|
||||||
|
parent,
|
||||||
|
layout_ids,
|
||||||
|
mode,
|
||||||
|
&WhenRecursive::Unreachable,
|
||||||
|
value,
|
||||||
|
layout,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
|
enum WhenRecursive<'a> {
|
||||||
|
Unreachable,
|
||||||
|
Loop(UnionLayout<'a>),
|
||||||
|
}
|
||||||
|
|
||||||
|
fn modify_refcount_layout_help<'a, 'ctx, 'env>(
|
||||||
|
env: &Env<'a, 'ctx, 'env>,
|
||||||
|
parent: FunctionValue<'ctx>,
|
||||||
|
layout_ids: &mut LayoutIds<'a>,
|
||||||
|
mode: Mode,
|
||||||
|
when_recursive: &WhenRecursive<'a>,
|
||||||
|
value: BasicValueEnum<'ctx>,
|
||||||
|
layout: &Layout<'a>,
|
||||||
) {
|
) {
|
||||||
use Layout::*;
|
use Layout::*;
|
||||||
|
|
||||||
match layout {
|
match layout {
|
||||||
Builtin(builtin) => modify_refcount_builtin(env, layout_ids, mode, value, layout, builtin),
|
Builtin(builtin) => modify_refcount_builtin(
|
||||||
|
env,
|
||||||
|
layout_ids,
|
||||||
|
mode,
|
||||||
|
when_recursive,
|
||||||
|
value,
|
||||||
|
layout,
|
||||||
|
builtin,
|
||||||
|
),
|
||||||
|
|
||||||
Union(variant) => {
|
Union(variant) => {
|
||||||
use UnionLayout::*;
|
use UnionLayout::*;
|
||||||
|
@ -408,6 +454,7 @@ fn modify_refcount_layout<'a, 'ctx, 'env>(
|
||||||
env,
|
env,
|
||||||
layout_ids,
|
layout_ids,
|
||||||
mode,
|
mode,
|
||||||
|
&WhenRecursive::Loop(variant.clone()),
|
||||||
tags,
|
tags,
|
||||||
value.into_pointer_value(),
|
value.into_pointer_value(),
|
||||||
true,
|
true,
|
||||||
|
@ -423,6 +470,7 @@ fn modify_refcount_layout<'a, 'ctx, 'env>(
|
||||||
env,
|
env,
|
||||||
layout_ids,
|
layout_ids,
|
||||||
mode,
|
mode,
|
||||||
|
&WhenRecursive::Loop(variant.clone()),
|
||||||
&*env.arena.alloc([other_fields]),
|
&*env.arena.alloc([other_fields]),
|
||||||
value.into_pointer_value(),
|
value.into_pointer_value(),
|
||||||
true,
|
true,
|
||||||
|
@ -436,6 +484,7 @@ fn modify_refcount_layout<'a, 'ctx, 'env>(
|
||||||
env,
|
env,
|
||||||
layout_ids,
|
layout_ids,
|
||||||
mode,
|
mode,
|
||||||
|
&WhenRecursive::Loop(variant.clone()),
|
||||||
&*env.arena.alloc([*fields]),
|
&*env.arena.alloc([*fields]),
|
||||||
value.into_pointer_value(),
|
value.into_pointer_value(),
|
||||||
true,
|
true,
|
||||||
|
@ -448,13 +497,16 @@ fn modify_refcount_layout<'a, 'ctx, 'env>(
|
||||||
env,
|
env,
|
||||||
layout_ids,
|
layout_ids,
|
||||||
mode,
|
mode,
|
||||||
|
&WhenRecursive::Loop(variant.clone()),
|
||||||
tags,
|
tags,
|
||||||
value.into_pointer_value(),
|
value.into_pointer_value(),
|
||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
NonRecursive(tags) => modify_refcount_union(env, layout_ids, mode, tags, value),
|
NonRecursive(tags) => {
|
||||||
|
modify_refcount_union(env, layout_ids, mode, when_recursive, tags, value)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Closure(_, closure_layout, _) => {
|
Closure(_, closure_layout, _) => {
|
||||||
|
@ -466,11 +518,12 @@ fn modify_refcount_layout<'a, 'ctx, 'env>(
|
||||||
.build_extract_value(wrapper_struct, 1, "modify_rc_closure_data")
|
.build_extract_value(wrapper_struct, 1, "modify_rc_closure_data")
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
modify_refcount_layout(
|
modify_refcount_layout_help(
|
||||||
env,
|
env,
|
||||||
parent,
|
parent,
|
||||||
layout_ids,
|
layout_ids,
|
||||||
mode,
|
mode,
|
||||||
|
when_recursive,
|
||||||
field_ptr,
|
field_ptr,
|
||||||
&closure_layout.as_block_of_memory_layout(),
|
&closure_layout.as_block_of_memory_layout(),
|
||||||
)
|
)
|
||||||
|
@ -478,12 +531,45 @@ fn modify_refcount_layout<'a, 'ctx, 'env>(
|
||||||
}
|
}
|
||||||
|
|
||||||
Struct(layouts) => {
|
Struct(layouts) => {
|
||||||
modify_refcount_struct(env, parent, layout_ids, value, layouts, mode);
|
modify_refcount_struct(
|
||||||
|
env,
|
||||||
|
parent,
|
||||||
|
layout_ids,
|
||||||
|
value,
|
||||||
|
layouts,
|
||||||
|
mode,
|
||||||
|
when_recursive,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
PhantomEmptyStruct => {}
|
PhantomEmptyStruct => {}
|
||||||
|
|
||||||
RecursivePointer => todo!("TODO implement decrement layout of recursive tag union"),
|
Layout::RecursivePointer => match when_recursive {
|
||||||
|
WhenRecursive::Unreachable => {
|
||||||
|
unreachable!("recursion pointers should never be hashed directly")
|
||||||
|
}
|
||||||
|
WhenRecursive::Loop(union_layout) => {
|
||||||
|
let layout = Layout::Union(union_layout.clone());
|
||||||
|
|
||||||
|
let bt = basic_type_from_layout(env.arena, env.context, &layout, env.ptr_bytes);
|
||||||
|
|
||||||
|
// cast the i64 pointer to a pointer to block of memory
|
||||||
|
let field_cast = env
|
||||||
|
.builder
|
||||||
|
.build_bitcast(value, bt, "i64_to_opaque")
|
||||||
|
.into_pointer_value();
|
||||||
|
|
||||||
|
modify_refcount_layout_help(
|
||||||
|
env,
|
||||||
|
parent,
|
||||||
|
layout_ids,
|
||||||
|
mode,
|
||||||
|
when_recursive,
|
||||||
|
field_cast.into(),
|
||||||
|
&layout,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
FunctionPointer(_, _) | Pointer(_) => {}
|
FunctionPointer(_, _) | Pointer(_) => {}
|
||||||
}
|
}
|
||||||
|
@ -493,6 +579,7 @@ fn modify_refcount_list<'a, 'ctx, 'env>(
|
||||||
env: &Env<'a, 'ctx, 'env>,
|
env: &Env<'a, 'ctx, 'env>,
|
||||||
layout_ids: &mut LayoutIds<'a>,
|
layout_ids: &mut LayoutIds<'a>,
|
||||||
mode: Mode,
|
mode: Mode,
|
||||||
|
when_recursive: &WhenRecursive<'a>,
|
||||||
layout: &Layout<'a>,
|
layout: &Layout<'a>,
|
||||||
element_layout: &Layout<'a>,
|
element_layout: &Layout<'a>,
|
||||||
original_wrapper: StructValue<'ctx>,
|
original_wrapper: StructValue<'ctx>,
|
||||||
|
@ -519,6 +606,7 @@ fn modify_refcount_list<'a, 'ctx, 'env>(
|
||||||
env,
|
env,
|
||||||
layout_ids,
|
layout_ids,
|
||||||
mode,
|
mode,
|
||||||
|
when_recursive,
|
||||||
layout,
|
layout,
|
||||||
element_layout,
|
element_layout,
|
||||||
function_value,
|
function_value,
|
||||||
|
@ -546,6 +634,7 @@ fn modify_refcount_list_help<'a, 'ctx, 'env>(
|
||||||
env: &Env<'a, 'ctx, 'env>,
|
env: &Env<'a, 'ctx, 'env>,
|
||||||
layout_ids: &mut LayoutIds<'a>,
|
layout_ids: &mut LayoutIds<'a>,
|
||||||
mode: Mode,
|
mode: Mode,
|
||||||
|
when_recursive: &WhenRecursive<'a>,
|
||||||
layout: &Layout<'a>,
|
layout: &Layout<'a>,
|
||||||
element_layout: &Layout<'a>,
|
element_layout: &Layout<'a>,
|
||||||
fn_val: FunctionValue<'ctx>,
|
fn_val: FunctionValue<'ctx>,
|
||||||
|
@ -594,7 +683,15 @@ fn modify_refcount_list_help<'a, 'ctx, 'env>(
|
||||||
let (len, ptr) = load_list(env.builder, original_wrapper, ptr_type);
|
let (len, ptr) = load_list(env.builder, original_wrapper, ptr_type);
|
||||||
|
|
||||||
let loop_fn = |_index, element| {
|
let loop_fn = |_index, element| {
|
||||||
modify_refcount_layout(env, parent, layout_ids, mode, element, element_layout);
|
modify_refcount_layout_help(
|
||||||
|
env,
|
||||||
|
parent,
|
||||||
|
layout_ids,
|
||||||
|
mode,
|
||||||
|
when_recursive,
|
||||||
|
element,
|
||||||
|
element_layout,
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
incrementing_elem_loop(
|
incrementing_elem_loop(
|
||||||
|
@ -720,6 +817,7 @@ fn modify_refcount_dict<'a, 'ctx, 'env>(
|
||||||
env: &Env<'a, 'ctx, 'env>,
|
env: &Env<'a, 'ctx, 'env>,
|
||||||
layout_ids: &mut LayoutIds<'a>,
|
layout_ids: &mut LayoutIds<'a>,
|
||||||
mode: Mode,
|
mode: Mode,
|
||||||
|
when_recursive: &WhenRecursive<'a>,
|
||||||
layout: &Layout<'a>,
|
layout: &Layout<'a>,
|
||||||
key_layout: &Layout<'a>,
|
key_layout: &Layout<'a>,
|
||||||
value_layout: &Layout<'a>,
|
value_layout: &Layout<'a>,
|
||||||
|
@ -747,6 +845,7 @@ fn modify_refcount_dict<'a, 'ctx, 'env>(
|
||||||
env,
|
env,
|
||||||
layout_ids,
|
layout_ids,
|
||||||
mode,
|
mode,
|
||||||
|
when_recursive,
|
||||||
layout,
|
layout,
|
||||||
key_layout,
|
key_layout,
|
||||||
value_layout,
|
value_layout,
|
||||||
|
@ -768,11 +867,18 @@ fn modify_refcount_dict_help<'a, 'ctx, 'env>(
|
||||||
env: &Env<'a, 'ctx, 'env>,
|
env: &Env<'a, 'ctx, 'env>,
|
||||||
layout_ids: &mut LayoutIds<'a>,
|
layout_ids: &mut LayoutIds<'a>,
|
||||||
mode: Mode,
|
mode: Mode,
|
||||||
|
when_recursive: &WhenRecursive<'a>,
|
||||||
layout: &Layout<'a>,
|
layout: &Layout<'a>,
|
||||||
key_layout: &Layout<'a>,
|
key_layout: &Layout<'a>,
|
||||||
value_layout: &Layout<'a>,
|
value_layout: &Layout<'a>,
|
||||||
fn_val: FunctionValue<'ctx>,
|
fn_val: FunctionValue<'ctx>,
|
||||||
) {
|
) {
|
||||||
|
debug_assert_eq!(
|
||||||
|
when_recursive,
|
||||||
|
&WhenRecursive::Unreachable,
|
||||||
|
"TODO pipe when_recursive through the dict key/value inc/dec"
|
||||||
|
);
|
||||||
|
|
||||||
let builder = env.builder;
|
let builder = env.builder;
|
||||||
let ctx = env.context;
|
let ctx = env.context;
|
||||||
|
|
||||||
|
@ -909,6 +1015,7 @@ fn build_rec_union<'a, 'ctx, 'env>(
|
||||||
env: &Env<'a, 'ctx, 'env>,
|
env: &Env<'a, 'ctx, 'env>,
|
||||||
layout_ids: &mut LayoutIds<'a>,
|
layout_ids: &mut LayoutIds<'a>,
|
||||||
mode: Mode,
|
mode: Mode,
|
||||||
|
when_recursive: &WhenRecursive<'a>,
|
||||||
fields: &'a [&'a [Layout<'a>]],
|
fields: &'a [&'a [Layout<'a>]],
|
||||||
value: PointerValue<'ctx>,
|
value: PointerValue<'ctx>,
|
||||||
is_nullable: bool,
|
is_nullable: bool,
|
||||||
|
@ -935,7 +1042,15 @@ fn build_rec_union<'a, 'ctx, 'env>(
|
||||||
.into();
|
.into();
|
||||||
let function_value = build_header(env, basic_type, mode, &fn_name);
|
let function_value = build_header(env, basic_type, mode, &fn_name);
|
||||||
|
|
||||||
build_rec_union_help(env, layout_ids, mode, fields, function_value, is_nullable);
|
build_rec_union_help(
|
||||||
|
env,
|
||||||
|
layout_ids,
|
||||||
|
mode,
|
||||||
|
when_recursive,
|
||||||
|
fields,
|
||||||
|
function_value,
|
||||||
|
is_nullable,
|
||||||
|
);
|
||||||
|
|
||||||
env.builder.position_at_end(block);
|
env.builder.position_at_end(block);
|
||||||
env.builder
|
env.builder
|
||||||
|
@ -952,6 +1067,7 @@ fn build_rec_union_help<'a, 'ctx, 'env>(
|
||||||
env: &Env<'a, 'ctx, 'env>,
|
env: &Env<'a, 'ctx, 'env>,
|
||||||
layout_ids: &mut LayoutIds<'a>,
|
layout_ids: &mut LayoutIds<'a>,
|
||||||
mode: Mode,
|
mode: Mode,
|
||||||
|
when_recursive: &WhenRecursive<'a>,
|
||||||
tags: &[&[Layout<'a>]],
|
tags: &[&[Layout<'a>]],
|
||||||
fn_val: FunctionValue<'ctx>,
|
fn_val: FunctionValue<'ctx>,
|
||||||
is_nullable: bool,
|
is_nullable: bool,
|
||||||
|
@ -1108,7 +1224,15 @@ fn build_rec_union_help<'a, 'ctx, 'env>(
|
||||||
refcount_ptr.modify(call_mode, &layout, env);
|
refcount_ptr.modify(call_mode, &layout, env);
|
||||||
|
|
||||||
for (field, field_layout) in deferred_nonrec {
|
for (field, field_layout) in deferred_nonrec {
|
||||||
modify_refcount_layout(env, parent, layout_ids, mode, field, field_layout);
|
modify_refcount_layout_help(
|
||||||
|
env,
|
||||||
|
parent,
|
||||||
|
layout_ids,
|
||||||
|
mode,
|
||||||
|
when_recursive,
|
||||||
|
field,
|
||||||
|
field_layout,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let call_name = pick("recursive_tag_increment", "recursive_tag_decrement");
|
let call_name = pick("recursive_tag_increment", "recursive_tag_decrement");
|
||||||
|
@ -1223,6 +1347,7 @@ fn modify_refcount_union<'a, 'ctx, 'env>(
|
||||||
env: &Env<'a, 'ctx, 'env>,
|
env: &Env<'a, 'ctx, 'env>,
|
||||||
layout_ids: &mut LayoutIds<'a>,
|
layout_ids: &mut LayoutIds<'a>,
|
||||||
mode: Mode,
|
mode: Mode,
|
||||||
|
when_recursive: &WhenRecursive<'a>,
|
||||||
fields: &'a [&'a [Layout<'a>]],
|
fields: &'a [&'a [Layout<'a>]],
|
||||||
value: BasicValueEnum<'ctx>,
|
value: BasicValueEnum<'ctx>,
|
||||||
) {
|
) {
|
||||||
|
@ -1246,7 +1371,14 @@ fn modify_refcount_union<'a, 'ctx, 'env>(
|
||||||
let basic_type = block_of_memory(env.context, &layout, env.ptr_bytes);
|
let basic_type = block_of_memory(env.context, &layout, env.ptr_bytes);
|
||||||
let function_value = build_header(env, basic_type, mode, &fn_name);
|
let function_value = build_header(env, basic_type, mode, &fn_name);
|
||||||
|
|
||||||
modify_refcount_union_help(env, layout_ids, mode, fields, function_value);
|
modify_refcount_union_help(
|
||||||
|
env,
|
||||||
|
layout_ids,
|
||||||
|
mode,
|
||||||
|
when_recursive,
|
||||||
|
fields,
|
||||||
|
function_value,
|
||||||
|
);
|
||||||
|
|
||||||
function_value
|
function_value
|
||||||
}
|
}
|
||||||
|
@ -1263,6 +1395,7 @@ fn modify_refcount_union_help<'a, 'ctx, 'env>(
|
||||||
env: &Env<'a, 'ctx, 'env>,
|
env: &Env<'a, 'ctx, 'env>,
|
||||||
layout_ids: &mut LayoutIds<'a>,
|
layout_ids: &mut LayoutIds<'a>,
|
||||||
mode: Mode,
|
mode: Mode,
|
||||||
|
when_recursive: &WhenRecursive<'a>,
|
||||||
tags: &[&[Layout<'a>]],
|
tags: &[&[Layout<'a>]],
|
||||||
fn_val: FunctionValue<'ctx>,
|
fn_val: FunctionValue<'ctx>,
|
||||||
) {
|
) {
|
||||||
|
@ -1347,7 +1480,15 @@ fn modify_refcount_union_help<'a, 'ctx, 'env>(
|
||||||
.build_extract_value(wrapper_struct, i as u32, "modify_tag_field")
|
.build_extract_value(wrapper_struct, i as u32, "modify_tag_field")
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
modify_refcount_layout(env, parent, layout_ids, mode, field_ptr, field_layout);
|
modify_refcount_layout_help(
|
||||||
|
env,
|
||||||
|
parent,
|
||||||
|
layout_ids,
|
||||||
|
mode,
|
||||||
|
when_recursive,
|
||||||
|
field_ptr,
|
||||||
|
field_layout,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue