@@ -244,17 +244,17 @@ static jl_datatype_layout_t *jl_get_layout(uint32_t sz,
244
244
if (fielddesc_type == 0 ) {
245
245
desc8 [i ].offset = desc [i ].offset ;
246
246
desc8 [i ].size = desc [i ].size ;
247
- desc8 [i ].isptr = desc [i ].isptr ;
247
+ desc8 [i ].kind = desc [i ].kind ;
248
248
}
249
249
else if (fielddesc_type == 1 ) {
250
250
desc16 [i ].offset = desc [i ].offset ;
251
251
desc16 [i ].size = desc [i ].size ;
252
- desc16 [i ].isptr = desc [i ].isptr ;
252
+ desc16 [i ].kind = desc [i ].kind ;
253
253
}
254
254
else {
255
255
desc32 [i ].offset = desc [i ].offset ;
256
256
desc32 [i ].size = desc [i ].size ;
257
- desc32 [i ].isptr = desc [i ].isptr ;
257
+ desc32 [i ].kind = desc [i ].kind ;
258
258
}
259
259
}
260
260
if (first_ptr >= 0 ) {
@@ -686,23 +686,32 @@ void jl_compute_field_offsets(jl_datatype_t *st)
686
686
for (i = 0 ; i < nfields ; i ++ ) {
687
687
jl_value_t * fld = jl_field_type (st , i );
688
688
int isatomic = jl_field_isatomic (st , i );
689
+ jl_value_t * restfld = fld ;
690
+ if (jl_is_uniontype (fld ) && jl_is_datatype_singleton (((jl_uniontype_t * )fld )-> a )) {
691
+ restfld = ((jl_uniontype_t * )fld )-> b ;
692
+ }
689
693
size_t fsz = 0 , al = 1 ;
690
- if (jl_islayout_inline (fld , & fsz , & al ) && (!isatomic || jl_is_datatype (fld ))) { // aka jl_datatype_isinlinealloc
694
+ if (jl_islayout_inline (restfld , & fsz , & al ) && (!isatomic || jl_is_datatype (fld ))) { // aka jl_datatype_isinlinealloc
691
695
if (__unlikely (fsz > max_size ))
692
696
// Should never happen
693
697
throw_ovf (should_malloc , desc , st , fsz );
694
- desc [i ].isptr = 0 ;
695
- if (jl_is_uniontype (fld )) {
698
+ if (!jl_is_datatype (restfld ) || (restfld != fld && jl_islayout_inline (fld , & fsz , & al )))
699
+ desc [i ].kind = JL_FIELDKIND_ISUNION ;
700
+ else if (((jl_datatype_t * )restfld )-> layout -> first_ptr >= 0 )
701
+ desc [i ].kind = JL_FIELDKIND_ISOTHER ;
702
+ else
703
+ desc [i ].kind = JL_FIELDKIND_ISBITS ;
704
+ if (desc [i ].kind == JL_FIELDKIND_ISUNION ) {
696
705
fsz += 1 ; // selector byte
697
706
zeroinit = 1 ;
698
707
// TODO: Some unions could be bits comparable.
699
708
isbitsegal = 0 ;
700
709
}
701
710
else {
702
- uint32_t fld_npointers = ((jl_datatype_t * )fld )-> layout -> npointers ;
703
- if (((jl_datatype_t * )fld )-> layout -> flags .haspadding )
711
+ uint32_t fld_npointers = ((jl_datatype_t * )restfld )-> layout -> npointers ;
712
+ if (((jl_datatype_t * )restfld )-> layout -> flags .haspadding )
704
713
haspadding = 1 ;
705
- if (!((jl_datatype_t * )fld )-> layout -> flags .isbitsegal )
714
+ if (!((jl_datatype_t * )restfld )-> layout -> flags .isbitsegal )
706
715
isbitsegal = 0 ;
707
716
if (i >= nfields - st -> name -> n_uninitialized && fld_npointers &&
708
717
fld_npointers * sizeof (void * ) != fsz ) {
@@ -719,7 +728,7 @@ void jl_compute_field_offsets(jl_datatype_t *st)
719
728
isbitsegal = 0 ;
720
729
}
721
730
if (!zeroinit )
722
- zeroinit = ((jl_datatype_t * )fld )-> zeroinit ;
731
+ zeroinit = ((jl_datatype_t * )restfld )-> zeroinit ;
723
732
npointers += fld_npointers ;
724
733
}
725
734
}
@@ -728,7 +737,7 @@ void jl_compute_field_offsets(jl_datatype_t *st)
728
737
if (fsz > MAX_ALIGN )
729
738
fsz = MAX_ALIGN ;
730
739
al = fsz ;
731
- desc [i ].isptr = 1 ;
740
+ desc [i ].kind = JL_FIELDKIND_ISPTR ;
732
741
zeroinit = 1 ;
733
742
npointers ++ ;
734
743
if (!jl_pointer_egal (fld )) {
@@ -783,9 +792,12 @@ void jl_compute_field_offsets(jl_datatype_t *st)
783
792
for (i = 0 ; i < nfields ; i ++ ) {
784
793
jl_value_t * fld = jl_field_type (st , i );
785
794
uint32_t offset = desc [i ].offset / sizeof (jl_value_t * * );
786
- if (desc [i ].isptr )
795
+ if (desc [i ].kind == JL_FIELDKIND_ISPTR )
787
796
pointers [ptr_i ++ ] = offset ;
788
- else if (jl_is_datatype (fld )) {
797
+ else if (desc [i ].kind == JL_FIELDKIND_ISOTHER ) {
798
+ if (jl_is_uniontype (fld )) {
799
+ fld = ((jl_uniontype_t * )fld )-> b ;
800
+ }
789
801
int j , npointers = ((jl_datatype_t * )fld )-> layout -> npointers ;
790
802
for (j = 0 ; j < npointers ; j ++ ) {
791
803
pointers [ptr_i ++ ] = offset + jl_ptr_offset ((jl_datatype_t * )fld , j );
@@ -1755,18 +1767,28 @@ JL_DLLEXPORT jl_value_t *jl_get_nth_field(jl_value_t *v, size_t i)
1755
1767
if (i >= jl_datatype_nfields (st ))
1756
1768
jl_bounds_error_int (v , i + 1 );
1757
1769
size_t offs = jl_field_offset (st , i );
1758
- if (jl_field_isptr (st , i )) {
1770
+ enum jl_fieldkind_t kind = jl_field_kind (st , i );
1771
+ if (kind == JL_FIELDKIND_ISPTR ) {
1759
1772
return jl_atomic_load_relaxed ((_Atomic (jl_value_t * )* )((char * )v + offs ));
1760
1773
}
1761
1774
jl_value_t * ty = jl_field_type_concrete (st , i );
1762
1775
int isatomic = jl_field_isatomic (st , i );
1763
- if (jl_is_uniontype (ty )) {
1776
+ jl_value_t * undefval = NULL ;
1777
+ if (kind != JL_FIELDKIND_ISBITS ) {
1764
1778
assert (!isatomic );
1765
- size_t fsz = jl_field_size (st , i );
1766
- uint8_t sel = ((uint8_t * )v )[offs + fsz - 1 ];
1767
- ty = jl_nth_union_component (ty , sel );
1768
- if (jl_is_datatype_singleton ((jl_datatype_t * )ty ))
1769
- return ((jl_datatype_t * )ty )-> instance ;
1779
+ if (kind == JL_FIELDKIND_ISUNION ) {
1780
+ size_t fsz = jl_field_size (st , i );
1781
+ uint8_t sel = ((uint8_t * )v )[offs + fsz - 1 ];
1782
+ ty = jl_nth_union_component (ty , sel );
1783
+ if (jl_is_datatype_singleton ((jl_datatype_t * )ty ))
1784
+ return ((jl_datatype_t * )ty )-> instance ;
1785
+ }
1786
+ else { // kind == JL_FIELDKIND_ISOTHER
1787
+ assert (jl_is_uniontype (ty ));
1788
+ jl_uniontype_t * uty = (jl_uniontype_t * )ty ;
1789
+ undefval = ((jl_datatype_t * )uty -> a )-> instance ;
1790
+ ty = uty -> b ;
1791
+ }
1770
1792
}
1771
1793
jl_value_t * r ;
1772
1794
size_t fsz = jl_datatype_size (ty );
@@ -1785,7 +1807,9 @@ JL_DLLEXPORT jl_value_t *jl_get_nth_field(jl_value_t *v, size_t i)
1785
1807
// TODO: a finalizer here could make the isunion case not quite right
1786
1808
r = jl_new_bits (ty , (char * )v + offs );
1787
1809
}
1788
- return undefref_check ((jl_datatype_t * )ty , r );
1810
+ if (kind != JL_FIELDKIND_ISOTHER )
1811
+ return r ;
1812
+ return undefref_check ((jl_datatype_t * )ty , r , undefval );
1789
1813
}
1790
1814
1791
1815
JL_DLLEXPORT jl_value_t * jl_get_nth_field_noalloc (jl_value_t * v JL_PROPAGATES_ROOT , size_t i ) JL_NOTSAFEPOINT
@@ -1812,16 +1836,16 @@ inline void set_nth_field(jl_datatype_t *st, jl_value_t *v, size_t i, jl_value_t
1812
1836
assert (jl_field_isptr (st , i ) && * (jl_value_t * * )((char * )v + offs ) == NULL );
1813
1837
return ;
1814
1838
}
1815
- if (jl_field_isptr (st , i )) {
1839
+ enum jl_fieldkind_t kind = jl_field_kind (st , i );
1840
+ if (kind == JL_FIELDKIND_ISPTR ) {
1816
1841
jl_atomic_store_release ((_Atomic (jl_value_t * )* )((char * )v + offs ), rhs );
1817
1842
jl_gc_wb (v , rhs );
1818
1843
}
1819
1844
else {
1820
1845
jl_value_t * ty = jl_field_type_concrete (st , i );
1821
1846
jl_value_t * rty = jl_typeof (rhs );
1822
- int hasptr ;
1823
- int isunion = jl_is_uniontype (ty );
1824
- if (isunion ) {
1847
+ int hasptr = (kind == JL_FIELDKIND_ISOTHER );
1848
+ if (kind == JL_FIELDKIND_ISUNION ) {
1825
1849
assert (!isatomic );
1826
1850
size_t fsz = jl_field_size (st , i );
1827
1851
uint8_t * psel = & ((uint8_t * )v )[offs + fsz - 1 ];
@@ -1831,10 +1855,19 @@ inline void set_nth_field(jl_datatype_t *st, jl_value_t *v, size_t i, jl_value_t
1831
1855
* psel = nth ;
1832
1856
if (jl_is_datatype_singleton ((jl_datatype_t * )rty ))
1833
1857
return ;
1834
- hasptr = 0 ;
1835
1858
}
1836
1859
else {
1837
- hasptr = ((jl_datatype_t * )ty )-> layout -> first_ptr >= 0 ;
1860
+ if (hasptr && jl_is_uniontype (ty )) {
1861
+ jl_uniontype_t * uty = (jl_uniontype_t * )ty ;
1862
+ jl_value_t * undefval = ((jl_datatype_t * )uty -> a )-> instance ;
1863
+ ty = uty -> b ;
1864
+ assert (((jl_datatype_t * )ty )-> layout -> first_ptr >= 0 );
1865
+ if (undefval == rhs ) {
1866
+ jl_atomic_store_relaxed ((_Atomic (jl_value_t * )* )((char * )v + offs ) + ((jl_datatype_t * )ty )-> layout -> first_ptr , NULL );
1867
+ return ;
1868
+ }
1869
+ }
1870
+ assert (hasptr == (((jl_datatype_t * )ty )-> layout -> first_ptr >= 0 ));
1838
1871
}
1839
1872
size_t fsz = jl_datatype_size ((jl_datatype_t * )rty ); // need to shrink-wrap the final copy
1840
1873
assert (!isatomic || jl_typeis (rhs , ty ));
@@ -2235,9 +2268,9 @@ JL_DLLEXPORT int jl_field_isdefined(jl_value_t *v, size_t i) JL_NOTSAFEPOINT
2235
2268
jl_datatype_t * st = (jl_datatype_t * )jl_typeof (v );
2236
2269
size_t offs = jl_field_offset (st , i );
2237
2270
_Atomic(jl_value_t * ) * fld = (_Atomic (jl_value_t * )* )((char * )v + offs );
2238
- if (! jl_field_isptr ( st , i )) {
2239
- jl_datatype_t * ft = ( jl_datatype_t * ) jl_field_type_concrete ( st , i );
2240
- if (! jl_is_datatype ( ft ) || ft -> layout -> first_ptr < 0 )
2271
+ enum jl_fieldkind_t kind = jl_field_kind ( st , i );
2272
+ if ( kind != JL_FIELDKIND_ISPTR ) {
2273
+ if (kind != JL_FIELDKIND_ISOTHER || jl_is_uniontype ( jl_field_type_concrete ( st , i )) )
2241
2274
return 2 ; // isbits are always defined
2242
2275
fld += ft -> layout -> first_ptr ;
2243
2276
}
0 commit comments