@@ -1487,22 +1487,38 @@ static int equiv_field_types(jl_value_t *old, jl_value_t *ft)
1487
1487
return 1 ;
1488
1488
}
1489
1489
1490
+ // If a field can reference its enclosing type, then the inlining
1491
+ // recursive depth is not statically bounded for some layouts, so we cannot
1492
+ // inline it. The only way fields can reference this type (due to
1493
+ // syntax-enforced restrictions) is via being passed as a type parameter. Thus
1494
+ // we can conservatively check this by examining only the parameters of the
1495
+ // dependent types.
1496
+ // affects_layout is a hack introduced by #35275 to workaround a problem
1497
+ // introduced by #34223: it checks whether we will potentially need to
1498
+ // compute the layout of the object before we have fully computed the types of
1499
+ // the fields during recursion over the allocation of the parameters for the
1500
+ // field types (of the concrete subtypes)
1490
1501
static int references_name (jl_value_t * p , jl_typename_t * name , int affects_layout ) JL_NOTSAFEPOINT
1491
1502
{
1492
1503
if (jl_is_uniontype (p ))
1493
1504
return references_name (((jl_uniontype_t * )p )-> a , name , affects_layout ) ||
1494
1505
references_name (((jl_uniontype_t * )p )-> b , name , affects_layout );
1495
1506
if (jl_is_unionall (p ))
1496
- return references_name ((jl_value_t * )((jl_unionall_t * )p )-> var , name , 0 ) ||
1507
+ return references_name ((jl_value_t * )((jl_unionall_t * )p )-> var -> lb , name , 0 ) ||
1508
+ references_name ((jl_value_t * )((jl_unionall_t * )p )-> var -> ub , name , 0 ) ||
1497
1509
references_name (((jl_unionall_t * )p )-> body , name , affects_layout );
1498
1510
if (jl_is_typevar (p ))
1499
- return references_name (((jl_tvar_t * )p )-> ub , name , 0 ) ||
1500
- references_name (((jl_tvar_t * )p )-> lb , name , 0 );
1511
+ return 0 ; // already checked by unionall, if applicable
1501
1512
if (jl_is_datatype (p )) {
1502
1513
jl_datatype_t * dp = (jl_datatype_t * )p ;
1503
1514
if (affects_layout && dp -> name == name )
1504
1515
return 1 ;
1505
- affects_layout = dp -> types == NULL || jl_svec_len (dp -> types ) != 0 ;
1516
+ // affects_layout checks whether we will need to attempt to layout this
1517
+ // type (based on whether all copies of it have the same layout) in
1518
+ // that case, we still need to check the recursive parameters for
1519
+ // layout recursion happening also, but we know it won't itself cause
1520
+ // problems for the layout computation
1521
+ affects_layout = ((jl_datatype_t * )jl_unwrap_unionall (dp -> name -> wrapper ))-> layout == NULL ;
1506
1522
size_t i , l = jl_nparams (p );
1507
1523
for (i = 0 ; i < l ; i ++ ) {
1508
1524
if (references_name (jl_tparam (p , i ), name , affects_layout ))
@@ -1537,16 +1553,21 @@ JL_CALLABLE(jl_f__typebody)
1537
1553
else {
1538
1554
dt -> types = (jl_svec_t * )ft ;
1539
1555
jl_gc_wb (dt , ft );
1540
- if (!dt -> name -> mutabl ) {
1541
- dt -> name -> mayinlinealloc = 1 ;
1556
+ // If a supertype can reference the same type, then we may not be
1557
+ // able to compute the layout of the object before needing to
1558
+ // publish it, so we must assume it cannot be inlined, if that
1559
+ // check passes, then we also still need to check the fields too.
1560
+ if (!dt -> name -> mutabl && !references_name ((jl_value_t * )dt -> super , dt -> name , 1 )) {
1561
+ int mayinlinealloc = 1 ;
1542
1562
size_t i , nf = jl_svec_len (ft );
1543
1563
for (i = 0 ; i < nf ; i ++ ) {
1544
1564
jl_value_t * fld = jl_svecref (ft , i );
1545
1565
if (references_name (fld , dt -> name , 1 )) {
1546
- dt -> name -> mayinlinealloc = 0 ;
1566
+ mayinlinealloc = 0 ;
1547
1567
break ;
1548
1568
}
1549
1569
}
1570
+ dt -> name -> mayinlinealloc = mayinlinealloc ;
1550
1571
}
1551
1572
}
1552
1573
}
0 commit comments