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 Sep 14, 2016
1 parent 6111fb8 commit 7b0803c
Show file tree
Hide file tree
Showing 31 changed files with 354 additions and 253 deletions.
4 changes: 2 additions & 2 deletions base/REPL.jl
Original file line number Diff line number Diff line change
Expand Up @@ -153,9 +153,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
5 changes: 3 additions & 2 deletions base/client.jl
Original file line number Diff line number Diff line change
Expand Up @@ -116,11 +116,12 @@ function eval_user_input(ast::ANY, show_value)
ast = expand(ast)
value = eval(Main, ast)
eval(Main, Expr(:(=), :ans, Expr(:call, ()->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
53 changes: 32 additions & 21 deletions base/inference.jl
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ type InferenceState
# info on the state of inference and the linfo
linfo::MethodInstance # used here for the tuple (specTypes, env, Method)
src::CodeInfo
world::UInt
nargs::Int
stmt_types::Vector{Any}
# return type
Expand Down Expand Up @@ -79,7 +80,7 @@ type InferenceState
inferred::Bool

# src is assumed to be a newly-allocated CodeInfo, that can be modified in-place to contain intermediate results
function InferenceState(linfo::MethodInstance, src::CodeInfo, optimize::Bool, inlining::Bool, cached::Bool)
function InferenceState(linfo::MethodInstance, src::CodeInfo, world::UInt, optimize::Bool, inlining::Bool, cached::Bool)
code = src.code::Array{Any,1}
nl = label_counter(code) + 1
toplevel = !isdefined(linfo, :def)
Expand Down Expand Up @@ -157,7 +158,7 @@ type InferenceState
inmodule = toplevel ? current_module() : linfo.def.module # toplevel thunks are inferred in the current module
frame = new(
sp, nl, inmodule, 0,
linfo, src, nargs, s, Union{}, W, n,
linfo, src, world, nargs, s, Union{}, W, n,
cur_hand, handler_at, n_handlers,
ssavalue_uses, ssavalue_init,
ObjectIdDict(), #Dict{InferenceState, Vector{LineNum}}(),
Expand Down Expand Up @@ -651,14 +652,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 @@ -908,7 +909,7 @@ function abstract_call_gf_by_type(f::ANY, argtype::ANY, sv)
sig = recomputed[1]::DataType
sparams = recomputed[2]::SimpleVector
end
(_tree, rt) = typeinf_edge(method, sig, sparams, sv)
(_tree, rt) = typeinf_edge(method, sig, sparams, sv, sv.world)
rettype = tmerge(rettype, rt)
if is(rettype,Any)
break
Expand Down Expand Up @@ -1465,23 +1466,32 @@ function newvar!(sv::InferenceState, typ::ANY)
end

# create a specialized MethodInstance from a method
function get_linfo(method::Method, types::ANY, sp::SimpleVector)
return ccall(:jl_specializations_get_linfo, Ref{MethodInstance}, (Any, Any, Any), method, types, sp)
function get_linfo(method::Method, types::ANY, sp::SimpleVector, world::UInt)
return ccall(:jl_specializations_get_linfo, Ref{MethodInstance}, (Any, Any, Any, UInt), method, types, sp, world)
end

inlining_enabled() = (JLOptions().can_inline == 1)
coverage_enabled() = (JLOptions().code_coverage != 0)

#### entry points for inferring a MethodInstance 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)
if world < min_age(method) || world > max_age(method)
return (nothing, Union{}, false)
end

local code = nothing
local frame = nothing
if isa(caller, MethodInstance)
code = caller
elseif cached && !is(method.specializations, nothing)
# check cached specializations
# for an existing result stored there
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, MethodInstance)
Expand Down Expand Up @@ -1570,7 +1580,7 @@ function typeinf_edge(method::Method, atypes::ANY, sparams::SimpleVector, needtr
# XXX: this test is wrong if Types (such as DataType) are present
return (nothing, Any, false)
end
linfo = get_linfo(method, atypes, sparams)
linfo = get_linfo(method, atypes, sparams, world)
end

ccall(:jl_typeinf_begin, Void, ())
Expand Down Expand Up @@ -1603,7 +1613,7 @@ function typeinf_edge(method::Method, atypes::ANY, sparams::SimpleVector, needtr
src = get_source(linfo)
end
linfo.inInference = true
frame = InferenceState(linfo::MethodInstance, src, optimize, inlining_enabled(), cached)
frame = InferenceState(linfo::MethodInstance, src, world, optimize, inlining_enabled(), cached)
end
frame = frame::InferenceState

Expand All @@ -1628,32 +1638,33 @@ function typeinf_edge(method::Method, atypes::ANY, sparams::SimpleVector, needtr
return (frame.src, widenconst(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::MethodInstance)
function typeinf_ext(linfo::MethodInstance, world::UInt)
if isdefined(linfo, :def)
# method lambda - infer this specialization via the method cache
if isdefined(linfo, :inferred) && isa(linfo.inferred, CodeInfo)
return linfo.inferred
end
(code, typ, inferred) = typeinf_edge(linfo.def, linfo.specTypes, linfo.sparam_vals, true, true, true, linfo)
(code, typ, inferred) = typeinf_edge(linfo.def, linfo.specTypes, linfo.sparam_vals, true, true, true, linfo, world)
return code
else
# toplevel lambda - infer directly
linfo.inInference = true
ccall(:jl_typeinf_begin, Void, ())
frame = InferenceState(linfo, linfo.inferred, true, inlining_enabled(), true)
frame = InferenceState(linfo, linfo.inferred, world, true, inlining_enabled(), true)
typeinf_loop(frame)
ccall(:jl_typeinf_end, Void, ())
@assert frame.inferred # TODO: deal with this better
Expand Down Expand Up @@ -2446,7 +2457,7 @@ function inlineable(f::ANY, ft::ANY, e::Expr, atypes::Vector{Any}, sv::Inference
function splitunion(atypes::Vector{Any}, i::Int)
if i == 0
local sig = argtypes_to_type(atypes)
local li = ccall(:jl_get_spec_lambda, Any, (Any,), sig)
local li = ccall(:jl_get_spec_lambda, Any, (Any, UInt), sig, sv.world)
li === nothing && return false
local stmt = []
push!(stmt, Expr(:(=), linfo_var, li))
Expand Down Expand Up @@ -2513,7 +2524,7 @@ function inlineable(f::ANY, ft::ANY, e::Expr, atypes::Vector{Any}, sv::Inference
return (ret_var, stmts)
end
else
local cache_linfo = ccall(:jl_get_spec_lambda, Any, (Any,), atype_unlimited)
local cache_linfo = ccall(:jl_get_spec_lambda, Any, (Any, UInt), atype_unlimited, sv.world)
cache_linfo === nothing && return NF
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 @@ -58,9 +58,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
src = kwli.isstaged ? kwli.unspecialized.inferred : kwli.source
Expand Down Expand Up @@ -104,7 +104,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 @@ -227,7 +227,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
2 changes: 1 addition & 1 deletion base/multi.jl
Original file line number Diff line number Diff line change
Expand Up @@ -813,7 +813,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
3 changes: 2 additions & 1 deletion base/multidimensional.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1025,9 +1025,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 = similar(inds->zeros(UInt, inds), indices(A, dim))
hashes = similar($inds, indices(A, dim))

# Compute hash for each row
k = 0
Expand Down
14 changes: 8 additions & 6 deletions base/reflection.jl
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,7 @@ function _dump_function(f::ANY, t::ANY, native::Bool, wrapper::Bool, strip_ir_me
throw(ArgumentError("argument is not a generic function"))
end
# get the MethodInstance for the method match
world = ccall(:jl_get_world_counter, UInt, ())
meth = which(f, t)
t = to_tuple_type(t)
ft = isa(f, Type) ? Type{f} : typeof(f)
Expand All @@ -503,14 +504,14 @@ function _dump_function(f::ANY, t::ANY, native::Bool, wrapper::Bool, strip_ir_me
meth = func_for_method_checked(meth, tt)
linfo = ccall(:jl_specializations_get_linfo, Ref{Core.MethodInstance}, (Any, Any, Any), meth, tt, env)
# get the code for it
return _dump_function(linfo, native, wrapper, strip_ir_metadata, dump_module)
return _dump_function_linfo(linfo, world, native, wrapper, strip_ir_metadata, dump_module)
end

function _dump_function(linfo::Core.MethodInstance, native::Bool, wrapper::Bool, strip_ir_metadata::Bool, dump_module::Bool)
function _dump_function_linfo(linfo::Core.MethodInstance, world::UInt, native::Bool, wrapper::Bool, strip_ir_metadata::Bool, dump_module::Bool)
if native
llvmf = ccall(:jl_get_llvmf_decl, Ptr{Void}, (Any, Bool), linfo, wrapper)
llvmf = ccall(:jl_get_llvmf_decl, Ptr{Void}, (Any, UInt, Bool), linfo, world, wrapper)
else
llvmf = ccall(:jl_get_llvmf_defn, Ptr{Void}, (Any, Bool), linfo, wrapper)
llvmf = ccall(:jl_get_llvmf_defn, Ptr{Void}, (Any, UInt, Bool), linfo, world, wrapper)
end
if llvmf == C_NULL
error("could not compile the specified method")
Expand Down Expand Up @@ -624,7 +625,7 @@ function which(f::ANY, t::ANY)
else
ft = isa(f,Type) ? Type{f} : typeof(f)
tt = Tuple{ft, t.parameters...}
m = ccall(:jl_gf_invoke_lookup, Any, (Any,), tt)
m = ccall(:jl_gf_invoke_lookup, Any, (Any, UInt), tt, typemax(UInt))
if m === nothing
error("no method found for the specified argument types")
end
Expand Down Expand Up @@ -730,7 +731,8 @@ true
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, UInt, ())) != 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 @@ -1735,8 +1735,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
9 changes: 7 additions & 2 deletions src/alloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -456,8 +456,9 @@ STATIC_INLINE jl_value_t *jl_call_staged(jl_svec_t *sparam_vals, jl_method_insta
fptr.fptr = generator->fptr;
fptr.jlcall_api = generator->jlcall_api;
if (__unlikely(fptr.fptr == NULL || fptr.jlcall_api == 0)) {
void *F = jl_compile_linfo(generator, (jl_code_info_t*)generator->inferred).functionObject;
fptr = jl_generate_fptr(generator, F);
size_t world = generator->def->min_world;
void *F = jl_compile_linfo(generator, (jl_code_info_t*)generator->inferred, world).functionObject;
fptr = jl_generate_fptr(generator, F, world);
}
assert(jl_svec_len(generator->def->sparam_syms) == jl_svec_len(sparam_vals));
if (fptr.jlcall_api == 1)
Expand Down Expand Up @@ -508,6 +509,7 @@ JL_DLLEXPORT jl_code_info_t *jl_code_for_staged(jl_method_instance_t *linfo)
// invoke code generator
assert(jl_nparams(tt) == jl_array_len(argnames) ||
(linfo->def->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, generator, jl_svec_data(tt->parameters), jl_nparams(tt)));

Expand Down Expand Up @@ -626,6 +628,8 @@ JL_DLLEXPORT jl_method_t *jl_new_method_uninit(void)
m->nargs = 0;
m->needs_sparam_vals_ducttape = 2;
m->traced = 0;
m->min_world = 1;
m->max_world = ~(size_t)0;
JL_MUTEX_INIT(&m->writelock);
return m;
}
Expand All @@ -647,6 +651,7 @@ jl_method_t *jl_new_method(jl_code_info_t *definition,
JL_GC_PUSH1(&root);

jl_method_t *m = jl_new_method_uninit();
m->min_world = ++jl_world_counter;
m->isstaged = isstaged;
m->name = name;
m->sig = sig;
Expand Down
3 changes: 2 additions & 1 deletion src/ast.c
Original file line number Diff line number Diff line change
Expand Up @@ -148,11 +148,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 @@ -219,6 +219,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;
#ifdef ENABLE_TIMINGS
eh->timing_stack = current_task->timing_stack;
Expand Down Expand Up @@ -592,7 +593,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 @@ -999,7 +999,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 @@ -629,7 +629,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->source, ctx->linfo->sparam_vals);
jl_get_ptls_states()->world_age = last_age;
}
JL_CATCH {
if (compiletime)
Expand Down
Loading

0 comments on commit 7b0803c

Please sign in to comment.