Merge pull request #1786 from rtfeldman/list-non-recursive-rc

make list inc/dec non-recursive (except when freeing the list)
This commit is contained in:
Richard Feldman 2021-10-17 18:13:24 -04:00 committed by GitHub
commit 6e0341890d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 59 additions and 22 deletions

View file

@ -736,32 +736,69 @@ fn modify_refcount_list_help<'a, 'ctx, 'env>(
builder.position_at_end(modification_block);
let ptr_type = basic_type_from_layout(env, element_layout).ptr_type(AddressSpace::Generic);
if element_layout.contains_refcounted() {
let ptr_type = basic_type_from_layout(env, element_layout).ptr_type(AddressSpace::Generic);
let (len, ptr) = load_list(env.builder, original_wrapper, ptr_type);
let loop_fn = |_index, element| {
modify_refcount_layout_help(
env,
parent,
layout_ids,
mode.to_call_mode(fn_val),
when_recursive,
element,
element_layout,
);
};
let refcount_ptr = PointerToRefcount::from_ptr_to_data(env, ptr);
let call_mode = mode_to_call_mode(fn_val, mode);
incrementing_elem_loop(env, parent, ptr, len, "modify_rc_index", loop_fn);
match mode {
Mode::Inc => {
// inc is cheap; we never recurse
refcount_ptr.modify(call_mode, layout, env);
builder.build_unconditional_branch(cont_block);
}
Mode::Dec => {
let do_recurse_block = env.context.append_basic_block(parent, "do_recurse");
let no_recurse_block = env.context.append_basic_block(parent, "no_recurse");
builder.build_conditional_branch(
refcount_ptr.is_1(env),
do_recurse_block,
no_recurse_block,
);
{
env.builder.position_at_end(no_recurse_block);
refcount_ptr.modify(call_mode, layout, env);
builder.build_unconditional_branch(cont_block);
}
{
env.builder.position_at_end(do_recurse_block);
let loop_fn = |_index, element| {
modify_refcount_layout_help(
env,
parent,
layout_ids,
mode.to_call_mode(fn_val),
when_recursive,
element,
element_layout,
);
};
incrementing_elem_loop(env, parent, ptr, len, "modify_rc_index", loop_fn);
builder.build_unconditional_branch(cont_block);
}
}
}
} else {
// just increment/decrement the list itself, don't touch the elements
let (_, ptr) = load_list(env.builder, original_wrapper, ptr_type);
let refcount_ptr = PointerToRefcount::from_ptr_to_data(env, ptr);
let call_mode = mode_to_call_mode(fn_val, mode);
refcount_ptr.modify(call_mode, layout, env);
builder.build_unconditional_branch(cont_block);
}
let refcount_ptr = PointerToRefcount::from_list_wrapper(env, original_wrapper);
let call_mode = mode_to_call_mode(fn_val, mode);
refcount_ptr.modify(call_mode, layout, env);
builder.build_unconditional_branch(cont_block);
builder.position_at_end(cont_block);
// this function returns void