Skip to content

Commit

Permalink
some updates to code metadata handling
Browse files Browse the repository at this point in the history
- detect pure and inline meta once, in the front end
- fixes #16712
- remove `skip_meta` since it probably assumes too much about where meta nodes occur
- add jl_ prefix to has_meta
- remove location/pure/inline meta early, in the front end
  (the first line node isn't needed, since this info is in the Method object)
- remove null_sym; this Expr head doesn't occur in the IR
  • Loading branch information
JeffBezanson committed Jun 29, 2016
1 parent 70a7da9 commit bd06d27
Show file tree
Hide file tree
Showing 11 changed files with 80 additions and 73 deletions.
29 changes: 17 additions & 12 deletions base/inference.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1927,6 +1927,8 @@ function finish(me::InferenceState)
end
alloc_elim_pass!(me.linfo, me)
getfield_elim_pass!(me.linfo, me)
# remove placeholders
filter!(x->x!==nothing, me.linfo.code)
reindex_labels!(me.linfo, me)
end
widen_all_consts!(me.linfo)
Expand All @@ -1935,7 +1937,9 @@ function finish(me::InferenceState)
me.linfo.pure = ispure

# determine and cache inlineability
me.linfo.inlineable = isinlineable(me.linfo)
if !me.linfo.inlineable
me.linfo.inlineable = isinlineable(me.linfo)
end

if !me.needtree
me.needtree = me.linfo.inlineable || ccall(:jl_is_cacheable_sig, Int32, (Any, Any, Any),
Expand Down Expand Up @@ -2736,13 +2740,16 @@ function inlineable(f::ANY, ft::ANY, e::Expr, atypes::Vector{Any}, sv::Inference
end
end

if !isempty(stmts)
if all(stmt -> isa(stmt,Expr) && stmt.head === :line || isa(stmt, LineNumberNode), stmts)
empty!(stmts)
else
unshift!(stmts, Expr(:meta, :push_loc, linfo.def.file, linfo.def.name))
push!(stmts, Expr(:meta, :pop_loc))
end
if !isempty(stmts)
if all(stmt -> (isa(stmt,Expr) && stmt.head === :line) || isa(stmt, LineNumberNode) || stmt === nothing,
stmts)
empty!(stmts)
else
isa(stmts[1], LineNumberNode) && shift!(stmts)
unshift!(stmts, Expr(:meta, :push_loc, linfo.def.file, linfo.def.name, linfo.def.line))
isa(stmts[end], LineNumberNode) && pop!(stmts)
push!(stmts, Expr(:meta, :pop_loc))
end
end
if !isempty(stmts) && !propagate_inbounds
# avoid redundant inbounds annotations
Expand Down Expand Up @@ -2779,16 +2786,14 @@ const inline_incompletematch_allowed = false
inline_worthy(body::ANY, cost::Integer) = true

# should the expression be part of the inline cost model
function inline_ignore(ex)
function inline_ignore(ex::ANY)
isa(ex, LineNumberNode) ||
ex === nothing ||
isa(ex, Expr) && ((ex::Expr).head === :line ||
(ex::Expr).head === :meta)
end

function inline_worthy(body::Expr, cost::Integer=1000) # precondition: 0 < cost; nominal cost = 1000
if popmeta!(body, :inline)[1]
return true
end
if popmeta!(body, :noinline)[1]
return false
end
Expand Down
48 changes: 35 additions & 13 deletions src/alloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ jl_sym_t *line_sym; jl_sym_t *jl_incomplete_sym;
jl_sym_t *goto_sym; jl_sym_t *goto_ifnot_sym;
jl_sym_t *label_sym; jl_sym_t *return_sym;
jl_sym_t *lambda_sym; jl_sym_t *assign_sym;
jl_sym_t *null_sym; jl_sym_t *body_sym;
jl_sym_t *body_sym;
jl_sym_t *method_sym; jl_sym_t *core_sym;
jl_sym_t *enter_sym; jl_sym_t *leave_sym;
jl_sym_t *exc_sym; jl_sym_t *error_sym;
Expand All @@ -103,7 +103,7 @@ jl_sym_t *pure_sym; jl_sym_t *simdloop_sym;
jl_sym_t *meta_sym; jl_sym_t *compiler_temp_sym;
jl_sym_t *inert_sym; jl_sym_t *vararg_sym;
jl_sym_t *unused_sym; jl_sym_t *static_parameter_sym;
jl_sym_t *polly_sym;
jl_sym_t *polly_sym; jl_sym_t *inline_sym;

typedef struct {
int64_t a;
Expand Down Expand Up @@ -316,8 +316,28 @@ static void jl_lambda_info_set_ast(jl_lambda_info_t *li, jl_expr_t *ast)
assert(jl_is_expr(bodyex));
jl_array_t *body = bodyex->args;
li->code = (jl_value_t*)body; jl_gc_wb(li, li->code);
if (has_meta(body, pure_sym))
li->pure = 1;
size_t j, n = jl_array_len(body);
jl_value_t **bd = (jl_value_t**)jl_array_data((jl_array_t*)li->code);
for(j=0; j < n; j++) {
jl_value_t *st = bd[j];
if (jl_is_expr(st) && ((jl_expr_t*)st)->head == meta_sym) {
size_t k, ins = 0, na = jl_expr_nargs(st);
jl_array_t *meta = ((jl_expr_t*)st)->args;
for(k=0; k < na; k++) {
jl_value_t *ma = jl_array_ptr_ref(meta, k);
if (ma == (jl_value_t*)pure_sym)
li->pure = 1;
else if (ma == (jl_value_t*)inline_sym)
li->inlineable = 1;
else
jl_array_ptr_set(meta, ins++, ma);
}
if (ins == 0)
bd[j] = jl_nothing;
else
jl_array_del_end(meta, na-ins);
}
}
jl_array_t *vinfo = (jl_array_t*)jl_exprarg(ast, 1);
jl_array_t *vis = (jl_array_t*)jl_array_ptr_ref(vinfo, 0);
size_t nslots = jl_array_len(vis);
Expand Down Expand Up @@ -530,15 +550,17 @@ JL_DLLEXPORT jl_lambda_info_t *jl_get_specialized(jl_method_t *m, jl_tupletype_t
JL_DLLEXPORT void jl_method_init_properties(jl_method_t *m)
{
jl_lambda_info_t *li = m->lambda_template;
jl_value_t *body1 = skip_meta((jl_array_t*)li->code);
if (jl_is_linenode(body1)) {
m->line = jl_linenode_line(body1);
}
else if (jl_is_expr(body1) && ((jl_expr_t*)body1)->head == line_sym) {
m->file = (jl_sym_t*)jl_exprarg(body1, 1);
m->line = jl_unbox_long(jl_exprarg(body1, 0));
size_t j, n = jl_array_len((jl_array_t*)li->code);
jl_value_t **body = (jl_value_t**)jl_array_data((jl_array_t*)li->code);
for(j=0; j < n; j++) {
jl_value_t *st = body[j];
if (jl_is_expr(st) && ((jl_expr_t*)st)->head == line_sym) {
m->line = jl_unbox_long(jl_exprarg(st, 0));
m->file = (jl_sym_t*)jl_exprarg(st, 1);
body[j] = jl_nothing;
break;
}
}

int i;
uint8_t called=0;
for(i=1; i < li->nargs && i <= 8; i++) {
Expand All @@ -563,7 +585,7 @@ JL_DLLEXPORT jl_method_t *jl_new_method_uninit(void)
m->module = jl_current_module;
m->lambda_template = NULL;
m->name = NULL;
m->file = null_sym;
m->file = empty_sym;
m->line = 0;
m->called = 0xff;
m->invokes.unknown = NULL;
Expand Down
11 changes: 1 addition & 10 deletions src/ast.c
Original file line number Diff line number Diff line change
Expand Up @@ -874,16 +874,7 @@ JL_DLLEXPORT int jl_operator_precedence(char *sym)
return res;
}

jl_value_t *skip_meta(jl_array_t *body)
{
jl_value_t *body1 = jl_array_ptr_ref(body,0);
if (jl_is_expr(body1) && ((jl_expr_t*)body1)->head == meta_sym
&& jl_array_len(body) > 1)
body1 = jl_array_ptr_ref(body,1);
return body1;
}

int has_meta(jl_array_t *body, jl_sym_t *sym)
int jl_has_meta(jl_array_t *body, jl_sym_t *sym)
{
size_t i, l = jl_array_len(body);
for (i = 0; i < l; i++) {
Expand Down
44 changes: 20 additions & 24 deletions src/codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3245,9 +3245,6 @@ static jl_cgval_t emit_expr(jl_value_t *expr, jl_codectx_t *ctx)
literal_pointer_val(bnd));
}
}
else if (head == null_sym) {
return ghostValue(jl_void_type);
}
else if (head == static_typeof_sym) {
jl_value_t *extype = expr_type((jl_value_t*)ex, ctx);
if (jl_is_type_type(extype)) {
Expand Down Expand Up @@ -3369,8 +3366,7 @@ static jl_cgval_t emit_expr(jl_value_t *expr, jl_codectx_t *ctx)
jl_value_t *arg = args[0];
if (jl_is_quotenode(arg)) {
jl_value_t *arg1 = jl_fieldref(arg,0);
if (!((jl_is_expr(arg1) && ((jl_expr_t*)arg1)->head!=null_sym) ||
jl_typeis(arg1,jl_array_any_type) || jl_is_quotenode(arg1))) {
if (!(jl_is_expr(arg1) || jl_typeis(arg1,jl_array_any_type) || jl_is_quotenode(arg1))) {
// elide call to jl_copy_ast when possible
return emit_expr(arg, ctx);
}
Expand Down Expand Up @@ -4155,7 +4151,7 @@ static std::unique_ptr<Module> emit_function(jl_lambda_info_t *lam, jl_llvm_func
#endif

#ifdef USE_POLLY
if (!has_meta(code, polly_sym)) {
if (!jl_has_meta(code, polly_sym)) {
f->addFnAttr(polly::PollySkipFnAttr);
}
#endif
Expand All @@ -4172,24 +4168,14 @@ static std::unique_ptr<Module> emit_function(jl_lambda_info_t *lam, jl_llvm_func
(jl_options.code_coverage == JL_LOG_USER && in_user_code);
bool do_malloc_log = jl_options.malloc_log == JL_LOG_ALL ||
(jl_options.malloc_log == JL_LOG_USER && in_user_code);
jl_value_t *stmt = skip_meta(stmts);
StringRef filename = "<missing>";
StringRef dbgFuncName = ctx.name;
int lno = -1;
// look for initial (line num filename [funcname]) node, [funcname] for kwarg methods.
if (jl_is_linenode(stmt)) {
lno = jl_linenode_line(stmt);
}
else if (jl_is_expr(stmt) && ((jl_expr_t*)stmt)->head == line_sym &&
jl_array_dim0(((jl_expr_t*)stmt)->args) > 0) {
jl_value_t *a1 = jl_exprarg(stmt,0);
if (jl_is_long(a1))
lno = jl_unbox_long(a1);
}
if (lno == -1 && lam->def)
if (lam->def) {
lno = lam->def->line;
if (lam->def && lam->def->file != empty_sym)
filename = jl_symbol_name(lam->def->file);
if (lam->def->file != empty_sym)
filename = jl_symbol_name(lam->def->file);
}
ctx.file = filename;
int toplineno = lno;

Expand Down Expand Up @@ -4689,10 +4675,20 @@ static std::unique_ptr<Module> emit_function(jl_lambda_info_t *lam, jl_llvm_func
DI_sp_stack.push_back(SP);
DI_loc_stack.push_back(builder.getCurrentDebugLocation());
std::string inl_name;
if (jl_array_len(stmt_e->args) > 2)
inl_name = jl_symbol_name((jl_sym_t*)jl_exprarg(stmt_e, 2));
else
int inlined_func_lineno = 0;
if (jl_array_len(stmt_e->args) > 2) {
size_t ii;
for(ii=2; ii < jl_array_len(stmt_e->args); ii++) {
jl_value_t *arg = jl_exprarg(stmt_e, ii);
if (jl_is_symbol(arg))
inl_name = jl_symbol_name((jl_sym_t*)arg);
else if (jl_is_long(arg))
inlined_func_lineno = jl_unbox_long(arg);
}
}
else {
inl_name = "macro expansion";
}
SP = dbuilder.createFunction(new_file,
inl_name + ";",
inl_name,
Expand All @@ -4705,7 +4701,7 @@ static std::unique_ptr<Module> emit_function(jl_lambda_info_t *lam, jl_llvm_func
0,
true,
nullptr);
builder.SetCurrentDebugLocation(DebugLoc::get(0, 0, (MDNode*)SP, builder.getCurrentDebugLocation()));
builder.SetCurrentDebugLocation(DebugLoc::get(inlined_func_lineno, 0, (MDNode*)SP, builder.getCurrentDebugLocation()));
}
else if (meta_arg == (jl_value_t*)jl_symbol("pop_loc")) {
SP = DI_sp_stack.back();
Expand Down
3 changes: 0 additions & 3 deletions src/interpreter.c
Original file line number Diff line number Diff line change
Expand Up @@ -202,9 +202,6 @@ static jl_value_t *eval(jl_value_t *e, interpreter_state *s)
JL_GC_POP();
return v;
}
else if (ex->head == null_sym) {
return (jl_value_t*)jl_nothing;
}
else if (ex->head == static_parameter_sym) {
ssize_t n = jl_unbox_long(args[0]);
assert(n > 0);
Expand Down
2 changes: 1 addition & 1 deletion src/jltypes.c
Original file line number Diff line number Diff line change
Expand Up @@ -3942,7 +3942,6 @@ void jl_init_types(void)
using_sym = jl_symbol("using");
importall_sym = jl_symbol("importall");
assign_sym = jl_symbol("=");
null_sym = jl_symbol("null");
body_sym = jl_symbol("body");
colons_sym = jl_symbol("::");
method_sym = jl_symbol("method");
Expand Down Expand Up @@ -3978,6 +3977,7 @@ void jl_init_types(void)
static_parameter_sym = jl_symbol("static_parameter");
compiler_temp_sym = jl_symbol("#temp#");
polly_sym = jl_symbol("polly");
inline_sym = jl_symbol("inline");

tttvar = jl_new_typevar(jl_symbol("T"),
(jl_value_t*)jl_bottom_type,
Expand Down
4 changes: 2 additions & 2 deletions src/julia.h
Original file line number Diff line number Diff line change
Expand Up @@ -560,7 +560,7 @@ extern jl_sym_t *importall_sym; extern jl_sym_t *using_sym;
extern jl_sym_t *goto_sym; extern jl_sym_t *goto_ifnot_sym;
extern jl_sym_t *label_sym; extern jl_sym_t *return_sym;
extern jl_sym_t *lambda_sym; extern jl_sym_t *assign_sym;
extern jl_sym_t *null_sym; extern jl_sym_t *body_sym;
extern jl_sym_t *body_sym;
extern jl_sym_t *method_sym; extern jl_sym_t *slot_sym;
extern jl_sym_t *enter_sym; extern jl_sym_t *leave_sym;
extern jl_sym_t *exc_sym; extern jl_sym_t *new_sym;
Expand All @@ -575,7 +575,7 @@ extern jl_sym_t *copyast_sym; extern jl_sym_t *fastmath_sym;
extern jl_sym_t *pure_sym; extern jl_sym_t *simdloop_sym;
extern jl_sym_t *meta_sym; extern jl_sym_t *list_sym;
extern jl_sym_t *inert_sym; extern jl_sym_t *static_parameter_sym;
extern jl_sym_t *polly_sym;
extern jl_sym_t *polly_sym; extern jl_sym_t *inline_sym;

// gc -------------------------------------------------------------------------

Expand Down
3 changes: 1 addition & 2 deletions src/julia_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -326,8 +326,7 @@ uint32_t jl_module_next_counter(jl_module_t *m);
void jl_fptr_to_llvm(jl_fptr_t fptr, jl_lambda_info_t *lam, int specsig);
jl_tupletype_t *arg_type_tuple(jl_value_t **args, size_t nargs);

jl_value_t *skip_meta(jl_array_t *body);
int has_meta(jl_array_t *body, jl_sym_t *sym);
int jl_has_meta(jl_array_t *body, jl_sym_t *sym);

// backtraces
typedef struct {
Expand Down
2 changes: 1 addition & 1 deletion src/toplevel.c
Original file line number Diff line number Diff line change
Expand Up @@ -428,7 +428,7 @@ jl_value_t *jl_toplevel_eval_flex(jl_value_t *e, int fast, int expanded)
}

jl_expr_t *ex = (jl_expr_t*)e;
if (ex->head == null_sym || ex->head == error_sym || ex->head == jl_incomplete_sym) {
if (ex->head == error_sym || ex->head == jl_incomplete_sym) {
// expression types simple enough not to need expansion
return jl_interpret_toplevel_expr(e);
}
Expand Down
2 changes: 1 addition & 1 deletion test/core.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3342,7 +3342,7 @@ typealias PossiblyInvalidUnion{T} Union{T,Int}
@test split(string(gensym("abc")),'#')[3] == "abc"

# meta nodes for optional positional arguments
@test Base.uncompressed_ast(expand(:(@inline f(p::Int=2) = 3)).args[2].args[3])[1].args[1] === :inline
@test expand(:(@inline f(p::Int=2) = 3)).args[2].args[3].inlineable

# issue #13007
call13007{T,N}(::Type{Array{T,N}}) = 0
Expand Down
5 changes: 1 addition & 4 deletions test/reflection.jl
Original file line number Diff line number Diff line change
Expand Up @@ -364,10 +364,7 @@ function test_typed_ast_printing(f::ANY, types::ANY, must_used_vars)
for str in (sprint(io->code_warntype(io, f, types)),
sprint(io->show(io, li)))
# Test to make sure the clearing of file path below works
# If we don't store the full path in line number node/ast printing
# anymore, the test and the string replace below should be fixed.
@test contains(str, @__FILE__)
str = replace(str, @__FILE__, "")
@test string(li.def.file) == @__FILE__
for var in must_used_vars
@test contains(str, string(var))
end
Expand Down

0 comments on commit bd06d27

Please sign in to comment.