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/gc.c b/src/gc.c index 98ed32cd4a54a..65b52b7130dcc 100644 --- a/src/gc.c +++ b/src/gc.c @@ -1014,6 +1014,7 @@ STATIC_INLINE jl_value_t *jl_gc_big_alloc_inner(jl_ptls_t ptls, size_t sz) memset(v, 0xee, allocsz); #endif v->sz = allocsz; + v->header = 0; gc_big_object_link(ptls->gc_tls.heap.young_generation_of_bigvals, v); return jl_valueof(&v->header); } 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/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