@@ -550,6 +550,9 @@ typedef struct {
550
550
jl_array_t * link_ids_gctags ;
551
551
jl_array_t * link_ids_gvars ;
552
552
jl_array_t * link_ids_external_fnvars ;
553
+ jl_array_t * method_roots_list ;
554
+ htable_t method_roots_index ;
555
+ uint64_t worklist_key ;
553
556
jl_ptls_t ptls ;
554
557
jl_image_t * image ;
555
558
int8_t incremental ;
@@ -931,22 +934,57 @@ static void jl_insert_into_serialization_queue(jl_serializer_state *s, jl_value_
931
934
int is_relocatable = jl_is_code_info (inferred ) ||
932
935
(jl_is_string (inferred ) && jl_string_len (inferred ) > 0 && jl_string_data (inferred )[jl_string_len (inferred ) - 1 ]);
933
936
if (!is_relocatable ) {
934
- record_field_change (( jl_value_t * * ) & ci -> inferred , jl_nothing ) ;
937
+ inferred = jl_nothing ;
935
938
}
936
939
else if (def -> source == NULL ) {
937
940
// don't delete code from optimized opaque closures that can't be reconstructed (and builtins)
938
941
}
939
942
else if (jl_atomic_load_relaxed (& ci -> max_world ) != ~(size_t )0 || // delete all code that cannot run
940
943
jl_atomic_load_relaxed (& ci -> invoke ) == jl_fptr_const_return ) { // delete all code that just returns a constant
941
- record_field_change (( jl_value_t * * ) & ci -> inferred , jl_nothing ) ;
944
+ inferred = jl_nothing ;
942
945
}
943
946
else if (native_functions && // don't delete any code if making a ji file
944
947
(ci -> owner == jl_nothing ) && // don't delete code for external interpreters
945
948
!effects_foldable (jl_atomic_load_relaxed (& ci -> ipo_purity_bits )) && // don't delete code we may want for irinterp
946
949
jl_ir_inlining_cost (inferred ) == UINT16_MAX ) { // don't delete inlineable code
947
950
// delete the code now: if we thought it was worth keeping, it would have been converted to object code
951
+ inferred = jl_nothing ;
952
+ }
953
+ if (inferred == jl_nothing ) {
948
954
record_field_change ((jl_value_t * * )& ci -> inferred , jl_nothing );
949
955
}
956
+ else if (jl_is_string (inferred )) {
957
+ // New roots for external methods
958
+ if (jl_object_in_image ((jl_value_t * )def )) {
959
+ void * * pfound = ptrhash_bp (& s -> method_roots_index , def );
960
+ if (* pfound == HT_NOTFOUND ) {
961
+ * pfound = def ;
962
+ size_t nwithkey = nroots_with_key (def , s -> worklist_key );
963
+ if (nwithkey ) {
964
+ jl_array_ptr_1d_push (s -> method_roots_list , (jl_value_t * )def );
965
+ jl_array_t * newroots = jl_alloc_vec_any (nwithkey );
966
+ jl_array_ptr_1d_push (s -> method_roots_list , (jl_value_t * )newroots );
967
+ rle_iter_state rootiter = rle_iter_init (0 );
968
+ uint64_t * rletable = NULL ;
969
+ size_t nblocks2 = 0 ;
970
+ size_t nroots = jl_array_nrows (def -> roots );
971
+ size_t k = 0 ;
972
+ if (def -> root_blocks ) {
973
+ rletable = jl_array_data (def -> root_blocks , uint64_t );
974
+ nblocks2 = jl_array_nrows (def -> root_blocks );
975
+ }
976
+ while (rle_iter_increment (& rootiter , nroots , rletable , nblocks2 )) {
977
+ if (rootiter .key == s -> worklist_key ) {
978
+ jl_value_t * newroot = jl_array_ptr_ref (def -> roots , rootiter .i );
979
+ jl_queue_for_serialization (s , newroot );
980
+ jl_array_ptr_set (newroots , k ++ , newroot );
981
+ }
982
+ }
983
+ assert (k == nwithkey );
984
+ }
985
+ }
986
+ }
987
+ }
950
988
}
951
989
}
952
990
}
@@ -2861,10 +2899,9 @@ JL_DLLEXPORT jl_value_t *jl_as_global_root(jl_value_t *val, int insert)
2861
2899
return val ;
2862
2900
}
2863
2901
2864
- static void jl_prepare_serialization_data (jl_array_t * mod_array , jl_array_t * newly_inferred , uint64_t worklist_key ,
2902
+ static void jl_prepare_serialization_data (jl_array_t * mod_array , jl_array_t * newly_inferred ,
2865
2903
/* outputs */ jl_array_t * * extext_methods JL_REQUIRE_ROOTED_SLOT ,
2866
2904
jl_array_t * * new_ext_cis JL_REQUIRE_ROOTED_SLOT ,
2867
- jl_array_t * * method_roots_list JL_REQUIRE_ROOTED_SLOT ,
2868
2905
jl_array_t * * edges JL_REQUIRE_ROOTED_SLOT )
2869
2906
{
2870
2907
// extext_methods: [method1, ...], worklist-owned "extending external" methods added to functions owned by modules outside the worklist
@@ -2888,24 +2925,20 @@ static void jl_prepare_serialization_data(jl_array_t *mod_array, jl_array_t *new
2888
2925
}
2889
2926
2890
2927
if (edges ) {
2928
+ // Extract `edges` now (from info prepared by jl_collect_methcache_from_mod)
2891
2929
size_t world = jl_atomic_load_acquire (& jl_world_counter );
2892
- // Extract `new_ext_cis` and `edges` now (from info prepared by jl_collect_methcache_from_mod)
2893
- * method_roots_list = jl_alloc_vec_any (0 );
2894
- // Collect the new method roots for external specializations
2895
- jl_collect_new_roots (* method_roots_list , * new_ext_cis , worklist_key );
2896
2930
* edges = jl_alloc_vec_any (0 );
2897
2931
jl_collect_internal_cis (* edges , world );
2898
2932
}
2899
- internal_methods = NULL ;
2933
+ internal_methods = NULL ; // global
2900
2934
2901
2935
JL_GC_POP ();
2902
2936
}
2903
2937
2904
2938
// In addition to the system image (where `worklist = NULL`), this can also save incremental images with external linkage
2905
2939
static void jl_save_system_image_to_stream (ios_t * f , jl_array_t * mod_array ,
2906
2940
jl_array_t * worklist , jl_array_t * extext_methods ,
2907
- jl_array_t * new_ext_cis , jl_array_t * method_roots_list ,
2908
- jl_array_t * edges ) JL_GC_DISABLED
2941
+ jl_array_t * new_ext_cis , jl_array_t * edges )
2909
2942
{
2910
2943
htable_new (& field_replace , 0 );
2911
2944
htable_new (& bits_replace , 0 );
@@ -3035,9 +3068,14 @@ static void jl_save_system_image_to_stream(ios_t *f, jl_array_t *mod_array,
3035
3068
s .link_ids_gctags = jl_alloc_array_1d (jl_array_int32_type , 0 );
3036
3069
s .link_ids_gvars = jl_alloc_array_1d (jl_array_int32_type , 0 );
3037
3070
s .link_ids_external_fnvars = jl_alloc_array_1d (jl_array_int32_type , 0 );
3071
+ s .method_roots_list = NULL ;
3072
+ htable_new (& s .method_roots_index , 0 );
3073
+ if (worklist ) {
3074
+ s .method_roots_list = jl_alloc_vec_any (0 );
3075
+ s .worklist_key = jl_worklist_key (worklist );
3076
+ }
3038
3077
jl_value_t * * const * const tags = get_tags (); // worklist == NULL ? get_tags() : NULL;
3039
3078
3040
-
3041
3079
if (worklist == NULL ) {
3042
3080
// empty!(Core.ARGS)
3043
3081
if (jl_core_module != NULL ) {
@@ -3082,8 +3120,6 @@ static void jl_save_system_image_to_stream(ios_t *f, jl_array_t *mod_array,
3082
3120
jl_queue_for_serialization (& s , extext_methods );
3083
3121
// Queue the new specializations
3084
3122
jl_queue_for_serialization (& s , new_ext_cis );
3085
- // Queue the new roots
3086
- jl_queue_for_serialization (& s , method_roots_list );
3087
3123
// Queue the edges
3088
3124
jl_queue_for_serialization (& s , edges );
3089
3125
}
@@ -3094,7 +3130,15 @@ static void jl_save_system_image_to_stream(ios_t *f, jl_array_t *mod_array,
3094
3130
if (jl_options .trim )
3095
3131
record_gvars (& s , & MIs );
3096
3132
jl_serialize_reachable (& s );
3097
- // step 1.3: prune (garbage collect) special weak references from the jl_global_roots_list
3133
+ // Beyond this point, all content should already have been visited, so now we can prune
3134
+ // the rest and add some internal root arrays.
3135
+ // step 1.3: include some other special roots
3136
+ if (s .incremental ) {
3137
+ // Queue the new roots array
3138
+ jl_queue_for_serialization (& s , s .method_roots_list );
3139
+ jl_serialize_reachable (& s );
3140
+ }
3141
+ // step 1.4: prune (garbage collect) special weak references from the jl_global_roots_list
3098
3142
if (worklist == NULL ) {
3099
3143
global_roots_list = jl_alloc_memory_any (0 );
3100
3144
global_roots_keyset = jl_alloc_memory_any (0 );
@@ -3110,7 +3154,7 @@ static void jl_save_system_image_to_stream(ios_t *f, jl_array_t *mod_array,
3110
3154
jl_queue_for_serialization (& s , global_roots_keyset );
3111
3155
jl_serialize_reachable (& s );
3112
3156
}
3113
- // step 1.4 : prune (garbage collect) some special weak references from
3157
+ // step 1.5 : prune (garbage collect) some special weak references from
3114
3158
// built-in type caches too
3115
3159
for (i = 0 ; i < serialization_queue .len ; i ++ ) {
3116
3160
jl_value_t * v = (jl_value_t * )serialization_queue .items [i ];
@@ -3130,7 +3174,8 @@ static void jl_save_system_image_to_stream(ios_t *f, jl_array_t *mod_array,
3130
3174
if (ptrhash_get (& serialization_order , mi ) == HT_NOTFOUND )
3131
3175
jl_svecset (specializations , i , jl_nothing );
3132
3176
}
3133
- } else if (jl_is_module (v )) {
3177
+ }
3178
+ else if (jl_is_module (v )) {
3134
3179
jl_prune_module_bindings ((jl_module_t * )v );
3135
3180
}
3136
3181
}
@@ -3262,7 +3307,7 @@ static void jl_save_system_image_to_stream(ios_t *f, jl_array_t *mod_array,
3262
3307
jl_write_value (& s , jl_module_init_order );
3263
3308
jl_write_value (& s , extext_methods );
3264
3309
jl_write_value (& s , new_ext_cis );
3265
- jl_write_value (& s , method_roots_list );
3310
+ jl_write_value (& s , s . method_roots_list );
3266
3311
jl_write_value (& s , edges );
3267
3312
}
3268
3313
write_uint32 (f , jl_array_len (s .link_ids_gctags ));
@@ -3293,6 +3338,7 @@ static void jl_save_system_image_to_stream(ios_t *f, jl_array_t *mod_array,
3293
3338
arraylist_free (& s .gctags_list );
3294
3339
arraylist_free (& gvars );
3295
3340
arraylist_free (& external_fns );
3341
+ htable_free (& s .method_roots_index );
3296
3342
htable_free (& field_replace );
3297
3343
htable_free (& bits_replace );
3298
3344
htable_free (& serialization_order );
@@ -3353,18 +3399,17 @@ JL_DLLEXPORT void jl_create_system_image(void **_native_data, jl_array_t *workli
3353
3399
}
3354
3400
3355
3401
jl_array_t * mod_array = NULL , * extext_methods = NULL , * new_ext_cis = NULL ;
3356
- jl_array_t * method_roots_list = NULL , * edges = NULL ;
3402
+ jl_array_t * edges = NULL ;
3357
3403
int64_t checksumpos = 0 ;
3358
3404
int64_t checksumpos_ff = 0 ;
3359
3405
int64_t datastartpos = 0 ;
3360
- JL_GC_PUSH5 (& mod_array , & extext_methods , & new_ext_cis , & method_roots_list , & edges );
3406
+ JL_GC_PUSH4 (& mod_array , & extext_methods , & new_ext_cis , & edges );
3361
3407
3362
3408
if (worklist ) {
3363
3409
mod_array = jl_get_loaded_modules (); // __toplevel__ modules loaded in this session (from Base.loaded_modules_array)
3364
3410
// Generate _native_data`
3365
3411
if (_native_data != NULL ) {
3366
- jl_prepare_serialization_data (mod_array , newly_inferred , jl_worklist_key (worklist ),
3367
- & extext_methods , & new_ext_cis , NULL , NULL );
3412
+ jl_prepare_serialization_data (mod_array , newly_inferred , & extext_methods , & new_ext_cis , NULL );
3368
3413
jl_precompile_toplevel_module = (jl_module_t * )jl_array_ptr_ref (worklist , jl_array_len (worklist )- 1 );
3369
3414
* _native_data = jl_precompile_worklist (worklist , extext_methods , new_ext_cis );
3370
3415
jl_precompile_toplevel_module = NULL ;
@@ -3395,8 +3440,7 @@ JL_DLLEXPORT void jl_create_system_image(void **_native_data, jl_array_t *workli
3395
3440
assert ((ct -> reentrant_timing & 0b1110 ) == 0 );
3396
3441
ct -> reentrant_timing |= 0b1000 ;
3397
3442
if (worklist ) {
3398
- jl_prepare_serialization_data (mod_array , newly_inferred , jl_worklist_key (worklist ),
3399
- & extext_methods , & new_ext_cis , & method_roots_list , & edges );
3443
+ jl_prepare_serialization_data (mod_array , newly_inferred , & extext_methods , & new_ext_cis , & edges );
3400
3444
if (!emit_split ) {
3401
3445
write_int32 (f , 0 ); // No clone_targets
3402
3446
write_padding (f , LLT_ALIGN (ios_pos (f ), JL_CACHE_BYTE_ALIGNMENT ) - ios_pos (f ));
@@ -3408,7 +3452,7 @@ JL_DLLEXPORT void jl_create_system_image(void **_native_data, jl_array_t *workli
3408
3452
}
3409
3453
if (_native_data != NULL )
3410
3454
native_functions = * _native_data ;
3411
- jl_save_system_image_to_stream (ff , mod_array , worklist , extext_methods , new_ext_cis , method_roots_list , edges );
3455
+ jl_save_system_image_to_stream (ff , mod_array , worklist , extext_methods , new_ext_cis , edges );
3412
3456
if (_native_data != NULL )
3413
3457
native_functions = NULL ;
3414
3458
// make sure we don't run any Julia code concurrently before this point
@@ -4185,7 +4229,6 @@ static jl_value_t *jl_restore_package_image_from_stream(void* pkgimage_handle, i
4185
4229
& edges , & base , & ccallable_list , & cachesizes );
4186
4230
JL_SIGATOMIC_END ();
4187
4231
4188
- // No special processing of `new_ext_cis` is required because recaching handled it
4189
4232
// Add roots to methods
4190
4233
jl_copy_roots (method_roots_list , jl_worklist_key ((jl_array_t * )restored ));
4191
4234
// Insert method extensions and handle edges
0 commit comments