Skip to content

Commit

Permalink
record all invoke targets as edges as test
Browse files Browse the repository at this point in the history
  • Loading branch information
vtjnash committed Jun 23, 2024
1 parent d0b35b0 commit af946a0
Show file tree
Hide file tree
Showing 11 changed files with 159 additions and 88 deletions.
6 changes: 3 additions & 3 deletions base/boot.jl
Original file line number Diff line number Diff line change
Expand Up @@ -510,11 +510,11 @@ function CodeInstance(
mi::MethodInstance, owner, @nospecialize(rettype), @nospecialize(exctype), @nospecialize(inferred_const),
@nospecialize(inferred), const_flags::Int32, min_world::UInt, max_world::UInt,
effects::UInt32, @nospecialize(analysis_results),
relocatability::UInt8, edges::Union{DebugInfo,Nothing})
relocatability::UInt8, di::Union{DebugInfo,Nothing}, edges::SimpleVector)
return ccall(:jl_new_codeinst, Ref{CodeInstance},
(Any, Any, Any, Any, Any, Any, Int32, UInt, UInt, UInt32, Any, UInt8, Any),
(Any, Any, Any, Any, Any, Any, Int32, UInt, UInt, UInt32, Any, UInt8, Any, Any),
mi, owner, rettype, exctype, inferred_const, inferred, const_flags, min_world, max_world,
effects, analysis_results, relocatability, edges)
effects, analysis_results, relocatability, di, edges)
end
GlobalRef(m::Module, s::Symbol) = ccall(:jl_module_globalref, Ref{GlobalRef}, (Any, Any), m, s)
Module(name::Symbol=:anonymous, std_imports::Bool=true, default_names::Bool=true) = ccall(:jl_f_new_module, Ref{Module}, (Any, Bool, Bool), name, std_imports, default_names)
Expand Down
19 changes: 11 additions & 8 deletions base/compiler/typeinfer.jl
Original file line number Diff line number Diff line change
Expand Up @@ -224,13 +224,16 @@ function finish!(interp::AbstractInterpreter, caller::InferenceState;
if isdefined(result, :ci)
ci = result.ci
inferred_result = nothing
edges = Core.svec() # This should be a computed input, for now it is approximated (badly) here
relocatability = 0x1
const_flag = is_result_constabi_eligible(result)
if !can_discard_trees || (is_cached(caller) && !const_flag)
inferred_result = transform_result_for_cache(interp, result.linfo, result.valid_worlds, result, can_discard_trees)
relocatability = 0x0
if inferred_result isa CodeInfo
edges = inferred_result.debuginfo
edges = ccall(:jl_ir_edges_legacy, Any, (Any,), inferred_result.code)
inferred_result.edges = edges
di = inferred_result.debuginfo
uncompressed = inferred_result
inferred_result = maybe_compress_codeinfo(interp, result.linfo, inferred_result, can_discard_trees)
result.is_src_volatile |= uncompressed !== inferred_result
Expand All @@ -245,14 +248,14 @@ function finish!(interp::AbstractInterpreter, caller::InferenceState;
end
end
# n.b. relocatability = isa(inferred_result, String) && inferred_result[end]
if !@isdefined edges
edges = DebugInfo(result.linfo)
if !@isdefined di
di = DebugInfo(result.linfo)
end
ccall(:jl_update_codeinst, Cvoid, (Any, Any, Int32, UInt, UInt, UInt32, Any, UInt8, Any),
ccall(:jl_update_codeinst, Cvoid, (Any, Any, Int32, UInt, UInt, UInt32, Any, UInt8, Any, Any),
ci, inferred_result, const_flag,
first(result.valid_worlds), last(result.valid_worlds),
encode_effects(result.ipo_effects), result.analysis_results,
relocatability, edges)
relocatability, di, edges)
engine_reject(interp, ci)
end
return nothing
Expand Down Expand Up @@ -334,7 +337,6 @@ function is_result_constabi_eligible(result::InferenceResult)
return isa(result_type, Const) && is_foldable_nothrow(result.ipo_effects) && is_inlineable_constant(result_type.val)
end


function transform_result_for_cache(interp::AbstractInterpreter,
::MethodInstance, valid_worlds::WorldRange, result::InferenceResult,
can_discard_trees::Bool=may_discard_trees(interp))
Expand Down Expand Up @@ -991,6 +993,7 @@ function codeinfo_for_const(interp::AbstractInterpreter, mi::MethodInstance, @no
tree.debuginfo = DebugInfo(mi)
tree.ssaflags = UInt32[0]
tree.rettype = Core.Typeof(val)
tree.edges = Core.svec()
set_inlineable!(tree, true)
tree.parent = mi
return tree
Expand All @@ -1008,7 +1011,7 @@ function codeinstance_for_const_with_code(interp::AbstractInterpreter, code::Cod
return CodeInstance(code.def, cache_owner(interp), code.rettype, code.exctype, code.rettype_const, src,
Int32(0x3), code.min_world, code.max_world,
code.ipo_purity_bits, code.analysis_results,
code.relocatability, src.debuginfo)
code.relocatability, src.debuginfo, src.edges)
end

result_is_constabi(interp::AbstractInterpreter, result::InferenceResult,
Expand Down Expand Up @@ -1170,7 +1173,7 @@ function typeinf_ext(interp::AbstractInterpreter, mi::MethodInstance, source_mod
src isa CodeInfo || return nothing
return CodeInstance(mi, cache_owner(interp), Any, Any, nothing, src, Int32(0),
get_inference_world(interp), get_inference_world(interp),
UInt32(0), nothing, UInt8(0), src.debuginfo)
UInt32(0), nothing, UInt8(0), src.debuginfo, src.edges)
end
end
ci = engine_reserve(interp, mi)
Expand Down
2 changes: 1 addition & 1 deletion base/expr.jl
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ function copy(c::CodeInfo)
cnew.slottypes = copy(cnew.slottypes::Vector{Any})
end
cnew.ssaflags = copy(cnew.ssaflags)
cnew.edges = cnew.edges === nothing || cnew.edges === Core.svec() ? cnew.edges : copy(cnew.edges::Vector)
cnew.edges = cnew.edges === nothing || cnew.edges isa Core.SimpleVector ? cnew.edges : copy(cnew.edges::Vector)
ssavaluetypes = cnew.ssavaluetypes
ssavaluetypes isa Vector{Any} && (cnew.ssavaluetypes = copy(ssavaluetypes))
return cnew
Expand Down
2 changes: 0 additions & 2 deletions src/common_symbols1.inc
Original file line number Diff line number Diff line change
Expand Up @@ -88,5 +88,3 @@ jl_symbol("ifelse"),
jl_symbol("Array"),
jl_symbol("eq_int"),
jl_symbol("throw_inexacterror"),
jl_symbol("|"),
jl_symbol("setproperty!"),
4 changes: 2 additions & 2 deletions src/common_symbols2.inc
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
jl_symbol("|"),
jl_symbol("setproperty!"),
jl_symbol("sext_int"),
jl_symbol("String"),
jl_symbol("Int"),
Expand Down Expand Up @@ -244,5 +246,3 @@ jl_symbol("invokelatest"),
jl_symbol("jl_array_del_end"),
jl_symbol("_mod64"),
jl_symbol("parameters"),
jl_symbol("monotonic"),
jl_symbol("regex.jl"),
45 changes: 26 additions & 19 deletions src/gf.c
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ jl_datatype_t *jl_mk_builtin_func(jl_datatype_t *dt, const char *name, jl_fptr_a

jl_code_instance_t *codeinst = jl_new_codeinst(mi, jl_nothing,
(jl_value_t*)jl_any_type, (jl_value_t*)jl_any_type, jl_nothing, jl_nothing,
0, 1, ~(size_t)0, 0, jl_nothing, 0, NULL);
0, 1, ~(size_t)0, 0, jl_nothing, 0, NULL, NULL);
jl_mi_cache_insert(mi, codeinst);
jl_atomic_store_relaxed(&codeinst->specptr.fptr1, fptr);
jl_atomic_store_relaxed(&codeinst->invoke, jl_fptr_args);
Expand Down Expand Up @@ -480,7 +480,7 @@ JL_DLLEXPORT jl_value_t *jl_call_in_typeinf_world(jl_value_t **args, int nargs)

JL_DLLEXPORT jl_code_instance_t *jl_get_method_inferred(
jl_method_instance_t *mi JL_PROPAGATES_ROOT, jl_value_t *rettype,
size_t min_world, size_t max_world, jl_debuginfo_t *di /*jl_svec_t *edges*/)
size_t min_world, size_t max_world, jl_debuginfo_t *di, jl_svec_t *edges)
{
jl_value_t *owner = jl_nothing; // TODO: owner should be arg
jl_code_instance_t *codeinst = jl_atomic_load_relaxed(&mi->cache);
Expand All @@ -492,24 +492,27 @@ JL_DLLEXPORT jl_code_instance_t *jl_get_method_inferred(
if (di == NULL)
return codeinst;
jl_debuginfo_t *debuginfo = jl_atomic_load_relaxed(&codeinst->debuginfo);
if (di == debuginfo)
return codeinst;
if (debuginfo == NULL && jl_atomic_cmpswap_relaxed(&codeinst->debuginfo, &debuginfo, di))
return codeinst;
if (debuginfo && jl_egal((jl_value_t*)debuginfo, (jl_value_t*)di))
if (di != debuginfo) {
if (!(debuginfo == NULL && jl_atomic_cmpswap_relaxed(&codeinst->debuginfo, &debuginfo, di)))
if (!(debuginfo && jl_egal((jl_value_t*)debuginfo, (jl_value_t*)di)))
continue;
}
// TODO: this is implied by the matching worlds, since it is intrinsic, so do we really need to verify it?
jl_svec_t *e = jl_atomic_load_relaxed(&codeinst->edges);
if (e && jl_egal((jl_value_t*)e, (jl_value_t*)edges))
return codeinst;
}
codeinst = jl_atomic_load_relaxed(&codeinst->next);
}
codeinst = jl_new_codeinst(
mi, owner, rettype, (jl_value_t*)jl_any_type, NULL, NULL,
0, min_world, max_world, 0, jl_nothing, 0, di);
0, min_world, max_world, 0, jl_nothing, 0, di, edges);
jl_mi_cache_insert(mi, codeinst);
return codeinst;
}

JL_DLLEXPORT int jl_mi_cache_has_ci(jl_method_instance_t *mi,
jl_code_instance_t *ci)
jl_code_instance_t *ci)
{
jl_code_instance_t *codeinst = jl_atomic_load_relaxed(&mi->cache);
while (codeinst) {
Expand All @@ -527,15 +530,15 @@ JL_DLLEXPORT jl_code_instance_t *jl_new_codeinst(
int32_t const_flags, size_t min_world, size_t max_world,
uint32_t effects, jl_value_t *analysis_results,
uint8_t relocatability,
jl_debuginfo_t *di /*, jl_svec_t *edges, int absolute_max*/)
jl_debuginfo_t *di, jl_svec_t *edges /*, int absolute_max*/)
{
jl_task_t *ct = jl_current_task;
assert(min_world <= max_world && "attempting to set invalid world constraints");
jl_code_instance_t *codeinst = (jl_code_instance_t*)jl_gc_alloc(ct->ptls, sizeof(jl_code_instance_t),
jl_code_instance_type);
codeinst->def = mi;
codeinst->owner = owner;
codeinst->edges = jl_emptysvec;
codeinst->edges = edges;
jl_atomic_store_relaxed(&codeinst->min_world, min_world);
jl_atomic_store_relaxed(&codeinst->max_world, max_world);
codeinst->rettype = rettype;
Expand Down Expand Up @@ -564,13 +567,15 @@ JL_DLLEXPORT void jl_update_codeinst(
jl_code_instance_t *codeinst, jl_value_t *inferred,
int32_t const_flags, size_t min_world, size_t max_world,
uint32_t effects, jl_value_t *analysis_results,
uint8_t relocatability, jl_debuginfo_t *edges /* , int absolute_max*/)
uint8_t relocatability, jl_debuginfo_t *di, jl_svec_t *edges /* , int absolute_max*/)
{
codeinst->relocatability = relocatability;
codeinst->analysis_results = analysis_results;
jl_gc_wb(codeinst, analysis_results);
jl_atomic_store_relaxed(&codeinst->ipo_purity_bits, effects);
jl_atomic_store_relaxed(&codeinst->debuginfo, edges);
jl_atomic_store_relaxed(&codeinst->debuginfo, di);
jl_gc_wb(codeinst, di);
jl_atomic_store_relaxed(&codeinst->edges, edges);
jl_gc_wb(codeinst, edges);
if ((const_flags & 1) != 0) {
assert(codeinst->rettype_const);
Expand Down Expand Up @@ -2564,8 +2569,10 @@ jl_code_instance_t *jl_compile_method_internal(jl_method_instance_t *mi, size_t
jl_code_instance_t *codeinst2 = jl_compile_method_internal(mi2, world);
jl_code_instance_t *codeinst = jl_get_method_inferred(
mi, codeinst2->rettype,
jl_atomic_load_relaxed(&codeinst2->min_world), jl_atomic_load_relaxed(&codeinst2->max_world),
jl_atomic_load_relaxed(&codeinst2->debuginfo));
jl_atomic_load_relaxed(&codeinst2->min_world),
jl_atomic_load_relaxed(&codeinst2->max_world),
jl_atomic_load_relaxed(&codeinst2->debuginfo),
jl_atomic_load_relaxed(&codeinst2->edges));
if (jl_atomic_load_relaxed(&codeinst->invoke) == NULL) {
codeinst->rettype_const = codeinst2->rettype_const;
jl_gc_wb(codeinst, codeinst->rettype_const);
Expand Down Expand Up @@ -2624,7 +2631,7 @@ jl_code_instance_t *jl_compile_method_internal(jl_method_instance_t *mi, size_t
if (unspec && (unspec_invoke = jl_atomic_load_acquire(&unspec->invoke))) {
jl_code_instance_t *codeinst = jl_new_codeinst(mi, jl_nothing,
(jl_value_t*)jl_any_type, (jl_value_t*)jl_any_type, NULL, NULL,
0, 1, ~(size_t)0, 0, jl_nothing, 0, NULL);
0, 1, ~(size_t)0, 0, jl_nothing, 0, NULL, NULL);
void *unspec_fptr = jl_atomic_load_relaxed(&unspec->specptr.fptr);
if (unspec_fptr) {
// wait until invoke and specsigflags are properly set
Expand All @@ -2651,7 +2658,7 @@ jl_code_instance_t *jl_compile_method_internal(jl_method_instance_t *mi, size_t
if (!jl_code_requires_compiler(src, 0)) {
jl_code_instance_t *codeinst = jl_new_codeinst(mi, jl_nothing,
(jl_value_t*)jl_any_type, (jl_value_t*)jl_any_type, NULL, NULL,
0, 1, ~(size_t)0, 0, jl_nothing, 0, NULL);
0, 1, ~(size_t)0, 0, jl_nothing, 0, NULL, NULL);
jl_atomic_store_release(&codeinst->invoke, jl_fptr_interpret_call);
jl_mi_cache_insert(mi, codeinst);
record_precompile_statement(mi, 0);
Expand Down Expand Up @@ -2711,7 +2718,7 @@ jl_code_instance_t *jl_compile_method_internal(jl_method_instance_t *mi, size_t
jl_method_instance_t *unspec = jl_get_unspecialized(def);
if (unspec == NULL)
unspec = mi;
jl_code_instance_t *ucache = jl_get_method_inferred(unspec, (jl_value_t*)jl_any_type, 1, ~(size_t)0, NULL);
jl_code_instance_t *ucache = jl_get_method_inferred(unspec, (jl_value_t*)jl_any_type, 1, ~(size_t)0, NULL, NULL);
// ask codegen to make the fptr for unspec
jl_callptr_t ucache_invoke = jl_atomic_load_acquire(&ucache->invoke);
if (ucache_invoke == NULL) {
Expand All @@ -2731,7 +2738,7 @@ jl_code_instance_t *jl_compile_method_internal(jl_method_instance_t *mi, size_t
}
codeinst = jl_new_codeinst(mi, jl_nothing,
(jl_value_t*)jl_any_type, (jl_value_t*)jl_any_type, NULL, NULL,
0, 1, ~(size_t)0, 0, jl_nothing, 0, NULL);
0, 1, ~(size_t)0, 0, jl_nothing, 0, NULL, NULL);
void *unspec_fptr = jl_atomic_load_relaxed(&ucache->specptr.fptr);
if (unspec_fptr) {
// wait until invoke and specsigflags are properly set
Expand Down
60 changes: 58 additions & 2 deletions src/ircode.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ typedef struct {
ios_t *s;
// method we're compressing for
jl_method_t *method;
jl_svec_t *edges;
jl_ptls_t ptls;
uint8_t relocatability;
} jl_ircode_state;
Expand Down Expand Up @@ -72,7 +73,7 @@ static void literal_val_id(rle_reference *rr, jl_ircode_state *s, jl_value_t *v)
{
jl_array_t *rs = s->method->roots;
int i, l = jl_array_nrows(rs);
if (jl_is_symbol(v) || jl_is_concrete_type(v)) {
if (jl_is_symbol(v) || jl_is_concrete_type(v)) { // TODO: or more generally, any ptr-egal value
for (i = 0; i < l; i++) {
if (jl_array_ptr_ref(rs, i) == v)
return tagged_root(rr, s, i);
Expand All @@ -84,6 +85,12 @@ static void literal_val_id(rle_reference *rr, jl_ircode_state *s, jl_value_t *v)
return tagged_root(rr, s, i);
}
}
for (size_t i = 0; i < jl_svec_len(s->edges); i++) {
if (jl_svecref(s->edges, i) == v) {
rr->index = i;
return;
}
}
jl_add_method_root(s->method, jl_precompile_toplevel_module, v);
return tagged_root(rr, s, jl_array_nrows(rs) - 1);
}
Expand All @@ -102,13 +109,24 @@ static void jl_encode_int32(jl_ircode_state *s, int32_t x)

static void jl_encode_as_indexed_root(jl_ircode_state *s, jl_value_t *v)
{
rle_reference rr;
rle_reference rr = {.key = -1, .index = -1};

if (jl_is_string(v))
v = jl_as_global_root(v, 1);
literal_val_id(&rr, s, v);
int id = rr.index;
assert(id >= 0);
if (rr.key == -1) {
if (id <= UINT8_MAX) {
write_uint8(s->s, TAG_EDGE);
write_uint8(s->s, id);
}
else {
write_uint8(s->s, TAG_LONG_EDGE);
write_uint32(s->s, id);
}
return;
}
if (rr.key) {
write_uint8(s->s, TAG_RELOC_METHODROOT);
write_uint64(s->s, rr.key);
Expand Down Expand Up @@ -689,6 +707,10 @@ static jl_value_t *jl_decode_value(jl_ircode_state *s) JL_GC_DISABLED
return lookup_root(s->method, 0, read_uint8(s->s));
case TAG_LONG_METHODROOT:
return lookup_root(s->method, 0, read_uint32(s->s));
case TAG_EDGE:
return jl_svecref(s->edges, read_uint8(s->s));
case TAG_LONG_EDGE:
return jl_svecref(s->edges, read_uint32(s->s));
case TAG_SVEC: JL_FALLTHROUGH; case TAG_LONG_SVEC:
return jl_decode_value_svec(s, tag);
case TAG_COMMONSYM:
Expand Down Expand Up @@ -846,6 +868,37 @@ typedef enum {
#define checked_size(data, macro_size) \
(declaration_context(static_assert(sizeof(data) == macro_size, #macro_size " does not match written size")), data)

// n.b. this does not compute edges correctly, but is just a temporary legacy helper while porting
JL_DLLEXPORT jl_value_t *jl_ir_edges_legacy(jl_array_t *src)
{
arraylist_t edges;
arraylist_new(&edges, 0);
for (size_t i = 0; i < jl_array_dim0(src); i++) {
jl_value_t *v = jl_array_ptr_ref(src, i);
if (jl_is_expr(v)) {
jl_expr_t *e = (jl_expr_t*)v;
if (e->head == jl_assign_sym && jl_expr_nargs(e) == 2 && jl_is_expr(jl_exprarg(e, 1))) {
e = (jl_expr_t*)jl_exprarg(e, 1);
}
if (e->head == jl_invoke_sym) {
jl_value_t *target = jl_array_ptr_ref(e->args, 0);
if (jl_is_code_instance(target) || jl_is_method_instance(target)) {
size_t j;
for (j = 0; j < edges.len; j++)
if (edges.items[j] == (void*)target)
break;
if (j == edges.len)
arraylist_push(&edges, target);
}
}
}
}
jl_value_t *e = jl_f_svec(NULL, (jl_value_t**)edges.items, edges.len);
arraylist_free(&edges);
return e;
}


JL_DLLEXPORT jl_string_t *jl_compress_ir(jl_method_t *m, jl_code_info_t *code)
{
JL_TIMING(AST_COMPRESS, AST_COMPRESS);
Expand All @@ -865,9 +918,11 @@ JL_DLLEXPORT jl_string_t *jl_compress_ir(jl_method_t *m, jl_code_info_t *code)
m->roots = jl_alloc_vec_any(0);
jl_gc_wb(m, m->roots);
}
jl_value_t *edges = code->edges;
jl_ircode_state s = {
&dest,
m,
(!isdef && jl_is_svec(edges)) ? (jl_svec_t*)edges : jl_emptysvec,
jl_current_task->ptls,
1
};
Expand Down Expand Up @@ -950,6 +1005,7 @@ JL_DLLEXPORT jl_code_info_t *jl_uncompress_ir(jl_method_t *m, jl_code_instance_t
jl_ircode_state s = {
&src,
m,
metadata == NULL ? NULL : metadata->edges,
jl_current_task->ptls,
1
};
Expand Down
Loading

0 comments on commit af946a0

Please sign in to comment.