Skip to content

Commit

Permalink
internals: share slotnames table via Method
Browse files Browse the repository at this point in the history
Also store a few other unnecessary properties in CodeInfo,
which some users might be interested in having.
  • Loading branch information
vtjnash committed Feb 13, 2019
1 parent 3bb8404 commit c8510e3
Show file tree
Hide file tree
Showing 22 changed files with 283 additions and 203 deletions.
4 changes: 2 additions & 2 deletions base/compiler/inferencestate.jl
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ mutable struct InferenceState
s_types = Any[ nothing for i = 1:n ]

# initial types
nslots = length(src.slotnames)
nslots = length(src.slotflags)
argtypes = result.argtypes
nargs = length(argtypes)
s_argtypes = VarTable(undef, nslots)
Expand Down Expand Up @@ -122,7 +122,7 @@ end

function sptypes_from_meth_instance(linfo::MethodInstance)
toplevel = !isa(linfo.def, Method)
if !toplevel && isempty(linfo.sparam_vals) && !isempty(linfo.def.sparam_syms)
if !toplevel && isempty(linfo.sparam_vals) && isa(linfo.def.sig, UnionAll)
# linfo is unspecialized
sp = Any[]
sig = linfo.def.sig
Expand Down
9 changes: 6 additions & 3 deletions base/compiler/optimize.jl
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,11 @@ mutable struct OptimizationState
if nssavalues isa Int
src.ssavaluetypes = Any[ Any for i = 1:nssavalues ]
end
nslots = length(src.slotnames)
slottypes = Any[ Any for i = 1:nslots ]
nslots = length(src.slotflags)
slottypes = src.slottypes
if slottypes === nothing
slottypes = Any[ Any for i = 1:nslots ]
end
s_edges = []
# cache some useful state computations
toplevel = !isa(linfo.def, Method)
Expand Down Expand Up @@ -73,7 +76,7 @@ end
# This is implied by `SLOT_USEDUNDEF`.
# If this is not set, all the uses are (statically) dominated by the defs.
# In particular, if a slot has `AssignedOnce && !StaticUndef`, it is an SSA.
const SLOT_STATICUNDEF = 1
const SLOT_STATICUNDEF = 1 # slot might be used before it is defined (structurally)
const SLOT_ASSIGNEDONCE = 16 # slot is assigned to only once
const SLOT_USEDUNDEF = 32 # slot has uses that might raise UndefVarError
# const SLOT_CALLED = 64
Expand Down
7 changes: 4 additions & 3 deletions base/compiler/ssair/legacy.jl
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
# This file is a part of Julia. License is MIT: https://julialang.org/license

inflate_ir(ci::CodeInfo) = inflate_ir(ci, Any[], Any[ Any for i = 1:length(ci.slotnames) ])

function inflate_ir(ci::CodeInfo, linfo::MethodInstance)
sptypes = sptypes_from_meth_instance(linfo)
if ci.inferred
argtypes, _ = matching_cache_argtypes(linfo, nothing)
else
argtypes = Any[ Any for i = 1:length(ci.slotnames) ]
argtypes = Any[ Any for i = 1:length(ci.slotflags) ]
end
return inflate_ir(ci, sptypes, argtypes)
end
Expand Down Expand Up @@ -92,3 +90,6 @@ function replace_code_newstyle!(ci::CodeInfo, ir::IRCode, nargs::Int)
end
end
end

# used by some tests
inflate_ir(ci::CodeInfo) = inflate_ir(ci, Any[], Any[ Any for i = 1:length(ci.slotflags) ])
4 changes: 2 additions & 2 deletions base/compiler/ssair/slot2ssa.jl
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ end

