Skip to content

Commit 50a6216

Browse files
committed
thread world counter through more of libjulia
1 parent b61c3c2 commit 50a6216

32 files changed

+350
-218
lines changed

base/REPL.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,9 +131,9 @@ function print_response(errio::IO, val::ANY, bt, show_value::Bool, have_color::B
131131
if val !== nothing && show_value
132132
try
133133
if specialdisplay === nothing
134-
display(val)
134+
eval(Main, Expr(:call, () -> display(val)))
135135
else
136-
display(specialdisplay,val)
136+
eval(Main, Expr(:call, () -> display(specialdisplay, val)))
137137
end
138138
catch err
139139
println(errio, "Error showing value of type ", typeof(val), ":")

base/client.jl

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -114,13 +114,14 @@ function eval_user_input(ast::ANY, show_value)
114114
errcount, lasterr = 0, ()
115115
else
116116
ast = expand(ast)
117-
value = eval(Main,ast)
117+
value = eval(Main, ast)
118118
eval(Main, :(ans = $(Expr(:quote, value))))
119-
if !is(value,nothing) && show_value
119+
if !is(value, nothing) && show_value
120120
if have_color
121121
print(answer_color())
122122
end
123-
try display(value)
123+
try
124+
eval(Main, Expr(:call, () -> display(value)))
124125
catch err
125126
println(STDERR, "Evaluation succeeded, but an error occurred while showing value of type ", typeof(value), ":")
126127
rethrow(err)

base/inference.jl

Lines changed: 32 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ type InferenceState
4949

5050
# info on the state of inference and the linfo
5151
linfo::LambdaInfo
52+
world::UInt
5253
nargs::Int
5354
stmt_types::Vector{Any}
5455
# return type
@@ -75,7 +76,7 @@ type InferenceState
7576
optimize::Bool
7677
inferred::Bool
7778

78-
function InferenceState(linfo::LambdaInfo, optimize::Bool)
79+
function InferenceState(linfo::LambdaInfo, world::UInt, optimize::Bool)
7980
@assert isa(linfo.code,Array{Any,1})
8081
nslots = length(linfo.slotnames)
8182
nl = label_counter(linfo.code)+1
@@ -155,7 +156,7 @@ type InferenceState
155156
inmodule = isdefined(linfo, :def) ? linfo.def.module : current_module() # toplevel thunks are inferred in the current module
156157
frame = new(
157158
sp, nl, Dict{SSAValue, Bool}(), inmodule, 0, false,
158-
linfo, la, s, Union{}, W, n,
159+
linfo, world, la, s, Union{}, W, n,
159160
cur_hand, handler_at, n_handlers,
160161
ssavalue_uses, ssavalue_init,
161162
ObjectIdDict(), #Dict{InferenceState, Vector{LineNum}}(),
@@ -607,14 +608,14 @@ function invoke_tfunc(f::ANY, types::ANY, argtype::ANY, sv::InferenceState)
607608
ft = type_typeof(f)
608609
types = Tuple{ft, types.parameters...}
609610
argtype = Tuple{ft, argtype.parameters...}
610-
entry = ccall(:jl_gf_invoke_lookup, Any, (Any,), types)
611+
entry = ccall(:jl_gf_invoke_lookup, Any, (Any, UInt), types, sv.world)
611612
if is(entry, nothing)
612613
return Any
613614
end
614615
meth = entry.func
615616
(ti, env) = ccall(:jl_match_method, Any, (Any, Any, Any),
616617
argtype, meth.sig, meth.tvars)::SimpleVector
617-
return typeinf_edge(meth::Method, ti, env, sv)[2]
618+
return typeinf_edge(meth::Method, ti, env, sv, sv.world)[2]
618619
end
619620

620621
function tuple_tfunc(argtype::ANY)
@@ -842,7 +843,7 @@ function abstract_call_gf_by_type(f::ANY, argtype::ANY, sv)
842843
end
843844
end
844845
#print(m,"\n")
845-
(_tree, rt) = typeinf_edge(method, sig, m[2], sv)
846+
(_tree, rt) = typeinf_edge(method, sig, m[2], sv, sv.world)
846847
rettype = tmerge(rettype, rt)
847848
if is(rettype,Any)
848849
break
@@ -1384,9 +1385,9 @@ function newvar!(sv::InferenceState, typ)
13841385
end
13851386

13861387
# create a specialized LambdaInfo from a method
1387-
function specialize_method(method::Method, types::ANY, sp::SimpleVector, cached)
1388+
function specialize_method(method::Method, types::ANY, sp::SimpleVector, cached, world)
13881389
if cached
1389-
return ccall(:jl_specializations_get_linfo, Ref{LambdaInfo}, (Any, Any, Any), method, types, sp)
1390+
return ccall(:jl_specializations_get_linfo, Ref{LambdaInfo}, (Any, Any, Any, UInt), method, types, sp, world)
13901391
else
13911392
return ccall(:jl_get_specialized, Ref{LambdaInfo}, (Any, Any, Any), method, types, sp)
13921393
end
@@ -1408,16 +1409,24 @@ function unshare_linfo!(li::LambdaInfo)
14081409
end
14091410

14101411
#### entry points for inferring a LambdaInfo given a type signature ####
1411-
function typeinf_edge(method::Method, atypes::ANY, sparams::SimpleVector, needtree::Bool, optimize::Bool, cached::Bool, caller)
1412+
let _min_age = Symbol("min-age"), _max_age = Symbol("max-age")
1413+
global min_age(m::Method) = getfield(m, _min_age) % UInt
1414+
global max_age(m::Method) = getfield(m, _max_age) % UInt
1415+
end
1416+
function typeinf_edge(method::Method, atypes::ANY, sparams::SimpleVector, needtree::Bool, optimize::Bool, cached::Bool, caller, world::UInt)
14121417
local code = nothing
14131418
local frame = nothing
1419+
if world < min_age(method) || world > max_age(method)
1420+
ccall(:jl_breakpoint, Void, (Any,), (method, world))
1421+
return (nothing, Union{}, false)
1422+
end
14141423
if isa(caller, LambdaInfo)
14151424
code = caller
14161425
elseif cached
14171426
# check cached specializations
14181427
# for an existing result stored there
14191428
if !is(method.specializations, nothing)
1420-
code = ccall(:jl_specializations_lookup, Any, (Any, Any), method, atypes)
1429+
code = ccall(:jl_specializations_lookup, Any, (Any, Any, UInt), method, atypes, world)
14211430
if isa(code, Void)
14221431
# something completely new
14231432
elseif isa(code, LambdaInfo)
@@ -1479,12 +1488,12 @@ function typeinf_edge(method::Method, atypes::ANY, sparams::SimpleVector, needtr
14791488
end
14801489
try
14811490
# user code might throw errors – ignore them
1482-
linfo = specialize_method(method, atypes, sparams, cached)
1491+
linfo = specialize_method(method, atypes, sparams, cached, world)
14831492
catch
14841493
return (nothing, Any, false)
14851494
end
14861495
else
1487-
linfo = specialize_method(method, atypes, sparams, cached)
1496+
linfo = specialize_method(method, atypes, sparams, cached, world)
14881497
end
14891498

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

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

1530-
function typeinf_edge(method::Method, atypes::ANY, sparams::SimpleVector, caller)
1531-
return typeinf_edge(method, atypes, sparams, false, true, true, caller)
1539+
world_counter() = ccall(:jl_get_world_counter, UInt, ())
1540+
function typeinf_edge(method::Method, atypes::ANY, sparams::SimpleVector, caller::InferenceState, world::UInt)
1541+
return typeinf_edge(method, atypes, sparams, false, true, true, caller, world)
15321542
end
15331543
function typeinf(method::Method, atypes::ANY, sparams::SimpleVector, needtree::Bool=false)
1534-
return typeinf_edge(method, atypes, sparams, needtree, true, true, nothing)
1544+
return typeinf_edge(method, atypes, sparams, needtree, true, true, nothing, world_counter())
15351545
end
15361546
# compute an inferred (optionally optimized) AST without global effects (i.e. updating the cache)
15371547
function typeinf_uncached(method::Method, atypes::ANY, sparams::ANY; optimize::Bool=true)
1538-
return typeinf_edge(method, atypes, sparams, true, optimize, false, nothing)
1548+
return typeinf_edge(method, atypes, sparams, true, optimize, false, nothing, world_counter())
15391549
end
15401550
function typeinf_uncached(method::Method, atypes::ANY, sparams::SimpleVector, optimize::Bool)
1541-
return typeinf_edge(method, atypes, sparams, true, optimize, false, nothing)
1551+
return typeinf_edge(method, atypes, sparams, true, optimize, false, nothing, world_counter())
15421552
end
1543-
function typeinf_ext(linfo::LambdaInfo)
1553+
function typeinf_ext(linfo::LambdaInfo, world::UInt)
15441554
if isdefined(linfo, :def)
15451555
# method lambda - infer this specialization via the method cache
1546-
(code, _t, _) = typeinf_edge(linfo.def, linfo.specTypes, linfo.sparam_vals, true, true, true, linfo)
1547-
if code.inferred && linfo !== code
1556+
(code, _t, inferred) = typeinf_edge(linfo.def, linfo.specTypes, linfo.sparam_vals, true, true, true, linfo, world)
1557+
if inferred && code.inferred && linfo !== code
15481558
# This case occurs when the IR for a function has been deleted.
15491559
# `code` will be a newly-created LambdaInfo, and we need to copy its
15501560
# contents to the existing one to copy the info to the method cache.
@@ -1564,7 +1574,7 @@ function typeinf_ext(linfo::LambdaInfo)
15641574
else
15651575
# toplevel lambda - infer directly
15661576
linfo.inInference = true
1567-
frame = InferenceState(linfo, true)
1577+
frame = InferenceState(linfo, world, true)
15681578
typeinf_loop(frame)
15691579
@assert frame.inferred # TODO: deal with this better
15701580
return linfo
@@ -2342,7 +2352,7 @@ function inlineable(f::ANY, ft::ANY, e::Expr, atypes::Vector{Any}, sv::Inference
23422352
end
23432353
function invoke_NF()
23442354
# converts a :call to :invoke
2345-
cache_linfo = ccall(:jl_get_spec_lambda, Any, (Any,), atype_unlimited)
2355+
cache_linfo = ccall(:jl_get_spec_lambda, Any, (Any, UInt), atype_unlimited, sv.world)
23462356
if cache_linfo !== nothing
23472357
e.head = :invoke
23482358
unshift!(e.args, cache_linfo)

base/methodshow.jl

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,9 @@ function arg_decl_parts(m::Method)
7373
return tv, decls, file, line
7474
end
7575

76-
function kwarg_decl(sig::ANY, kwtype::DataType)
77-
sig = Tuple{kwtype, Core.AnyVector, sig.parameters...}
78-
kwli = ccall(:jl_methtable_lookup, Any, (Any, Any), kwtype.name.mt, sig)
76+
function kwarg_decl(m::Method, kwtype::DataType)
77+
sig = Tuple{kwtype, Core.AnyVector, m.sig.parameters...}
78+
kwli = ccall(:jl_methtable_lookup, Any, (Any, Any, UInt), kwtype.name.mt, sig, getfield(m, Symbol("max-age")) % UInt)
7979
if kwli !== nothing
8080
kwli = kwli::Method
8181
return filter(x->!('#' in string(x)), kwli.lambda_template.slotnames[kwli.lambda_template.nargs+1:end])
@@ -108,7 +108,7 @@ function show(io::IO, m::Method; kwtype::Nullable{DataType}=Nullable{DataType}()
108108
join(io, [isempty(d[2]) ? d[1] : d[1]*"::"*d[2] for d in decls[2:end]],
109109
", ", ", ")
110110
if !isnull(kwtype)
111-
kwargs = kwarg_decl(m.sig, get(kwtype))
111+
kwargs = kwarg_decl(m, get(kwtype))
112112
if !isempty(kwargs)
113113
print(io, "; ")
114114
join(io, kwargs, ", ", ", ")
@@ -231,7 +231,7 @@ function show(io::IO, ::MIME"text/html", m::Method; kwtype::Nullable{DataType}=N
231231
join(io, [isempty(d[2]) ? d[1] : d[1]*"::<b>"*d[2]*"</b>"
232232
for d in decls[2:end]], ", ", ", ")
233233
if !isnull(kwtype)
234-
kwargs = kwarg_decl(m.sig, get(kwtype))
234+
kwargs = kwarg_decl(m, get(kwtype))
235235
if !isempty(kwargs)
236236
print(io, "; <i>")
237237
join(io, kwargs, ", ", ", ")

base/multi.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -610,7 +610,7 @@ function lookup_ref(pg, rrid, f)
610610
rv = get(pg.refs, rrid, false)
611611
if rv === false
612612
# first we've heard of this ref
613-
rv = RemoteValue(f())
613+
rv = RemoteValue(eval(Main, Expr(:call, f)))
614614
pg.refs[rrid] = rv
615615
push!(rv.clientset, rrid.whence)
616616
end
@@ -778,7 +778,7 @@ function run_work_thunk(thunk, print_error)
778778
result = RemoteException(ce)
779779
print_error && showerror(STDERR, ce)
780780
end
781-
result
781+
return result
782782
end
783783
function run_work_thunk(rv::RemoteValue, thunk)
784784
put!(rv, run_work_thunk(thunk, false))

base/multidimensional.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -784,9 +784,10 @@ the order that the first of each set of equivalent elements originally appears.
784784
If `dim` is specified, returns unique regions of the array `itr` along `dim`.
785785
"""
786786
@generated function unique{T,N}(A::AbstractArray{T,N}, dim::Int)
787+
inds = inds -> zeros(UInt, inds)
787788
quote
788789
1 <= dim <= $N || return copy(A)
789-
hashes = allocate_for(inds->zeros(UInt, inds), A, shape(A, dim))
790+
hashes = allocate_for($inds, A, shape(A, dim))
790791

791792
# Compute hash for each row
792793
k = 0

base/reflection.jl

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -385,7 +385,7 @@ function which(f::ANY, t::ANY)
385385
return first(ms)
386386
else
387387
ft = isa(f,Type) ? Type{f} : typeof(f)
388-
m = ccall(:jl_gf_invoke_lookup, Any, (Any,), Tuple{ft, t.parameters...})
388+
m = ccall(:jl_gf_invoke_lookup, Any, (Any, UInt), Tuple{ft, t.parameters...}, typemax(UInt))
389389
if m === nothing
390390
error("no method found for the specified argument types")
391391
end
@@ -439,7 +439,8 @@ end
439439
function method_exists(f::ANY, t::ANY)
440440
t = to_tuple_type(t)
441441
t = Tuple{isa(f,Type) ? Type{f} : typeof(f), t.parameters...}
442-
return ccall(:jl_method_exists, Cint, (Any, Any), typeof(f).name.mt, t) != 0
442+
return ccall(:jl_method_exists, Cint, (Any, Any, UInt), typeof(f).name.mt, t,
443+
ccall(:jl_get_world_counter, Int32, ())) != 0
443444
end
444445

445446
function isambiguous(m1::Method, m2::Method)

base/sparse/sparsematrix.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1387,8 +1387,8 @@ for (Bsig, A1sig, A2sig, gbb, funcname) in
13871387
global $funcname
13881388
function $funcname(f::Function, B::$Bsig, A1::$A1sig, A2::$A2sig)
13891389
func = @get! cache f gen_broadcast_function_sparse($gbb, f, ($A1sig) <: SparseMatrixCSC)
1390-
func(B, A1, A2)
1391-
B
1390+
eval(Expr(:call, () -> func(B, A1, A2))) # need eval because func was just created by gen_broadcast_function_sparse
1391+
return B
13921392
end
13931393
end # let broadcast_cache
13941394
end

src/alloc.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,7 @@ STATIC_INLINE jl_value_t *jl_call_staged(jl_svec_t *sparam_vals, jl_lambda_info_
407407
jl_value_t **args, uint32_t nargs)
408408
{
409409
if (__unlikely(meth->fptr == NULL)) {
410-
jl_compile_linfo(meth);
410+
jl_compile_linfo(meth, meth->def->min_world);
411411
jl_generate_fptr(meth);
412412
}
413413
assert(jl_svec_len(meth->sparam_syms) == jl_svec_len(sparam_vals));
@@ -448,6 +448,7 @@ static jl_lambda_info_t *jl_instantiate_staged(jl_method_t *generator, jl_tuplet
448448
// invoke code generator
449449
assert(jl_nparams(tt) == jl_array_len(argnames) ||
450450
(func->isva && (jl_nparams(tt) >= jl_array_len(argnames) - 1)));
451+
// TODO: set world to that of the generator while calling func
451452
jl_array_ptr_set(body->args, 1,
452453
jl_call_staged(sparam_vals, func, jl_svec_data(tt->parameters), jl_nparams(tt)));
453454

@@ -582,6 +583,8 @@ JL_DLLEXPORT jl_method_t *jl_new_method_uninit(void)
582583
m->isstaged = 0;
583584
m->needs_sparam_vals_ducttape = 2;
584585
m->traced = 0;
586+
m->min_world = 1;
587+
m->max_world = ~(size_t)0;
585588
return m;
586589
}
587590

@@ -608,6 +611,7 @@ jl_method_t *jl_new_method(jl_lambda_info_t *definition, jl_sym_t *name, jl_tupl
608611
jl_gc_wb(m, definition);
609612
definition->def = m;
610613
jl_gc_wb(definition, m);
614+
m->min_world = ++jl_world_counter;
611615

612616
if (reused) {
613617
m->file = oldm->file;

src/anticodegen.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ int32_t jl_get_llvm_gv(jl_value_t *p) UNAVAILABLE
1515
void jl_write_malloc_log(void) UNAVAILABLE
1616
void jl_write_coverage_data(void) UNAVAILABLE
1717
void jl_generate_fptr(jl_lambda_info_t *li) UNAVAILABLE
18-
void jl_compile_linfo(jl_lambda_info_t *li, void *cyclectx) UNAVAILABLE
18+
void jl_compile_linfo(jl_lambda_info_t *li, size_t world) UNAVAILABLE
1919

2020
JL_DLLEXPORT void jl_clear_malloc_data(void) UNAVAILABLE
2121
JL_DLLEXPORT void jl_extern_c(jl_function_t *f, jl_value_t *rt, jl_value_t *argt, char *name) UNAVAILABLE

0 commit comments

Comments
 (0)