diff --git a/base/options.jl b/base/options.jl index 1a52bf1a4e2ef..4daae3752ccda 100644 --- a/base/options.jl +++ b/base/options.jl @@ -62,6 +62,7 @@ struct JLOptions safe_crash_log_file::Ptr{UInt8} task_metrics::Int8 timeout_for_safepoint_straggler_s::Int16 + serialize_machine_code_only::Int8 end # This runs early in the sysimage != is not defined yet diff --git a/src/gf.c b/src/gf.c index 4b77da21d9911..db987e1a2ddf4 100644 --- a/src/gf.c +++ b/src/gf.c @@ -2882,6 +2882,10 @@ static void _generate_from_hint(jl_method_instance_t *mi, size_t world) if (jl_atomic_load_relaxed(&((jl_code_instance_t*)codeinst)->invoke) == jl_fptr_const_return) return; // probably not a good idea to generate code jl_atomic_store_relaxed(&((jl_code_instance_t*)codeinst)->precompile, 1); + if (jl_options.serialize_machine_code_only) { + // also trigger compilation so that JIT-based compilation heuristics can succeed + (void)jl_compile_method_internal(mi, world); + } } } diff --git a/src/jloptions.c b/src/jloptions.c index 751418cac7c47..732ec14e2da49 100644 --- a/src/jloptions.c +++ b/src/jloptions.c @@ -95,6 +95,7 @@ JL_DLLEXPORT void jl_init_options(void) NULL, // safe_crash_log_file 0, // task_metrics 25, // timeout_for_safepoint_straggler_s + 0, // serialize_machine_code_only }; jl_options_initialized = 1; } @@ -245,6 +246,7 @@ JL_DLLEXPORT void jl_parse_opts(int *argcp, char ***argvp) opt_warn_scope, opt_inline, opt_polly, + opt_serialize_machine_code_only, opt_timeout_for_safepoint_straggler, opt_trace_compile, opt_trace_compile_timing, @@ -325,6 +327,7 @@ JL_DLLEXPORT void jl_parse_opts(int *argcp, char ***argvp) { "warn-scope", required_argument, 0, opt_warn_scope }, { "inline", required_argument, 0, opt_inline }, { "polly", required_argument, 0, opt_polly }, + { "serialize-machine-code-only", no_argument, 0, opt_serialize_machine_code_only }, { "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 }, @@ -893,6 +896,9 @@ JL_DLLEXPORT void jl_parse_opts(int *argcp, char ***argvp) jl_errorf("julia: --timeout-for-safepoint-straggler=; seconds must be an integer between 1 and %d", INT16_MAX); jl_options.timeout_for_safepoint_straggler_s = (int16_t)timeout; break; + case opt_serialize_machine_code_only: + jl_options.serialize_machine_code_only = 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 da1791a6b936c..84de297b81043 100644 --- a/src/jloptions.h +++ b/src/jloptions.h @@ -66,6 +66,7 @@ typedef struct { const char *safe_crash_log_file; int8_t task_metrics; int16_t timeout_for_safepoint_straggler_s; + int8_t serialize_machine_code_only; } jl_options_t; #endif diff --git a/src/precompile_utils.c b/src/precompile_utils.c index 055ec4b3330f1..80121d47faf68 100644 --- a/src/precompile_utils.c +++ b/src/precompile_utils.c @@ -184,14 +184,20 @@ static int precompile_enq_specialization_(jl_method_instance_t *mi, void *closur int do_compile = 0; if (jl_atomic_load_relaxed(&codeinst->invoke) != jl_fptr_const_return) { jl_value_t *inferred = jl_atomic_load_relaxed(&codeinst->inferred); - if (inferred && - inferred != jl_nothing && - jl_ir_flag_inferred(inferred) && - (jl_ir_inlining_cost(inferred) == UINT16_MAX)) { - do_compile = 1; - } - else if (jl_atomic_load_relaxed(&codeinst->invoke) != NULL || jl_atomic_load_relaxed(&codeinst->precompile)) { - do_compile = 1; + if (jl_options.serialize_machine_code_only) { + if (jl_atomic_load_relaxed(&codeinst->invoke) != NULL) { + do_compile = 1; + } + } else { + if (inferred && + inferred != jl_nothing && + jl_ir_flag_inferred(inferred) && + (jl_ir_inlining_cost(inferred) == UINT16_MAX)) { + do_compile = 1; + } + else if (jl_atomic_load_relaxed(&codeinst->invoke) != NULL || jl_atomic_load_relaxed(&codeinst->precompile)) { + do_compile = 1; + } } } if (do_compile) { diff --git a/src/staticdata_utils.c b/src/staticdata_utils.c index f08ca21017700..6a476340814d1 100644 --- a/src/staticdata_utils.c +++ b/src/staticdata_utils.c @@ -234,7 +234,10 @@ static jl_array_t *queue_external_cis(jl_array_t *list) continue; jl_method_instance_t *mi = ci->def; jl_method_t *m = mi->def.method; - if (ci->inferred && jl_is_method(m) && jl_object_in_image((jl_value_t*)m->module)) { + void *code = (jl_options.serialize_machine_code_only) ? (void *)ci->invoke : (void *)ci->inferred; + int for_serialized_method = jl_is_method(m) && jl_object_in_image((jl_value_t*)m->module); + int has_code = code != NULL; + if (has_code && for_serialized_method) { int found = has_backedge_to_worklist(mi, &visited, &stack); assert(found == 0 || found == 1 || found == 2); assert(stack.len == 0); diff --git a/test/cmdlineargs.jl b/test/cmdlineargs.jl index 4fe5ef16eb2ff..27b828629c0b5 100644 --- a/test/cmdlineargs.jl +++ b/test/cmdlineargs.jl @@ -1132,3 +1132,8 @@ end timeout = 120 @test parse(Int,read(`$exename --timeout-for-safepoint-straggler=$timeout -E "Base.JLOptions().timeout_for_safepoint_straggler_s"`, String)) == timeout end + +@testset "--serialize-machine-code-only" begin + exename = `$(Base.julia_cmd())` + @test parse(Int,read(`$exename --serialize-machine-code-only -E "Base.JLOptions().serialize_machine_code_only"`, String)) == 1 +end