Skip to content

Commit

Permalink
thread world counter through more of libjulia
Browse files Browse the repository at this point in the history
  • Loading branch information
vtjnash committed Jun 22, 2016
1 parent b61c3c2 commit 50a6216
Show file tree
Hide file tree
Showing 32 changed files with 350 additions and 218 deletions.
4 changes: 2 additions & 2 deletions base/REPL.jl
Original file line number Diff line number Diff line change
Expand Up @@ -131,9 +131,9 @@ function print_response(errio::IO, val::ANY, bt, show_value::Bool, have_color::B
if val !== nothing && show_value
try
if specialdisplay === nothing
display(val)
eval(Main, Expr(:call, () -> display(val)))
else
display(specialdisplay,val)
eval(Main, Expr(:call, () -> display(specialdisplay, val)))
end
catch err
println(errio, "Error showing value of type ", typeof(val), ":")
Expand Down
7 changes: 4 additions & 3 deletions base/client.jl
Original file line number Diff line number Diff line change
Expand Up @@ -114,13 +114,14 @@ function eval_user_input(ast::ANY, show_value)
errcount, lasterr = 0, ()
else
ast = expand(ast)
value = eval(Main,ast)
value = eval(Main, ast)
eval(Main, :(ans = $(Expr(:quote, value))))
if !is(value,nothing) && show_value
if !is(value, nothing) && show_value
if have_color
print(answer_color())
end
try display(value)
try
eval(Main, Expr(:call, () -> display(value)))
catch err
println(STDERR, "Evaluation succeeded, but an error occurred while showing value of type ", typeof(value), ":")
rethrow(err)
Expand Down
54 changes: 32 additions & 22 deletions base/inference.jl
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ type InferenceState

# info on the state of inference and the linfo
linfo::LambdaInfo
world::UInt
nargs::Int
stmt_types::Vector{Any}
# return type
Expand All @@ -75,7 +76,7 @@ type InferenceState
optimize::Bool
inferred::Bool

function InferenceState(linfo::LambdaInfo, optimize::Bool)
function InferenceState(linfo::LambdaInfo, world::UInt, optimize::Bool)
@assert isa(linfo.code,Array{Any,1})
nslots = length(linfo.slotnames)
nl = label_counter(linfo.code)+1
Expand Down Expand Up @@ -155,7 +156,7 @@ type InferenceState
inmodule = isdefined(linfo, :def) ? linfo.def.module : current_module() # toplevel thunks are inferred in the current module
frame = new(
sp, nl, Dict{SSAValue, Bool}(), inmodule, 0, false,
linfo, la, s, Union{}, W, n,
linfo, world, la, s, Union{}, W, n,
cur_hand, handler_at, n_handlers,
ssavalue_uses, ssavalue_init,
ObjectIdDict(), #Dict{InferenceState, Vector{LineNum}}(),
Expand Down Expand Up @@ -607,14 +608,14 @@ function invoke_tfunc(f::ANY, types::ANY, argtype::ANY, sv::InferenceState)
ft = type_typeof(f)
types = Tuple{ft, types.parameters...}
argtype = Tuple{ft, argtype.parameters...}
entry = ccall(:jl_gf_invoke_lookup, Any, (Any,), types)
entry = ccall(:jl_gf_invoke_lookup, Any, (Any, UInt), types, sv.world)
if is(entry, nothing)
return Any
end
meth = entry.func
(ti, env) = ccall(:jl_match_method, Any, (Any, Any, Any),
argtype, meth.sig, meth.tvars)::SimpleVector
return typeinf_edge(meth::Method, ti, env, sv)[2]
return typeinf_edge(meth::Method, ti, env, sv, sv.world)[2]
end

function tuple_tfunc(argtype::ANY)
Expand Down Expand Up @@ -842,7 +843,7 @@ function abstract_call_gf_by_type(f::ANY, argtype::ANY, sv)
end
end
#print(m,"\n")
(_tree, rt) = typeinf_edge(method, sig, m[2], sv)
(_tree, rt) = typeinf_edge(method, sig, m[2], sv, sv.world)
rettype = tmerge(rettype, rt)
if is(rettype,Any)
break
Expand Down Expand Up @@ -1384,9 +1385,9 @@ function newvar!(sv::InferenceState, typ)
end

# create a specialized LambdaInfo from a method
function specialize_method(method::Method, types::ANY, sp::SimpleVector, cached)
function specialize_method(method::Method, types::ANY, sp::SimpleVector, cached, world)
if cached
return ccall(:jl_specializations_get_linfo, Ref{LambdaInfo}, (Any, Any, Any), method, types, sp)
return ccall(:jl_specializations_get_linfo, Ref{LambdaInfo}, (Any, Any, Any, UInt), method, types, sp, world)
else
return ccall(:jl_get_specialized, Ref{LambdaInfo}, (Any, Any, Any), method, types, sp)
end
Expand All @@ -1408,16 +1409,24 @@ function unshare_linfo!(li::LambdaInfo)
end

#### entry points for inferring a LambdaInfo given a type signature ####
function typeinf_edge(method::Method, atypes::ANY, sparams::SimpleVector, needtree::Bool, optimize::Bool, cached::Bool, caller)
let _min_age = Symbol("min-age"), _max_age = Symbol("max-age")
global min_age(m::Method) = getfield(m, _min_age) % UInt
global max_age(m::Method) = getfield(m, _max_age) % UInt
end
function typeinf_edge(method::Method, atypes::ANY, sparams::SimpleVector, needtree::Bool, optimize::Bool, cached::Bool, caller, world::UInt)
local code = nothing
local frame = nothing
if world < min_age(method) || world > max_age(method)
ccall(:jl_breakpoint, Void, (Any,), (method, world))
return (nothing, Union{}, false)
end
if isa(caller, LambdaInfo)
code = caller
elseif cached
# check cached specializations
# for an existing result stored there
if !is(method.specializations, nothing)
code = ccall(:jl_specializations_lookup, Any, (Any, Any), method, atypes)
code = ccall(:jl_specializations_lookup, Any, (Any, Any, UInt), method, atypes, world)
if isa(code, Void)
# something completely new
elseif isa(code, LambdaInfo)
Expand Down Expand Up @@ -1479,12 +1488,12 @@ function typeinf_edge(method::Method, atypes::ANY, sparams::SimpleVector, needtr
end
try
# user code might throw errors – ignore them
linfo = specialize_method(method, atypes, sparams, cached)
linfo = specialize_method(method, atypes, sparams, cached, world)
catch
return (nothing, Any, false)
end
else
linfo = specialize_method(method, atypes, sparams, cached)
linfo = specialize_method(method, atypes, sparams, cached, world)
end

if linfo.inInference
Expand All @@ -1503,7 +1512,7 @@ function typeinf_edge(method::Method, atypes::ANY, sparams::SimpleVector, needtr
else
# inference not started yet, make a new frame for a new lambda
linfo.inInference = true
frame = InferenceState(unshare_linfo!(linfo::LambdaInfo), optimize)
frame = InferenceState(unshare_linfo!(linfo::LambdaInfo), world, optimize)
end
frame = frame::InferenceState

Expand All @@ -1527,24 +1536,25 @@ function typeinf_edge(method::Method, atypes::ANY, sparams::SimpleVector, needtr
return (frame.linfo, frame.bestguess, frame.inferred)
end

function typeinf_edge(method::Method, atypes::ANY, sparams::SimpleVector, caller)
return typeinf_edge(method, atypes, sparams, false, true, true, caller)
world_counter() = ccall(:jl_get_world_counter, UInt, ())
function typeinf_edge(method::Method, atypes::ANY, sparams::SimpleVector, caller::InferenceState, world::UInt)
return typeinf_edge(method, atypes, sparams, false, true, true, caller, world)
end
function typeinf(method::Method, atypes::ANY, sparams::SimpleVector, needtree::Bool=false)
return typeinf_edge(method, atypes, sparams, needtree, true, true, nothing)
return typeinf_edge(method, atypes, sparams, needtree, true, true, nothing, world_counter())
end
# compute an inferred (optionally optimized) AST without global effects (i.e. updating the cache)
function typeinf_uncached(method::Method, atypes::ANY, sparams::ANY; optimize::Bool=true)
return typeinf_edge(method, atypes, sparams, true, optimize, false, nothing)
return typeinf_edge(method, atypes, sparams, true, optimize, false, nothing, world_counter())
end
function typeinf_uncached(method::Method, atypes::ANY, sparams::SimpleVector, optimize::Bool)
return typeinf_edge(method, atypes, sparams, true, optimize, false, nothing)
return typeinf_edge(method, atypes, sparams, true, optimize, false, nothing, world_counter())
end
function typeinf_ext(linfo::LambdaInfo)
function typeinf_ext(linfo::LambdaInfo, world::UInt)
if isdefined(linfo, :def)
# method lambda - infer this specialization via the method cache
(code, _t, _) = typeinf_edge(linfo.def, linfo.specTypes, linfo.sparam_vals, true, true, true, linfo)
if code.inferred && linfo !== code
(code, _t, inferred) = typeinf_edge(linfo.def, linfo.specTypes, linfo.sparam_vals, true, true, true, linfo, world)
if inferred && code.inferred && linfo !== code
# This case occurs when the IR for a function has been deleted.
# `code` will be a newly-created LambdaInfo, and we need to copy its
# contents to the existing one to copy the info to the method cache.
Expand All @@ -1564,7 +1574,7 @@ function typeinf_ext(linfo::LambdaInfo)
else
# toplevel lambda - infer directly
linfo.inInference = true
frame = InferenceState(linfo, true)
frame = InferenceState(linfo, world, true)
typeinf_loop(frame)
@assert frame.inferred # TODO: deal with this better
return linfo
Expand Down Expand Up @@ -2342,7 +2352,7 @@ function inlineable(f::ANY, ft::ANY, e::Expr, atypes::Vector{Any}, sv::Inference
end
function invoke_NF()
# converts a :call to :invoke
cache_linfo = ccall(:jl_get_spec_lambda, Any, (Any,), atype_unlimited)
cache_linfo = ccall(:jl_get_spec_lambda, Any, (Any, UInt), atype_unlimited, sv.world)
if cache_linfo !== nothing
e.head = :invoke
unshift!(e.args, cache_linfo)
Expand Down
10 changes: 5 additions & 5 deletions base/methodshow.jl
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,9 @@ function arg_decl_parts(m::Method)
return tv, decls, file, line
end

function kwarg_decl(sig::ANY, kwtype::DataType)
sig = Tuple{kwtype, Core.AnyVector, sig.parameters...}
kwli = ccall(:jl_methtable_lookup, Any, (Any, Any), kwtype.name.mt, sig)
function kwarg_decl(m::Method, kwtype::DataType)
sig = Tuple{kwtype, Core.AnyVector, m.sig.parameters...}
kwli = ccall(:jl_methtable_lookup, Any, (Any, Any, UInt), kwtype.name.mt, sig, getfield(m, Symbol("max-age")) % UInt)
if kwli !== nothing
kwli = kwli::Method
return filter(x->!('#' in string(x)), kwli.lambda_template.slotnames[kwli.lambda_template.nargs+1:end])
Expand Down Expand Up @@ -108,7 +108,7 @@ function show(io::IO, m::Method; kwtype::Nullable{DataType}=Nullable{DataType}()
join(io, [isempty(d[2]) ? d[1] : d[1]*"::"*d[2] for d in decls[2:end]],
", ", ", ")
if !isnull(kwtype)
kwargs = kwarg_decl(m.sig, get(kwtype))
kwargs = kwarg_decl(m, get(kwtype))
if !isempty(kwargs)
print(io, "; ")
join(io, kwargs, ", ", ", ")
Expand Down Expand Up @@ -231,7 +231,7 @@ function show(io::IO, ::MIME"text/html", m::Method; kwtype::Nullable{DataType}=N
join(io, [isempty(d[2]) ? d[1] : d[1]*"::<b>"*d[2]*"</b>"
for d in decls[2:end]], ", ", ", ")
if !isnull(kwtype)
kwargs = kwarg_decl(m.sig, get(kwtype))
kwargs = kwarg_decl(m, get(kwtype))
if !isempty(kwargs)
print(io, "; <i>")
join(io, kwargs, ", ", ", ")
Expand Down
4 changes: 2 additions & 2 deletions base/multi.jl
Original file line number Diff line number Diff line change
Expand Up @@ -610,7 +610,7 @@ function lookup_ref(pg, rrid, f)
rv = get(pg.refs, rrid, false)
if rv === false
# first we've heard of this ref
rv = RemoteValue(f())
rv = RemoteValue(eval(Main, Expr(:call, f)))
pg.refs[rrid] = rv
push!(rv.clientset, rrid.whence)
end
Expand Down Expand Up @@ -778,7 +778,7 @@ function run_work_thunk(thunk, print_error)
result = RemoteException(ce)
print_error && showerror(STDERR, ce)
end
result
return result
end
function run_work_thunk(rv::RemoteValue, thunk)
put!(rv, run_work_thunk(thunk, false))
Expand Down
3 changes: 2 additions & 1 deletion base/multidimensional.jl
Original file line number Diff line number Diff line change
Expand Up @@ -784,9 +784,10 @@ the order that the first of each set of equivalent elements originally appears.
If `dim` is specified, returns unique regions of the array `itr` along `dim`.
"""
@generated function unique{T,N}(A::AbstractArray{T,N}, dim::Int)
inds = inds -> zeros(UInt, inds)
quote
1 <= dim <= $N || return copy(A)
hashes = allocate_for(inds->zeros(UInt, inds), A, shape(A, dim))
hashes = allocate_for($inds, A, shape(A, dim))

# Compute hash for each row
k = 0
Expand Down
5 changes: 3 additions & 2 deletions base/reflection.jl
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,7 @@ function which(f::ANY, t::ANY)
return first(ms)
else
ft = isa(f,Type) ? Type{f} : typeof(f)
m = ccall(:jl_gf_invoke_lookup, Any, (Any,), Tuple{ft, t.parameters...})
m = ccall(:jl_gf_invoke_lookup, Any, (Any, UInt), Tuple{ft, t.parameters...}, typemax(UInt))
if m === nothing
error("no method found for the specified argument types")
end
Expand Down Expand Up @@ -439,7 +439,8 @@ end
function method_exists(f::ANY, t::ANY)
t = to_tuple_type(t)
t = Tuple{isa(f,Type) ? Type{f} : typeof(f), t.parameters...}
return ccall(:jl_method_exists, Cint, (Any, Any), typeof(f).name.mt, t) != 0
return ccall(:jl_method_exists, Cint, (Any, Any, UInt), typeof(f).name.mt, t,
ccall(:jl_get_world_counter, Int32, ())) != 0
end

function isambiguous(m1::Method, m2::Method)
Expand Down
4 changes: 2 additions & 2 deletions base/sparse/sparsematrix.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1387,8 +1387,8 @@ for (Bsig, A1sig, A2sig, gbb, funcname) in
global $funcname
function $funcname(f::Function, B::$Bsig, A1::$A1sig, A2::$A2sig)
func = @get! cache f gen_broadcast_function_sparse($gbb, f, ($A1sig) <: SparseMatrixCSC)
func(B, A1, A2)
B
eval(Expr(:call, () -> func(B, A1, A2))) # need eval because func was just created by gen_broadcast_function_sparse
return B
end
end # let broadcast_cache
end
Expand Down
6 changes: 5 additions & 1 deletion src/alloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -407,7 +407,7 @@ STATIC_INLINE jl_value_t *jl_call_staged(jl_svec_t *sparam_vals, jl_lambda_info_
jl_value_t **args, uint32_t nargs)
{
if (__unlikely(meth->fptr == NULL)) {
jl_compile_linfo(meth);
jl_compile_linfo(meth, meth->def->min_world);
jl_generate_fptr(meth);
}
assert(jl_svec_len(meth->sparam_syms) == jl_svec_len(sparam_vals));
Expand Down Expand Up @@ -448,6 +448,7 @@ static jl_lambda_info_t *jl_instantiate_staged(jl_method_t *generator, jl_tuplet
// invoke code generator
assert(jl_nparams(tt) == jl_array_len(argnames) ||
(func->isva && (jl_nparams(tt) >= jl_array_len(argnames) - 1)));
// TODO: set world to that of the generator while calling func
jl_array_ptr_set(body->args, 1,
jl_call_staged(sparam_vals, func, jl_svec_data(tt->parameters), jl_nparams(tt)));

Expand Down Expand Up @@ -582,6 +583,8 @@ JL_DLLEXPORT jl_method_t *jl_new_method_uninit(void)
m->isstaged = 0;
m->needs_sparam_vals_ducttape = 2;
m->traced = 0;
m->min_world = 1;
m->max_world = ~(size_t)0;
return m;
}

Expand All @@ -608,6 +611,7 @@ jl_method_t *jl_new_method(jl_lambda_info_t *definition, jl_sym_t *name, jl_tupl
jl_gc_wb(m, definition);
definition->def = m;
jl_gc_wb(definition, m);
m->min_world = ++jl_world_counter;

if (reused) {
m->file = oldm->file;
Expand Down
2 changes: 1 addition & 1 deletion src/anticodegen.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ int32_t jl_get_llvm_gv(jl_value_t *p) UNAVAILABLE
void jl_write_malloc_log(void) UNAVAILABLE
void jl_write_coverage_data(void) UNAVAILABLE
void jl_generate_fptr(jl_lambda_info_t *li) UNAVAILABLE
void jl_compile_linfo(jl_lambda_info_t *li, void *cyclectx) UNAVAILABLE
void jl_compile_linfo(jl_lambda_info_t *li, size_t world) UNAVAILABLE

JL_DLLEXPORT void jl_clear_malloc_data(void) UNAVAILABLE
JL_DLLEXPORT void jl_extern_c(jl_function_t *f, jl_value_t *rt, jl_value_t *argt, char *name) UNAVAILABLE
Expand Down
3 changes: 2 additions & 1 deletion src/ast.c
Original file line number Diff line number Diff line change
Expand Up @@ -143,11 +143,12 @@ value_t fl_invoke_julia_macro(fl_context_t *fl_ctx, value_t *args, uint32_t narg
int i;
for(i=1; i < nargs; i++) margs[i] = scm_to_julia(fl_ctx, args[i], 1);
jl_value_t *result = NULL;
size_t world = jl_get_ptls_states()->world_age;

JL_TRY {
margs[0] = scm_to_julia(fl_ctx, args[0], 1);
margs[0] = jl_toplevel_eval(margs[0]);
mfunc = jl_method_lookup(jl_gf_mtable(margs[0]), margs, nargs, 1);
mfunc = jl_method_lookup(jl_gf_mtable(margs[0]), margs, nargs, 1, world);
if (mfunc == NULL) {
JL_GC_POP();
jl_method_error((jl_function_t*)margs[0], margs, nargs);
Expand Down
5 changes: 3 additions & 2 deletions src/builtins.c
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ JL_DLLEXPORT void jl_enter_handler(jl_handler_t *eh)
#endif
eh->defer_signal = ptls->defer_signal;
eh->finalizers_inhibited = ptls->finalizers_inhibited;
eh->world_age = ptls->world_age;
current_task->eh = eh;
}

Expand Down Expand Up @@ -574,7 +575,6 @@ jl_value_t *jl_toplevel_eval_in_warn(jl_module_t *m, jl_value_t *ex, int delay_w
v = jl_toplevel_eval(ex);
}
JL_CATCH {
ptls->world_age = last_age;
ptls->current_module = last_m;
ptls->current_task->current_module = task_last_m;
jl_warn_on_eval = last_delay_warn;
Expand Down Expand Up @@ -966,7 +966,8 @@ static void jl_check_type_tuple(jl_value_t *t, jl_sym_t *name, const char *ctx)
JL_CALLABLE(jl_f_applicable)
{
JL_NARGSV(applicable, 1);
return jl_method_lookup(jl_gf_mtable(args[0]), args, nargs, 1) != NULL ?
size_t world = jl_get_ptls_states()->world_age;
return jl_method_lookup(jl_gf_mtable(args[0]), args, nargs, 1, world) != NULL ?
jl_true : jl_false;
}

Expand Down
3 changes: 3 additions & 0 deletions src/ccall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -408,7 +408,10 @@ static jl_value_t* try_eval(jl_value_t *ex, jl_codectx_t *ctx, const char *failu
if (constant || jl_is_ssavalue(ex))
return constant;
JL_TRY {
size_t last_age = jl_get_ptls_states()->world_age;
jl_get_ptls_states()->world_age = ctx->world;
constant = jl_interpret_toplevel_expr_in(ctx->module, ex, ctx->linfo);
jl_get_ptls_states()->world_age = last_age;
}
JL_CATCH {
if (compiletime)
Expand Down
Loading

0 comments on commit 50a6216

Please sign in to comment.