diff --git a/base/options.jl b/base/options.jl index 4daae3752ccda..950bc2bed0bed 100644 --- a/base/options.jl +++ b/base/options.jl @@ -63,6 +63,7 @@ struct JLOptions task_metrics::Int8 timeout_for_safepoint_straggler_s::Int16 serialize_machine_code_only::Int8 + drop_edges::Int8 end # This runs early in the sysimage != is not defined yet diff --git a/src/jloptions.c b/src/jloptions.c index 732ec14e2da49..74cf952ba9f98 100644 --- a/src/jloptions.c +++ b/src/jloptions.c @@ -96,6 +96,7 @@ JL_DLLEXPORT void jl_init_options(void) 0, // task_metrics 25, // timeout_for_safepoint_straggler_s 0, // serialize_machine_code_only + 0, // drop_edges }; jl_options_initialized = 1; } @@ -247,6 +248,7 @@ JL_DLLEXPORT void jl_parse_opts(int *argcp, char ***argvp) opt_inline, opt_polly, opt_serialize_machine_code_only, + opt_drop_edges, opt_timeout_for_safepoint_straggler, opt_trace_compile, opt_trace_compile_timing, @@ -328,6 +330,7 @@ JL_DLLEXPORT void jl_parse_opts(int *argcp, char ***argvp) { "inline", required_argument, 0, opt_inline }, { "polly", required_argument, 0, opt_polly }, { "serialize-machine-code-only", no_argument, 0, opt_serialize_machine_code_only }, + { "drop-edges", no_argument, 0, opt_drop_edges }, { "timeout-for-safepoint-straggler", required_argument, 0, opt_timeout_for_safepoint_straggler }, { "trace-compile", required_argument, 0, opt_trace_compile }, { "trace-compile-timing", no_argument, 0, opt_trace_compile_timing }, @@ -899,6 +902,9 @@ JL_DLLEXPORT void jl_parse_opts(int *argcp, char ***argvp) case opt_serialize_machine_code_only: jl_options.serialize_machine_code_only = 1; break; + case opt_drop_edges: + jl_options.drop_edges = 1; + break; case opt_task_metrics: if (!strcmp(optarg, "no")) jl_options.task_metrics = JL_OPTIONS_TASK_METRICS_OFF; diff --git a/src/jloptions.h b/src/jloptions.h index 84de297b81043..c8bf2e8b3f410 100644 --- a/src/jloptions.h +++ b/src/jloptions.h @@ -67,6 +67,7 @@ typedef struct { int8_t task_metrics; int16_t timeout_for_safepoint_straggler_s; int8_t serialize_machine_code_only; + int8_t drop_edges; } jl_options_t; #endif diff --git a/src/staticdata.c b/src/staticdata.c index 9775b9ecc6f5a..2e3f9a1808071 100644 --- a/src/staticdata.c +++ b/src/staticdata.c @@ -2244,9 +2244,11 @@ static void strip_specializations_(jl_method_instance_t *mi) } codeinst = jl_atomic_load_relaxed(&codeinst->next); } + if (jl_options.strip_ir || jl_options.drop_edges) { + record_field_change((jl_value_t**)&mi->backedges, NULL); + } if (jl_options.strip_ir) { record_field_change((jl_value_t**)&mi->uninferred, NULL); - record_field_change((jl_value_t**)&mi->backedges, NULL); record_field_change((jl_value_t**)&mi->callbacks, NULL); } } @@ -2300,7 +2302,7 @@ static int strip_all_codeinfos__(jl_typemap_entry_t *def, void *_env) static int strip_all_codeinfos_(jl_methtable_t *mt, void *_env) { - if (jl_options.strip_ir && mt->backedges) + if ((jl_options.strip_ir || jl_options.drop_edges) && mt->backedges) record_field_change((jl_value_t**)&mt->backedges, NULL); return jl_typemap_visitor(mt->defs, strip_all_codeinfos__, NULL); } @@ -2411,7 +2413,7 @@ static void jl_save_system_image_to_stream(ios_t *f, jl_array_t *mod_array, { htable_new(&field_replace, 0); // strip metadata and IR when requested - if (jl_options.strip_metadata || jl_options.strip_ir) + if (jl_options.strip_metadata || jl_options.strip_ir || jl_options.drop_edges) jl_strip_all_codeinfos(); int en = jl_gc_enable(0); @@ -2525,6 +2527,17 @@ static void jl_save_system_image_to_stream(ios_t *f, jl_array_t *mod_array, // Queue the new roots jl_queue_for_serialization(&s, method_roots_list); // Queue the edges + if (jl_options.drop_edges) { + // Empty ext_targets + ext_targets = jl_alloc_vec_any(0); + // The caller field in `edges` is used in loading so we only empty the + // callees array when we drop edges. + size_t i, l = jl_array_len(edges) / 2; + for (i = 0; i < l; i++) { + jl_array_t *cids = jl_alloc_array_1d(jl_array_int32_type, 0); + jl_array_ptr_set(edges, 2 * i + 1, cids); + } + } jl_queue_for_serialization(&s, ext_targets); jl_queue_for_serialization(&s, edges); } diff --git a/src/staticdata_utils.c b/src/staticdata_utils.c index 6a476340814d1..31063c87fd7fe 100644 --- a/src/staticdata_utils.c +++ b/src/staticdata_utils.c @@ -985,20 +985,22 @@ static jl_array_t *jl_verify_methods(jl_array_t *edges, jl_array_t *maxvalids) int32_t *idxs = (int32_t*)jl_array_data(callee_ids); size_t j; maxvalids2_data[i] = ~(size_t)0; - for (j = 0; j < idxs[0]; j++) { - int32_t idx = idxs[j + 1]; - size_t max_valid = ((size_t*)(jl_array_data(maxvalids)))[idx]; - if (max_valid != ~(size_t)0 && _jl_debug_method_invalidation) { - jl_array_ptr_1d_push(_jl_debug_method_invalidation, (jl_value_t*)caller); - loctag = jl_cstr_to_string("verify_methods"); - jl_array_ptr_1d_push(_jl_debug_method_invalidation, loctag); - loctag = jl_box_int32((int32_t)idx); - jl_array_ptr_1d_push(_jl_debug_method_invalidation, loctag); + if (jl_array_len(callee_ids) > 0) { + for (j = 0; j < idxs[0]; j++) { + int32_t idx = idxs[j + 1]; + size_t max_valid = ((size_t*)(jl_array_data(maxvalids)))[idx]; + if (max_valid != ~(size_t)0 && _jl_debug_method_invalidation) { + jl_array_ptr_1d_push(_jl_debug_method_invalidation, (jl_value_t*)caller); + loctag = jl_cstr_to_string("verify_methods"); + jl_array_ptr_1d_push(_jl_debug_method_invalidation, loctag); + loctag = jl_box_int32((int32_t)idx); + jl_array_ptr_1d_push(_jl_debug_method_invalidation, loctag); + } + if (max_valid < maxvalids2_data[i]) + maxvalids2_data[i] = max_valid; + if (max_valid == 0) + break; } - if (max_valid < maxvalids2_data[i]) - maxvalids2_data[i] = max_valid; - if (max_valid == 0) - break; } } //jl_static_show((JL_STREAM*)ios_stderr, (jl_value_t*)caller); @@ -1138,23 +1140,25 @@ static void jl_insert_backedges(jl_array_t *edges, jl_array_t *ext_targets, jl_a if (maxvalid == ~(size_t)0) { // if this callee is still valid, add all the backedges jl_array_t *callee_ids = (jl_array_t*)jl_array_ptr_ref(edges, 2 * i + 1); - int32_t *idxs = (int32_t*)jl_array_data(callee_ids); - for (size_t j = 0; j < idxs[0]; j++) { - int32_t idx = idxs[j + 1]; - jl_value_t *invokesig = jl_array_ptr_ref(ext_targets, idx * 3); - jl_value_t *callee = jl_array_ptr_ref(ext_targets, idx * 3 + 1); - if (callee && jl_is_method_instance(callee)) { - jl_method_instance_add_backedge((jl_method_instance_t*)callee, invokesig, caller); - } - else { - jl_value_t *sig = callee == NULL ? invokesig : callee; - jl_methtable_t *mt = jl_method_table_for(sig); - // FIXME: rarely, `callee` has an unexpected `Union` signature, - // see https://github.com/JuliaLang/julia/pull/43990#issuecomment-1030329344 - // Fix the issue and turn this back into an `assert((jl_value_t*)mt != jl_nothing)` - // This workaround exposes us to (rare) 265-violations. - if ((jl_value_t*)mt != jl_nothing) - jl_method_table_add_backedge(mt, sig, (jl_value_t*)caller); + if (jl_array_len(callee_ids) > 0) { + int32_t *idxs = (int32_t*)jl_array_data(callee_ids); + for (size_t j = 0; j < idxs[0]; j++) { + int32_t idx = idxs[j + 1]; + jl_value_t *invokesig = jl_array_ptr_ref(ext_targets, idx * 3); + jl_value_t *callee = jl_array_ptr_ref(ext_targets, idx * 3 + 1); + if (callee && jl_is_method_instance(callee)) { + jl_method_instance_add_backedge((jl_method_instance_t*)callee, invokesig, caller); + } + else { + jl_value_t *sig = callee == NULL ? invokesig : callee; + jl_methtable_t *mt = jl_method_table_for(sig); + // FIXME: rarely, `callee` has an unexpected `Union` signature, + // see https://github.com/JuliaLang/julia/pull/43990#issuecomment-1030329344 + // Fix the issue and turn this back into an `assert((jl_value_t*)mt != jl_nothing)` + // This workaround exposes us to (rare) 265-violations. + if ((jl_value_t*)mt != jl_nothing) + jl_method_table_add_backedge(mt, sig, (jl_value_t*)caller); + } } } } diff --git a/test/cmdlineargs.jl b/test/cmdlineargs.jl index 27b828629c0b5..591c5447317ed 100644 --- a/test/cmdlineargs.jl +++ b/test/cmdlineargs.jl @@ -1137,3 +1137,8 @@ end exename = `$(Base.julia_cmd())` @test parse(Int,read(`$exename --serialize-machine-code-only -E "Base.JLOptions().serialize_machine_code_only"`, String)) == 1 end + +@testset "--drop-edges" begin + exename = `$(Base.julia_cmd())` + @test parse(Int,read(`$exename --drop-edges -E "Base.JLOptions().drop_edges`, String)) == 1 +end