@@ -2229,50 +2229,52 @@ JL_DLLEXPORT jl_value_t *jl_as_global_root(jl_value_t *val JL_MAYBE_UNROOTED)
22292229}
22302230
22312231static void jl_prepare_serialization_data (jl_array_t * mod_array , jl_array_t * newly_inferred , uint64_t worklist_key ,
2232- /* outputs */ jl_array_t * * extext_methods ,
2233- jl_array_t * * new_specializations , jl_array_t * * method_roots_list ,
2234- jl_array_t * * ext_targets , jl_array_t * * edges )
2232+ /* outputs */ jl_array_t * * extext_methods , jl_array_t * * new_specializations ,
2233+ jl_array_t * * method_roots_list , jl_array_t * * ext_targets , jl_array_t * * edges )
22352234{
22362235 // extext_methods: [method1, ...], worklist-owned "extending external" methods added to functions owned by modules outside the worklist
22372236 // ext_targets: [invokesig1, callee1, matches1, ...] non-worklist callees of worklist-owned methods
22382237 // ordinary dispatch: invokesig=NULL, callee is MethodInstance
22392238 // `invoke` dispatch: invokesig is signature, callee is MethodInstance
22402239 // abstract call: callee is signature
22412240 // edges: [caller1, ext_targets_indexes1, ...] for worklist-owned methods calling external methods
2242-
22432241 assert (edges_map == NULL );
2244- JL_GC_PUSH1 (& edges_map );
22452242
2246- // Save the inferred code from newly inferred, external methods
22472243 htable_new (& external_mis , 0 ); // we need external_mis until after `jl_collect_edges` finishes
2244+ // Save the inferred code from newly inferred, external methods
22482245 * new_specializations = queue_external_cis (newly_inferred );
2249- // Collect the new method roots
2250- htable_t methods_with_newspecs ;
2251- htable_new (& methods_with_newspecs , 0 );
2252- jl_collect_methods (& methods_with_newspecs , * new_specializations );
2253- * method_roots_list = jl_alloc_vec_any (0 );
2254- jl_collect_new_roots (* method_roots_list , & methods_with_newspecs , worklist_key );
2255- htable_free (& methods_with_newspecs );
22562246
22572247 // Collect method extensions and edges data
2258- edges_map = jl_alloc_vec_any (0 );
2248+ JL_GC_PUSH1 (& edges_map );
2249+ if (edges )
2250+ edges_map = jl_alloc_vec_any (0 );
22592251 * extext_methods = jl_alloc_vec_any (0 );
2252+ jl_collect_methtable_from_mod (jl_type_type_mt , * extext_methods );
2253+ jl_collect_methtable_from_mod (jl_nonfunction_mt , * extext_methods );
22602254 size_t i , len = jl_array_len (mod_array );
22612255 for (i = 0 ; i < len ; i ++ ) {
22622256 jl_module_t * m = (jl_module_t * )jl_array_ptr_ref (mod_array , i );
22632257 assert (jl_is_module (m ));
22642258 if (m -> parent == m ) // some toplevel modules (really just Base) aren't actually
22652259 jl_collect_extext_methods_from_mod (* extext_methods , m );
22662260 }
2267- jl_collect_methtable_from_mod (* extext_methods , jl_type_type_mt );
2268- jl_collect_missing_backedges (jl_type_type_mt );
2269- jl_collect_methtable_from_mod (* extext_methods , jl_nonfunction_mt );
2270- jl_collect_missing_backedges (jl_nonfunction_mt );
2271- // jl_collect_extext_methods_from_mod and jl_collect_missing_backedges also accumulate data in callers_with_edges.
2272- // Process this to extract `edges` and `ext_targets`.
2273- * ext_targets = jl_alloc_vec_any (0 );
2274- * edges = jl_alloc_vec_any (0 );
2275- jl_collect_edges (* edges , * ext_targets );
2261+
2262+ if (edges ) {
2263+ jl_collect_missing_backedges (jl_type_type_mt );
2264+ jl_collect_missing_backedges (jl_nonfunction_mt );
2265+ // jl_collect_extext_methods_from_mod and jl_collect_missing_backedges also accumulate data in callers_with_edges.
2266+ // Process this to extract `edges` and `ext_targets`.
2267+ * ext_targets = jl_alloc_vec_any (0 );
2268+ * edges = jl_alloc_vec_any (0 );
2269+ * method_roots_list = jl_alloc_vec_any (0 );
2270+ // Collect the new method roots
2271+ htable_t methods_with_newspecs ;
2272+ htable_new (& methods_with_newspecs , 0 );
2273+ jl_collect_methods (& methods_with_newspecs , * new_specializations );
2274+ jl_collect_new_roots (* method_roots_list , & methods_with_newspecs , worklist_key );
2275+ htable_free (& methods_with_newspecs );
2276+ jl_collect_edges (* edges , * ext_targets );
2277+ }
22762278 htable_free (& external_mis );
22772279 assert (edges_map == NULL ); // jl_collect_edges clears this when done
22782280
@@ -2562,9 +2564,8 @@ static void jl_save_system_image_to_stream(ios_t *f,
25622564 jl_gc_enable (en );
25632565}
25642566
2565- static void jl_write_header_for_incremental (ios_t * f , jl_array_t * worklist , jl_array_t * * mod_array , jl_array_t * * udeps , int64_t * srctextpos , int64_t * checksumpos )
2567+ static void jl_write_header_for_incremental (ios_t * f , jl_array_t * worklist , jl_array_t * mod_array , jl_array_t * * udeps , int64_t * srctextpos , int64_t * checksumpos )
25662568{
2567- * mod_array = jl_get_loaded_modules (); // __toplevel__ modules loaded in this session (from Base.loaded_modules_array)
25682569 assert (jl_precompile_toplevel_module == NULL );
25692570 jl_precompile_toplevel_module = (jl_module_t * )jl_array_ptr_ref (worklist , jl_array_len (worklist )- 1 );
25702571
@@ -2580,7 +2581,7 @@ static void jl_write_header_for_incremental(ios_t *f, jl_array_t *worklist, jl_a
25802581 // write description of requirements for loading (modules that must be pre-loaded if initialization is to succeed)
25812582 // this can return errors during deserialize,
25822583 // best to keep it early (before any actual initialization)
2583- write_mod_list (f , * mod_array );
2584+ write_mod_list (f , mod_array );
25842585}
25852586
25862587JL_DLLEXPORT void jl_create_system_image (void * * _native_data , jl_array_t * worklist , bool_t emit_split ,
@@ -2611,49 +2612,58 @@ JL_DLLEXPORT void jl_create_system_image(void **_native_data, jl_array_t *workli
26112612 int64_t checksumpos_ff = 0 ;
26122613 int64_t datastartpos = 0 ;
26132614 JL_GC_PUSH6 (& mod_array , & extext_methods , & new_specializations , & method_roots_list , & ext_targets , & edges );
2614- if (worklist ) {
2615- jl_write_header_for_incremental (f , worklist , & mod_array , udeps , srctextpos , & checksumpos );
2616- if (emit_split ) {
2617- checksumpos_ff = write_header (ff , 1 );
2618- write_uint8 (ff , jl_cache_flags ());
2619- write_mod_list (ff , mod_array );
2620- } else {
2621- checksumpos_ff = checksumpos ;
2622- }
2623- {
2624- // make sure we don't run any Julia code concurrently after this point
2625- jl_gc_enable_finalizers (ct , 0 );
2626- assert (ct -> reentrant_inference == 0 );
2627- ct -> reentrant_inference = (uint16_t )-1 ;
2628- }
2629- jl_prepare_serialization_data (mod_array , newly_inferred , jl_worklist_key (worklist ), & extext_methods , & new_specializations , & method_roots_list , & ext_targets , & edges );
26302615
2616+ if (worklist ) {
2617+ mod_array = jl_get_loaded_modules (); // __toplevel__ modules loaded in this session (from Base.loaded_modules_array)
26312618 // Generate _native_data`
26322619 if (jl_options .outputo || jl_options .outputbc || jl_options .outputunoptbc || jl_options .outputasm ) {
2620+ jl_prepare_serialization_data (mod_array , newly_inferred , jl_worklist_key (worklist ),
2621+ & extext_methods , & new_specializations , NULL , NULL , NULL );
26332622 jl_precompile_toplevel_module = (jl_module_t * )jl_array_ptr_ref (worklist , jl_array_len (worklist )- 1 );
26342623 * _native_data = jl_precompile_worklist (worklist , extext_methods , new_specializations );
26352624 jl_precompile_toplevel_module = NULL ;
2625+ extext_methods = NULL ;
2626+ new_specializations = NULL ;
26362627 }
2628+ jl_write_header_for_incremental (f , worklist , mod_array , udeps , srctextpos , & checksumpos );
2629+ if (emit_split ) {
2630+ checksumpos_ff = write_header (ff , 1 );
2631+ write_uint8 (ff , jl_cache_flags ());
2632+ write_mod_list (ff , mod_array );
2633+ }
2634+ else {
2635+ checksumpos_ff = checksumpos ;
2636+ }
2637+ }
2638+ else {
2639+ * _native_data = jl_precompile (jl_options .compile_enabled == JL_OPTIONS_COMPILE_ALL );
2640+ }
26372641
2642+ // Make sure we don't run any Julia code concurrently after this point
2643+ // since it will invalidate our serialization preparations
2644+ jl_gc_enable_finalizers (ct , 0 );
2645+ assert (ct -> reentrant_inference == 0 );
2646+ ct -> reentrant_inference = (uint16_t )-1 ;
2647+ if (worklist ) {
2648+ jl_prepare_serialization_data (mod_array , newly_inferred , jl_worklist_key (worklist ),
2649+ & extext_methods , & new_specializations , & method_roots_list , & ext_targets , & edges );
26382650 if (!emit_split ) {
26392651 write_int32 (f , 0 ); // No clone_targets
26402652 write_padding (f , LLT_ALIGN (ios_pos (f ), JL_CACHE_BYTE_ALIGNMENT ) - ios_pos (f ));
2641- } else {
2653+ }
2654+ else {
26422655 write_padding (ff , LLT_ALIGN (ios_pos (ff ), JL_CACHE_BYTE_ALIGNMENT ) - ios_pos (ff ));
26432656 }
26442657 datastartpos = ios_pos (ff );
2645- } else {
2646- * _native_data = jl_precompile (jl_options .compile_enabled == JL_OPTIONS_COMPILE_ALL );
26472658 }
26482659 native_functions = * _native_data ;
26492660 jl_save_system_image_to_stream (ff , worklist , extext_methods , new_specializations , method_roots_list , ext_targets , edges );
26502661 native_functions = NULL ;
2651- if (worklist ) {
2652- // Re-enable running julia code for postoutput hooks, atexit, etc.
2653- jl_gc_enable_finalizers (ct , 1 );
2654- ct -> reentrant_inference = 0 ;
2655- jl_precompile_toplevel_module = NULL ;
2656- }
2662+ // make sure we don't run any Julia code concurrently before this point
2663+ // Re-enable running julia code for postoutput hooks, atexit, etc.
2664+ jl_gc_enable_finalizers (ct , 1 );
2665+ ct -> reentrant_inference = 0 ;
2666+ jl_precompile_toplevel_module = NULL ;
26572667
26582668 if (worklist ) {
26592669 // Go back and update the checksum in the header
0 commit comments