Skip to content

Commit ff61785

Browse files
committed
do a better job at generating code for known functions
closes #15048
1 parent 03fad40 commit ff61785

File tree

3 files changed

+105
-27
lines changed

3 files changed

+105
-27
lines changed

base/loading.jl

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,19 @@ else
8080
end
8181
end
8282

83+
function try_path(prefix::ByteString, base::ByteString, name::ByteString)
84+
path = joinpath(prefix, name)
85+
isfile_casesensitive(path) && return abspath(path)
86+
path = joinpath(prefix, base, "src", name)
87+
isfile_casesensitive(path) && return abspath(path)
88+
path = joinpath(prefix, name, "src", name)
89+
isfile_casesensitive(path) && return abspath(path)
90+
return nothing
91+
end
92+
8393
# `wd` is a working directory to search. defaults to current working directory.
8494
# if `wd === nothing`, no extra path is searched.
85-
function find_in_path(name::AbstractString, wd = pwd())
95+
function find_in_path(name::ByteString, wd = pwd())
8696
isabspath(name) && return name
8797
base = name
8898
if endswith(name,".jl")
@@ -93,26 +103,24 @@ function find_in_path(name::AbstractString, wd = pwd())
93103
if wd !== nothing
94104
isfile_casesensitive(joinpath(wd,name)) && return joinpath(wd,name)
95105
end
96-
for prefix in [Pkg.dir(); LOAD_PATH]
97-
path = joinpath(prefix, name)
98-
isfile_casesensitive(path) && return abspath(path)
99-
path = joinpath(prefix, base, "src", name)
100-
isfile_casesensitive(path) && return abspath(path)
101-
path = joinpath(prefix, name, "src", name)
102-
isfile_casesensitive(path) && return abspath(path)
106+
p = try_path(Pkg.dir(), base, name)
107+
p !== nothing && return p
108+
for prefix in LOAD_PATH
109+
p = try_path(prefix, base, name)
110+
p !== nothing && return p
103111
end
104112
return nothing
105113
end
106114

107-
function find_in_node_path(name, srcpath, node::Int=1)
115+
function find_in_node_path(name::ByteString, srcpath, node::Int=1)
108116
if myid() == node
109117
find_in_path(name, srcpath)
110118
else
111119
remotecall_fetch(find_in_path, node, name, srcpath)
112120
end
113121
end
114122

115-
function find_source_file(file)
123+
function find_source_file(file::ByteString)
116124
(isabspath(file) || isfile(file)) && return file
117125
file2 = find_in_path(file)
118126
file2 !== nothing && return file2

src/gf.c

Lines changed: 84 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1959,6 +1959,11 @@ jl_lambda_info_t *jl_get_specialization1(jl_tupletype_t *types)
19591959
return NULL;
19601960
}
19611961

1962+
JL_DLLEXPORT void jl_compile_hint(jl_tupletype_t *types)
1963+
{
1964+
(void)jl_get_specialization1(types);
1965+
}
1966+
19621967
// add type of `f` to front of argument tuple type
19631968
jl_tupletype_t *jl_argtype_with_function(jl_function_t *f, jl_tupletype_t *types)
19641969
{
@@ -2229,13 +2234,6 @@ static int _compile_all_enq(jl_typemap_entry_t *ml, void *env)
22292234
return 1;
22302235
}
22312236

2232-
static void _compile_all_enq_mt(jl_methtable_t *mt, jl_array_t *found)
2233-
{
2234-
if (mt == NULL || (jl_value_t*)mt == jl_nothing) return;
2235-
jl_typemap_visitor(mt->defs, _compile_all_enq, (void*)found);
2236-
jl_typemap_visitor(mt->cache, _compile_all_enq, (void*)found);
2237-
}
2238-
22392237
static void _compile_all_enq_module(jl_module_t *m, jl_array_t *found)
22402238
{
22412239
// scan through all types reachable from 'v' and
@@ -2249,7 +2247,11 @@ static void _compile_all_enq_module(jl_module_t *m, jl_array_t *found)
22492247
if (jl_is_datatype(v)) {
22502248
jl_typename_t *tn = ((jl_datatype_t*)v)->name;
22512249
if (tn->module == m && tn->name == b->name) {
2252-
_compile_all_enq_mt(tn->mt, found);
2250+
jl_methtable_t *mt = tn->mt;
2251+
if (mt != NULL && (jl_value_t*)mt != jl_nothing) {
2252+
jl_typemap_visitor(mt->defs, _compile_all_enq, (void*)found);
2253+
jl_typemap_visitor(mt->cache, _compile_all_enq, (void*)found);
2254+
}
22532255
}
22542256
}
22552257
else if (jl_is_module(v)) {
@@ -2264,11 +2266,10 @@ static void _compile_all_enq_module(jl_module_t *m, jl_array_t *found)
22642266
}
22652267
}
22662268

