@@ -101,6 +101,9 @@ static int backref_table_numel;
101101static arraylist_t layout_table ;
102102static arraylist_t builtin_typenames ;
103103
104+ // # of typenames whose caches are treated as weak references
105+ #define NUM_BUILTIN_TYPENAMES 9
106+
104107// list of (size_t pos, (void *f)(jl_value_t*)) entries
105108// for the serializer to mark values in need of rework by function f
106109// during deserialization later
@@ -1304,7 +1307,7 @@ static void jl_prune_type_cache(jl_svec_t *cache)
13041307 for (i = 0 ; i < l ; i ++ ) {
13051308 jl_value_t * ti = jl_svecref (cache , i );
13061309 if (ti == NULL )
1307- break ;
1310+ continue ;
13081311 if (ptrhash_get (& backref_table , ti ) != HT_NOTFOUND || jl_get_llvm_gv (native_functions , ti ) != 0 )
13091312 jl_svecset (cache , ins ++ , ti );
13101313 else if (jl_is_datatype (ti )) {
@@ -1316,6 +1319,9 @@ static void jl_prune_type_cache(jl_svec_t *cache)
13161319 }
13171320 if (i > ins ) {
13181321 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 ;
13191325 }
13201326}
13211327
@@ -1324,6 +1330,7 @@ static void jl_prune_type_cache(jl_svec_t *cache)
13241330
13251331static void jl_init_serializer2 (int );
13261332static void jl_cleanup_serializer2 (void );
1333+ static void init_builtin_typenames (void );
13271334
13281335static void jl_save_system_image_to_stream (ios_t * f )
13291336{
@@ -1353,6 +1360,8 @@ static void jl_save_system_image_to_stream(ios_t *f)
13531360 s .ptls = jl_get_ptls_states ();
13541361 arraylist_new (& s .relocs_list , 0 );
13551362 arraylist_new (& s .gctags_list , 0 );
1363+ arraylist_t typecaches ;
1364+ arraylist_new (& typecaches , 0 );
13561365
13571366 // empty!(Core.ARGS)
13581367 if (jl_core_module != NULL ) {
@@ -1372,19 +1381,22 @@ static void jl_save_system_image_to_stream(ios_t *f)
13721381
13731382 { // step 1: record values (recursively) that need to go in the image
13741383 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+ }
13751392 for (i = 0 ; tags [i ] != NULL ; i ++ ) {
13761393 jl_value_t * tag = * tags [i ];
13771394 jl_serialize_value (& s , tag );
13781395 }
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 );
13881400 }
13891401 }
13901402
@@ -1437,6 +1449,13 @@ static void jl_save_system_image_to_stream(ios_t *f)
14371449 jl_write_value (& s , tag );
14381450 }
14391451 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+ }
14401459 write_uint32 (f , jl_get_gs_ctr ());
14411460 write_uint32 (f , jl_world_counter );
14421461 write_uint32 (f , jl_typeinf_world );
@@ -1449,6 +1468,7 @@ static void jl_save_system_image_to_stream(ios_t *f)
14491468 arraylist_free (& ccallable_list );
14501469 arraylist_free (& s .relocs_list );
14511470 arraylist_free (& s .gctags_list );
1471+ arraylist_free (& typecaches );
14521472 jl_cleanup_serializer2 ();
14531473
14541474 jl_gc_enable (en );
@@ -1561,6 +1581,11 @@ static void jl_restore_system_image_from_stream(ios_t *f)
15611581 s .ptls -> root_task = (jl_task_t * )jl_gc_alloc (s .ptls , sizeof (jl_task_t ), jl_task_type );
15621582 memset (s .ptls -> root_task , 0 , sizeof (jl_task_t ));
15631583 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+ }
15641589 jl_init_int32_int64_cache ();
15651590 jl_init_box_caches ();
15661591
@@ -1591,6 +1616,13 @@ static void jl_restore_system_image_from_stream(ios_t *f)
15911616 s .s = NULL ;
15921617
15931618 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+ }
15941626 // reinit items except ccallables
15951627 jl_finalize_deserializer (& s );
15961628 s .s = NULL ;
@@ -1623,6 +1655,7 @@ static void jl_restore_system_image_from_stream(ios_t *f)
16231655 ios_close (& fptr_record );
16241656 ios_close (& sysimg );
16251657 s .s = NULL ;
1658+ arraylist_free (& typecaches );
16261659
16271660 jl_gc_reset_alloc_count ();
16281661 jl_gc_enable (en );
@@ -1674,13 +1707,28 @@ JL_DLLEXPORT void jl_restore_system_image_data(const char *buf, size_t len)
16741707
16751708// --- init ---
16761709
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+
16771725static void jl_init_serializer2 (int for_serialize )
16781726{
16791727 if (for_serialize ) {
16801728 htable_new (& symbol_table , 0 );
16811729 htable_new (& fptr_to_id , sizeof (id_to_fptrs ) / sizeof (* id_to_fptrs ));
16821730 htable_new (& backref_table , 0 );
1683- arraylist_new ( & builtin_typenames , 0 );
1731+ init_builtin_typenames ( );
16841732 uintptr_t i ;
16851733 for (i = 0 ; id_to_fptrs [i ] != NULL ; i ++ ) {
16861734 ptrhash_put (& fptr_to_id , (void * )(uintptr_t )id_to_fptrs [i ], (void * )(i + 2 ));
0 commit comments