Skip to content

Commit c8510e3

Browse files
committed
internals: share slotnames table via Method
Also store a few other unnecessary properties in CodeInfo, which some users might be interested in having.
1 parent 3bb8404 commit c8510e3

22 files changed

+283
-203
lines changed

base/compiler/inferencestate.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ mutable struct InferenceState
5858
s_types = Any[ nothing for i = 1:n ]
5959

6060
# initial types
61-
nslots = length(src.slotnames)
61+
nslots = length(src.slotflags)
6262
argtypes = result.argtypes
6363
nargs = length(argtypes)
6464
s_argtypes = VarTable(undef, nslots)
@@ -122,7 +122,7 @@ end
122122

123123
function sptypes_from_meth_instance(linfo::MethodInstance)
124124
toplevel = !isa(linfo.def, Method)
125-
if !toplevel && isempty(linfo.sparam_vals) && !isempty(linfo.def.sparam_syms)
125+
if !toplevel && isempty(linfo.sparam_vals) && isa(linfo.def.sig, UnionAll)
126126
# linfo is unspecialized
127127
sp = Any[]
128128
sig = linfo.def.sig

base/compiler/optimize.jl

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,11 @@ mutable struct OptimizationState
3737
if nssavalues isa Int
3838
src.ssavaluetypes = Any[ Any for i = 1:nssavalues ]
3939
end
40-
nslots = length(src.slotnames)
41-
slottypes = Any[ Any for i = 1:nslots ]
40+
nslots = length(src.slotflags)
41+
slottypes = src.slottypes
42+
if slottypes === nothing
43+
slottypes = Any[ Any for i = 1:nslots ]
44+
end
4245
s_edges = []
4346
# cache some useful state computations
4447
toplevel = !isa(linfo.def, Method)
@@ -73,7 +76,7 @@ end
7376
# This is implied by `SLOT_USEDUNDEF`.
7477
# If this is not set, all the uses are (statically) dominated by the defs.
7578
# In particular, if a slot has `AssignedOnce && !StaticUndef`, it is an SSA.
76-
const SLOT_STATICUNDEF = 1
79+
const SLOT_STATICUNDEF = 1 # slot might be used before it is defined (structurally)
7780
const SLOT_ASSIGNEDONCE = 16 # slot is assigned to only once
7881
const SLOT_USEDUNDEF = 32 # slot has uses that might raise UndefVarError
7982
# const SLOT_CALLED = 64

base/compiler/ssair/legacy.jl

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
# This file is a part of Julia. License is MIT: https://julialang.org/license
22

3-
inflate_ir(ci::CodeInfo) = inflate_ir(ci, Any[], Any[ Any for i = 1:length(ci.slotnames) ])
4-
53
function inflate_ir(ci::CodeInfo, linfo::MethodInstance)
64
sptypes = sptypes_from_meth_instance(linfo)
75
if ci.inferred
86
argtypes, _ = matching_cache_argtypes(linfo, nothing)
97
else
10-
argtypes = Any[ Any for i = 1:length(ci.slotnames) ]
8+
argtypes = Any[ Any for i = 1:length(ci.slotflags) ]
119
end
1210
return inflate_ir(ci, sptypes, argtypes)
1311
end
@@ -92,3 +90,6 @@ function replace_code_newstyle!(ci::CodeInfo, ir::IRCode, nargs::Int)
9290
end
9391
end
9492
end
93+
94+
# used by some tests
95+
inflate_ir(ci::CodeInfo) = inflate_ir(ci, Any[], Any[ Any for i = 1:length(ci.slotflags) ])

base/compiler/ssair/slot2ssa.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ end
4545

4646
@inline slot_id(s) = isa(s, SlotNumber) ? (s::SlotNumber).id : (s::TypedSlot).id
4747
function scan_slot_def_use(nargs::Int, ci::CodeInfo, code::Vector{Any})
48-
nslots = length(ci.slotnames)
48+
nslots = length(ci.slotflags)
4949
result = SlotInfo[SlotInfo() for i = 1:nslots]
5050
# Set defs for arguments
5151
for var in result[1:(1+nargs)]
@@ -654,7 +654,7 @@ function construct_ssa!(ci::CodeInfo, code::Vector{Any}, ir::IRCode, domtree::Do
654654
undef_token
655655
else
656656
SSAValue(-1)
657-
end for x in 1:length(ci.slotnames)
657+
end for x in 1:length(ci.slotflags)
658658
]
659659
worklist = Tuple{Int, Int, Vector{Any}}[(1, 0, initial_incoming_vals)]
660660
visited = BitSet()

