Skip to content

Commit 4e0d353

Browse files
carnavalvtjnash
authored andcommitted
datatype: generalize the format used for isptr handling
This lets us scan a datatype slightly easier, and opens up a future possibility where we don't have a one-to-one relationship between fields and contained pointers.
1 parent b7d5328 commit 4e0d353

9 files changed

Lines changed: 126 additions & 154 deletions

File tree

base/reflection.jl

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -317,10 +317,10 @@ datatype_fieldtypes(x::DataType) = ccall(:jl_get_fieldtypes, Any, (Any,), x)
317317

318318
struct DataTypeLayout
319319
nfields::UInt32
320+
npointers::UInt32
320321
alignment::UInt32
321-
# alignment : 28;
322+
# alignment : 9;
322323
# haspadding : 1;
323-
# pointerfree : 1;
324324
# fielddesc_type : 2;
325325
end
326326

@@ -380,8 +380,8 @@ Can be called on any `isconcretetype`.
380380
function datatype_pointerfree(dt::DataType)
381381
@_pure_meta
382382
dt.layout == C_NULL && throw(UndefRefError())
383-
alignment = unsafe_load(convert(Ptr{DataTypeLayout}, dt.layout)).alignment
384-
return (alignment >> 10) & 0xFFFFF == 0
383+
npointers = unsafe_load(convert(Ptr{DataTypeLayout}, dt.layout)).npointers
384+
return npointers == 0
385385
end
386386

387387
"""
@@ -397,7 +397,7 @@ function datatype_fielddesc_type(dt::DataType)
397397
@_pure_meta
398398
dt.layout == C_NULL && throw(UndefRefError())
399399
alignment = unsafe_load(convert(Ptr{DataTypeLayout}, dt.layout)).alignment
400-
return (alignment >> 30) & 3
400+
return (alignment >> 10) & 3
401401
end
402402

403403
"""

src/datatype.c

Lines changed: 44 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -99,29 +99,22 @@ jl_datatype_t *jl_new_uninitialized_datatype(void)
9999
}
100100