2267-
void jl_compile_all(void)
2269+
static void jl_compile_all(void)
22682270
{
22692271
// this "found" array will contain
2270-
// LambdaInfos that need to be compiled
2271-
// and (generic-function, method) pairs that may be optimized (and need to be compiled)
2272+
// TypeMapEntries for Methods and LambdaInfos that need to be compiled
22722273
jl_array_t *m = jl_alloc_cell_1d(0);
22732274
JL_GC_PUSH1(&m);
22742275
while (1) {
@@ -2281,12 +2282,81 @@ void jl_compile_all(void)
22812282
}
22822283
JL_GC_POP();
22832284
}
2284-
//
2285-
JL_DLLEXPORT void jl_compile_hint(jl_tupletype_t *types)
2285+
2286+
static int _precompile_enq_tfunc(jl_typemap_entry_t *l, void *closure)
22862287
{
2287-
(void)jl_get_specialization1(types);
2288+
if (jl_is_lambda_info(l->func.value) && !l->func.linfo->functionID)
2289+
jl_cell_1d_push(closure, (jl_value_t*)l->func.linfo->specTypes);
2290+
return 1;
2291+
}
2292+
2293+
static int _precompile_enq_spec(jl_typemap_entry_t *def, void *closure)
2294+
{
2295+
jl_array_t *spec = def->func.method->specializations;
2296+
if (spec == NULL)
2297+
return 1;
2298+
size_t i, l;
2299+
for (i = 0, l = jl_array_len(spec); i < l; i++) {
2300+
jl_value_t *li = jl_cellref(spec, i);
2301+
if (jl_is_lambda_info(li) && !((jl_lambda_info_t*)li)->functionID)
2302+
jl_cell_1d_push(closure, (jl_value_t*)((jl_lambda_info_t*)li)->specTypes);
2303+
}
2304+
jl_typemap_visitor(def->func.method->tfunc, _precompile_enq_tfunc, closure);
2305+
return 1;
2306+
}
2307+
2308+
static void _precompile_enq_module(jl_module_t *m, jl_array_t *unspec)
2309+
{
2310+
// removes all method caches
2311+
size_t i;
2312+
void **table = m->bindings.table;
2313+
for(i=1; i < m->bindings.size; i+=2) {
2314+
if (table[i] != HT_NOTFOUND) {
2315+
jl_binding_t *b = (jl_binding_t*)table[i];
2316+
if (b->owner == m && b->value && b->constp) {
2317+
if (jl_is_datatype(b->value)) {
2318+
jl_typename_t *tn = ((jl_datatype_t*)b->value)->name;
2319+
if (tn->module == m && tn->name == b->name) {
2320+
jl_methtable_t *mt = tn->mt;
2321+
if (mt != NULL && (jl_value_t*)mt != jl_nothing) {
2322+
jl_typemap_visitor(mt->defs, _precompile_enq_spec, (void*)unspec);
2323+
}
2324+
}
2325+
}
2326+
else if (jl_is_module(b->value)) {
2327+
jl_module_t *child = (jl_module_t*)b->value;
2328+
if (child != m && child->parent == m && child->name == b->name) {
2329+
// this is the original/primary binding for the submodule
2330+
_precompile_enq_module((jl_module_t*)b->value, unspec);
2331+
}
2332+
}
2333+
}
2334+
}
2335+
}
2336+
}
2337+
2338+
static void jl_compile_specializations(void)
2339+
{
2340+
// this "found" array will contain function
2341+
// type signatures that were inferred but haven't been compiled
2342+
jl_array_t *m = jl_alloc_cell_1d(0);
2343+
JL_GC_PUSH1(&m);
2344+
_precompile_enq_module(jl_main_module, m);
2345+
size_t i, l;
2346+
for (i = 0, l = jl_array_len(m); i < l; i++) {
2347+
jl_compile_hint((jl_tupletype_t*)jl_cellref(m, i));
2348+
}
2349+
JL_GC_POP();
22882350
}
22892351

2352+
void jl_precompile(int all) {
2353+
jl_compile_specializations();
2354+
if (all)
2355+
jl_compile_all();
2356+
}
2357+
2358+
//
2359+
22902360
#ifdef JL_TRACE
22912361
static int trace_en = 0;
22922362
static int error_en = 1;

src/init.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -715,15 +715,15 @@ JL_DLLEXPORT int jl_generating_output(void)
715715
return jl_options.outputo || jl_options.outputbc || jl_options.outputji;
716716
}
717717

718-
void jl_compile_all(void);
718+
void jl_precompile(int all);
719719

720720
static void julia_save(void)
721721
{
722722
if (!jl_generating_output())
723723
return;
724724

725-
if (jl_options.compile_enabled == JL_OPTIONS_COMPILE_ALL)
726-
jl_compile_all();
725+
if (!jl_options.incremental)
726+
jl_precompile(jl_options.compile_enabled == JL_OPTIONS_COMPILE_ALL);
727727

728728
if (!jl_module_init_order) {
729729
jl_printf(JL_STDERR, "WARNING: --output requested, but no modules defined during run\n");

0 commit comments

Comments
 (0)