Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 28 additions & 7 deletions src/builtins.c
Original file line number Diff line number Diff line change
Expand Up @@ -1487,22 +1487,38 @@ static int equiv_field_types(jl_value_t *old, jl_value_t *ft)
return 1;
}

// If a field can reference its enclosing type, then the inlining
// recursive depth is not statically bounded for some layouts, so we cannot
// inline it. The only way fields can reference this type (due to
// syntax-enforced restrictions) is via being passed as a type parameter. Thus
// we can conservatively check this by examining only the parameters of the
// dependent types.
// affects_layout is a hack introduced by #35275 to workaround a problem
// introduced by #34223: it checks whether we will potentially need to
// compute the layout of the object before we have fully computed the types of
// the fields during recursion over the allocation of the parameters for the
// field types (of the concrete subtypes)
static int references_name(jl_value_t *p, jl_typename_t *name, int affects_layout) JL_NOTSAFEPOINT
{
if (jl_is_uniontype(p))
return references_name(((jl_uniontype_t*)p)->a, name, affects_layout) ||
references_name(((jl_uniontype_t*)p)->b, name, affects_layout);
if (jl_is_unionall(p))
return references_name((jl_value_t*)((jl_unionall_t*)p)->var, name, 0) ||
return references_name((jl_value_t*)((jl_unionall_t*)p)->var->lb, name, 0) ||
references_name((jl_value_t*)((jl_unionall_t*)p)->var->ub, name, 0) ||
references_name(((jl_unionall_t*)p)->body, name, affects_layout);
if (jl_is_typevar(p))
return references_name(((jl_tvar_t*)p)->ub, name, 0) ||
references_name(((jl_tvar_t*)p)->lb, name, 0);
return 0; // already checked by unionall, if applicable
if (jl_is_datatype(p)) {
jl_datatype_t *dp = (jl_datatype_t*)p;
if (affects_layout && dp->name == name)
return 1;
affects_layout = dp->types == NULL || jl_svec_len(dp->types) != 0;
// affects_layout checks whether we will need to attempt to layout this
// type (based on whether all copies of it have the same layout) in
// that case, we still need to check the recursive parameters for
// layout recursion happening also, but we know it won't itself cause
// problems for the layout computation
affects_layout = ((jl_datatype_t*)jl_unwrap_unionall(dp->name->wrapper))->layout == NULL;
size_t i, l = jl_nparams(p);
for (i = 0; i < l; i++) {
if (references_name(jl_tparam(p, i), name, affects_layout))
Expand Down Expand Up @@ -1537,16 +1553,21 @@ JL_CALLABLE(jl_f__typebody)
else {
dt->types = (jl_svec_t*)ft;
jl_gc_wb(dt, ft);
if (!dt->name->mutabl) {
dt->name->mayinlinealloc = 1;
// If a supertype can reference the same type, then we may not be
// able to compute the layout of the object before needing to
// publish it, so we must assume it cannot be inlined, if that
// check passes, then we also still need to check the fields too.
if (!dt->name->mutabl && !references_name((jl_value_t*)dt->super, dt->name, 1)) {
int mayinlinealloc = 1;
size_t i, nf = jl_svec_len(ft);
for (i = 0; i < nf; i++) {
jl_value_t *fld = jl_svecref(ft, i);
if (references_name(fld, dt->name, 1)) {
dt->name->mayinlinealloc = 0;
mayinlinealloc = 0;
break;
}
}
dt->name->mayinlinealloc = mayinlinealloc;
}
}
}
Expand Down
13 changes: 11 additions & 2 deletions test/core.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7219,8 +7219,17 @@ end
struct B33954
x::Q33954{B33954}
end
@test_broken isbitstype(Tuple{B33954})
@test_broken isbitstype(B33954)
@test isbitstype(Tuple{B33954})
@test isbitstype(B33954)

struct A41503{d}
e::d
end
struct B41503{j,k} <: AbstractArray{A41503{B41503{Any,k}},Any}
l::k
end
@test !isbitstype(B41503{Any,Any})
@test_broken isbitstype(B41503{Any,Int})

struct B40050 <: Ref{Tuple{B40050}}
end
Expand Down