Skip to content

Commit

Permalink
Force compilation with Expr(:meta, :compile, :force)
Browse files Browse the repository at this point in the history
This more explicit directive distinguishes `@compile`
(now moved to Experimental) from `@compiler_options`
(which uses the same `:compile` symbol). It eliminates
a collision between #42128 and #37041.

Fixes #42373
Closes #42379
  • Loading branch information
timholy committed Sep 28, 2021
1 parent 84cc901 commit 80de59a
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 32 deletions.
24 changes: 24 additions & 0 deletions base/experimental.jl
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,30 @@ macro compiler_options(args...)
return opts
end

"""
Experimental.@compile
Force compilation of the block or function (Julia's built-in interpreter is blocked from executing it).
# Examples
```
module WithPrecompiles
#=
code definitions
=#
if Sys.iswindows()
Experimental.@compile
compile_me() # `compile_me` will be compiled before execution (not run in the interpreter)
end
end
```
"""
macro compile() Expr(:meta, :compile, :force) end


# UI features for errors

"""
Expand Down
7 changes: 0 additions & 7 deletions base/expr.jl
Original file line number Diff line number Diff line change
Expand Up @@ -384,13 +384,6 @@ macro propagate_inbounds(ex)
esc(ex)
end

"""
@compile
Force compilation of the block or function (Julia's built-in interpreter is blocked from executing it).
"""
macro compile() Expr(:meta, :compile) end

"""
@polly
Expand Down
10 changes: 5 additions & 5 deletions base/timing.jl
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ julia> @time begin
"""
macro time(ex)
quote
@compile
Experimental.@compile
local stats = gc_num()
local elapsedtime = time_ns()
local compile_elapsedtime = cumulative_compile_time_ns_before()
Expand Down Expand Up @@ -260,7 +260,7 @@ pool allocs: 1
"""
macro timev(ex)
quote
@compile
Experimental.@compile
local stats = gc_num()
local elapsedtime = time_ns()
local compile_elapsedtime = cumulative_compile_time_ns_before()
Expand Down Expand Up @@ -294,7 +294,7 @@ julia> @elapsed sleep(0.3)
"""
macro elapsed(ex)
quote
@compile
Experimental.@compile
local t0 = time_ns()
$(esc(ex))
(time_ns() - t0) / 1e9
Expand Down Expand Up @@ -326,7 +326,7 @@ julia> @allocated rand(10^6)
"""
macro allocated(ex)
quote
@compile
Experimental.@compile
local b0 = Ref{Int64}(0)
local b1 = Ref{Int64}(0)
gc_bytes(b0)
Expand Down Expand Up @@ -374,7 +374,7 @@ julia> stats.gcstats.total_time
"""
macro timed(ex)
quote
@compile
Experimental.@compile
local stats = gc_num()
local elapsedtime = time_ns()
local val = $(esc(ex))
Expand Down
3 changes: 2 additions & 1 deletion src/ast.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ jl_sym_t *coverageeffect_sym; jl_sym_t *escape_sym;
jl_sym_t *aliasscope_sym; jl_sym_t *popaliasscope_sym;
jl_sym_t *optlevel_sym; jl_sym_t *thismodule_sym;
jl_sym_t *atom_sym; jl_sym_t *statement_sym; jl_sym_t *all_sym;
jl_sym_t *compile_sym; jl_sym_t *infer_sym;
jl_sym_t *compile_sym; jl_sym_t *infer_sym; jl_sym_t *force_sym;

jl_sym_t *atomic_sym;
jl_sym_t *not_atomic_sym;
Expand Down Expand Up @@ -406,6 +406,7 @@ void jl_init_common_symbols(void)
optlevel_sym = jl_symbol("optlevel");
compile_sym = jl_symbol("compile");
infer_sym = jl_symbol("infer");
force_sym = jl_symbol("force");
macrocall_sym = jl_symbol("macrocall");
escape_sym = jl_symbol("escape");
hygienicscope_sym = jl_symbol("hygienic-scope");
Expand Down
2 changes: 1 addition & 1 deletion src/julia_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -1411,7 +1411,7 @@ extern jl_sym_t *throw_undef_if_not_sym; extern jl_sym_t *getfield_undefref_sym;
extern jl_sym_t *gc_preserve_begin_sym; extern jl_sym_t *gc_preserve_end_sym;
extern jl_sym_t *coverageeffect_sym; extern jl_sym_t *escape_sym;
extern jl_sym_t *optlevel_sym; extern jl_sym_t *compile_sym;
extern jl_sym_t *infer_sym;
extern jl_sym_t *infer_sym; extern jl_sym_t *force_sym;
extern jl_sym_t *atom_sym; extern jl_sym_t *statement_sym; extern jl_sym_t *all_sym;

extern jl_sym_t *atomic_sym;
Expand Down
39 changes: 21 additions & 18 deletions src/toplevel.c
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,7 @@ JL_DLLEXPORT jl_module_t *jl_base_relative_to(jl_module_t *m)
return jl_top_module;
}

static void expr_attributes(jl_value_t *v, int *has_intrinsics, int *has_defs, int *has_opaque)
static void expr_attributes(jl_value_t *v, int *has_intrinsics, int *has_defs, int *has_opaque, int *has_forcedcompile)
{
if (!jl_is_expr(v))
return;
Expand Down Expand Up @@ -339,6 +339,12 @@ static void expr_attributes(jl_value_t *v, int *has_intrinsics, int *has_defs, i
*has_opaque = 1;
return;
}
else if (head == meta_sym && jl_expr_nargs(e) == 2 &&
jl_exprarg(e, 0) == (jl_value_t*)compile_sym &&
jl_exprarg(e, 1) == (jl_value_t*)force_sym) {
*has_forcedcompile = 1;
return;
}
else if (head == call_sym && jl_expr_nargs(e) > 0) {
jl_value_t *called = NULL;
jl_value_t *f = jl_exprarg(e, 0);
Expand Down Expand Up @@ -368,7 +374,7 @@ static void expr_attributes(jl_value_t *v, int *has_intrinsics, int *has_defs, i
for (i = 0; i < jl_array_len(e->args); i++) {
jl_value_t *a = jl_exprarg(e, i);
if (jl_is_expr(a))
expr_attributes(a, has_intrinsics, has_defs, has_opaque);
expr_attributes(a, has_intrinsics, has_defs, has_opaque, has_forcedcompile);
}
}

Expand All @@ -377,19 +383,17 @@ int jl_code_requires_compiler(jl_code_info_t *src)
jl_array_t *body = src->code;
assert(jl_typeis(body, jl_array_any_type));
size_t i;
int has_intrinsics = 0, has_defs = 0, has_opaque = 0;
if (jl_has_meta(body, compile_sym))
return 1;
int has_intrinsics = 0, has_defs = 0, has_opaque = 0, has_forcedcompile = 0;
for(i=0; i < jl_array_len(body); i++) {
jl_value_t *stmt = jl_array_ptr_ref(body,i);
expr_attributes(stmt, &has_intrinsics, &has_defs, &has_opaque);
if (has_intrinsics)
expr_attributes(stmt, &has_intrinsics, &has_defs, &has_opaque, &has_forcedcompile);
if (has_intrinsics || has_forcedcompile)
return 1;
}
return 0;
}

static void body_attributes(jl_array_t *body, int *has_intrinsics, int *has_defs, int *has_loops, int *has_opaque, int *has_compile)
static void body_attributes(jl_array_t *body, int *has_intrinsics, int *has_defs, int *has_loops, int *has_opaque, int *has_forcedcompile)
{
size_t i;
*has_loops = 0;
Expand All @@ -405,9 +409,8 @@ static void body_attributes(jl_array_t *body, int *has_intrinsics, int *has_defs
*has_loops = 1;
}
}
expr_attributes(stmt, has_intrinsics, has_defs, has_opaque);
expr_attributes(stmt, has_intrinsics, has_defs, has_opaque, has_forcedcompile);
}
*has_compile = jl_has_meta(body, compile_sym);
}

static jl_module_t *call_require(jl_module_t *mod, jl_sym_t *var) JL_GLOBALLY_ROOTED
Expand Down Expand Up @@ -851,20 +854,20 @@ jl_value_t *jl_toplevel_eval_flex(jl_module_t *JL_NONNULL m, jl_value_t *e, int
return (jl_value_t*)ex;
}

int has_intrinsics = 0, has_defs = 0, has_loops = 0, has_opaque = 0, has_compile = 0;
int has_intrinsics = 0, has_defs = 0, has_loops = 0, has_opaque = 0, has_forcedcompile = 0;
assert(head == thunk_sym);
thk = (jl_code_info_t*)jl_exprarg(ex, 0);
assert(jl_is_code_info(thk));
assert(jl_typeis(thk->code, jl_array_any_type));
body_attributes((jl_array_t*)thk->code, &has_intrinsics, &has_defs, &has_loops, &has_opaque, &has_compile);
body_attributes((jl_array_t*)thk->code, &has_intrinsics, &has_defs, &has_loops, &has_opaque, &has_forcedcompile);

jl_value_t *result;
if (has_intrinsics || (!has_defs && fast && has_loops &&
jl_options.compile_enabled != JL_OPTIONS_COMPILE_OFF &&
jl_options.compile_enabled != JL_OPTIONS_COMPILE_MIN &&
jl_get_module_compile(m) != JL_OPTIONS_COMPILE_OFF &&
jl_get_module_compile(m) != JL_OPTIONS_COMPILE_MIN) ||
has_compile) {
if (has_intrinsics || has_forcedcompile ||
(!has_defs && fast && has_loops &&
jl_options.compile_enabled != JL_OPTIONS_COMPILE_OFF &&
jl_options.compile_enabled != JL_OPTIONS_COMPILE_MIN &&
jl_get_module_compile(m) != JL_OPTIONS_COMPILE_OFF &&
jl_get_module_compile(m) != JL_OPTIONS_COMPILE_MIN)) {
// use codegen
mfunc = method_instance_for_thunk(thk, m);
jl_resolve_globals_in_ir((jl_array_t*)thk->code, m, NULL, 0);
Expand Down

0 comments on commit 80de59a

Please sign in to comment.