base/compiler/typeinfer.jl

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,12 @@ function typeinf(frame::InferenceState)
5656
end
5757
end
5858
end
59+
end
60+
for caller in frames
61+
caller.src.min_world = min_valid % Int
62+
caller.src.max_world = max_valid % Int
5963
if cached
60-
for caller in results
61-
cache_result(caller, min_valid, max_valid)
62-
end
64+
cache_result(caller.result, min_valid, max_valid)
6365
end
6466
end
6567
# if we aren't cached, we don't need this edge
@@ -308,6 +310,8 @@ function type_annotate!(sv::InferenceState)
308310
# compute the required type for each slot
309311
# to hold all of the items assigned into it
310312
record_slot_assign!(sv)
313+
sv.src.slottypes = sv.slottypes
314+
sv.src.rettype = sv.bestguess
311315

312316
# annotate variables load types
313317
# remove dead code optimization
@@ -544,16 +548,20 @@ function typeinf_ext(linfo::MethodInstance, params::Params)
544548
if invoke_api(linfo) == 2
545549
tree = ccall(:jl_new_code_info_uninit, Ref{CodeInfo}, ())
546550
tree.code = Any[ Expr(:return, quoted(linfo.inferred_const)) ]
547-
tree.method_for_inference_limit_heuristics = nothing
548-
tree.slotnames = Any[ COMPILER_TEMP_SYM for i = 1:method.nargs ]
549-
tree.slotflags = fill(0x00, Int(method.nargs))
550-
tree.ssavaluetypes = 0
551+
nargs = Int(method.nargs)
552+
tree.slotnames = ccall(:jl_uncompress_argnames, Any, (Any,), method.slot_syms)
553+
tree.slotflags = fill(0x00, nargs)
554+
tree.ssavaluetypes = 1
551555
tree.codelocs = Int32[1]
552556
tree.linetable = [LineInfoNode(method.module, method.name, method.file, Int(method.line), 0)]
553557
tree.inferred = true
554-
tree.ssaflags = UInt8[]
558+
tree.ssaflags = UInt8[0]
555559
tree.pure = true
556560
tree.inlineable = true
561+
tree.parent = linfo
562+
tree.rettype = typeof(linfo.inferred_const)
563+
tree.min_world = li.min_world
564+
tree.max_world = li.max_world
557565
i == 2 && ccall(:jl_typeinf_end, Cvoid, ())
558566
return svec(linfo, tree)
559567
elseif isa(inf, CodeInfo)

base/compiler/utilities.jl

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -96,19 +96,23 @@ end
9696

9797
function retrieve_code_info(linfo::MethodInstance)
9898
m = linfo.def::Method
99+
c = nothing
99100
if isdefined(m, :generator)
100101
# user code might throw errors – ignore them
101-
return get_staged(linfo)
102-
else
103-
# TODO: post-inference see if we can swap back to the original arrays?
102+
c = get_staged(linfo)
103+
end
104+
if c === nothing && isdefined(m, :source)
104105
src = m.source
105106
if isa(src, Array{UInt8,1})
106107
c = ccall(:jl_uncompress_ast, Any, (Any, Any), m, src)
107108
else
108109
c = copy(src::CodeInfo)
109110
end
110111
end
111-
return c::CodeInfo
112+
if c isa CodeInfo
113+
c.parent = linfo
114+
return c
115+
end
112116
end
113117

114118
function code_for_method(method::Method, @nospecialize(atypes), sparams::SimpleVector, world::UInt, preexisting::Bool=false)

