Skip to content

Commit

Permalink
CodeInstance: remove relocatability field
Browse files Browse the repository at this point in the history
This field lost its meaning awhile back and is better tracked only as
part of the compressed CodeInfo instead of trying to accurately copy and
update this field.
  • Loading branch information
vtjnash committed Jan 8, 2025
1 parent 75cdffe commit d5ff803
Show file tree
Hide file tree
Showing 13 changed files with 41 additions and 75 deletions.
21 changes: 5 additions & 16 deletions Compiler/src/typeinfer.jl
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,6 @@ function finish!(interp::AbstractInterpreter, caller::InferenceState)
end
inferred_result = nothing
uncompressed = inferred_result
relocatability = 0x1
const_flag = is_result_constabi_eligible(result)
discard_src = caller.cache_mode === CACHE_MODE_NULL || const_flag
if !discard_src
Expand All @@ -139,22 +138,14 @@ function finish!(interp::AbstractInterpreter, caller::InferenceState)
elseif ci.owner === nothing
# The global cache can only handle objects that codegen understands
inferred_result = nothing
else
relocatability = 0x0
end
if isa(inferred_result, String)
t = @_gc_preserve_begin inferred_result
relocatability = unsafe_load(unsafe_convert(Ptr{UInt8}, inferred_result), Core.sizeof(inferred_result))
@_gc_preserve_end t
end
end
# n.b. relocatability = !isa(inferred_result, String) || inferred_result[end]
if !@isdefined di
di = DebugInfo(result.linfo)
end
ccall(:jl_update_codeinst, Cvoid, (Any, Any, Int32, UInt, UInt, UInt32, Any, UInt8, Any, Any),
ccall(:jl_update_codeinst, Cvoid, (Any, Any, Int32, UInt, UInt, UInt32, Any, Any, Any),
ci, inferred_result, const_flag, first(result.valid_worlds), last(result.valid_worlds), encode_effects(result.ipo_effects),
result.analysis_results, relocatability, di, edges)
result.analysis_results, di, edges)
engine_reject(interp, ci)
if !discard_src && isdefined(interp, :codegen) && uncompressed isa CodeInfo
# record that the caller could use this result to generate code when required, if desired, to avoid repeating n^2 work
Expand All @@ -176,7 +167,6 @@ end
function finish!(interp::AbstractInterpreter, mi::MethodInstance, ci::CodeInstance, src::CodeInfo)
user_edges = src.edges
edges = user_edges isa SimpleVector ? user_edges : user_edges === nothing ? Core.svec() : Core.svec(user_edges...)
relocatability = 0x1
const_flag = false
di = src.debuginfo
rettype = Any
Expand All @@ -196,8 +186,8 @@ function finish!(interp::AbstractInterpreter, mi::MethodInstance, ci::CodeInstan
end
ccall(:jl_fill_codeinst, Cvoid, (Any, Any, Any, Any, Int32, UInt, UInt, UInt32, Any, Any, Any),
ci, rettype, exctype, nothing, const_flags, min_world, max_world, ipo_effects, nothing, di, edges)
ccall(:jl_update_codeinst, Cvoid, (Any, Any, Int32, UInt, UInt, UInt32, Any, UInt8, Any, Any),
ci, nothing, const_flag, min_world, max_world, ipo_effects, nothing, relocatability, di, edges)
ccall(:jl_update_codeinst, Cvoid, (Any, Any, Int32, UInt, UInt, UInt32, Any, Any, Any),
ci, nothing, const_flag, min_world, max_world, ipo_effects, nothing, di, edges)
code_cache(interp)[mi] = ci
if isdefined(interp, :codegen)
interp.codegen[ci] = src
Expand Down Expand Up @@ -523,7 +513,6 @@ function finishinfer!(me::InferenceState, interp::AbstractInterpreter)
rettype_const = nothing
const_flags = 0x0
end
relocatability = 0x1
di = nothing
edges = empty_edges # `edges` will be updated within `finish!`
ci = result.ci
Expand Down Expand Up @@ -827,7 +816,7 @@ function codeinst_as_edge(interp::AbstractInterpreter, sv::InferenceState, @nosp
end
end
ci = CodeInstance(mi, cache_owner(interp), Any, Any, nothing, nothing, zero(Int32),
min_world, max_world, zero(UInt32), nothing, zero(UInt8), nothing, edges)
min_world, max_world, zero(UInt32), nothing, nothing, edges)
if max_world == typemax(UInt)
# if we can record all of the backedges in the global reverse-cache,
# we can now widen our applicability in the global cache too
Expand Down
2 changes: 1 addition & 1 deletion Compiler/test/abioverride.jl
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ let world = Base.tls_world_age()
#=owner=#SecondArgConstOverride(1), new_source.rettype, Any#=new_source.exctype is missing=#,
#=inferred_const=#nothing, #=code=#nothing, #=const_flags=#Int32(0),
new_source.min_world, new_source.max_world, #=new_source.ipo_purity_bits is missing=#UInt32(0),
#=analysis_results=#nothing, #=not relocatable?=#UInt8(0), new_source.debuginfo, new_source.edges)
#=analysis_results=#nothing, new_source.debuginfo, new_source.edges)

# Poke the CI into the global cache
# This isn't necessary, but does conveniently give it the mandatory permanent GC-root before calling `invoke`
Expand Down
6 changes: 3 additions & 3 deletions base/boot.jl
Original file line number Diff line number Diff line change
Expand Up @@ -561,11 +561,11 @@ function CodeInstance(
mi::Union{MethodInstance, ABIOverride}, 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, di::Union{DebugInfo,Nothing}, edges::SimpleVector)
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, Any, Int32, UInt, UInt, UInt32, Any, Any, Any),
mi, owner, rettype, exctype, inferred_const, inferred, const_flags, min_world, max_world,
effects, analysis_results, relocatability, di, edges)
effects, analysis_results, 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
17 changes: 7 additions & 10 deletions src/gf.c
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,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, NULL);
0, 1, ~(size_t)0, 0, jl_nothing, 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 @@ -564,7 +564,7 @@ JL_DLLEXPORT jl_code_instance_t *jl_get_method_inferred(
}
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, edges);
0, min_world, max_world, 0, jl_nothing, di, edges);
jl_mi_cache_insert(mi, codeinst);
return codeinst;
}
Expand Down Expand Up @@ -614,7 +614,6 @@ JL_DLLEXPORT jl_code_instance_t *jl_new_codeinst(
jl_value_t *inferred_const, 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 *di, jl_svec_t *edges /*, int absolute_max*/)
{
assert(min_world <= max_world && "attempting to set invalid world constraints");
Expand Down Expand Up @@ -645,19 +644,17 @@ JL_DLLEXPORT jl_code_instance_t *jl_new_codeinst(
jl_atomic_store_relaxed(&codeinst->next, NULL);
jl_atomic_store_relaxed(&codeinst->ipo_purity_bits, effects);
codeinst->analysis_results = analysis_results;
codeinst->relocatability = relocatability;
return codeinst;
}

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 *di, jl_svec_t *edges /* , int absolute_max*/)
jl_debuginfo_t *di, jl_svec_t *edges /* , int absolute_max*/)
{
assert(min_world <= max_world && "attempting to set invalid world constraints");
//assert((!jl_is_method(codeinst->def->def.value) || max_world != ~(size_t)0 || min_world <= 1 || jl_svec_len(edges) != 0) && "missing edges");
codeinst->relocatability = relocatability;
codeinst->analysis_results = analysis_results;
jl_gc_wb(codeinst, analysis_results);
jl_atomic_store_relaxed(&codeinst->ipo_purity_bits, effects);
Expand Down Expand Up @@ -715,7 +712,7 @@ JL_DLLEXPORT void jl_fill_codeinst(

JL_DLLEXPORT jl_code_instance_t *jl_new_codeinst_uninit(jl_method_instance_t *mi, jl_value_t *owner)
{
jl_code_instance_t *codeinst = jl_new_codeinst(mi, owner, NULL, NULL, NULL, NULL, 0, 0, 0, 0, NULL, 0, NULL, NULL);
jl_code_instance_t *codeinst = jl_new_codeinst(mi, owner, NULL, NULL, NULL, NULL, 0, 0, 0, 0, NULL, NULL, NULL);
jl_atomic_store_relaxed(&codeinst->min_world, 1); // make temporarily invalid before returning, so that jl_fill_codeinst is valid later
return codeinst;
}
Expand Down Expand Up @@ -2908,7 +2905,7 @@ jl_code_instance_t *jl_compile_method_internal(jl_method_instance_t *mi, size_t
jl_read_codeinst_invoke(unspec, &specsigflags, &invoke, &fptr, 1);
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, NULL);
0, 1, ~(size_t)0, 0, jl_nothing, NULL, NULL);
codeinst->rettype_const = unspec->rettype_const;
jl_atomic_store_relaxed(&codeinst->specptr.fptr, fptr);
jl_atomic_store_relaxed(&codeinst->invoke, invoke);
Expand All @@ -2929,7 +2926,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, NULL);
0, 1, ~(size_t)0, 0, jl_nothing, NULL, NULL);
jl_atomic_store_release(&codeinst->invoke, jl_fptr_interpret_call);
jl_mi_cache_insert(mi, codeinst);
record_precompile_statement(mi, 0, 0);
Expand Down Expand Up @@ -3019,7 +3016,7 @@ jl_code_instance_t *jl_compile_method_internal(jl_method_instance_t *mi, size_t
jl_read_codeinst_invoke(ucache, &specsigflags, &invoke, &fptr, 1);
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, NULL);
0, 1, ~(size_t)0, 0, jl_nothing, NULL, NULL);
codeinst->rettype_const = ucache->rettype_const;
// unspec is always not specsig, but might use specptr
jl_atomic_store_relaxed(&codeinst->specptr.fptr, fptr);
Expand Down
13 changes: 6 additions & 7 deletions src/jltypes.c
Original file line number Diff line number Diff line change
Expand Up @@ -3638,7 +3638,7 @@ void jl_init_types(void) JL_GC_DISABLED
jl_code_instance_type =
jl_new_datatype(jl_symbol("CodeInstance"), core,
jl_any_type, jl_emptysvec,
jl_perm_symsvec(18,
jl_perm_symsvec(17,
"def",
"owner",
"next",
Expand All @@ -3653,9 +3653,9 @@ void jl_init_types(void) JL_GC_DISABLED
//"absolute_max",
"ipo_purity_bits",
"analysis_results",
"specsigflags", "precompile", "relocatability",
"specsigflags", "precompile",
"invoke", "specptr"), // function object decls
jl_svec(18,
jl_svec(17,
jl_any_type,
jl_any_type,
jl_any_type,
Expand All @@ -3672,13 +3672,12 @@ void jl_init_types(void) JL_GC_DISABLED
jl_any_type,
jl_bool_type,
jl_bool_type,
jl_uint8_type,
jl_any_type, jl_any_type), // fptrs
jl_emptysvec,
0, 1, 1);
jl_svecset(jl_code_instance_type->types, 2, jl_code_instance_type);
const static uint32_t code_instance_constfields[1] = { 0b000001000011100011 }; // Set fields 1, 2, 6-8, 13 as const
const static uint32_t code_instance_atomicfields[1] = { 0b110110111100011100 }; // Set fields 3-5, 9-12, 14-15, 17-18 as atomic
const static uint32_t code_instance_constfields[1] = { 0b00001000011100011 }; // Set fields 1, 2, 6-8, 13 as const
const static uint32_t code_instance_atomicfields[1] = { 0b11110111100011100 }; // Set fields 3-5, 9-12, 14-17 as atomic
// Fields 4-5 are only operated on by construction and deserialization, so are effectively const at runtime
// Fields ipo_purity_bits and analysis_results are not currently threadsafe or reliable, as they get mutated after optimization, but are not declared atomic
// and there is no way to tell (during inference) if their value is finalized yet (to wait for them to be narrowed if applicable)
Expand Down Expand Up @@ -3854,8 +3853,8 @@ void jl_init_types(void) JL_GC_DISABLED
jl_svecset(jl_method_type->types, 13, jl_method_instance_type);
//jl_svecset(jl_debuginfo_type->types, 0, jl_method_instance_type); // union(jl_method_instance_type, jl_method_type, jl_symbol_type)
jl_svecset(jl_method_instance_type->types, 4, jl_code_instance_type);
jl_svecset(jl_code_instance_type->types, 15, jl_voidpointer_type);
jl_svecset(jl_code_instance_type->types, 16, jl_voidpointer_type);
jl_svecset(jl_code_instance_type->types, 17, jl_voidpointer_type);
jl_svecset(jl_binding_type->types, 0, jl_globalref_type);
jl_svecset(jl_binding_partition_type->types, 3, jl_binding_partition_type);

Expand Down
1 change: 0 additions & 1 deletion src/julia.h
Original file line number Diff line number Diff line change
Expand Up @@ -467,7 +467,6 @@ typedef struct _jl_code_instance_t {
// & 0b010 == invokeptr matches specptr
// & 0b100 == From image
_Atomic(uint8_t) precompile; // if set, this will be added to the output system image
uint8_t relocatability; // nonzero if all roots are built into sysimg or tagged by module key
_Atomic(jl_callptr_t) invoke; // jlcall entry point usually, but if this codeinst belongs to an OC Method, then this is an jl_fptr_args_t fptr1 instead, unless it is not, because it is a special token object instead
union _jl_generic_specptr_t {
_Atomic(void*) fptr;
Expand Down
2 changes: 1 addition & 1 deletion src/julia_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -691,7 +691,7 @@ JL_DLLEXPORT jl_code_instance_t *jl_new_codeinst(
jl_value_t *inferred_const, 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 *di, jl_svec_t *edges /* , int absolute_max*/);
jl_debuginfo_t *di, jl_svec_t *edges /* , int absolute_max*/);
JL_DLLEXPORT jl_code_instance_t *jl_get_ci_equiv(jl_code_instance_t *ci JL_PROPAGATES_ROOT, int compiled) JL_NOTSAFEPOINT;

STATIC_INLINE jl_method_instance_t *jl_get_ci_mi(jl_code_instance_t *ci JL_PROPAGATES_ROOT) JL_NOTSAFEPOINT
Expand Down
4 changes: 0 additions & 4 deletions src/method.c
Original file line number Diff line number Diff line change
Expand Up @@ -1384,10 +1384,6 @@ JL_DLLEXPORT jl_method_t* jl_method_def(jl_svec_t *argdata,
// at the time of writing the system image (such occur first in the list of
// roots). These are the cases with `key = 0` that do not prevent
// serialization.
// - CodeInstances have a `relocatability` field which when 1 indicates that
// every root is "safe," meaning it was either added at sysimg creation or is
// tagged with a non-zero `key`. Even a single unsafe root will cause this to
// have value 0.

// Get the key of the current (final) block of roots
static uint64_t current_root_id(jl_array_t *root_blocks)
Expand Down
2 changes: 1 addition & 1 deletion src/opaque_closure.c
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ JL_DLLEXPORT jl_opaque_closure_t *jl_new_opaque_closure_from_code_info(jl_tuplet
if (!jl_is_svec(edges))
edges = jl_emptysvec; // OC doesn't really have edges, so just drop them for now
inst = jl_new_codeinst(mi, jl_nothing, rt_ub, (jl_value_t*)jl_any_type, NULL, (jl_value_t*)ci,
0, world, world, 0, jl_nothing, 0, ci->debuginfo, edges);
0, world, world, 0, jl_nothing, ci->debuginfo, edges);
jl_mi_cache_insert(mi, inst);
}

Expand Down
Loading

0 comments on commit d5ff803

Please sign in to comment.