@inline slot_id(s) = isa(s, SlotNumber) ? (s::SlotNumber).id : (s::TypedSlot).id
function scan_slot_def_use(nargs::Int, ci::CodeInfo, code::Vector{Any})
nslots = length(ci.slotnames)
nslots = length(ci.slotflags)
result = SlotInfo[SlotInfo() for i = 1:nslots]
# Set defs for arguments
for var in result[1:(1+nargs)]
Expand Down Expand Up @@ -654,7 +654,7 @@ function construct_ssa!(ci::CodeInfo, code::Vector{Any}, ir::IRCode, domtree::Do
undef_token
else
SSAValue(-1)
end for x in 1:length(ci.slotnames)
end for x in 1:length(ci.slotflags)
]
worklist = Tuple{Int, Int, Vector{Any}}[(1, 0, initial_incoming_vals)]
visited = BitSet()
Expand Down
24 changes: 16 additions & 8 deletions base/compiler/typeinfer.jl
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,12 @@ function typeinf(frame::InferenceState)
end
end
end
end
for caller in frames
caller.src.min_world = min_valid % Int
caller.src.max_world = max_valid % Int
if cached
for caller in results
cache_result(caller, min_valid, max_valid)
end
cache_result(caller.result, min_valid, max_valid)
end
end
# if we aren't cached, we don't need this edge
Expand Down Expand Up @@ -308,6 +310,8 @@ function type_annotate!(sv::InferenceState)
# compute the required type for each slot
# to hold all of the items assigned into it
record_slot_assign!(sv)
sv.src.slottypes = sv.slottypes
sv.src.rettype = sv.bestguess

# annotate variables load types
# remove dead code optimization
Expand Down Expand Up @@ -544,16 +548,20 @@ function typeinf_ext(linfo::MethodInstance, params::Params)
if invoke_api(linfo) == 2
tree = ccall(:jl_new_code_info_uninit, Ref{CodeInfo}, ())
tree.code = Any[ Expr(:return, quoted(linfo.inferred_const)) ]
tree.method_for_inference_limit_heuristics = nothing
tree.slotnames = Any[ COMPILER_TEMP_SYM for i = 1:method.nargs ]
tree.slotflags = fill(0x00, Int(method.nargs))
tree.ssavaluetypes = 0
nargs = Int(method.nargs)
tree.slotnames = ccall(:jl_uncompress_argnames, Any, (Any,), method.slot_syms)
tree.slotflags = fill(0x00, nargs)
tree.ssavaluetypes = 1
tree.codelocs = Int32[1]
tree.linetable = [LineInfoNode(method.module, method.name, method.file, Int(method.line), 0)]
tree.inferred = true
tree.ssaflags = UInt8[]
tree.ssaflags = UInt8[0]
tree.pure = true
tree.inlineable = true
tree.parent = linfo
tree.rettype = typeof(linfo.inferred_const)
tree.min_world = li.min_world
tree.max_world = li.max_world
i == 2 && ccall(:jl_typeinf_end, Cvoid, ())
return svec(linfo, tree)
elseif isa(inf, CodeInfo)
Expand Down
12 changes: 8 additions & 4 deletions base/compiler/utilities.jl
Original file line number Diff line number Diff line change
Expand Up @@ -96,19 +96,23 @@ end

function retrieve_code_info(linfo::MethodInstance)
m = linfo.def::Method
c = nothing
if isdefined(m, :generator)
# user code might throw errors – ignore them
return get_staged(linfo)
else
# TODO: post-inference see if we can swap back to the original arrays?
c = get_staged(linfo)
end
if c === nothing && isdefined(m, :source)
src = m.source
if isa(src, Array{UInt8,1})
c = ccall(:jl_uncompress_ast, Any, (Any, Any), m, src)
else
c = copy(src::CodeInfo)
end
end
return c::CodeInfo
if c isa CodeInfo
c.parent = linfo
return c
end
end

