Skip to content

Commit ad37021

Browse files
committed
do a better job at generating code for known functions
closes #15048
1 parent 8b8f939 commit ad37021

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
@@ -1888,6 +1888,11 @@ jl_lambda_info_t *jl_get_specialization1(jl_tupletype_t *types)
18881888
return NULL;
18891889
}
18901890

1891+
JL_DLLEXPORT void jl_compile_hint(jl_tupletype_t *types)
1892+
{
1893+
(void)jl_get_specialization1(types);
1894+
}
1895+
18911896
// add type of `f` to front of argument tuple type
18921897
jl_tupletype_t *jl_argtype_with_function(jl_function_t *f, jl_tupletype_t *types)
18931898
{
@@ -2158,13 +2163,6 @@ static int _compile_all_enq(jl_typemap_entry_t *ml, void *env)
21582163
return 1;
21592164
}
21602165

2161-
static void _compile_all_enq_mt(jl_methtable_t *mt, jl_array_t *found)
2162-
{
2163-
if (mt == NULL || (jl_value_t*)mt == jl_nothing) return;
2164-
jl_typemap_visitor(mt->defs, _compile_all_enq, (void*)found);
2165-
jl_typemap_visitor(mt->cache, _compile_all_enq, (void*)found);
2166-
}
2167-
21682166
static void _compile_all_enq_module(jl_module_t *m, jl_array_t *found)
21692167
{
21702168
// scan through all types reachable from 'v' and
@@ -2178,7 +2176,11 @@ static void _compile_all_enq_module(jl_module_t *m, jl_array_t *found)
21782176
if (jl_is_datatype(v)) {
21792177
jl_typename_t *tn = ((jl_datatype_t*)v)->name;
21802178
if (tn->module == m && tn->name == b->name) {
2181-
_compile_all_enq_mt(tn->mt, found);
2179+
jl_methtable_t *mt = tn->mt;
2180+
if (mt != NULL && (jl_value_t*)mt != jl_nothing) {
2181+
jl_typemap_visitor(mt->defs, _compile_all_enq, (void*)found);
2182+
jl_typemap_visitor(mt->cache, _compile_all_enq, (void*)found);
2183+
}
21822184
}
21832185
}
21842186
else if (jl_is_module(v)) {
@@ -2193,11 +2195,10 @@ static void _compile_all_enq_module(jl_module_t *m, jl_array_t *found)
21932195
}
21942196
}
21952197

2196-
void jl_compile_all(void)
2198+
static void jl_compile_all(void)
21972199
{
21982200
// this "found" array will contain
2199-
// LambdaInfos that need to be compiled
2200-
// and (generic-function, method) pairs that may be optimized (and need to be compiled)
2201+
// TypeMapEntries for Methods and LambdaInfos that need to be compiled
22012202
jl_array_t *m = jl_alloc_cell_1d(0);
22022203
JL_GC_PUSH1(&m);
22032204
while (1) {
@@ -2210,12 +2211,81 @@ void jl_compile_all(void)
22102211
}
22112212
JL_GC_POP();
22122213
}
2213-
//
2214-
JL_DLLEXPORT void jl_compile_hint(jl_tupletype_t *types)
2214+
2215+
static int _precompile_enq_tfunc(jl_typemap_entry_t *l, void *closure)
22152216
{
2216-
(void)jl_get_specialization1(types);
2217+
if (jl_is_lambda_info(l->func.value) && !l->func.linfo->functionID)
2218+
jl_cell_1d_push(closure, (jl_value_t*)l->func.linfo->specTypes);
2219+
return 1;
2220+
}
2221+
2222+
static int _precompile_enq_spec(jl_typemap_entry_t *def, void *closure)
2223+
{
2224+
jl_array_t *spec = def->func.method->specializations;
2225+
if (spec == NULL)
2226+
return 1;
2227+
size_t i, l;
2228+
for (i = 0, l = jl_array_len(spec); i < l; i++) {
2229+
jl_value_t *li = jl_cellref(spec, i);
2230+
if (jl_is_lambda_info(li) && !((jl_lambda_info_t*)li)->functionID)
2231+
jl_cell_1d_push(closure, (jl_value_t*)((jl_lambda_info_t*)li)->specTypes);
2232+
}
2233+
jl_typemap_visitor(def->func.method->tfunc, _precompile_enq_tfunc, closure);
2234+
return 1;
2235+
}
2236+
2237+
static void _precompile_enq_module(jl_module_t *m, jl_array_t *unspec)
2238+
{
2239+
// removes all method caches
2240+
size_t i;
2241+
void **table = m->bindings.table;
2242+
for(i=1; i < m->bindings.size; i+=2) {
2243+
if (table[i] != HT_NOTFOUND) {
2244+
jl_binding_t *b = (jl_binding_t*)table[i];
2245+
if (b->owner == m && b->value && b->constp) {
2246+
if (jl_is_datatype(b->value)) {
2247+
jl_typename_t *tn = ((jl_datatype_t*)b->value)->name;
2248+
if (tn->module == m && tn->name == b->name) {
2249+
jl_methtable_t *mt = tn->mt;
2250+
if (mt != NULL && (jl_value_t*)mt != jl_nothing) {
2251+
jl_typemap_visitor(mt->defs, _precompile_enq_spec, (void*)unspec);
2252+
}
2253+
}
2254+
}
2255+
else if (jl_is_module(b->value)) {
2256+
jl_module_t *child = (jl_module_t*)b->value;
2257+
if (child != m && child->parent == m && child->name == b->name) {
2258+
// this is the original/primary binding for the submodule
2259+
_precompile_enq_module((jl_module_t*)b->value, unspec);
2260+
}
2261+
}
2262+
}
2263+
}
2264+
}
22172265
}
22182266

2267+
static void jl_compile_specializations(void)
2268+
{
2269+
// this "found" array will contain function
2270+
// type signatures that were inferred but haven't been compiled
2271+
jl_array_t *m = jl_alloc_cell_1d(0);
2272+
JL_GC_PUSH1(&m);
2273+
_precompile_enq_module(jl_main_module, m);
2274+
size_t i, l;
2275+
for (i = 0, l = jl_array_len(m); i < l; i++) {
2276+
jl_compile_hint((jl_tupletype_t*)jl_cellref(m, i));
2277+
}
2278+
JL_GC_POP();
2279+
}
2280+
2281+
void jl_precompile(int all) {
2282+
jl_compile_specializations();
2283+
if (all)
2284+
jl_compile_all();
2285+
}
2286+
2287+
//
2288+
22192289
#ifdef JL_TRACE
22202290
static int trace_en = 0;
22212291
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)