@@ -220,27 +220,36 @@ unsigned jl_special_vector_alignment(size_t nfields, jl_value_t *t)
220220 return next_power_of_two (size );
221221}
222222
223- STATIC_INLINE int jl_is_datatype_make_singleton (jl_datatype_t * d )
223+ STATIC_INLINE int jl_is_datatype_make_singleton (jl_datatype_t * d ) JL_NOTSAFEPOINT
224224{
225225 return (!d -> name -> abstract && jl_datatype_size (d ) == 0 && d != jl_symbol_type && d -> name != jl_array_typename &&
226226 d -> isconcretetype && !d -> name -> mutabl );
227227}
228228
229- STATIC_INLINE void jl_maybe_allocate_singleton_instance (jl_datatype_t * st )
229+ STATIC_INLINE void jl_maybe_allocate_singleton_instance (jl_datatype_t * st ) JL_NOTSAFEPOINT
230230{
231231 if (jl_is_datatype_make_singleton (st )) {
232232 // It's possible for st to already have an ->instance if it was redefined
233- if (!st -> instance ) {
234- jl_task_t * ct = jl_current_task ;
235- st -> instance = jl_gc_alloc (ct -> ptls , 0 , st );
236- jl_gc_wb (st , st -> instance );
237- }
233+ if (!st -> instance )
234+ st -> instance = jl_gc_permobj (0 , st );
238235 }
239236}
240237
238+ // return whether all concrete subtypes of this type have the same layout
239+ int jl_struct_try_layout (jl_datatype_t * dt )
240+ {
241+ if (dt -> layout )
242+ return 1 ;
243+ else if (!jl_has_fixed_layout (dt ))
244+ return 0 ;
245+ jl_compute_field_offsets (dt );
246+ assert (dt -> layout );
247+ return 1 ;
248+ }
249+
241250int jl_datatype_isinlinealloc (jl_datatype_t * ty , int pointerfree ) JL_NOTSAFEPOINT
242251{
243- if (ty -> name -> mayinlinealloc && ty -> layout ) {
252+ 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)
244253 if (ty -> layout -> npointers > 0 ) {
245254 if (pointerfree )
246255 return 0 ;
@@ -348,28 +357,31 @@ void jl_compute_field_offsets(jl_datatype_t *st)
348357 if (st -> name -> wrapper == NULL )
349358 return ; // we got called too early--we'll be back
350359 jl_datatype_t * w = (jl_datatype_t * )jl_unwrap_unionall (st -> name -> wrapper );
351- assert (st -> types && w -> types );
352- size_t i , nfields = jl_svec_len (st -> types );
353- assert (st -> name -> n_uninitialized <= nfields );
354360 if (st == w && st -> layout ) {
355361 // this check allows us to force re-computation of the layout for some types during init
356362 st -> layout = NULL ;
357363 st -> size = 0 ;
358364 st -> zeroinit = 0 ;
359365 st -> has_concrete_subtype = 1 ;
360366 }
367+ int isbitstype = st -> isconcretetype && st -> name -> mayinlinealloc ;
361368 // If layout doesn't depend on type parameters, it's stored in st->name->wrapper
362369 // and reused by all subtypes.
363370 if (w -> layout ) {
364371 st -> layout = w -> layout ;
365372 st -> size = w -> size ;
366373 st -> zeroinit = w -> zeroinit ;
367374 st -> has_concrete_subtype = w -> has_concrete_subtype ;
368- if (jl_is_layout_opaque (st -> layout )) { // e.g. jl_array_typename
369- return ;
375+ if (!jl_is_layout_opaque (st -> layout )) { // e.g. jl_array_typename
376+ st -> isbitstype = isbitstype && st -> layout -> npointers == 0 ;
377+ jl_maybe_allocate_singleton_instance (st );
370378 }
379+ return ;
371380 }
372- else if (nfields == 0 ) {
381+ assert (st -> types && w -> types );
382+ size_t i , nfields = jl_svec_len (st -> types );
383+ assert (st -> name -> n_uninitialized <= nfields );
384+ if (nfields == 0 ) {
373385 // if we have no fields, we can trivially skip the rest
374386 if (st == jl_symbol_type || st == jl_string_type ) {
375387 // opaque layout - heap-allocated blob
@@ -404,7 +416,6 @@ void jl_compute_field_offsets(jl_datatype_t *st)
404416 }
405417 }
406418
407- int isbitstype = st -> isconcretetype && st -> name -> mayinlinealloc ;
408419 for (i = 0 ; isbitstype && i < nfields ; i ++ ) {
409420 jl_value_t * fld = jl_field_type (st , i );
410421 isbitstype = jl_isbits (fld );
0 commit comments