Skip to content

Commit

Permalink
datatype: finish layout corrections (JuliaLang#43306)
Browse files Browse the repository at this point in the history
We still had some discrepancies between what the code thought could be
computed for a layout, and what we actually could compute layout for.
This hopefully makes those two computations now always give the same
answers (with the assistance of the layout cache).

Fixes JuliaLang#43303
  • Loading branch information
vtjnash authored and LilithHafner committed Mar 8, 2022
1 parent 668d16f commit 83ea91a
Show file tree
Hide file tree
Showing 5 changed files with 29 additions and 45 deletions.
39 changes: 8 additions & 31 deletions src/array.c
Original file line number Diff line number Diff line change
Expand Up @@ -219,51 +219,28 @@ JL_DLLEXPORT jl_array_t *jl_reshape_array(jl_value_t *atype, jl_array_t *data,
jl_value_t *_dims)
{
jl_task_t *ct = jl_current_task;
jl_array_t *a;
assert(jl_types_equal(jl_tparam0(jl_typeof(data)), jl_tparam0(atype)));

size_t ndims = jl_nfields(_dims);
assert(is_ntuple_long(_dims));
size_t *dims = (size_t*)_dims;
assert(jl_types_equal(jl_tparam0(jl_typeof(data)), jl_tparam0(atype)));

int ndimwords = jl_array_ndimwords(ndims);
int tsz = sizeof(jl_array_t) + ndimwords * sizeof(size_t) + sizeof(void*);
a = (jl_array_t*)jl_gc_alloc(ct->ptls, tsz, atype);
jl_array_t *a = (jl_array_t*)jl_gc_alloc(ct->ptls, tsz, atype);
// No allocation or safepoint allowed after this
// copy data (except dims) from the old object
a->flags.pooled = tsz <= GC_MAX_SZCLASS;
a->flags.ndims = ndims;
a->offset = 0;
a->data = NULL;
a->flags.isaligned = data->flags.isaligned;
jl_array_t *owner = (jl_array_t*)jl_array_owner(data);
jl_value_t *eltype = jl_tparam0(atype);
size_t elsz = 0, align = 0;
int isboxed = !jl_islayout_inline(eltype, &elsz, &align);
assert(isboxed == data->flags.ptrarray);
if (!isboxed) {
a->elsize = LLT_ALIGN(elsz, align);
jl_value_t *ownerty = jl_typeof(owner);
size_t oldelsz = 0, oldalign = 0;
if (ownerty == (jl_value_t*)jl_string_type) {
oldalign = 1;
}
else {
jl_islayout_inline(jl_tparam0(ownerty), &oldelsz, &oldalign);
}
if (oldalign < align)
jl_exceptionf(jl_argumenterror_type,
"reinterpret from alignment %d bytes to alignment %d bytes not allowed",
(int) oldalign, (int) align);
a->flags.ptrarray = 0;
a->flags.hasptr = data->flags.hasptr;
}
else {
a->elsize = sizeof(void*);
a->flags.ptrarray = 1;
a->flags.hasptr = 0;
}
a->elsize = data->elsize;
a->flags.ptrarray = data->flags.ptrarray;
a->flags.hasptr = data->flags.hasptr;

// if data is itself a shared wrapper,
// owner should point back to the original array
jl_array_t *owner = (jl_array_t*)jl_array_owner(data);
jl_array_data_owner(a) = (jl_value_t*)owner;

a->flags.how = 3;
Expand Down
12 changes: 6 additions & 6 deletions src/datatype.c
Original file line number Diff line number Diff line change
Expand Up @@ -248,9 +248,9 @@ int jl_struct_try_layout(jl_datatype_t *dt)
return 1;
}

int jl_datatype_isinlinealloc(jl_datatype_t *ty, int pointerfree) JL_NOTSAFEPOINT
int jl_datatype_isinlinealloc(jl_datatype_t *ty, int pointerfree)
{
if (ty->name->mayinlinealloc && (ty->isconcretetype || ((jl_datatype_t*)jl_unwrap_unionall(ty->name->wrapper))->layout)) { // TODO: use jl_struct_try_layout(dt) (but it is a safepoint)
if (ty->name->mayinlinealloc && jl_struct_try_layout(ty)) {
if (ty->layout->npointers > 0) {
if (pointerfree)
return 0;
Expand All @@ -264,7 +264,7 @@ int jl_datatype_isinlinealloc(jl_datatype_t *ty, int pointerfree) JL_NOTSAFEPOIN
return 0;
}

static unsigned union_isinlinable(jl_value_t *ty, int pointerfree, size_t *nbytes, size_t *align, int asfield) JL_NOTSAFEPOINT
static unsigned union_isinlinable(jl_value_t *ty, int pointerfree, size_t *nbytes, size_t *align, int asfield)
{
if (jl_is_uniontype(ty)) {
unsigned na = union_isinlinable(((jl_uniontype_t*)ty)->a, 1, nbytes, align, asfield);
Expand All @@ -290,19 +290,19 @@ static unsigned union_isinlinable(jl_value_t *ty, int pointerfree, size_t *nbyte
return 0;
}

int jl_uniontype_size(jl_value_t *ty, size_t *sz) JL_NOTSAFEPOINT
int jl_uniontype_size(jl_value_t *ty, size_t *sz)
{
size_t al = 0;
return union_isinlinable(ty, 0, sz, &al, 0) != 0;
}

JL_DLLEXPORT int jl_islayout_inline(jl_value_t *eltype, size_t *fsz, size_t *al) JL_NOTSAFEPOINT
JL_DLLEXPORT int jl_islayout_inline(jl_value_t *eltype, size_t *fsz, size_t *al)
{
unsigned countbits = union_isinlinable(eltype, 0, fsz, al, 1);
return (countbits > 0 && countbits < 127) ? countbits : 0;
}

JL_DLLEXPORT int jl_stored_inline(jl_value_t *eltype) JL_NOTSAFEPOINT
JL_DLLEXPORT int jl_stored_inline(jl_value_t *eltype)
{
size_t fsz = 0, al = 0;
return jl_islayout_inline(eltype, &fsz, &al);
Expand Down
10 changes: 4 additions & 6 deletions src/jltypes.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,10 @@ static int layout_uses_free_typevars(jl_value_t *v, jl_typeenv_t *env)
layout_uses_free_typevars(((jl_uniontype_t*)v)->b, env);
if (jl_is_vararg(v)) {
jl_vararg_t *vm = (jl_vararg_t*)v;
if (vm->T) {
if (layout_uses_free_typevars(vm->T, env))
return 1;
if (vm->N && layout_uses_free_typevars(vm->N, env))
return 1;
}
if (vm->T && layout_uses_free_typevars(vm->T, env))
return 1;
if (vm->N && layout_uses_free_typevars(vm->N, env))
return 1;
return 0;
}
if (jl_is_unionall(v)) {
Expand Down
4 changes: 2 additions & 2 deletions src/julia.h
Original file line number Diff line number Diff line change
Expand Up @@ -1480,8 +1480,8 @@ JL_DLLEXPORT void jl_set_nth_field(jl_value_t *v, size_t i, jl_value_t *r
JL_DLLEXPORT int jl_field_isdefined(jl_value_t *v, size_t i) JL_NOTSAFEPOINT;
JL_DLLEXPORT jl_value_t *jl_get_field(jl_value_t *o, const char *fld);
JL_DLLEXPORT jl_value_t *jl_value_ptr(jl_value_t *a);
int jl_uniontype_size(jl_value_t *ty, size_t *sz) JL_NOTSAFEPOINT;
JL_DLLEXPORT int jl_islayout_inline(jl_value_t *eltype, size_t *fsz, size_t *al) JL_NOTSAFEPOINT;
int jl_uniontype_size(jl_value_t *ty, size_t *sz);
JL_DLLEXPORT int jl_islayout_inline(jl_value_t *eltype, size_t *fsz, size_t *al);

// arrays
JL_DLLEXPORT jl_array_t *jl_new_array(jl_value_t *atype, jl_value_t *dims);
Expand Down
9 changes: 9 additions & 0 deletions test/compiler/codegen.jl
Original file line number Diff line number Diff line change
Expand Up @@ -603,6 +603,15 @@ get_llvm(g41438, ()); # cause allocation of layout
@test S41438{Int}.layout != C_NULL
@test !Base.datatype_pointerfree(S41438{Int})


# issue #43303
struct A43303{T}
x::Pair{Ptr{T},Ptr{T}}
end
@test A43303.body.layout != C_NULL
@test isbitstype(A43303{Int})
@test A43303.body.types[1].layout != C_NULL

# issue #41157
f41157(a, b) = a[1] = b[1]
@test_throws BoundsError f41157(Tuple{Int}[], Tuple{Union{}}[])
Expand Down

0 comments on commit 83ea91a

Please sign in to comment.