@@ -2170,50 +2170,52 @@ JL_DLLEXPORT jl_value_t *jl_as_global_root(jl_value_t *val JL_MAYBE_UNROOTED)
2170
2170
}
2171
2171
2172
2172
static void jl_prepare_serialization_data (jl_array_t * mod_array , jl_array_t * newly_inferred , uint64_t worklist_key ,
2173
- /* outputs */ jl_array_t * * extext_methods ,
2174
- jl_array_t * * new_specializations , jl_array_t * * method_roots_list ,
2175
- jl_array_t * * ext_targets , jl_array_t * * edges )
2173
+ /* outputs */ jl_array_t * * extext_methods , jl_array_t * * new_specializations ,
2174
+ jl_array_t * * method_roots_list , jl_array_t * * ext_targets , jl_array_t * * edges )
2176
2175
{
2177
2176
// extext_methods: [method1, ...], worklist-owned "extending external" methods added to functions owned by modules outside the worklist
2178
2177
// ext_targets: [invokesig1, callee1, matches1, ...] non-worklist callees of worklist-owned methods
2179
2178
// ordinary dispatch: invokesig=NULL, callee is MethodInstance
2180
2179
// `invoke` dispatch: invokesig is signature, callee is MethodInstance
2181
2180
// abstract call: callee is signature
2182
2181
// edges: [caller1, ext_targets_indexes1, ...] for worklist-owned methods calling external methods
2183
-
2184
2182
assert (edges_map == NULL );
2185
- JL_GC_PUSH1 (& edges_map );
2186
2183
2187
- // Save the inferred code from newly inferred, external methods
2188
2184
htable_new (& external_mis , 0 ); // we need external_mis until after `jl_collect_edges` finishes
2185
+ // Save the inferred code from newly inferred, external methods
2189
2186
* new_specializations = queue_external_cis (newly_inferred );
2190
- // Collect the new method roots
2191
- htable_t methods_with_newspecs ;
2192
- htable_new (& methods_with_newspecs , 0 );
2193
- jl_collect_methods (& methods_with_newspecs , * new_specializations );
2194
- * method_roots_list = jl_alloc_vec_any (0 );
2195
- jl_collect_new_roots (* method_roots_list , & methods_with_newspecs , worklist_key );
2196
- htable_free (& methods_with_newspecs );
2197
2187
2198
2188
// Collect method extensions and edges data
2199
- edges_map = jl_alloc_vec_any (0 );
2189
+ JL_GC_PUSH1 (& edges_map );
2190
+ if (edges )
2191
+ edges_map = jl_alloc_vec_any (0 );
2200
2192
* extext_methods = jl_alloc_vec_any (0 );
2193
+ jl_collect_methtable_from_mod (jl_type_type_mt , * extext_methods );
2194
+ jl_collect_methtable_from_mod (jl_nonfunction_mt , * extext_methods );
2201
2195
size_t i , len = jl_array_len (mod_array );
2202
2196
for (i = 0 ; i < len ; i ++ ) {
2203
2197
jl_module_t * m = (jl_module_t * )jl_array_ptr_ref (mod_array , i );
2204
2198
assert (jl_is_module (m ));
2205
2199
if (m -> parent == m ) // some toplevel modules (really just Base) aren't actually
2206
2200
jl_collect_extext_methods_from_mod (* extext_methods , m );
2207
2201
}
2208
- jl_collect_methtable_from_mod (* extext_methods , jl_type_type_mt );
2209
- jl_collect_missing_backedges (jl_type_type_mt );
2210
- jl_collect_methtable_from_mod (* extext_methods , jl_nonfunction_mt );
2211
- jl_collect_missing_backedges (jl_nonfunction_mt );
2212
- // jl_collect_extext_methods_from_mod and jl_collect_missing_backedges also accumulate data in callers_with_edges.
2213
- // Process this to extract `edges` and `ext_targets`.
2214
- * ext_targets = jl_alloc_vec_any (0 );
2215
- * edges = jl_alloc_vec_any (0 );
2216
- jl_collect_edges (* edges , * ext_targets );
2202
+
2203
+ if (edges ) {
2204
+ jl_collect_missing_backedges (jl_type_type_mt );
2205
+ jl_collect_missing_backedges (jl_nonfunction_mt );
2206
+ // jl_collect_extext_methods_from_mod and jl_collect_missing_backedges also accumulate data in callers_with_edges.
2207
+ // Process this to extract `edges` and `ext_targets`.
2208
+ * ext_targets = jl_alloc_vec_any (0 );
2209
+ * edges = jl_alloc_vec_any (0 );
2210
+ * method_roots_list = jl_alloc_vec_any (0 );
2211
+ // Collect the new method roots
2212
+ htable_t methods_with_newspecs ;
2213
+ htable_new (& methods_with_newspecs , 0 );
2214
+ jl_collect_methods (& methods_with_newspecs , * new_specializations );
2215
+ jl_collect_new_roots (* method_roots_list , & methods_with_newspecs , worklist_key );
2216
+ htable_free (& methods_with_newspecs );
2217
+ jl_collect_edges (* edges , * ext_targets );
2218
+ }
2217
2219
htable_free (& external_mis );
2218
2220
assert (edges_map == NULL ); // jl_collect_edges clears this when done
2219
2221
@@ -2501,9 +2503,8 @@ static void jl_save_system_image_to_stream(ios_t *f,
2501
2503
jl_gc_enable (en );
2502
2504
}
2503
2505
2504
- 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 )
2506
+ 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 )
2505
2507
{
2506
- * mod_array = jl_get_loaded_modules (); // __toplevel__ modules loaded in this session (from Base.loaded_modules_array)
2507
2508
assert (jl_precompile_toplevel_module == NULL );
2508
2509
jl_precompile_toplevel_module = (jl_module_t * )jl_array_ptr_ref (worklist , jl_array_len (worklist )- 1 );
2509
2510
@@ -2519,7 +2520,7 @@ static void jl_write_header_for_incremental(ios_t *f, jl_array_t *worklist, jl_a
2519
2520
// write description of requirements for loading (modules that must be pre-loaded if initialization is to succeed)
2520
2521
// this can return errors during deserialize,
2521
2522
// best to keep it early (before any actual initialization)
2522
- write_mod_list (f , * mod_array );
2523
+ write_mod_list (f , mod_array );
2523
2524
}
2524
2525
2525
2526
JL_DLLEXPORT void jl_create_system_image (void * * _native_data , jl_array_t * worklist , bool_t emit_split ,
@@ -2550,49 +2551,58 @@ JL_DLLEXPORT void jl_create_system_image(void **_native_data, jl_array_t *workli
2550
2551
int64_t checksumpos_ff = 0 ;
2551
2552
int64_t datastartpos = 0 ;
2552
2553
JL_GC_PUSH6 (& mod_array , & extext_methods , & new_specializations , & method_roots_list , & ext_targets , & edges );
2553
- if (worklist ) {
2554
- jl_write_header_for_incremental (f , worklist , & mod_array , udeps , srctextpos , & checksumpos );
2555
- if (emit_split ) {
2556
- checksumpos_ff = write_header (ff , 1 );
2557
- write_uint8 (ff , jl_cache_flags ());
2558
- write_mod_list (ff , mod_array );
2559
- } else {
2560
- checksumpos_ff = checksumpos ;
2561
- }
2562
- {
2563
- // make sure we don't run any Julia code concurrently after this point
2564
- jl_gc_enable_finalizers (ct , 0 );
2565
- assert (ct -> reentrant_inference == 0 );
2566
- ct -> reentrant_inference = (uint16_t )-1 ;
2567
- }
2568
- jl_prepare_serialization_data (mod_array , newly_inferred , jl_worklist_key (worklist ), & extext_methods , & new_specializations , & method_roots_list , & ext_targets , & edges );
2569
2554
2555
+ if (worklist ) {
2556
+ mod_array = jl_get_loaded_modules (); // __toplevel__ modules loaded in this session (from Base.loaded_modules_array)
2570
2557
// Generate _native_data`
2571
2558
if (jl_options .outputo || jl_options .outputbc || jl_options .outputunoptbc || jl_options .outputasm ) {
2559
+ jl_prepare_serialization_data (mod_array , newly_inferred , jl_worklist_key (worklist ),
2560
+ & extext_methods , & new_specializations , NULL , NULL , NULL );
2572
2561
jl_precompile_toplevel_module = (jl_module_t * )jl_array_ptr_ref (worklist , jl_array_len (worklist )- 1 );
2573
2562
* _native_data = jl_precompile_worklist (worklist , extext_methods , new_specializations );
2574
2563
jl_precompile_toplevel_module = NULL ;
2564
+ extext_methods = NULL ;
2565
+ new_specializations = NULL ;
2575
2566
}
2567
+ jl_write_header_for_incremental (f , worklist , mod_array , udeps , srctextpos , & checksumpos );
2568
+ if (emit_split ) {
2569
+ checksumpos_ff = write_header (ff , 1 );
2570
+ write_uint8 (ff , jl_cache_flags ());
2571
+ write_mod_list (ff , mod_array );
2572
+ }
2573
+ else {
2574
+ checksumpos_ff = checksumpos ;
2575
+ }
2576
+ }
2577
+ else {
2578
+ * _native_data = jl_precompile (jl_options .compile_enabled == JL_OPTIONS_COMPILE_ALL );
2579
+ }
2576
2580
2581
+ // Make sure we don't run any Julia code concurrently after this point
2582
+ // since it will invalidate our serialization preparations
2583
+ jl_gc_enable_finalizers (ct , 0 );
2584
+ assert (ct -> reentrant_inference == 0 );
2585
+ ct -> reentrant_inference = (uint16_t )-1 ;
2586
+ if (worklist ) {
2587
+ jl_prepare_serialization_data (mod_array , newly_inferred , jl_worklist_key (worklist ),
2588
+ & extext_methods , & new_specializations , & method_roots_list , & ext_targets , & edges );
2577
2589
if (!emit_split ) {
2578
2590
write_int32 (f , 0 ); // No clone_targets
2579
2591
write_padding (f , LLT_ALIGN (ios_pos (f ), JL_CACHE_BYTE_ALIGNMENT ) - ios_pos (f ));
2580
- } else {
2592
+ }
2593
+ else {
2581
2594
write_padding (ff , LLT_ALIGN (ios_pos (ff ), JL_CACHE_BYTE_ALIGNMENT ) - ios_pos (ff ));
2582
2595
}
2583
2596
datastartpos = ios_pos (ff );
2584
- } else {
2585
- * _native_data = jl_precompile (jl_options .compile_enabled == JL_OPTIONS_COMPILE_ALL );
2586
2597
}
2587
2598
native_functions = * _native_data ;
2588
2599
jl_save_system_image_to_stream (ff , worklist , extext_methods , new_specializations , method_roots_list , ext_targets , edges );
2589
2600
native_functions = NULL ;
2590
- if (worklist ) {
2591
- // Re-enable running julia code for postoutput hooks, atexit, etc.
2592
- jl_gc_enable_finalizers (ct , 1 );
2593
- ct -> reentrant_inference = 0 ;
2594
- jl_precompile_toplevel_module = NULL ;
2595
- }
2601
+ // make sure we don't run any Julia code concurrently before this point
2602
+ // Re-enable running julia code for postoutput hooks, atexit, etc.
2603
+ jl_gc_enable_finalizers (ct , 1 );
2604
+ ct -> reentrant_inference = 0 ;
2605
+ jl_precompile_toplevel_module = NULL ;
2596
2606
2597
2607
if (worklist ) {
2598
2608
// Go back and update the checksum in the header
0 commit comments