base/compiler/validation.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ const INVALID_RVALUE = "invalid RHS value"
4141
const INVALID_RETURN = "invalid argument to :return"
4242
const INVALID_CALL_ARG = "invalid :call argument"
4343
const EMPTY_SLOTNAMES = "slotnames field is empty"
44-
const SLOTFLAGS_MISMATCH = "length(slotnames) != length(slotflags)"
44+
const SLOTFLAGS_MISMATCH = "length(slotnames) < length(slotflags)"
4545
const SSAVALUETYPES_MISMATCH = "not all SSAValues in AST have a type in ssavaluetypes"
4646
const SSAVALUETYPES_MISMATCH_UNINFERRED = "uninferred CodeInfo ssavaluetypes field does not equal the number of present SSAValues"
4747
const NON_TOP_LEVEL_METHOD = "encountered `Expr` head `:method` in non-top-level code (i.e. `nargs` > 0)"
@@ -168,7 +168,7 @@ function validate_code!(errors::Vector{>:InvalidCodeError}, c::CodeInfo, is_top_
168168
nslotflags = length(c.slotflags)
169169
nssavals = length(c.code)
170170
!is_top_level && nslotnames == 0 && push!(errors, InvalidCodeError(EMPTY_SLOTNAMES))
171-
nslotnames != nslotflags && push!(errors, InvalidCodeError(SLOTFLAGS_MISMATCH, (nslotnames, nslotflags)))
171+
nslotnames < nslotflags && push!(errors, InvalidCodeError(SLOTFLAGS_MISMATCH, (nslotnames, nslotflags)))
172172
if c.inferred
173173
nssavaluetypes = length(c.ssavaluetypes)
174174
nssavaluetypes < nssavals && push!(errors, InvalidCodeError(SSAVALUETYPES_MISMATCH, (nssavals, nssavaluetypes)))

base/methodshow.jl

Lines changed: 16 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,9 @@ function argtype_decl(env, n, sig::DataType, i::Int, nargs, isva::Bool) # -> (ar
4343
end
4444

4545
function method_argnames(m::Method)
46-
if !isdefined(m, :source) && isdefined(m, :generator)
47-
return m.generator.argnames
48-
end
49-
argnames = Vector{Any}(undef, m.nargs)
50-
ccall(:jl_fill_argnames, Cvoid, (Any, Any), m.source, argnames)
51-
return argnames
46+
argnames = ccall(:jl_uncompress_argnames, Vector{Any}, (Any,), m.slot_syms)
47+
isempty(argnames) && return argnames
48+
return argnames[1:m.nargs]
5249
end
5350

5451
function arg_decl_parts(m::Method)
@@ -60,8 +57,8 @@ function arg_decl_parts(m::Method)
6057
end
6158
file = m.file
6259
line = m.line
63-
if isdefined(m, :source) || isdefined(m, :generator)
64-
argnames = method_argnames(m)
60+
argnames = method_argnames(m)
61+
if length(argnames) >= m.nargs
6562
show_env = ImmutableDict{Symbol, Any}()
6663
for t in tv
6764
show_env = ImmutableDict(show_env, :unionall_env => t)
@@ -74,26 +71,23 @@ function arg_decl_parts(m::Method)
7471
return tv, decls, file, line
7572
end
7673

74+
const empty_sym = Symbol("")
75+
7776
function kwarg_decl(m::Method, kwtype::DataType)
7877
sig = rewrap_unionall(Tuple{kwtype, Any, unwrap_unionall(m.sig).parameters...}, m.sig)
7978
kwli = ccall(:jl_methtable_lookup, Any, (Any, Any, UInt), kwtype.name.mt, sig, max_world(m))
8079
if kwli !== nothing
8180
kwli = kwli::Method
82-
if isdefined(kwli, :source)
83-
src = kwli.source
84-
nslots = ccall(:jl_ast_nslots, Int, (Any,), src)
85-
slotnames = Vector{Any}(undef, nslots)
86-
ccall(:jl_fill_argnames, Cvoid, (Any, Any), src, slotnames)
87-
kws = filter(x -> !('#' in string(x)), slotnames[(kwli.nargs + 1):end])
88-
# ensure the kwarg... is always printed last. The order of the arguments are not
89-
# necessarily the same as defined in the function
90-
i = findfirst(x -> endswith(string(x), "..."), kws)
91-
if i !== nothing
92-
push!(kws, kws[i])
93-
deleteat!(kws, i)
94-
end
95-
return kws
81+
slotnames = ccall(:jl_uncompress_argnames, Vector{Any}, (Any,), kwli.slot_syms)
82+
kws = filter(x -> !(x === empty_sym || '#' in string(x)), slotnames[(kwli.nargs + 1):end])
83+
# ensure the kwarg... is always printed last. The order of the arguments are not
84+
# necessarily the same as defined in the function
85+
i = findfirst(x -> endswith(string(x), "..."), kws)
86+
if i !== nothing
87+
push!(kws, kws[i])
88+
deleteat!(kws, i)
9689
end
90+
return kws
9791
end
9892
return ()
9993
end

src/array.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,8 @@ JL_DLLEXPORT jl_value_t *jl_array_to_string(jl_array_t *a)
470470
JL_DLLEXPORT jl_value_t *jl_pchar_to_string(const char *str, size_t len)
471471
{
472472
size_t sz = sizeof(size_t) + len + 1; // add space for trailing \nul protector and size
473+
if (len == 0)
474+
return jl_an_empty_string;
473475
jl_value_t *s = jl_gc_alloc_(jl_get_ptls_states(), sz, jl_string_type); // force inlining
474476
*(size_t*)s = len;
475477
memcpy((char*)s + sizeof(size_t), str, len);
@@ -480,6 +482,8 @@ JL_DLLEXPORT jl_value_t *jl_pchar_to_string(const char *str, size_t len)
480482
JL_DLLEXPORT jl_value_t *jl_alloc_string(size_t len)
481483
{
482484
size_t sz = sizeof(size_t) + len + 1; // add space for trailing \nul protector and size
485+
if (len == 0)
486+
return jl_an_empty_string;
483487
jl_value_t *s = jl_gc_alloc_(jl_get_ptls_states(), sz, jl_string_type); // force inlining
484488
*(size_t*)s = len;
485489
((char*)s + sizeof(size_t))[len] = 0;

src/ast.c

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -50,17 +50,17 @@ jl_sym_t *dot_sym; jl_sym_t *newvar_sym;
5050
jl_sym_t *boundscheck_sym; jl_sym_t *inbounds_sym;
5151
jl_sym_t *copyast_sym; jl_sym_t *cfunction_sym;
5252
jl_sym_t *pure_sym; jl_sym_t *simdloop_sym;
53-
jl_sym_t *meta_sym; jl_sym_t *compiler_temp_sym;
54-
jl_sym_t *inert_sym; jl_sym_t *polly_sym;
55-
jl_sym_t *unused_sym; jl_sym_t *static_parameter_sym;
56-
jl_sym_t *inline_sym; jl_sym_t *noinline_sym;
57-
jl_sym_t *generated_sym; jl_sym_t *generated_only_sym;
58-
jl_sym_t *isdefined_sym; jl_sym_t *propagate_inbounds_sym;
59-
jl_sym_t *specialize_sym; jl_sym_t *nospecialize_sym;
60-
jl_sym_t *macrocall_sym; jl_sym_t *colon_sym;
61-
jl_sym_t *hygienicscope_sym; jl_sym_t *escape_sym;
62-
jl_sym_t *gc_preserve_begin_sym; jl_sym_t *gc_preserve_end_sym;
53+
jl_sym_t *meta_sym; jl_sym_t *inert_sym;
54+
jl_sym_t *polly_sym; jl_sym_t *unused_sym;
55+
jl_sym_t *static_parameter_sym; jl_sym_t *inline_sym;
56+
jl_sym_t *noinline_sym; jl_sym_t *generated_sym;
57+
jl_sym_t *generated_only_sym; jl_sym_t *isdefined_sym;
58+
jl_sym_t *propagate_inbounds_sym; jl_sym_t *specialize_sym;
59+
jl_sym_t *nospecialize_sym; jl_sym_t *macrocall_sym;
60+
jl_sym_t *colon_sym; jl_sym_t *hygienicscope_sym;
6361
jl_sym_t *throw_undef_if_not_sym; jl_sym_t *getfield_undefref_sym;
62+
jl_sym_t *gc_preserve_begin_sym; jl_sym_t *gc_preserve_end_sym;
63+
jl_sym_t *escape_sym;
6464

6565
static uint8_t flisp_system_image[] = {
6666
#include <julia_flisp.boot.inc>
@@ -347,7 +347,6 @@ void jl_init_frontend(void)
347347
unused_sym = jl_symbol("#unused#");
348348
slot_sym = jl_symbol("slot");
349349
static_parameter_sym = jl_symbol("static_parameter");
350-
compiler_temp_sym = jl_symbol("#temp#");
351350
inline_sym = jl_symbol("inline");
352351
noinline_sym = jl_symbol("noinline");
353352
polly_sym = jl_symbol("polly");

src/codegen.cpp

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3315,8 +3315,12 @@ static jl_cgval_t emit_sparam(jl_codectx_t &ctx, size_t i)
33153315
Value *sp = tbaa_decorate(tbaa_const, ctx.builder.CreateLoad(bp));
33163316
Value *isnull = ctx.builder.CreateICmpNE(emit_typeof(ctx, sp),
33173317
maybe_decay_untracked(literal_pointer_val(ctx, (jl_value_t*)jl_tvar_type)));
3318-
jl_sym_t *name = (jl_sym_t*)jl_svecref(ctx.linfo->def.method->sparam_syms, i);
3319-
undef_var_error_ifnot(ctx, isnull, name);
3318+
jl_unionall_t *sparam = (jl_unionall_t*)ctx.linfo->def.method->sig;
3319+
for (size_t j = 0; j < i; j++) {
3320+
sparam = (jl_unionall_t*)sparam->body;
3321+
assert(jl_is_unionall(sparam));
3322+
}
3323+
undef_var_error_ifnot(ctx, isnull, sparam->var->name);
33203324
return mark_julia_type(ctx, sp, true, jl_any_type);
33213325
}
33223326

@@ -5375,7 +5379,7 @@ static std::unique_ptr<Module> emit_function(
53755379

53765380
// step 2. process var-info lists to see what vars need boxing
53775381
int n_ssavalues = jl_is_long(src->ssavaluetypes) ? jl_unbox_long(src->ssavaluetypes) : jl_array_len(src->ssavaluetypes);
5378-
size_t vinfoslen = jl_array_dim0(src->slotnames);
5382+
size_t vinfoslen = jl_array_dim0(src->slotflags);
53795383
ctx.slots.resize(vinfoslen);
53805384
size_t nreq = ctx.nargs;
53815385
int va = 0;
@@ -5397,7 +5401,7 @@ static std::unique_ptr<Module> emit_function(
53975401

53985402
bool needsparams = false;
53995403
if (jl_is_method(lam->def.method)) {
5400-
if (jl_svec_len(lam->def.method->sparam_syms) != jl_svec_len(lam->sparam_vals))
5404+
if ((size_t)jl_subtype_env_size(lam->def.method->sig) != jl_svec_len(lam->sparam_vals))
54015405
needsparams = true;
54025406
for (size_t i = 0; i < jl_svec_len(lam->sparam_vals); ++i) {
54035407
if (jl_is_typevar(jl_svecref(lam->sparam_vals, i)))
@@ -5597,7 +5601,7 @@ static std::unique_ptr<Module> emit_function(
55975601
for (i = 0; i < vinfoslen; i++) {
55985602
jl_sym_t *s = (jl_sym_t*)jl_array_ptr_ref(src->slotnames, i);
55995603
jl_varinfo_t &varinfo = ctx.slots[i];
5600-
if (varinfo.isArgument || s == compiler_temp_sym || s == unused_sym)
5604+
if (varinfo.isArgument || s == empty_sym || s == unused_sym)
56015605
continue;
56025606
// LLVM 4.0: Assume the variable has default alignment
56035607
varinfo.dinfo = dbuilder.createAutoVariable(
@@ -6027,14 +6031,14 @@ static std::unique_ptr<Module> emit_function(
60276031
return;
60286032
while (dbg) {
60296033
new_lineinfo.push_back(dbg);
6030-
dbg = linetable[dbg].inlined_at;
6034+
dbg = linetable.at(dbg).inlined_at;
60316035
}
60326036
current_lineinfo.resize(new_lineinfo.size(), 0);
60336037
for (dbg = 0; dbg < new_lineinfo.size(); dbg++) {
60346038
unsigned newdbg = new_lineinfo[new_lineinfo.size() - dbg - 1];
60356039
if (newdbg != current_lineinfo[dbg]) {
60366040
current_lineinfo[dbg] = newdbg;
6037-
const auto &info = linetable[newdbg];
6041+
const auto &info = linetable.at(newdbg);
60386042
if (do_coverage(info.is_user_code))
60396043
coverageVisitLine(ctx, info.file, info.line);
60406044
}
@@ -6044,9 +6048,9 @@ static std::unique_ptr<Module> emit_function(
60446048
auto mallocVisitStmt = [&] (unsigned dbg) {
60456049
if (!do_malloc_log(mod_is_user_mod) || dbg == 0)
60466050
return;
6047-
while (linetable[dbg].inlined_at)
6048-
dbg = linetable[dbg].inlined_at;
6049-
mallocVisitLine(ctx, ctx.file, linetable[dbg].line);
6051+
while (linetable.at(dbg).inlined_at)
6052+
dbg = linetable.at(dbg).inlined_at;
6053+
mallocVisitLine(ctx, ctx.file, linetable.at(dbg).line);
60506054
};
60516055

60526056
come_from_bb[0] = ctx.builder.GetInsertBlock();
@@ -6111,7 +6115,7 @@ static std::unique_ptr<Module> emit_function(
61116115
int32_t debuginfoloc = ((int32_t*)jl_array_data(src->codelocs))[cursor];
61126116
if (debuginfoloc > 0) {
61136117
if (ctx.debug_enabled)
6114-
ctx.builder.SetCurrentDebugLocation(linetable[debuginfoloc].loc);
6118+
ctx.builder.SetCurrentDebugLocation(linetable.at(debuginfoloc).loc);
61156119
coverageVisitStmt(debuginfoloc);
61166120
}
61176121
jl_value_t *stmt = jl_array_ptr_ref(stmts, cursor);

0 commit comments

Comments
 (0)