@@ -216,6 +216,38 @@ unsigned jl_special_vector_alignment(size_t nfields, jl_value_t *t)
216
216
return alignment ;
217
217
}
218
218
219
+ static int jl_layout_isbits (jl_value_t * ty )
220
+ {
221
+ if (jl_isbits (ty ) && jl_is_leaf_type (ty )) {
222
+ if (((jl_datatype_t * )ty )-> layout ) // layout check handles possible layout recursion
223
+ return 1 ;
224
+ }
225
+ return 0 ;
226
+ }
227
+
228
+ static unsigned jl_union_isbits (jl_value_t * ty , size_t * nbytes , size_t * align )
229
+ {
230
+ if (jl_is_uniontype (ty )) {
231
+ unsigned na = jl_union_isbits (((jl_uniontype_t * )ty )-> a , nbytes , align );
232
+ if (na == 0 )
233
+ return 0 ;
234
+ unsigned nb = jl_union_isbits (((jl_uniontype_t * )ty )-> b , nbytes , align );
235
+ if (nb == 0 )
236
+ return 0 ;
237
+ return na + nb ;
238
+ }
239
+ if (jl_layout_isbits (ty )) {
240
+ size_t sz = jl_datatype_size (ty );
241
+ size_t al = ((jl_datatype_t * )ty )-> layout -> alignment ;
242
+ if (* nbytes < sz )
243
+ * nbytes = sz ;
244
+ if (* align < al )
245
+ * align = al ;
246
+ return 1 ;
247
+ }
248
+ return 0 ;
249
+ }
250
+
219
251
void jl_compute_field_offsets (jl_datatype_t * st )
220
252
{
221
253
size_t sz = 0 , alignm = 1 ;
@@ -277,16 +309,22 @@ void jl_compute_field_offsets(jl_datatype_t *st)
277
309
278
310
for (size_t i = 0 ; i < nfields ; i ++ ) {
279
311
jl_value_t * ty = jl_field_type (st , i );
280
- size_t fsz , al ;
281
- if ( jl_isbits ( ty ) && jl_is_leaf_type (ty ) && (( jl_datatype_t * ) ty ) -> layout ) {
282
- fsz = jl_datatype_size ( ty );
312
+ size_t fsz = 0 , al = 0 ;
313
+ unsigned countbits = jl_union_isbits (ty , & fsz , & al );
314
+ if ( countbits > 0 && countbits < 127 ) {
283
315
// Should never happen
284
316
if (__unlikely (fsz > max_size ))
285
317
goto throw_ovf ;
286
318
al = jl_datatype_align (ty );
287
319
desc [i ].isptr = 0 ;
288
- if ((( jl_datatype_t * ) ty )-> layout -> haspadding )
320
+ if (jl_is_uniontype ( ty )) {
289
321
haspadding = 1 ;
322
+ fsz += 1 ; // selector byte
323
+ }
324
+ else { // isbits struct
325
+ if (((jl_datatype_t * )ty )-> layout -> haspadding )
326
+ haspadding = 1 ;
327
+ }
290
328
}
291
329
else {
292
330
fsz = sizeof (void * );
@@ -312,7 +350,7 @@ void jl_compute_field_offsets(jl_datatype_t *st)
312
350
goto throw_ovf ;
313
351
sz += fsz ;
314
352
}
315
- if (homogeneous && lastty != NULL && jl_is_tuple_type (st )) {
353
+ if (homogeneous && lastty != NULL && jl_is_tuple_type (st )) {
316
354
// Some tuples become LLVM vectors with stronger alignment than what was calculated above.
317
355
unsigned al = jl_special_vector_alignment (nfields , lastty );
318
356
assert (al % alignm == 0 );
@@ -326,10 +364,12 @@ void jl_compute_field_offsets(jl_datatype_t *st)
326
364
if (st -> size > sz )
327
365
haspadding = 1 ;
328
366
st -> layout = jl_get_layout (nfields , alignm , haspadding , desc );
329
- if (descsz >= jl_page_size ) free (desc );
367
+ if (descsz >= jl_page_size )
368
+ free (desc );
330
369
return ;
331
370
throw_ovf :
332
- if (descsz >= jl_page_size ) free (desc );
371
+ if (descsz >= jl_page_size )
372
+ free (desc );
333
373
jl_throw (jl_overflow_exception );
334
374
}
335
375
@@ -704,46 +744,69 @@ JL_DLLEXPORT jl_value_t *jl_get_nth_field(jl_value_t *v, size_t i)
704
744
{
705
745
jl_datatype_t * st = (jl_datatype_t * )jl_typeof (v );
706
746
assert (i < jl_datatype_nfields (st ));
707
- size_t offs = jl_field_offset (st ,i );
708
- if (jl_field_isptr (st ,i )) {
747
+ size_t offs = jl_field_offset (st , i );
748
+ if (jl_field_isptr (st , i )) {
709
749
return * (jl_value_t * * )((char * )v + offs );
710
750
}
711
- return jl_new_bits (jl_field_type (st ,i ), (char * )v + offs );
751
+ jl_value_t * ty = jl_field_type (st , i );
752
+ if (jl_is_uniontype (ty )) {
753
+ uint8_t sel = ((uint8_t * )v )[offs + jl_field_size (st , i ) - 1 ];
754
+ ty = jl_nth_union_component (ty , sel );
755
+ }
756
+ return jl_new_bits (ty , (char * )v + offs );
712
757
}
713
758
714
759
JL_DLLEXPORT jl_value_t * jl_get_nth_field_checked (jl_value_t * v , size_t i )
715
760
{
716
761
jl_datatype_t * st = (jl_datatype_t * )jl_typeof (v );
717
762
if (i >= jl_datatype_nfields (st ))
718
- jl_bounds_error_int (v , i + 1 );
719
- size_t offs = jl_field_offset (st ,i );
720
- if (jl_field_isptr (st ,i )) {
763
+ jl_bounds_error_int (v , i + 1 );
764
+ size_t offs = jl_field_offset (st , i );
765
+ if (jl_field_isptr (st , i )) {
721
766
jl_value_t * fval = * (jl_value_t * * )((char * )v + offs );
722
767
if (fval == NULL )
723
768
jl_throw (jl_undefref_exception );
724
769
return fval ;
725
770
}
726
- return jl_new_bits (jl_field_type (st ,i ), (char * )v + offs );
771
+ jl_value_t * ty = jl_field_type (st , i );
772
+ if (jl_is_uniontype (ty )) {
773
+ size_t fsz = jl_field_size (st , i );
774
+ uint8_t sel = ((uint8_t * )v )[offs + fsz - 1 ];
775
+ ty = jl_nth_union_component (ty , sel );
776
+ if (jl_is_datatype_singleton ((jl_datatype_t * )ty ))
777
+ return ((jl_datatype_t * )ty )-> instance ;
778
+ }
779
+ return jl_new_bits (ty , (char * )v + offs );
727
780
}
728
781
729
782
JL_DLLEXPORT void jl_set_nth_field (jl_value_t * v , size_t i , jl_value_t * rhs )
730
783
{
731
784
jl_datatype_t * st = (jl_datatype_t * )jl_typeof (v );
732
- size_t offs = jl_field_offset (st ,i );
733
- if (jl_field_isptr (st ,i )) {
785
+ size_t offs = jl_field_offset (st , i );
786
+ if (jl_field_isptr (st , i )) {
734
787
* (jl_value_t * * )((char * )v + offs ) = rhs ;
735
788
if (rhs != NULL ) jl_gc_wb (v , rhs );
736
789
}
737
790
else {
791
+ jl_value_t * ty = jl_field_type (st , i );
792
+ if (jl_is_uniontype (ty )) {
793
+ uint8_t * psel = & ((uint8_t * )v )[offs + jl_field_size (st , i ) - 1 ];
794
+ unsigned nth = 0 ;
795
+ if (!jl_find_union_component (ty , jl_typeof (rhs ), & nth ))
796
+ assert (0 && "invalid field assignment to isbits union" );
797
+ * psel = nth ;
798
+ if (jl_is_datatype_singleton ((jl_datatype_t * )ty ))
799
+ return ;
800
+ }
738
801
jl_assign_bits ((char * )v + offs , rhs );
739
802
}
740
803
}
741
804
742
805
JL_DLLEXPORT int jl_field_isdefined (jl_value_t * v , size_t i )
743
806
{
744
807
jl_datatype_t * st = (jl_datatype_t * )jl_typeof (v );
745
- size_t offs = jl_field_offset (st ,i );
746
- if (jl_field_isptr (st ,i )) {
808
+ size_t offs = jl_field_offset (st , i );
809
+ if (jl_field_isptr (st , i )) {
747
810
return * (jl_value_t * * )((char * )v + offs ) != NULL ;
748
811
}
749
812
return 1 ;
0 commit comments