Skip to content

Commit c0478d8

Browse files
authored
improve precompilation coverage (#33006)
- move the place where --trace-compile outputs precompile statement to a location that catches more cases - tweak the REPL code to be more amenable to precompilation in light of - instead of trying to encode all the rules where the precompile emitter fails (#28808) just try to precompile and do nothing if it fails.
1 parent 5e75cfe commit c0478d8

File tree

4 files changed

+50
-47
lines changed

4 files changed

+50
-47
lines changed

contrib/generate_precompile.jl

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -142,12 +142,6 @@ function generate_precompile_statements()
142142
push!(statements, statement)
143143
end
144144

145-
if have_repl
146-
# Seems like a reasonable number right now, adjust as needed
147-
# comment out if debugging script
148-
@assert length(statements) > 700
149-
end
150-
151145
# Create a staging area where all the loaded packages are available
152146
PrecompileStagingArea = Module()
153147
for (_pkgid, _mod) in Base.loaded_modules
@@ -157,22 +151,23 @@ function generate_precompile_statements()
157151
end
158152

159153
# Execute the collected precompile statements
154+
n_succeeded = 0
160155
include_time = @elapsed for statement in sort(collect(statements))
161156
# println(statement)
162-
# Workarounds for #28808
163-
occursin("\"YYYY-mm-dd\\THH:MM:SS\"", statement) && continue
164-
statement == "precompile(Tuple{typeof(Base.show), Base.IOContext{Base.TTY}, Type{Vararg{Any, N} where N}})" && continue
165-
# check for `#x##s66` style variable names not in quotes
166-
occursin(r"#\w", statement) &&
167-
count(r"(?:#+\w+)+", statement) !=
168-
count(r"\"(?:#+\w+)+\"", statement) && continue
169157
try
170158
Base.include_string(PrecompileStagingArea, statement)
159+
n_succeeded += 1
171160
catch
172-
@error "Failed to precompile $statement"
173-
rethrow()
161+
# See #28808
162+
# @error "Failed to precompile $statement"
174163
end
175164
end
165+
if have_repl
166+
# Seems like a reasonable number right now, adjust as needed
167+
# comment out if debugging script
168+
@assert n_succeeded > 3500
169+
end
170+
176171
print(" $(length(statements)) generated in ")
177172
tot_time = time() - start_time
178173
Base.time_print(tot_time * 10^9)

src/codegen.cpp

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1042,6 +1042,10 @@ const char *name_from_method_instance(jl_method_instance_t *mi)
10421042
extern "C"
10431043
jl_code_instance_t *jl_compile_linfo(jl_method_instance_t *mi, jl_code_info_t *src, size_t world, const jl_cgparams_t *params)
10441044
{
1045+
// TODO: Merge with jl_dump_compiles?
1046+
static ios_t f_precompile;
1047+
static JL_STREAM* s_precompile = NULL;
1048+
10451049
// N.B.: `src` may have not been rooted by the caller.
10461050
JL_TIMING(CODEGEN);
10471051
assert(jl_is_method_instance(mi));
@@ -1266,12 +1270,34 @@ jl_code_instance_t *jl_compile_linfo(jl_method_instance_t *mi, jl_code_info_t *s
12661270
// ... unless mi->def isn't defined here meaning the function is a toplevel thunk and
12671271
// would have its CodeInfo printed in the stream, which might contain double-quotes that
12681272
// would not be properly escaped given the double-quotes added to the stream below.
1269-
if (dump_compiles_stream != NULL && jl_is_method(mi->def.method)) {
1270-
uint64_t this_time = jl_hrtime();
1271-
jl_printf(dump_compiles_stream, "%" PRIu64 "\t\"", this_time - last_time);
1272-
jl_static_show(dump_compiles_stream, mi->specTypes);
1273-
jl_printf(dump_compiles_stream, "\"\n");
1274-
last_time = this_time;
1273+
if (jl_is_method(mi->def.method)) {
1274+
if (jl_options.trace_compile != NULL) {
1275+
if (s_precompile == NULL) {
1276+
const char* t = jl_options.trace_compile;
1277+
if (!strncmp(t, "stderr", 6))
1278+
s_precompile = JL_STDERR;
1279+
else {
1280+
if (ios_file(&f_precompile, t, 1, 1, 1, 1) == NULL)
1281+
jl_errorf("cannot open precompile statement file \"%s\" for writing", t);
1282+
s_precompile = (JL_STREAM*) &f_precompile;
1283+
}
1284+
}
1285+
if (!jl_has_free_typevars(mi->specTypes)) {
1286+
jl_printf(s_precompile, "precompile(");
1287+
jl_static_show(s_precompile, mi->specTypes);
1288+
jl_printf(s_precompile, ")\n");
1289+
1290+
if (s_precompile != JL_STDERR)
1291+
ios_flush(&f_precompile);
1292+
}
1293+
}
1294+
if (dump_compiles_stream != NULL) {
1295+
uint64_t this_time = jl_hrtime();
1296+
jl_printf(dump_compiles_stream, "%" PRIu64 "\t\"", this_time - last_time);
1297+
jl_static_show(dump_compiles_stream, mi->specTypes);
1298+
jl_printf(dump_compiles_stream, "\"\n");
1299+
last_time = this_time;
1300+
}
12751301
}
12761302
JL_GC_POP();
12771303
return codeinst;

src/gf.c

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1079,10 +1079,6 @@ static jl_typemap_entry_t *jl_typemap_morespecific_by_type(jl_typemap_entry_t *f
10791079

10801080
static jl_method_instance_t *jl_mt_assoc_by_type(jl_methtable_t *mt, jl_datatype_t *tt, int mt_cache, size_t world)
10811081
{
1082-
// TODO: Merge with jl_dump_compiles?
1083-
static ios_t f_precompile;
1084-
static JL_STREAM* s_precompile = NULL;
1085-
10861082
// caller must hold the mt->writelock
10871083
jl_typemap_entry_t *entry = NULL;
10881084
entry = jl_typemap_assoc_by_type(mt->cache, (jl_value_t*)tt, NULL, /*subtype*/1, jl_cachearg_offset(mt), world, /*max_world_mask*/0);
@@ -1099,26 +1095,6 @@ static jl_method_instance_t *jl_mt_assoc_by_type(jl_methtable_t *mt, jl_datatype
10991095
entry = jl_typemap_morespecific_by_type(entry, (jl_value_t*)tt, &env, world);
11001096
if (entry != NULL) {
11011097
jl_method_t *m = entry->func.method;
1102-
if (jl_options.trace_compile != NULL) {
1103-
if (s_precompile == NULL) {
1104-
const char* t = jl_options.trace_compile;
1105-
if (!strncmp(t, "stderr", 6))
1106-
s_precompile = JL_STDERR;
1107-
else {
1108-
if (ios_file(&f_precompile, t, 1, 1, 1, 1) == NULL)
1109-
jl_errorf("cannot open precompile statement file \"%s\" for writing", t);
1110-
s_precompile = (JL_STREAM*) &f_precompile;
1111-
}
1112-
}
1113-
if (!jl_has_free_typevars((jl_value_t*)tt)) {
1114-
jl_printf(s_precompile, "precompile(");
1115-
jl_static_show(s_precompile, (jl_value_t*)tt);
1116-
jl_printf(s_precompile, ")\n");
1117-
1118-
if (s_precompile != JL_STDERR)
1119-
ios_flush(&f_precompile);
1120-
}
1121-
}
11221098
if (!mt_cache) {
11231099
intptr_t nspec = (mt == jl_type_type_mt ? m->nargs + 1 : mt->max_args + 2);
11241100
jl_compilation_sig(tt, env, m, nspec, &newparams);

stdlib/REPL/src/REPL.jl

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -765,15 +765,21 @@ setup_interface(
765765
repl::LineEditREPL;
766766
# those keyword arguments may be deprecated eventually in favor of the Options mechanism
767767
hascolor::Bool = repl.options.hascolor,
768-
extra_repl_keymap::Union{Dict,Vector{<:Dict}} = repl.options.extra_keymap
768+
extra_repl_keymap::Any = repl.options.extra_keymap
769769
) = setup_interface(repl, hascolor, extra_repl_keymap)
770770

771771
# This non keyword method can be precompiled which is important
772772
function setup_interface(
773773
repl::LineEditREPL,
774774
hascolor::Bool,
775-
extra_repl_keymap::Union{Dict,Vector{<:Dict}},
775+
extra_repl_keymap::Any, # Union{Dict,Vector{<:Dict}},
776776
)
777+
# The precompile statement emitter has problem outputting valid syntax for the
778+
# type of `Union{Dict,Vector{<:Dict}}` (see #28808).
779+
# This function is however important to precompile for REPL startup time, therefore,
780+
# make the type Any and just assert that we have the correct type below.
781+
@assert extra_repl_keymap isa Union{Dict,Vector{<:Dict}}
782+
777783
###
778784
#
779785
# This function returns the main interface that describes the REPL

0 commit comments

Comments
 (0)