@@ -101,6 +101,9 @@ static int backref_table_numel;
101
101
static arraylist_t layout_table ;
102
102
static arraylist_t builtin_typenames ;
103
103
104
+ // # of typenames whose caches are treated as weak references
105
+ #define NUM_BUILTIN_TYPENAMES 9
106
+
104
107
// list of (size_t pos, (void *f)(jl_value_t*)) entries
105
108
// for the serializer to mark values in need of rework by function f
106
109
// during deserialization later
@@ -1304,7 +1307,7 @@ static void jl_prune_type_cache(jl_svec_t *cache)
1304
1307
for (i = 0 ; i < l ; i ++ ) {
1305
1308
jl_value_t * ti = jl_svecref (cache , i );
1306
1309
if (ti == NULL )
1307
- break ;
1310
+ continue ;
1308
1311
if (ptrhash_get (& backref_table , ti ) != HT_NOTFOUND || jl_get_llvm_gv (native_functions , ti ) != 0 )
1309
1312
jl_svecset (cache , ins ++ , ti );
1310
1313
else if (jl_is_datatype (ti )) {
@@ -1316,6 +1319,9 @@ static void jl_prune_type_cache(jl_svec_t *cache)
1316
1319
}
1317
1320
if (i > ins ) {
1318
1321
memset (& jl_svec_data (cache )[ins ], 0 , (i - ins ) * sizeof (jl_value_t * ));
1322
+ while (l > 0 && l /2 >= ins )
1323
+ l = l /2 ;
1324
+ jl_svec_len (cache ) = l == 0 ? 1 : l ;
1319
1325
}
1320
1326
}
1321
1327
@@ -1324,6 +1330,7 @@ static void jl_prune_type_cache(jl_svec_t *cache)
1324
1330
1325
1331
static void jl_init_serializer2 (int );
1326
1332
static void jl_cleanup_serializer2 (void );
1333
+ static void init_builtin_typenames (void );
1327
1334
1328
1335
static void jl_save_system_image_to_stream (ios_t * f )
1329
1336
{
@@ -1353,6 +1360,8 @@ static void jl_save_system_image_to_stream(ios_t *f)
1353
1360
s .ptls = jl_get_ptls_states ();
1354
1361
arraylist_new (& s .relocs_list , 0 );
1355
1362
arraylist_new (& s .gctags_list , 0 );
1363
+ arraylist_t typecaches ;
1364
+ arraylist_new (& typecaches , 0 );
1356
1365
1357
1366
// empty!(Core.ARGS)
1358
1367
if (jl_core_module != NULL ) {
@@ -1372,19 +1381,22 @@ static void jl_save_system_image_to_stream(ios_t *f)
1372
1381
1373
1382
{ // step 1: record values (recursively) that need to go in the image
1374
1383
size_t i ;
1384
+ // temporarily un-reference builtin type caches to make them effectively weak references
1385
+ for (i = 0 ; i < builtin_typenames .len ; i ++ ) {
1386
+ jl_typename_t * tn = (jl_typename_t * )builtin_typenames .items [i ];
1387
+ arraylist_push (& typecaches , tn -> cache );
1388
+ tn -> cache = NULL ;
1389
+ arraylist_push (& typecaches , tn -> linearcache );
1390
+ tn -> linearcache = NULL ;
1391
+ }
1375
1392
for (i = 0 ; tags [i ] != NULL ; i ++ ) {
1376
1393
jl_value_t * tag = * tags [i ];
1377
1394
jl_serialize_value (& s , tag );
1378
1395
}
1379
- for (i = 0 ; i < builtin_typenames .len ; i ++ ) {
1380
- jl_typename_t * tn = (jl_typename_t * )builtin_typenames .items [i ];
1381
- jl_prune_type_cache (tn -> cache );
1382
- jl_prune_type_cache (tn -> linearcache );
1383
- }
1384
- for (i = 0 ; i < builtin_typenames .len ; i ++ ) {
1385
- jl_typename_t * tn = (jl_typename_t * )builtin_typenames .items [i ];
1386
- jl_serialize_value (& s , tn -> cache );
1387
- jl_serialize_value (& s , tn -> linearcache );
1396
+ for (i = 0 ; i < typecaches .len ; i ++ ) {
1397
+ jl_svec_t * sv = (jl_svec_t * )typecaches .items [i ];
1398
+ jl_prune_type_cache (sv );
1399
+ jl_serialize_value (& s , sv );
1388
1400
}
1389
1401
}
1390
1402
@@ -1437,6 +1449,13 @@ static void jl_save_system_image_to_stream(ios_t *f)
1437
1449
jl_write_value (& s , tag );
1438
1450
}
1439
1451
jl_write_value (& s , s .ptls -> root_task -> tls );
1452
+ for (i = 0 ; i < typecaches .len ;) {
1453
+ jl_typename_t * tn = (jl_typename_t * )builtin_typenames .items [i /2 ];
1454
+ tn -> cache = (jl_svec_t * )typecaches .items [i ++ ];
1455
+ jl_write_value (& s , tn -> cache );
1456
+ tn -> linearcache = (jl_svec_t * )typecaches .items [i ++ ];
1457
+ jl_write_value (& s , tn -> linearcache );
1458
+ }
1440
1459
write_uint32 (f , jl_get_gs_ctr ());
1441
1460
write_uint32 (f , jl_world_counter );
1442
1461
write_uint32 (f , jl_typeinf_world );
@@ -1449,6 +1468,7 @@ static void jl_save_system_image_to_stream(ios_t *f)
1449
1468
arraylist_free (& ccallable_list );
1450
1469
arraylist_free (& s .relocs_list );
1451
1470
arraylist_free (& s .gctags_list );
1471
+ arraylist_free (& typecaches );
1452
1472
jl_cleanup_serializer2 ();
1453
1473
1454
1474
jl_gc_enable (en );
@@ -1561,6 +1581,11 @@ static void jl_restore_system_image_from_stream(ios_t *f)
1561
1581
s .ptls -> root_task = (jl_task_t * )jl_gc_alloc (s .ptls , sizeof (jl_task_t ), jl_task_type );
1562
1582
memset (s .ptls -> root_task , 0 , sizeof (jl_task_t ));
1563
1583
s .ptls -> root_task -> tls = jl_read_value (& s );
1584
+ arraylist_t typecaches ;
1585
+ arraylist_new (& typecaches , 0 );
1586
+ for (i = 0 ; i < NUM_BUILTIN_TYPENAMES * 2 ; i ++ ) {
1587
+ arraylist_push (& typecaches , jl_read_value (& s ));
1588
+ }
1564
1589
jl_init_int32_int64_cache ();
1565
1590
jl_init_box_caches ();
1566
1591
@@ -1591,6 +1616,13 @@ static void jl_restore_system_image_from_stream(ios_t *f)
1591
1616
s .s = NULL ;
1592
1617
1593
1618
s .s = f ;
1619
+ init_builtin_typenames ();
1620
+ for (i = 0 ; i < builtin_typenames .len ; i ++ ) {
1621
+ jl_typename_t * tn = (jl_typename_t * )builtin_typenames .items [i ];
1622
+ tn -> cache = (jl_svec_t * )typecaches .items [i * 2 ];
1623
+ tn -> linearcache = (jl_svec_t * )typecaches .items [i * 2 + 1 ];
1624
+ jl_rehash_type_cache (tn );
1625
+ }
1594
1626
// reinit items except ccallables
1595
1627
jl_finalize_deserializer (& s );
1596
1628
s .s = NULL ;
@@ -1623,6 +1655,7 @@ static void jl_restore_system_image_from_stream(ios_t *f)
1623
1655
ios_close (& fptr_record );
1624
1656
ios_close (& sysimg );
1625
1657
s .s = NULL ;
1658
+ arraylist_free (& typecaches );
1626
1659
1627
1660
jl_gc_reset_alloc_count ();
1628
1661
jl_gc_enable (en );
@@ -1674,13 +1707,28 @@ JL_DLLEXPORT void jl_restore_system_image_data(const char *buf, size_t len)
1674
1707
1675
1708
// --- init ---
1676
1709
1710
+ static void init_builtin_typenames (void )
1711
+ {
1712
+ arraylist_new (& builtin_typenames , NUM_BUILTIN_TYPENAMES );
1713
+ arraylist_push (& builtin_typenames , jl_array_typename );
1714
+ arraylist_push (& builtin_typenames , ((jl_datatype_t * )jl_ref_type -> body )-> name );
1715
+ arraylist_push (& builtin_typenames , jl_pointer_typename );
1716
+ arraylist_push (& builtin_typenames , jl_type_typename );
1717
+ arraylist_push (& builtin_typenames , ((jl_datatype_t * )jl_unwrap_unionall ((jl_value_t * )jl_abstractarray_type ))-> name );
1718
+ arraylist_push (& builtin_typenames , ((jl_datatype_t * )jl_unwrap_unionall ((jl_value_t * )jl_densearray_type ))-> name );
1719
+ arraylist_push (& builtin_typenames , jl_tuple_typename );
1720
+ arraylist_push (& builtin_typenames , jl_vararg_typename );
1721
+ arraylist_push (& builtin_typenames , jl_namedtuple_typename );
1722
+ assert (builtin_typenames .len == NUM_BUILTIN_TYPENAMES );
1723
+ }
1724
+
1677
1725
static void jl_init_serializer2 (int for_serialize )
1678
1726
{
1679
1727
if (for_serialize ) {
1680
1728
htable_new (& symbol_table , 0 );
1681
1729
htable_new (& fptr_to_id , sizeof (id_to_fptrs ) / sizeof (* id_to_fptrs ));
1682
1730
htable_new (& backref_table , 0 );
1683
- arraylist_new ( & builtin_typenames , 0 );
1731
+ init_builtin_typenames ( );
1684
1732
uintptr_t i ;
1685
1733
for (i = 0 ; id_to_fptrs [i ] != NULL ; i ++ ) {
1686
1734
ptrhash_put (& fptr_to_id , (void * )(uintptr_t )id_to_fptrs [i ], (void * )(i + 2 ));
0 commit comments