101101
static jl_datatype_layout_t *jl_get_layout(uint32_t nfields,
102+
uint32_t npointers,
102103
uint32_t alignment,
103104
int haspadding,
104-
jl_fielddesc32_t desc[]) JL_NOTSAFEPOINT
105+
jl_fielddesc32_t desc[],
106+
uint32_t pointers[]) JL_NOTSAFEPOINT
105107
{
106108
// compute the smallest fielddesc type that can hold the layout description
107109
int fielddesc_type = 0;
108-
uint32_t npointers = 0;
109-
// First pointer field
110-
uint32_t first_ptr = (uint32_t)-1;
111-
// Last pointer field
112-
uint32_t last_ptr = 0;
113110
if (nfields > 0) {
114111
uint32_t max_size = 0;
115112
uint32_t max_offset = desc[nfields - 1].offset;
113+
if (npointers > 0 && pointers[npointers - 1] > max_offset)
114+
max_offset = pointers[npointers - 1];
116115
for (size_t i = 0; i < nfields; i++) {
117116
if (desc[i].size > max_size)
118117
max_size = desc[i].size;
119-
if (desc[i].isptr) {
120-
npointers++;
121-
if (first_ptr == (uint32_t)-1)
122-
first_ptr = i;
123-
last_ptr = i;
124-
}
125118
}
126119
jl_fielddesc8_t maxdesc8 = { 0, max_size, max_offset };
127120
jl_fielddesc16_t maxdesc16 = { 0, max_size, max_offset };
@@ -140,24 +133,14 @@ static jl_datatype_layout_t *jl_get_layout(uint32_t nfields,
140133
// allocate a new descriptor
141134
// TODO: lots of these are the same--take advantage of the fact these are immutable to combine them
142135
uint32_t fielddesc_size = jl_fielddesc_size(fielddesc_type);
143-
int has_padding = nfields && npointers;
144-
jl_datatype_layout_t *flddesc =
145-
(jl_datatype_layout_t*)jl_gc_perm_alloc(sizeof(jl_datatype_layout_t) +
146-
nfields * fielddesc_size +
147-
(has_padding ? sizeof(uint32_t) : 0), 0, 4, 0);
148-
if (has_padding) {
149-
if (first_ptr > UINT16_MAX)
150-
first_ptr = UINT16_MAX;
151-
last_ptr = nfields - last_ptr - 1;
152-
if (last_ptr > UINT16_MAX)
153-
last_ptr = UINT16_MAX;
154-
flddesc = (jl_datatype_layout_t*)(((char*)flddesc) + sizeof(uint32_t));
155-
jl_datatype_layout_n_nonptr(flddesc) = (first_ptr << 16) | last_ptr;
156-
}
136+
jl_datatype_layout_t *flddesc = (jl_datatype_layout_t*)jl_gc_perm_alloc(
137+
sizeof(jl_datatype_layout_t) + nfields * fielddesc_size + (npointers << fielddesc_type),
138+
0, 4, 0);
157139
flddesc->nfields = nfields;
158140
flddesc->alignment = alignment;
159141
flddesc->haspadding = haspadding;
160142
flddesc->fielddesc_type = fielddesc_type;
143+
flddesc->npointers = npointers;
161144

162145
// fill out the fields of the new descriptor
163146
jl_fielddesc8_t* desc8 = (jl_fielddesc8_t*)jl_dt_layout_fields(flddesc);
@@ -180,12 +163,20 @@ static jl_datatype_layout_t *jl_get_layout(uint32_t nfields,
180163
desc32[i].isptr = desc[i].isptr;
181164
}
182165
}
183-
uint32_t nexp = 0;
184-
while (npointers >= 0x10000) {
185-
nexp++;
186-
npointers = npointers >> 1;
166+
uint8_t* ptrs8 = (uint8_t*)jl_dt_layout_ptrs(flddesc);
167+
uint16_t* ptrs16 = (uint16_t*)jl_dt_layout_ptrs(flddesc);
168+
uint32_t* ptrs32 = (uint32_t*)jl_dt_layout_ptrs(flddesc);
169+
for (size_t i = 0; i < npointers; i++) {
170+
if (fielddesc_type == 0) {
171+
ptrs8[i] = pointers[i];
172+
}
173+
else if (fielddesc_type == 1) {
174+
ptrs16[i] = pointers[i];
175+
}
176+
else {
177+
ptrs32[i] = pointers[i];
178+
}
187179
}
188-
flddesc->npointers = npointers | (nexp << 16);
189180
return flddesc;
190181
}
191182

@@ -340,18 +331,18 @@ void jl_compute_field_offsets(jl_datatype_t *st)
340331
// if we have no fields, we can trivially skip the rest
341332
if (st == jl_symbol_type || st == jl_string_type) {
342333
// opaque layout - heap-allocated blob
343-
static const jl_datatype_layout_t opaque_byte_layout = {0, 1, 0, 1, 0};
334+
static const jl_datatype_layout_t opaque_byte_layout = {0, 1, 1, 0, 0};
344335
st->layout = &opaque_byte_layout;
345336
return;
346337
}
347338
else if (st == jl_simplevector_type || st->name == jl_array_typename) {
348-
static const jl_datatype_layout_t opaque_ptr_layout = {0, sizeof(void*), 0, 1, 0};
339+
static const jl_datatype_layout_t opaque_ptr_layout = {0, 1, sizeof(void*), 0, 0};
349340
st->layout = &opaque_ptr_layout;
350341
return;
351342
}
352343
else {
353344
// reuse the same layout for all singletons
354-
static const jl_datatype_layout_t singleton_layout = {0, 1, 0, 0, 0};
345+
static const jl_datatype_layout_t singleton_layout = {0, 0, 1, 0, 0};
355346
st->layout = &singleton_layout;
356347
}
357348
}
@@ -396,6 +387,7 @@ void jl_compute_field_offsets(jl_datatype_t *st)
396387
if (st->layout == NULL) {
397388
size_t descsz = nfields * sizeof(jl_fielddesc32_t);
398389
jl_fielddesc32_t *desc;
390+
uint32_t *pointers;
399391
int should_malloc = descsz >= jl_page_size;
400392
if (should_malloc)
401393
desc = (jl_fielddesc32_t*)malloc_s(descsz);
@@ -406,6 +398,7 @@ void jl_compute_field_offsets(jl_datatype_t *st)
406398
int zeroinit = 0;
407399
int haspadding = 0;
408400
int homogeneous = 1;
401+
uint32_t npointers = 0;
409402
jl_value_t *firstty = jl_field_type(st, 0);
410403
for (i = 0; i < nfields; i++) {
411404
jl_value_t *fld = jl_field_type(st, i);
@@ -434,6 +427,7 @@ void jl_compute_field_offsets(jl_datatype_t *st)
434427
al = fsz;
435428
desc[i].isptr = 1;
436429
zeroinit = 1;
430+
npointers++;
437431
}
438432
assert(al <= JL_HEAP_ALIGNMENT && (JL_HEAP_ALIGNMENT % al) == 0);
439433
if (al != 0) {
@@ -464,9 +458,22 @@ void jl_compute_field_offsets(jl_datatype_t *st)
464458
st->size = LLT_ALIGN(sz, alignm);
465459
if (st->size > sz)
466460
haspadding = 1;
467-
st->layout = jl_get_layout(nfields, alignm, haspadding, desc);
468-
if (should_malloc)
461+
if (should_malloc && npointers)
462+
pointers = (uint32_t*)malloc_s(npointers * sizeof(uint32_t));
463+
else
464+
pointers = (uint32_t*)alloca(npointers * sizeof(uint32_t));
465+
size_t ptr_i = 0;
466+
for (i = 0; i < nfields; i++) {
467+
if (desc[i].isptr)
468+
pointers[ptr_i++] = desc[i].offset / sizeof(jl_value_t**);
469+
}
470+
assert(ptr_i == npointers);
471+
st->layout = jl_get_layout(nfields, npointers, alignm, haspadding, desc, pointers);
472+
if (should_malloc) {
469473
free(desc);
474+
if (npointers)
475+
free(pointers);
476+
}
470477
}
471478
// now finish deciding if this instantiation qualifies for special properties
472479
assert(!isbitstype || st->layout->npointers == 0); // the definition of isbits
@@ -577,7 +584,7 @@ JL_DLLEXPORT jl_datatype_t *jl_new_primitivetype(jl_value_t *name, jl_module_t *
577584
alignm = MAX_ALIGN;
578585
bt->isbitstype = bt->isinlinealloc = (parameters == jl_emptysvec);
579586
bt->size = nbytes;
580-
bt->layout = jl_get_layout(0, alignm, 0, NULL);
587+
bt->layout = jl_get_layout(0, 0, alignm, 0, NULL, NULL);
581588
bt->instance = NULL;
582589
return bt;
583590
}

src/dump.c

Lines changed: 12 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -393,13 +393,10 @@ static void jl_serialize_datatype(jl_serializer_state *s, jl_datatype_t *dt) JL_
393393
write_uint8(s->s, layout);
394394
if (layout == 0) {
395395
uint32_t nf = dt->layout->nfields;
396-
write_int32(s->s, nf);
397-
uint32_t alignment = ((uint32_t*)dt->layout)[1];
398-
write_int32(s->s, alignment);
399-
if (dt->layout->npointers && nf)
400-
write_int32(s->s, ((uint32_t*)dt->layout)[-1]);
396+
uint32_t np = dt->layout->npointers;
401397
size_t fieldsize = jl_fielddesc_size(dt->layout->fielddesc_type);
402-
ios_write(s->s, (char*)(&dt->layout[1]), nf * fieldsize);
398+
ios_write(s->s, (const char*)dt->layout, sizeof(*dt->layout));
399+
ios_write(s->s, (const char*)(dt->layout + 1), nf * fieldsize + (np << dt->layout->fielddesc_type));
403400
}
404401
}
405402

@@ -1441,29 +1438,17 @@ static jl_value_t *jl_deserialize_datatype(jl_serializer_state *s, int pos, jl_v
14411438
}
14421439
else {
14431440
assert(layout == 0);
1444-
uint32_t nf = read_int32(s->s);
1445-
uint32_t alignment = read_int32(s->s);
1446-
union {
1447-
struct {
1448-
uint32_t nf;
1449-
uint32_t alignment;
1450-
} buffer;
1451-
jl_datatype_layout_t layout;
1452-
} header;
1453-
header.buffer.nf = nf;
1454-
header.buffer.alignment = alignment;
1455-
int has_padding = header.layout.npointers && nf;
1456-
uint8_t fielddesc_type = header.layout.fielddesc_type;
1441+
jl_datatype_layout_t buffer;
1442+
ios_read(s->s, (char*)&buffer, sizeof(buffer));
1443+
uint32_t nf = buffer.nfields;
1444+
uint32_t np = buffer.npointers;
1445+
uint8_t fielddesc_type = buffer.fielddesc_type;
14571446
size_t fielddesc_size = nf > 0 ? jl_fielddesc_size(fielddesc_type) : 0;
14581447
jl_datatype_layout_t *layout = (jl_datatype_layout_t*)jl_gc_perm_alloc(
1459-
sizeof(jl_datatype_layout_t) + nf * fielddesc_size +
1460-
(has_padding ? sizeof(uint32_t) : 0), 0, 4, 0);
1461-
if (has_padding) {
1462-
layout = (jl_datatype_layout_t*)(((char*)layout) + sizeof(uint32_t));
1463-
jl_datatype_layout_n_nonptr(layout) = read_int32(s->s);
1464-
}
1465-
*layout = header.layout;
1466-
ios_read(s->s, (char*)&layout[1], nf * fielddesc_size);
1448+
sizeof(jl_datatype_layout_t) + nf * fielddesc_size + (np << fielddesc_type),
1449+
0, 4, 0);
1450+
*layout = buffer;
1451+
ios_read(s->s, (char*)(layout + 1), nf * fielddesc_size + (np << fielddesc_type));
14671452
dt->layout = layout;
14681453
}
14691454
}

