Skip to content

Commit

Permalink
restore explicit module field to LineNumberNode
Browse files Browse the repository at this point in the history
While this takes a non-trivial amount of space in the system image
(about the same as putting the Method object here, but less than putting
the full edge to the MethodInstance), it is necessary to avoid the
regression JuliaLang#36462 caused by 2e37784.
  • Loading branch information
vtjnash committed Aug 28, 2020
1 parent 840ecac commit 42a1d34
Show file tree
Hide file tree
Showing 13 changed files with 67 additions and 66 deletions.
7 changes: 4 additions & 3 deletions base/boot.jl
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,8 @@
#end

#struct LineInfoNode
# method::Any
# module::Module
# method::Symbol
# file::Symbol
# line::Int
# inlined_at::Int
Expand Down Expand Up @@ -396,8 +397,8 @@ eval(Core, :(PiNode(val, typ) = $(Expr(:new, :PiNode, :val, :typ))))
eval(Core, :(PhiCNode(values::Array{Any, 1}) = $(Expr(:new, :PhiCNode, :values))))
eval(Core, :(UpsilonNode(val) = $(Expr(:new, :UpsilonNode, :val))))
eval(Core, :(UpsilonNode() = $(Expr(:new, :UpsilonNode))))
eval(Core, :(LineInfoNode(@nospecialize(method), file::Symbol, line::Int, inlined_at::Int) =
$(Expr(:new, :LineInfoNode, :method, :file, :line, :inlined_at))))
eval(Core, :(LineInfoNode(mod::Module, @nospecialize(method), file::Symbol, line::Int, inlined_at::Int) =
$(Expr(:new, :LineInfoNode, :mod, :method, :file, :line, :inlined_at))))
eval(Core, :(CodeInstance(mi::MethodInstance, @nospecialize(rettype), @nospecialize(inferred_const),
@nospecialize(inferred), const_flags::Int32,
min_world::UInt, max_world::UInt) =
Expand Down
25 changes: 12 additions & 13 deletions base/compiler/ssair/inlining.jl
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ struct InliningTodo
sparams::Vector{Any} # The static parameters we computed for this call site
metharg # ::Type
# The LineTable and IR of the inlinee
linetable::Vector{LineInfoNode}
ir::IRCode
# If the function being inlined is a single basic block we can use a
# simpler inlining algorithm. This flag determines whether that's allowed
Expand Down Expand Up @@ -307,8 +306,8 @@ function ir_inline_item!(compact::IncrementalCompact, idx::Int, argexprs::Vector
linetable_offset::Int32 = length(linetable)
# Append the linetable of the inlined function to our line table
inlined_at = Int(compact.result[idx][:line])
for entry in item.linetable
push!(linetable, LineInfoNode(entry.method, entry.file, entry.line,
for entry in item.ir.linetable
push!(linetable, LineInfoNode(entry.module, entry.method, entry.file, entry.line,
(entry.inlined_at > 0 ? entry.inlined_at + linetable_offset : inlined_at)))
end
if item.isva
Expand Down Expand Up @@ -735,23 +734,23 @@ function analyze_method!(idx::Int, atypes::Vector{Any}, match::MethodMatch,

@timeit "inline IR inflation" begin
ir2 = inflate_ir(src, mi)
# prepare inlining linetable with method instance information
inline_linetable = Vector{LineInfoNode}(undef, length(src.linetable))
for i = 1:length(src.linetable)
entry = src.linetable[i]
if entry.inlined_at === 0 && entry.method === method
entry = LineInfoNode(mi, entry.file, entry.line, entry.inlined_at)
end
inline_linetable[i] = entry
end
# #optional: prepare inlining linetable with method instance information
# inline_linetable = ir2.linetable
# for i = 1:length(inline_linetable)
# entry = inline_linetable[i]
# if entry.inlined_at === 0 && entry.method === method
# entry = LineInfoNode(entry.module, mi, entry.file, entry.line, entry.inlined_at)
# inline_linetable[i] = entry
# end
# end
end
#verify_ir(ir2)

return InliningTodo(idx,
na > 0 && method.isva,
isinvoke, na,
method, Any[match.sparams...], match.spec_types,
inline_linetable, ir2, linear_inline_eligible(ir2))
ir2, linear_inline_eligible(ir2))
end

# Neither the product iterator not CartesianIndices are available
Expand Down
2 changes: 1 addition & 1 deletion base/compiler/typeinfer.jl
Original file line number Diff line number Diff line change
Expand Up @@ -589,7 +589,7 @@ function typeinf_ext(interp::AbstractInterpreter, mi::MethodInstance)
tree.slotflags = fill(0x00, nargs)
tree.ssavaluetypes = 1
tree.codelocs = Int32[1]
tree.linetable = [LineInfoNode(method, method.file, Int(method.line), 0)]
tree.linetable = [LineInfoNode(method.module, method.name, method.file, Int(method.line), 0)]
tree.inferred = true
tree.ssaflags = UInt8[0]
tree.pure = true
Expand Down
2 changes: 1 addition & 1 deletion src/ast.c
Original file line number Diff line number Diff line change
Expand Up @@ -596,7 +596,7 @@ static jl_value_t *scm_to_julia_(fl_context_t *fl_ctx, value_t e, jl_module_t *m
else if (sym == thunk_sym) {
ex = scm_to_julia_(fl_ctx, car_(e), mod);
assert(jl_is_code_info(ex));
jl_linenumber_to_lineinfo((jl_code_info_t*)ex, (jl_value_t*)jl_symbol("top-level scope"));
jl_linenumber_to_lineinfo((jl_code_info_t*)ex, mod, (jl_value_t*)jl_symbol("top-level scope"));
temp = (jl_value_t*)jl_exprn(sym, 1);
jl_exprargset(temp, 0, ex);
}
Expand Down
42 changes: 23 additions & 19 deletions src/codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5665,8 +5665,8 @@ static std::pair<std::unique_ptr<Module>, jl_llvm_functions_t>
}
else if (jl_array_len(src->linetable) > 0) {
jl_value_t *locinfo = jl_array_ptr_ref(src->linetable, 0);
ctx.file = jl_symbol_name((jl_sym_t*)jl_fieldref_noalloc(locinfo, 1));
toplineno = jl_unbox_long(jl_fieldref(locinfo, 2));
ctx.file = jl_symbol_name((jl_sym_t*)jl_fieldref_noalloc(locinfo, 2));
toplineno = jl_unbox_long(jl_fieldref(locinfo, 3));
}
if (ctx.file.empty())
ctx.file = "<missing>";
Expand Down Expand Up @@ -6284,40 +6284,44 @@ static std::pair<std::unique_ptr<Module>, jl_llvm_functions_t>
ssize_t line;
bool is_user_code;
unsigned inlined_at;
bool operator ==(const DebugLineTable &other) const {
return other.loc == loc && other.file == file && other.line == line && other.is_user_code == is_user_code && other.inlined_at == inlined_at;
}
};
std::vector<DebugLineTable> linetable;
{
{ // populate the linetable data format
assert(jl_is_array(src->linetable));
size_t nlocs = jl_array_len(src->linetable);
std::map<std::tuple<StringRef, StringRef>, DISubprogram*> subprograms;
linetable.resize(nlocs + 1);
DebugLineTable &topinfo = linetable[0];
topinfo.file = ctx.file;
topinfo.line = toplineno;
topinfo.is_user_code = mod_is_user_mod;
topinfo.inlined_at = 0;
topinfo.loc = topdebugloc;
for (size_t i = 0; i < nlocs; i++) {
// LineInfoNode(mod::Module, method::Any, file::Symbol, line::Int, inlined_at::Int)
jl_value_t *locinfo = jl_array_ptr_ref(src->linetable, i);
DebugLineTable &info = linetable[i + 1];
assert(jl_typeis(locinfo, jl_lineinfonode_type));
jl_value_t *method = jl_fieldref_noalloc(locinfo, 0);
if (jl_is_method_instance(method))
method = ((jl_method_instance_t*)method)->def.value;
jl_sym_t *filesym = (jl_sym_t*)jl_fieldref_noalloc(locinfo, 1);
info.line = jl_unbox_long(jl_fieldref(locinfo, 2));
info.inlined_at = jl_unbox_long(jl_fieldref(locinfo, 3));
jl_module_t *module = (jl_module_t*)jl_fieldref_noalloc(locinfo, 0);
jl_value_t *method = jl_fieldref_noalloc(locinfo, 1);
jl_sym_t *filesym = (jl_sym_t*)jl_fieldref_noalloc(locinfo, 2);
info.line = jl_unbox_long(jl_fieldref(locinfo, 3));
info.inlined_at = jl_unbox_long(jl_fieldref(locinfo, 4));
assert(info.inlined_at <= i);
if (jl_is_method(method)) {
jl_module_t *module = ((jl_method_t*)method)->module;
if (module == ctx.module)
info.is_user_code = mod_is_user_mod;
else
info.is_user_code = in_user_mod(module);
}
else {
info.is_user_code = (info.inlined_at == 0) ? mod_is_user_mod : linetable.at(info.inlined_at).is_user_code;
}
if (module == ctx.module)
info.is_user_code = mod_is_user_mod;
else
info.is_user_code = in_user_mod(module);
info.file = jl_symbol_name(filesym);
if (info.file.empty())
info.file = "<missing>";
if (ctx.debug_enabled) {
StringRef fname;
if (jl_is_method_instance(method))
method = ((jl_method_instance_t*)method)->def.value;
if (jl_is_method(method))
method = (jl_value_t*)((jl_method_t*)method)->name;
if (jl_is_symbol(method))
Expand Down
10 changes: 1 addition & 9 deletions src/dump.c
Original file line number Diff line number Diff line change
Expand Up @@ -1656,7 +1656,7 @@ static jl_value_t *jl_deserialize_value(jl_serializer_state *s, jl_value_t **loc
{
assert(!ios_eof(s->s));
jl_value_t *v;
size_t i, n;
size_t n;
uintptr_t pos;
uint8_t tag = read_uint8(s->s);
if (tag > LAST_TAG)
Expand Down Expand Up @@ -1774,14 +1774,6 @@ static jl_value_t *jl_deserialize_value(jl_serializer_state *s, jl_value_t **loc
arraylist_push(&backref_list, v);
ios_readall(s->s, jl_string_data(v), n);
return v;
case TAG_LINEINFO:
v = jl_new_struct_uninit(jl_lineinfonode_type);
arraylist_push(&backref_list, v);
for (i = 0; i < jl_datatype_nfields(jl_lineinfonode_type); i++) {
size_t offs = jl_field_offset(jl_lineinfonode_type, i);
set_nth_field(jl_lineinfonode_type, (void*)v, i, jl_deserialize_value(s, (jl_value_t**)((char*)v + offs)));
}
return v;
case TAG_DATATYPE:
pos = backref_list.len;
arraylist_push(&backref_list, NULL);
Expand Down
5 changes: 3 additions & 2 deletions src/jltypes.c
Original file line number Diff line number Diff line change
Expand Up @@ -2193,8 +2193,9 @@ void jl_init_types(void) JL_GC_DISABLED

jl_lineinfonode_type =
jl_new_datatype(jl_symbol("LineInfoNode"), core, jl_any_type, jl_emptysvec,
jl_perm_symsvec(4, "method", "file", "line", "inlined_at"),
jl_svec(4, jl_any_type, jl_symbol_type, jl_long_type, jl_long_type), 0, 0, 4);
jl_perm_symsvec(5, "module", "method", "file", "line", "inlined_at"),
jl_svec(5, jl_module_type, jl_any_type, jl_symbol_type, jl_long_type, jl_long_type),
0, 0, 5);

jl_gotonode_type =
jl_new_datatype(jl_symbol("GotoNode"), core, jl_any_type, jl_emptysvec,
Expand Down
1 change: 1 addition & 0 deletions src/julia.h
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,7 @@ JL_EXTENSION typedef union {
typedef struct _jl_method_instance_t jl_method_instance_t;

typedef struct _jl_line_info_node_t {
struct _jl_module_t *module;
jl_value_t *method;
jl_sym_t *file;
intptr_t line;
Expand Down
2 changes: 1 addition & 1 deletion src/julia_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -476,7 +476,7 @@ jl_value_t *jl_interpret_toplevel_expr_in(jl_module_t *m, jl_value_t *e,
jl_svec_t *sparam_vals);
int jl_is_toplevel_only_expr(jl_value_t *e) JL_NOTSAFEPOINT;
jl_value_t *jl_call_scm_on_ast(const char *funcname, jl_value_t *expr, jl_module_t *inmodule);
void jl_linenumber_to_lineinfo(jl_code_info_t *ci, jl_value_t *name);
void jl_linenumber_to_lineinfo(jl_code_info_t *ci, jl_module_t *mod, jl_value_t *name);

jl_method_instance_t *jl_method_lookup(jl_value_t **args, size_t nargs, size_t world);
jl_value_t *jl_gf_invoke(jl_value_t *types, jl_value_t *f, jl_value_t **args, size_t nargs);
Expand Down
10 changes: 5 additions & 5 deletions src/method.c
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,7 @@ jl_code_info_t *jl_new_code_info_from_ir(jl_expr_t *ir)
return src;
}

void jl_linenumber_to_lineinfo(jl_code_info_t *ci, jl_value_t *name)
void jl_linenumber_to_lineinfo(jl_code_info_t *ci, jl_module_t *mod, jl_value_t *name)
{
jl_array_t *li = (jl_array_t*)ci->linetable;
size_t i, n = jl_array_len(li);
Expand All @@ -366,11 +366,11 @@ void jl_linenumber_to_lineinfo(jl_code_info_t *ci, jl_value_t *name)
jl_value_t *ln = jl_array_ptr_ref(li, i);
if (jl_is_linenode(ln)) {
rt = jl_box_long(jl_linenode_line(ln));
rt = jl_new_struct(jl_lineinfonode_type, name, jl_linenode_file(ln), rt, jl_box_long(0));
rt = jl_new_struct(jl_lineinfonode_type, mod, name, jl_linenode_file(ln), rt, jl_box_long(0));
jl_array_ptr_set(li, i, rt);
}
else if (jl_is_expr(ln) && ((jl_expr_t*)ln)->head == line_sym && jl_expr_nargs(ln) == 3) {
rt = jl_new_struct(jl_lineinfonode_type, jl_symbol("macro expansion"),
rt = jl_new_struct(jl_lineinfonode_type, mod, jl_symbol("macro expansion"),
jl_exprarg(ln, 1), jl_exprarg(ln, 0), jl_exprarg(ln, 2));
jl_array_ptr_set(li, i, rt);
}
Expand Down Expand Up @@ -461,7 +461,7 @@ JL_DLLEXPORT jl_code_info_t *jl_code_for_staged(jl_method_instance_t *linfo)
ptls->in_pure_callback = last_in;
jl_lineno = last_lineno;
ptls->world_age = last_age;
jl_linenumber_to_lineinfo(func, (jl_value_t*)def->name);
jl_linenumber_to_lineinfo(func, def->module, (jl_value_t*)def->name);
}
JL_CATCH {
ptls->in_pure_callback = last_in;
Expand Down Expand Up @@ -514,7 +514,7 @@ static void jl_method_set_source(jl_method_t *m, jl_code_info_t *src)
}
m->called = called;
m->pure = src->pure;
jl_linenumber_to_lineinfo(src, (jl_value_t*)m->name);
jl_linenumber_to_lineinfo(src, m->module, (jl_value_t*)m->name);

jl_array_t *copy = NULL;
jl_svec_t *sparam_vars = jl_outer_unionall_vars(m->sig);
Expand Down
12 changes: 6 additions & 6 deletions src/stackwalk.c
Original file line number Diff line number Diff line change
Expand Up @@ -660,14 +660,14 @@ void jl_print_bt_entry_codeloc(jl_bt_element_t *bt_entry) JL_NOTSAFEPOINT
jl_line_info_node_t *locinfo = (jl_line_info_node_t*)
jl_array_ptr_ref(src->linetable, debuginfoloc - 1);
assert(jl_typeis(locinfo, jl_lineinfonode_type));
const char *func_name = "Unknown";
jl_value_t *method = locinfo->method;
if (jl_is_method_instance(method)) {
if (jl_is_method_instance(method))
method = ((jl_method_instance_t*)method)->def.value;
if (jl_is_method(method))
method = (jl_value_t*)((jl_method_t*)method)->name;
}
const char *func_name = jl_is_symbol(method) ?
jl_symbol_name((jl_sym_t*)method) : "Unknown";
if (jl_is_method(method))
method = (jl_value_t*)((jl_method_t*)method)->name;
if (jl_is_symbol(method))
func_name = jl_symbol_name((jl_sym_t*)method);
jl_safe_print_codeloc(func_name, jl_symbol_name(locinfo->file),
locinfo->line, locinfo->inlined_at);
debuginfoloc = locinfo->inlined_at;
Expand Down
13 changes: 8 additions & 5 deletions stdlib/Serialization/src/Serialization.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1038,12 +1038,15 @@ function deserialize(s::AbstractSerializer, ::Type{Core.MethodInstance})
end

function deserialize(s::AbstractSerializer, ::Type{Core.LineInfoNode})
_meth = deserialize(s)
if _meth isa Module
# pre v1.2, skip
_meth = deserialize(s)
mod = deserialize(s)
if mod isa Module
method = deserialize(s)
else
# files post v1.2 and pre v1.6 are broken
method = mod
mod = Main
end
return Core.LineInfoNode(_meth::Symbol, deserialize(s)::Symbol, deserialize(s)::Int, deserialize(s)::Int)
return Core.LineInfoNode(mod, method, deserialize(s)::Symbol, deserialize(s)::Int, deserialize(s)::Int)
end

function deserialize(s::AbstractSerializer, ::Type{PhiNode})
Expand Down
2 changes: 1 addition & 1 deletion test/compiler/ssair.jl
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ end
# false, false, false, false
# ))
#
# NullLineInfo = Core.LineInfoNode(Symbol(""), Symbol(""), 0, 0)
# NullLineInfo = Core.LineInfoNode(Main, Symbol(""), Symbol(""), 0, 0)
# Compiler.run_passes(ci, 1, [NullLineInfo])
# # XXX: missing @test
#end
Expand Down

0 comments on commit 42a1d34

Please sign in to comment.