Skip to content

datatype: move size into layout #47170

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 29, 2022
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
4 changes: 2 additions & 2 deletions base/int.jl
Original file line number Diff line number Diff line change
Expand Up @@ -514,11 +514,11 @@ trailing_ones(x::Integer) = trailing_zeros(~x)

for to in BitInteger_types, from in (BitInteger_types..., Bool)
if !(to === from)
if to.size < from.size
if Core.sizeof(to) < Core.sizeof(from)
@eval rem(x::($from), ::Type{$to}) = trunc_int($to, x)
elseif from === Bool
@eval rem(x::($from), ::Type{$to}) = convert($to, x)
elseif from.size < to.size
elseif Core.sizeof(from) < Core.sizeof(to)
if from <: Signed
@eval rem(x::($from), ::Type{$to}) = sext_int($to, x)
else
Expand Down
7 changes: 3 additions & 4 deletions base/reflection.jl
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,7 @@ objectid(@nospecialize(x)) = ccall(:jl_object_id, UInt, (Any,), x)
datatype_fieldtypes(x::DataType) = ccall(:jl_get_fieldtypes, Core.SimpleVector, (Any,), x)

struct DataTypeLayout
size::UInt32
nfields::UInt32
npointers::UInt32
firstptr::Int32
Expand Down Expand Up @@ -546,8 +547,7 @@ function isstructtype(@nospecialize t)
t = unwrap_unionall(t)
# TODO: what to do for `Union`?
isa(t, DataType) || return false
hasfield = !isdefined(t, :types) || !isempty(t.types)
return hasfield || (t.size == 0 && !isabstracttype(t))
return !isprimitivetype(t) && !isabstracttype(t)
end