function code_for_method(method::Method, @nospecialize(atypes), sparams::SimpleVector, world::UInt, preexisting::Bool=false)
Expand Down
4 changes: 2 additions & 2 deletions base/compiler/validation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ const INVALID_RVALUE = "invalid RHS value"
const INVALID_RETURN = "invalid argument to :return"
const INVALID_CALL_ARG = "invalid :call argument"
const EMPTY_SLOTNAMES = "slotnames field is empty"
const SLOTFLAGS_MISMATCH = "length(slotnames) != length(slotflags)"
const SLOTFLAGS_MISMATCH = "length(slotnames) < length(slotflags)"
const SSAVALUETYPES_MISMATCH = "not all SSAValues in AST have a type in ssavaluetypes"
const SSAVALUETYPES_MISMATCH_UNINFERRED = "uninferred CodeInfo ssavaluetypes field does not equal the number of present SSAValues"
const NON_TOP_LEVEL_METHOD = "encountered `Expr` head `:method` in non-top-level code (i.e. `nargs` > 0)"
Expand Down Expand Up @@ -168,7 +168,7 @@ function validate_code!(errors::Vector{>:InvalidCodeError}, c::CodeInfo, is_top_
nslotflags = length(c.slotflags)
nssavals = length(c.code)
!is_top_level && nslotnames == 0 && push!(errors, InvalidCodeError(EMPTY_SLOTNAMES))
nslotnames != nslotflags && push!(errors, InvalidCodeError(SLOTFLAGS_MISMATCH, (nslotnames, nslotflags)))
nslotnames < nslotflags && push!(errors, InvalidCodeError(SLOTFLAGS_MISMATCH, (nslotnames, nslotflags)))
if c.inferred
nssavaluetypes = length(c.ssavaluetypes)
nssavaluetypes < nssavals && push!(errors, InvalidCodeError(SSAVALUETYPES_MISMATCH, (nssavals, nssavaluetypes)))
Expand Down
38 changes: 16 additions & 22 deletions base/methodshow.jl
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,9 @@ function argtype_decl(env, n, sig::DataType, i::Int, nargs, isva::Bool) # -> (ar
end

function method_argnames(m::Method)
if !isdefined(m, :source) && isdefined(m, :generator)
return m.generator.argnames
end
argnames = Vector{Any}(undef, m.nargs)
ccall(:jl_fill_argnames, Cvoid, (Any, Any), m.source, argnames)
return argnames
argnames = ccall(:jl_uncompress_argnames, Vector{Any}, (Any,), m.slot_syms)
isempty(argnames) && return argnames
return argnames[1:m.nargs]
end

function arg_decl_parts(m::Method)
Expand All @@ -60,8 +57,8 @@ function arg_decl_parts(m::Method)
end
file = m.file
line = m.line
if isdefined(m, :source) || isdefined(m, :generator)
argnames = method_argnames(m)
argnames = method_argnames(m)
if length(argnames) >= m.nargs
show_env = ImmutableDict{Symbol, Any}()
for t in tv
show_env = ImmutableDict(show_env, :unionall_env => t)
Expand All @@ -74,26 +71,23 @@ function arg_decl_parts(m::Method)
return tv, decls, file, line
end

const empty_sym = Symbol("")

function kwarg_decl(m::Method, kwtype::DataType)
sig = rewrap_unionall(Tuple{kwtype, Any, unwrap_unionall(m.sig).parameters...}, m.sig)
kwli = ccall(:jl_methtable_lookup, Any, (Any, Any, UInt), kwtype.name.mt, sig, max_world(m))
if kwli !== nothing
kwli = kwli::Method
if isdefined(kwli, :source)
src = kwli.source
nslots = ccall(:jl_ast_nslots, Int, (Any,), src)
slotnames = Vector{Any}(undef, nslots)
ccall(:jl_fill_argnames, Cvoid, (Any, Any), src, slotnames)
kws = filter(x -> !('#' in string(x)), slotnames[(kwli.nargs + 1):end])
# ensure the kwarg... is always printed last. The order of the arguments are not
# necessarily the same as defined in the function
i = findfirst(x -> endswith(string(x), "..."), kws)
if i !== nothing
push!(kws, kws[i])
deleteat!(kws, i)
end
return kws
slotnames = ccall(:jl_uncompress_argnames, Vector{Any}, (Any,), kwli.slot_syms)
kws = filter(x -> !(x === empty_sym || '#' in string(x)), slotnames[(kwli.nargs + 1):end])
# ensure the kwarg... is always printed last. The order of the arguments are not
# necessarily the same as defined in the function
i = findfirst(x -> endswith(string(x), "..."), kws)
if i !== nothing
push!(kws, kws[i])
deleteat!(kws, i)
end
return kws
end
return ()
end
Expand Down
4 changes: 4 additions & 0 deletions src/array.c
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,8 @@ JL_DLLEXPORT jl_value_t *jl_array_to_string(jl_array_t *a)
JL_DLLEXPORT jl_value_t *jl_pchar_to_string(const char *str, size_t len)
{
size_t sz = sizeof(size_t) + len + 1; // add space for trailing \nul protector and size
if (len == 0)
return jl_an_empty_string;
jl_value_t *s = jl_gc_alloc_(jl_get_ptls_states(), sz, jl_string_type); // force inlining
*(size_t*)s = len;
memcpy((char*)s + sizeof(size_t), str, len);
Expand All @@ -480,6 +482,8 @@ JL_DLLEXPORT jl_value_t *jl_pchar_to_string(const char *str, size_t len)
JL_DLLEXPORT jl_value_t *jl_alloc_string(size_t len)
{
size_t sz = sizeof(size_t) + len + 1; // add space for trailing \nul protector and size
if (len == 0)
return jl_an_empty_string;
jl_value_t *s = jl_gc_alloc_(jl_get_ptls_states(), sz, jl_string_type); // force inlining
*(size_t*)s = len;
((char*)s + sizeof(size_t))[len] = 0;
Expand Down
21 changes: 10 additions & 11 deletions src/ast.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,17 +50,17 @@ jl_sym_t *dot_sym; jl_sym_t *newvar_sym;
jl_sym_t *boundscheck_sym; jl_sym_t *inbounds_sym;
jl_sym_t *copyast_sym; jl_sym_t *cfunction_sym;
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 *polly_sym;
jl_sym_t *unused_sym; jl_sym_t *static_parameter_sym;
jl_sym_t *inline_sym; jl_sym_t *noinline_sym;
jl_sym_t *generated_sym; jl_sym_t *generated_only_sym;
jl_sym_t *isdefined_sym; jl_sym_t *propagate_inbounds_sym;
jl_sym_t *specialize_sym; jl_sym_t *nospecialize_sym;
jl_sym_t *macrocall_sym; jl_sym_t *colon_sym;
jl_sym_t *hygienicscope_sym; jl_sym_t *escape_sym;
jl_sym_t *gc_preserve_begin_sym; jl_sym_t *gc_preserve_end_sym;
jl_sym_t *meta_sym; jl_sym_t *inert_sym;
jl_sym_t *polly_sym; jl_sym_t *unused_sym;
jl_sym_t *static_parameter_sym; jl_sym_t *inline_sym;
jl_sym_t *noinline_sym; jl_sym_t *generated_sym;
jl_sym_t *generated_only_sym; jl_sym_t *isdefined_sym;
jl_sym_t *propagate_inbounds_sym; jl_sym_t *specialize_sym;
jl_sym_t *nospecialize_sym; jl_sym_t *macrocall_sym;
jl_sym_t *colon_sym; jl_sym_t *hygienicscope_sym;
jl_sym_t *throw_undef_if_not_sym; jl_sym_t *getfield_undefref_sym;
jl_sym_t *gc_preserve_begin_sym; jl_sym_t *gc_preserve_end_sym;
jl_sym_t *escape_sym;

static uint8_t flisp_system_image[] = {
#include <julia_flisp.boot.inc>
Expand Down Expand Up @@ -347,7 +347,6 @@ void jl_init_frontend(void)
unused_sym = jl_symbol("#unused#");
slot_sym = jl_symbol("slot");
static_parameter_sym = jl_symbol("static_parameter");
compiler_temp_sym = jl_symbol("#temp#");
inline_sym = jl_symbol("inline");
noinline_sym = jl_symbol("noinline");
polly_sym = jl_symbol("polly");
Expand Down
26 changes: 15 additions & 11 deletions src/codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3315,8 +3315,12 @@ static jl_cgval_t emit_sparam(jl_codectx_t &ctx, size_t i)
Value *sp = tbaa_decorate(tbaa_const, ctx.builder.CreateLoad(bp));
Value *isnull = ctx.builder.CreateICmpNE(emit_typeof(ctx, sp),
maybe_decay_untracked(literal_pointer_val(ctx, (jl_value_t*)jl_tvar_type)));
jl_sym_t *name = (jl_sym_t*)jl_svecref(ctx.linfo->def.method->sparam_syms, i);
undef_var_error_ifnot(ctx, isnull, name);
jl_unionall_t *sparam = (jl_unionall_t*)ctx.linfo->def.method->sig;
for (size_t j = 0; j < i; j++) {
sparam = (jl_unionall_t*)sparam->body;
assert(jl_is_unionall(sparam));
}
undef_var_error_ifnot(ctx, isnull, sparam->var->name);
return mark_julia_type(ctx, sp, true, jl_any_type);
}

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

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

bool needsparams = false;
if (jl_is_method(lam->def.method)) {
if (jl_svec_len(lam->def.method->sparam_syms) != jl_svec_len(lam->sparam_vals))
if ((size_t)jl_subtype_env_size(lam->def.method->sig) != jl_svec_len(lam->sparam_vals))
needsparams = true;
for (size_t i = 0; i < jl_svec_len(lam->sparam_vals); ++i) {
if (jl_is_typevar(jl_svecref(lam->sparam_vals, i)))
Expand Down Expand Up @@ -5597,7 +5601,7 @@ static std::unique_ptr<Module> emit_function(
for (i = 0; i < vinfoslen; i++) {
jl_sym_t *s = (jl_sym_t*)jl_array_ptr_ref(src->slotnames, i);
jl_varinfo_t &varinfo = ctx.slots[i];
if (varinfo.isArgument || s == compiler_temp_sym || s == unused_sym)
if (varinfo.isArgument || s == empty_sym || s == unused_sym)
continue;
// LLVM 4.0: Assume the variable has default alignment
varinfo.dinfo = dbuilder.createAutoVariable(
Expand Down Expand Up @@ -6027,14 +6031,14 @@ static std::unique_ptr<Module> emit_function(
return;
while (dbg) {
new_lineinfo.push_back(dbg);
dbg = linetable[dbg].inlined_at;
dbg = linetable.at(dbg).inlined_at;
}
current_lineinfo.resize(new_lineinfo.size(), 0);
for (dbg = 0; dbg < new_lineinfo.size(); dbg++) {
unsigned newdbg = new_lineinfo[new_lineinfo.size() - dbg - 1];
if (newdbg != current_lineinfo[dbg]) {
current_lineinfo[dbg] = newdbg;
const auto &info = linetable[newdbg];
const auto &info = linetable.at(newdbg);
if (do_coverage(info.is_user_code))
coverageVisitLine(ctx, info.file, info.line);
}
Expand All @@ -6044,9 +6048,9 @@ static std::unique_ptr<Module> emit_function(
auto mallocVisitStmt = [&] (unsigned dbg) {
if (!do_malloc_log(mod_is_user_mod) || dbg == 0)
return;
while (linetable[dbg].inlined_at)
dbg = linetable[dbg].inlined_at;
mallocVisitLine(ctx, ctx.file, linetable[dbg].line);
while (linetable.at(dbg).inlined_at)
dbg = linetable.at(dbg).inlined_at;
mallocVisitLine(ctx, ctx.file, linetable.at(dbg).line);
};

come_from_bb[0] = ctx.builder.GetInsertBlock();
Expand Down Expand Up @@ -6111,7 +6115,7 @@ static std::unique_ptr<Module> emit_function(
int32_t debuginfoloc = ((int32_t*)jl_array_data(src->codelocs))[cursor];
if (debuginfoloc > 0) {
if (ctx.debug_enabled)
ctx.builder.SetCurrentDebugLocation(linetable[debuginfoloc].loc);
ctx.builder.SetCurrentDebugLocation(linetable.at(debuginfoloc).loc);
coverageVisitStmt(debuginfoloc);
}
jl_value_t *stmt = jl_array_ptr_ref(stmts, cursor);
Expand Down
Loading

0 comments on commit c8510e3

Please sign in to comment.