src/gc-debug.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1310,7 +1310,7 @@ NOINLINE void gc_mark_loop_unwind(jl_ptls_t ptls, jl_gc_mark_sp_t sp, int pc_off
13101310
break;
13111311
}
13121312
jl_datatype_t *vt = (jl_datatype_t*)jl_typeof(data->parent);
1313-
jl_fielddesc8_t *desc = (jl_fielddesc8_t*)jl_dt_layout_fields(vt->layout);
1313+
uint8_t *desc = (uint8_t*)jl_dt_layout_ptrs(vt->layout);
13141314
jl_safe_printf("%p: %s Object (8bit) %p :: %p -- [%d, %d)\n of type ",
13151315
(void*)data, prefix, (void*)data->parent, ((void**)data->parent)[-1],
13161316
(int)(data->begin - desc), (int)(data->end - desc));
@@ -1323,7 +1323,7 @@ NOINLINE void gc_mark_loop_unwind(jl_ptls_t ptls, jl_gc_mark_sp_t sp, int pc_off
13231323
break;
13241324
}
13251325
jl_datatype_t *vt = (jl_datatype_t*)jl_typeof(data->parent);
1326-
jl_fielddesc16_t *desc = (jl_fielddesc16_t*)jl_dt_layout_fields(vt->layout);
1326+
uint16_t *desc = (uint16_t*)jl_dt_layout_ptrs(vt->layout);
13271327
jl_safe_printf("%p: %s Object (16bit) %p :: %p -- [%d, %d)\n of type ",
13281328
(void*)data, prefix, (void*)data->parent, ((void**)data->parent)[-1],
13291329
(int)(data->begin - desc), (int)(data->end - desc));
@@ -1336,7 +1336,7 @@ NOINLINE void gc_mark_loop_unwind(jl_ptls_t ptls, jl_gc_mark_sp_t sp, int pc_off
13361336
break;
13371337
}
13381338
jl_datatype_t *vt = (jl_datatype_t*)jl_typeof(data->parent);
1339-
jl_fielddesc32_t *desc = (jl_fielddesc32_t*)jl_dt_layout_fields(vt->layout);
1339+
uint32_t *desc = (uint32_t*)jl_dt_layout_ptrs(vt->layout);
13401340
jl_safe_printf("%p: %s Object (32bit) %p :: %p -- [%d, %d)\n of type ",
13411341
(void*)data, prefix, (void*)data->parent, ((void**)data->parent)[-1],
13421342
(int)(data->begin - desc), (int)(data->end - desc));

0 commit comments

Comments
 (0)