"""
Expand All @@ -561,8 +561,7 @@ function isprimitivetype(@nospecialize t)
t = unwrap_unionall(t)
# TODO: what to do for `Union`?
isa(t, DataType) || return false
hasfield = !isdefined(t, :types) || !isempty(t.types)
return !hasfield && t.size != 0 && !isabstracttype(t)
return (t.flags & 0x80) == 0x80
end

"""
Expand Down
5 changes: 3 additions & 2 deletions src/builtins.c
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ static int NOINLINE compare_fields(const jl_value_t *a, const jl_value_t *b, jl_
}
}
if (!ft->layout->haspadding) {
if (!bits_equal(ao, bo, ft->size))
if (!bits_equal(ao, bo, ft->layout->size))
return 0;
}
else {
Expand Down Expand Up @@ -1751,7 +1751,8 @@ static int equiv_type(jl_value_t *ta, jl_value_t *tb)
dta->name->abstract == dtb->name->abstract &&
dta->name->mutabl == dtb->name->mutabl &&
dta->name->n_uninitialized == dtb->name->n_uninitialized &&
(jl_svec_len(jl_field_names(dta)) != 0 || dta->size == dtb->size) &&
dta->isprimitivetype == dtb->isprimitivetype &&
(!dta->isprimitivetype || dta->layout->size == dtb->layout->size) &&
(dta->name->atomicfields == NULL
? dtb->name->atomicfields == NULL
: (dtb->name->atomicfields != NULL &&
Expand Down
24 changes: 15 additions & 9 deletions src/cgutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1076,9 +1076,13 @@ static Value *emit_datatype_nfields(jl_codectx_t &ctx, Value *dt)

static Value *emit_datatype_size(jl_codectx_t &ctx, Value *dt)
{
Value *Ptr = emit_bitcast(ctx, decay_derived(ctx, dt), getInt32PtrTy(ctx.builder.getContext()));
Value *Idx = ConstantInt::get(getSizeTy(ctx.builder.getContext()), offsetof(jl_datatype_t, size) / sizeof(int));
return tbaa_decorate(ctx.tbaa().tbaa_const, ctx.builder.CreateAlignedLoad(getInt32Ty(ctx.builder.getContext()), ctx.builder.CreateInBoundsGEP(getInt32Ty(ctx.builder.getContext()), Ptr, Idx), Align(sizeof(int32_t))));
Value *Ptr = emit_bitcast(ctx, decay_derived(ctx, dt), getInt32PtrTy(ctx.builder.getContext())->getPointerTo());
Value *Idx = ConstantInt::get(getSizeTy(ctx.builder.getContext()), offsetof(jl_datatype_t, layout) / sizeof(int32_t*));
Ptr = ctx.builder.CreateInBoundsGEP(getInt32PtrTy(ctx.builder.getContext()), Ptr, Idx);
Ptr = tbaa_decorate(ctx.tbaa().tbaa_const, ctx.builder.CreateAlignedLoad(getInt32PtrTy(ctx.builder.getContext()), Ptr, Align(sizeof(int32_t*))));
Idx = ConstantInt::get(getSizeTy(ctx.builder.getContext()), offsetof(jl_datatype_layout_t, size) / sizeof(int32_t));
Ptr = ctx.builder.CreateInBoundsGEP(getInt32Ty(ctx.builder.getContext()), Ptr, Idx);
return tbaa_decorate(ctx.tbaa().tbaa_const, ctx.builder.CreateAlignedLoad(getInt32Ty(ctx.builder.getContext()), Ptr, Align(sizeof(int32_t))));
}

/* this is valid code, it's simply unused
Expand Down Expand Up @@ -1129,7 +1133,6 @@ static Value *emit_sizeof(jl_codectx_t &ctx, const jl_cgval_t &p)
return dyn_size;
}
}
*/

static Value *emit_datatype_mutabl(jl_codectx_t &ctx, Value *dt)
{
Expand All @@ -1143,13 +1146,16 @@ static Value *emit_datatype_mutabl(jl_codectx_t &ctx, Value *dt)
mutabl = ctx.builder.CreateLShr(mutabl, 1);
return ctx.builder.CreateTrunc(mutabl, getInt1Ty(ctx.builder.getContext()));
}
*/

static Value *emit_datatype_isprimitivetype(jl_codectx_t &ctx, Value *dt)
static Value *emit_datatype_isprimitivetype(jl_codectx_t &ctx, Value *typ)
{
Value *immut = ctx.builder.CreateNot(emit_datatype_mutabl(ctx, dt));
Value *nofields = ctx.builder.CreateICmpEQ(emit_datatype_nfields(ctx, dt), Constant::getNullValue(getSizeTy(ctx.builder.getContext())));
Value *sized = ctx.builder.CreateICmpSGT(emit_datatype_size(ctx, dt), ConstantInt::get(getInt32Ty(ctx.builder.getContext()), 0));
return ctx.builder.CreateAnd(immut, ctx.builder.CreateAnd(nofields, sized));
Value *isprimitive;
isprimitive = ctx.builder.CreateConstInBoundsGEP1_32(getInt8Ty(ctx.builder.getContext()), emit_bitcast(ctx, decay_derived(ctx, typ), getInt8PtrTy(ctx.builder.getContext())), offsetof(jl_datatype_t, hash) + sizeof(((jl_datatype_t*)nullptr)->hash));
isprimitive = tbaa_decorate(ctx.tbaa().tbaa_const, ctx.builder.CreateAlignedLoad(getInt8Ty(ctx.builder.getContext()), isprimitive, Align(1)));
isprimitive = ctx.builder.CreateLShr(isprimitive, 7);
isprimitive = ctx.builder.CreateTrunc(isprimitive, getInt1Ty(ctx.builder.getContext()));
return isprimitive;
}

static Value *emit_datatype_name(jl_codectx_t &ctx, Value *dt)
Expand Down
39 changes: 21 additions & 18 deletions src/datatype.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ jl_datatype_t *jl_new_uninitialized_datatype(void)
t->hasfreetypevars = 0;
t->isdispatchtuple = 0;
t->isbitstype = 0;
t->isprimitivetype = 0;
t->zeroinit = 0;
t->has_concrete_subtype = 1;
t->cached_by_hash = 0;
Expand Down Expand Up @@ -169,7 +170,8 @@ HTIMPL_R(layoutcache, _hash_layout_djb2, layout_eq)
static htable_t layoutcache;
static int layoutcache_initialized = 0;

static jl_datatype_layout_t *jl_get_layout(uint32_t nfields,
static jl_datatype_layout_t *jl_get_layout(uint32_t sz,
uint32_t nfields,
uint32_t npointers,
uint32_t alignment,
int haspadding,
Expand Down Expand Up @@ -212,6 +214,7 @@ static jl_datatype_layout_t *jl_get_layout(uint32_t nfields,
jl_datatype_layout_t *allocamem = (jl_datatype_layout_t *)(should_malloc ? NULL : alloca(flddesc_sz));
jl_datatype_layout_t *flddesc = should_malloc ? mallocmem : allocamem;
assert(flddesc);
flddesc->size = sz;
flddesc->nfields = nfields;
flddesc->alignment = alignment;
flddesc->haspadding = haspadding;
Expand Down Expand Up @@ -453,7 +456,6 @@ void jl_compute_field_offsets(jl_datatype_t *st)
if (st == w && st->layout) {
// this check allows us to force re-computation of the layout for some types during init
st->layout = NULL;
st->size = 0;
st->zeroinit = 0;
st->has_concrete_subtype = 1;
}
Expand All @@ -462,7 +464,6 @@ void jl_compute_field_offsets(jl_datatype_t *st)
// and reused by all subtypes.
if (w->layout) {
st->layout = w->layout;
st->size = w->size;
st->zeroinit = w->zeroinit;
st->has_concrete_subtype = w->has_concrete_subtype;
if (!jl_is_layout_opaque(st->layout)) { // e.g. jl_array_typename
Expand All @@ -478,18 +479,18 @@ void jl_compute_field_offsets(jl_datatype_t *st)
// if we have no fields, we can trivially skip the rest
if (st == jl_symbol_type || st == jl_string_type) {
// opaque layout - heap-allocated blob
static const jl_datatype_layout_t opaque_byte_layout = {0, 1, -1, 1, 0, 0};
static const jl_datatype_layout_t opaque_byte_layout = {0, 0, 1, -1, 1, 0, 0};
st->layout = &opaque_byte_layout;
return;
}
else if (st == jl_simplevector_type || st == jl_module_type || st->name == jl_array_typename) {
static const jl_datatype_layout_t opaque_ptr_layout = {0, 1, -1, sizeof(void*), 0, 0};
static const jl_datatype_layout_t opaque_ptr_layout = {0, 0, 1, -1, sizeof(void*), 0, 0};
st->layout = &opaque_ptr_layout;
return;
}
else {
// reuse the same layout for all singletons
static const jl_datatype_layout_t singleton_layout = {0, 0, -1, 1, 0, 0};
static const jl_datatype_layout_t singleton_layout = {0, 0, 0, -1, 1, 0, 0};
st->layout = &singleton_layout;
}
}
Expand Down Expand Up @@ -610,9 +611,10 @@ void jl_compute_field_offsets(jl_datatype_t *st)
if (al > alignm)
alignm = al;
}
st->size = LLT_ALIGN(sz, alignm);
if (st->size > sz)
if (LLT_ALIGN(sz, alignm) > sz) {
haspadding = 1;
sz = LLT_ALIGN(sz, alignm);
}
if (should_malloc && npointers)
pointers = (uint32_t*)malloc_s(npointers * sizeof(uint32_t));
else
Expand All @@ -631,7 +633,7 @@ void jl_compute_field_offsets(jl_datatype_t *st)
}
}
assert(ptr_i == npointers);
st->layout = jl_get_layout(nfields, npointers, alignm, haspadding, desc, pointers);
st->layout = jl_get_layout(sz, nfields, npointers, alignm, haspadding, desc, pointers);
if (should_malloc) {
free(desc);
if (npointers)
Expand Down Expand Up @@ -679,7 +681,6 @@ JL_DLLEXPORT jl_datatype_t *jl_new_datatype(
jl_gc_wb(t, t->parameters);
t->types = ftypes;
if (ftypes != NULL) jl_gc_wb(t, t->types);
t->size = 0;

t->name = NULL;
if (jl_is_typename(name)) {
Expand Down Expand Up @@ -785,9 +786,12 @@ JL_DLLEXPORT jl_datatype_t *jl_new_primitivetype(jl_value_t *name, jl_module_t *
uint32_t alignm = next_power_of_two(nbytes);
if (alignm > MAX_ALIGN)
alignm = MAX_ALIGN;
// memoize isprimitivetype, since it is much easier than checking
// (dta->name->names == svec() && dta->layout && dta->layout->size != 0)
// and we easily have a free bit for it in the DataType flags
bt->isprimitivetype = 1;
bt->isbitstype = (parameters == jl_emptysvec);
bt->size = nbytes;
bt->layout = jl_get_layout(0, 0, alignm, 0, NULL, NULL);
bt->layout = jl_get_layout(nbytes, 0, 0, alignm, 0, NULL, NULL);
bt->instance = NULL;
return bt;
}
Expand All @@ -802,10 +806,10 @@ JL_DLLEXPORT jl_datatype_t * jl_new_foreign_type(jl_sym_t *name,
{
jl_datatype_t *bt = jl_new_datatype(name, module, super,
jl_emptysvec, jl_emptysvec, jl_emptysvec, jl_emptysvec, 0, 1, 0);
bt->size = large ? GC_MAX_SZCLASS+1 : 0;
jl_datatype_layout_t *layout = (jl_datatype_layout_t *)
jl_gc_perm_alloc(sizeof(jl_datatype_layout_t) + sizeof(jl_fielddescdyn_t),
0, 4, 0);
layout->size = large ? GC_MAX_SZCLASS+1 : 0;
layout->nfields = 0;
layout->alignment = sizeof(void *);
layout->haspadding = 1;
Expand Down Expand Up @@ -1064,7 +1068,7 @@ JL_DLLEXPORT jl_value_t *jl_atomic_cmpswap_bits(jl_datatype_t *dt, jl_datatype_t
// n.b.: this does not spuriously fail if there are padding bits
jl_task_t *ct = jl_current_task;
int isptr = jl_field_isptr(rettyp, 0);
jl_value_t *y = jl_gc_alloc(ct->ptls, isptr ? nb : rettyp->size, isptr ? dt : rettyp);
jl_value_t *y = jl_gc_alloc(ct->ptls, isptr ? nb : jl_datatype_size(rettyp), isptr ? dt : rettyp);
int success;
jl_datatype_t *et = (jl_datatype_t*)jl_typeof(expected);
if (nb == 0) {
Expand Down Expand Up @@ -1153,7 +1157,7 @@ JL_DLLEXPORT jl_value_t *jl_atomic_cmpswap_bits(jl_datatype_t *dt, jl_datatype_t
}
if (isptr) {
JL_GC_PUSH1(&y);
jl_value_t *z = jl_gc_alloc(ct->ptls, rettyp->size, rettyp);
jl_value_t *z = jl_gc_alloc(ct->ptls, jl_datatype_size(rettyp), rettyp);
*(jl_value_t**)z = y;
JL_GC_POP();
y = z;
Expand All @@ -1177,8 +1181,7 @@ JL_DLLEXPORT jl_value_t *jl_typemax_uint(jl_value_t *bt)

#define PERMBOXN_FUNC(nb,nw) \
jl_value_t *jl_permbox##nb(jl_datatype_t *t, int##nb##_t x) \
{ /* NOTE: t must be a concrete isbits datatype */ \
assert(jl_datatype_size(t) == sizeof(x)); \
{ /* n.b. t must be a concrete isbits datatype of the right size */ \
jl_value_t *v = jl_gc_permobj(nw * sizeof(void*), t); \
*(int##nb##_t*)jl_data_ptr(v) = x; \
return v; \
Expand Down Expand Up @@ -1823,7 +1826,7 @@ jl_value_t *replace_nth_field(jl_datatype_t *st, jl_value_t *v, size_t i, jl_val
rty = jl_nth_union_component(rty, *psel);
}
assert(!jl_field_isptr(rettyp, 0));
r = jl_gc_alloc(ct->ptls, rettyp->size, (jl_value_t*)rettyp);
r = jl_gc_alloc(ct->ptls, jl_datatype_size(rettyp), (jl_value_t*)rettyp);
int success = (rty == jl_typeof(expected));
if (needlock)
jl_lock_value(v);
Expand Down
14 changes: 7 additions & 7 deletions src/dump.c
Original file line number Diff line number Diff line change
Expand Up @@ -484,7 +484,6 @@ static void jl_serialize_datatype(jl_serializer_state *s, jl_datatype_t *dt) JL_
return;
}

write_int32(s->s, dt->size);
int has_instance = (dt->instance != NULL);
int has_layout = (dt->layout != NULL);
write_uint8(s->s, has_layout | (has_instance << 1));
Expand All @@ -494,7 +493,8 @@ static void jl_serialize_datatype(jl_serializer_state *s, jl_datatype_t *dt) JL_
| (dt->isbitstype << 3)
| (dt->zeroinit << 4)
| (dt->has_concrete_subtype << 5)
| (dt->cached_by_hash << 6));
| (dt->cached_by_hash << 6)
| (dt->isprimitivetype << 7));
write_int32(s->s, dt->hash);

if (has_layout) {
Expand Down Expand Up @@ -1071,13 +1071,14 @@ static void jl_serialize_value_(jl_serializer_state *s, jl_value_t *v, int as_li
return;
}
}
if (t->size <= 255) {
size_t tsz = jl_datatype_size(t);
if (tsz <= 255) {
write_uint8(s->s, TAG_SHORT_GENERAL);
write_uint8(s->s, t->size);
write_uint8(s->s, tsz);
}
else {
write_uint8(s->s, TAG_GENERAL);
write_int32(s->s, t->size);
write_int32(s->s, tsz);
}
jl_serialize_value(s, t);
if (t == jl_typename_type) {
Expand Down Expand Up @@ -1645,10 +1646,8 @@ static jl_value_t *jl_deserialize_datatype(jl_serializer_state *s, int pos, jl_v
backref_list.items[pos] = dt;
if (loc != NULL && loc != HT_NOTFOUND)
*loc = (jl_value_t*)dt;
size_t size = read_int32(s->s);
uint8_t flags = read_uint8(s->s);
uint8_t memflags = read_uint8(s->s);
dt->size = size;
int has_layout = flags & 1;
int has_instance = (flags >> 1) & 1;
dt->hasfreetypevars = memflags & 1;
Expand All @@ -1658,6 +1657,7 @@ static jl_value_t *jl_deserialize_datatype(jl_serializer_state *s, int pos, jl_v
dt->zeroinit = (memflags >> 4) & 1;
dt->has_concrete_subtype = (memflags >> 5) & 1;
dt->cached_by_hash = (memflags >> 6) & 1;
dt->isprimitivetype = (memflags >> 7) & 1;
dt->hash = read_int32(s->s);

if (has_layout) {
Expand Down
Loading