diff --git a/base/REPL.jl b/base/REPL.jl
index 977fb156bdfc4..eac428d51d36b 100644
--- a/base/REPL.jl
+++ b/base/REPL.jl
@@ -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), ":")
diff --git a/base/client.jl b/base/client.jl
index d3b163e9ff251..aaf4652f11467 100644
--- a/base/client.jl
+++ b/base/client.jl
@@ -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)
diff --git a/base/inference.jl b/base/inference.jl
index 5e166a79d6cf9..e8060546256be 100644
--- a/base/inference.jl
+++ b/base/inference.jl
@@ -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
@@ -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
@@ -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}}(),
@@ -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)
@@ -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
@@ -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
@@ -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)
@@ -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
@@ -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
@@ -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.
@@ -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
@@ -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)
diff --git a/base/methodshow.jl b/base/methodshow.jl
index 928c8b09fe70a..195eb68a99113 100644
--- a/base/methodshow.jl
+++ b/base/methodshow.jl
@@ -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])
@@ -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, ", ", ", ")
@@ -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]*"::"*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, ", ", ", ")
diff --git a/base/multi.jl b/base/multi.jl
index e7ae912babed2..fc62beadf03e8 100644
--- a/base/multi.jl
+++ b/base/multi.jl
@@ -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
@@ -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))
diff --git a/base/multidimensional.jl b/base/multidimensional.jl
index 52b078a89c5bd..4b5bc46742631 100644
--- a/base/multidimensional.jl
+++ b/base/multidimensional.jl
@@ -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
diff --git a/base/reflection.jl b/base/reflection.jl
index a2f5889b42bca..62ef72652c348 100644
--- a/base/reflection.jl
+++ b/base/reflection.jl
@@ -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
@@ -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)
diff --git a/base/sparse/sparsematrix.jl b/base/sparse/sparsematrix.jl
index 7e3bac45a3594..824df82f62695 100644
--- a/base/sparse/sparsematrix.jl
+++ b/base/sparse/sparsematrix.jl
@@ -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
diff --git a/src/alloc.c b/src/alloc.c
index 5c3541b71200f..7f8bc6ab071e9 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -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));
@@ -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)));
@@ -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;
}
@@ -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;
diff --git a/src/anticodegen.c b/src/anticodegen.c
index b803fe1f757e8..2999d49092628 100644
--- a/src/anticodegen.c
+++ b/src/anticodegen.c
@@ -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
diff --git a/src/ast.c b/src/ast.c
index 0d9fc15860af7..6368d813471f7 100644
--- a/src/ast.c
+++ b/src/ast.c
@@ -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);
diff --git a/src/builtins.c b/src/builtins.c
index 3f33510add18c..51fb1754ecf10 100644
--- a/src/builtins.c
+++ b/src/builtins.c
@@ -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;
}
@@ -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;
@@ -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;
}
diff --git a/src/ccall.cpp b/src/ccall.cpp
index 1103b4e918ad5..e984ad492d5fd 100644
--- a/src/ccall.cpp
+++ b/src/ccall.cpp
@@ -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)
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 2a852419dbd3e..bba442145f50d 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -1,5 +1,5 @@
// This file is a part of Julia. License is MIT: http://julialang.org/license
-
+;
#include "llvm-version.h"
#include "platform.h"
#include "options.h"
@@ -419,6 +419,7 @@ static Function *resetstkoflw_func;
#endif
static Function *diff_gc_total_bytes_func;
static Function *jlarray_data_owner_func;
+static Function *jlgetworld_func;
// placeholder functions
static Function *gcroot_func;
@@ -557,6 +558,8 @@ typedef struct {
std::map *handlers;
jl_module_t *module;
jl_lambda_info_t *linfo;
+ jl_array_t *code;
+ size_t world;
const char *name;
StringRef file;
Value *spvals_ptr;
@@ -572,6 +575,7 @@ typedef struct {
CallInst *ptlsStates;
Value *signalPage;
+ Value *world_age_field;
llvm::DIBuilder *dbuilder;
bool debug_enabled;
@@ -801,12 +805,12 @@ void jl_dump_compiles(void *s)
// --- entry point ---
//static int n_emit=0;
-static std::unique_ptr emit_function(jl_lambda_info_t *lam, jl_llvm_functions_t *declarations);
+static std::unique_ptr emit_function(jl_lambda_info_t *lam, size_t world, jl_llvm_functions_t *declarations);
void jl_add_linfo_in_flight(StringRef name, jl_lambda_info_t *linfo, const DataLayout &DL);
// this is the implementation component of jl_compile_linfo
// which compiles li and adds the result to the jitlayers
-static void to_function(jl_lambda_info_t *li)
+static void to_function(jl_lambda_info_t *li, size_t world)
{
// setup global state
JL_LOCK(&codegen_lock);
@@ -822,7 +826,7 @@ static void to_function(jl_lambda_info_t *li)
Function *f = NULL, *specf = NULL;
// actually do the work of emitting the function
JL_TRY {
- m = emit_function(li, &li->functionObjectsDecls);
+ m = emit_function(li, world, &li->functionObjectsDecls);
f = (Function*)li->functionObjectsDecls.functionObject;
specf = (Function*)li->functionObjectsDecls.specFunctionObject;
//n_emit++;
@@ -1018,11 +1022,11 @@ extern "C" void jl_generate_fptr(jl_lambda_info_t *li)
// this generates llvm code for the lambda info
// (and adds it to the shadow module), but doesn't yet compile
// or generate object code for it
-extern "C" void jl_compile_linfo(jl_lambda_info_t *li)
+extern "C" void jl_compile_linfo(jl_lambda_info_t *li, size_t world)
{
if (li->functionObjectsDecls.functionObject == NULL) {
// objective: assign li->functionObject
- to_function(li);
+ to_function(li, world);
}
}
@@ -1100,13 +1104,14 @@ void jl_extern_c(jl_function_t *f, jl_value_t *rt, jl_value_t *argt, char *name)
extern "C" JL_DLLEXPORT
void *jl_get_llvmf(jl_tupletype_t *tt, bool getwrapper, bool getdeclarations)
{
+ size_t world = jl_world_counter;
jl_lambda_info_t *linfo = NULL;
JL_GC_PUSH2(&linfo, &tt);
if (tt != NULL) {
- linfo = jl_get_specialization1(tt);
+ linfo = jl_get_specialization1(tt, world);
if (linfo == NULL) {
linfo = jl_method_lookup_by_type(
- ((jl_datatype_t*)jl_tparam0(tt))->name->mt, tt, 0, 0);
+ ((jl_datatype_t*)jl_tparam0(tt))->name->mt, tt, 0, 0, world);
if (linfo == NULL || jl_has_call_ambiguities(tt, linfo->def)) {
JL_GC_POP();
return NULL;
@@ -1119,7 +1124,7 @@ void *jl_get_llvmf(jl_tupletype_t *tt, bool getwrapper, bool getdeclarations)
}
// make sure to compile this normally first,
// since `emit_function` doesn't handle recursive compilation correctly
- linfo = jl_compile_for_dispatch(linfo);
+ linfo = jl_compile_for_dispatch(linfo, world);
if (!getdeclarations) {
if (linfo->code == jl_nothing) {
@@ -1127,7 +1132,7 @@ void *jl_get_llvmf(jl_tupletype_t *tt, bool getwrapper, bool getdeclarations)
// XXX: this only /partially/ corrupts linfo
// (by confusing the compiler about the
// validity of the code it already generated)
- linfo = jl_type_infer(linfo, 0);
+ linfo = jl_type_infer(linfo, world, 0);
if (linfo->code == jl_nothing || linfo->inInference) {
JL_GC_POP();
return NULL;
@@ -1136,7 +1141,7 @@ void *jl_get_llvmf(jl_tupletype_t *tt, bool getwrapper, bool getdeclarations)
// emit this function into a new module
Function *f, *specf;
jl_llvm_functions_t declarations;
- std::unique_ptr m = emit_function(linfo, &declarations);
+ std::unique_ptr m = emit_function(linfo, world, &declarations);
finalize_gc_frame(m.get());
PM->run(*m.get());
f = (llvm::Function*)declarations.functionObject;
@@ -2697,10 +2702,10 @@ static jl_cgval_t emit_invoke(jl_expr_t *ex, jl_codectx_t *ctx)
assert(!li->inCompile);
if (li->code == jl_nothing && !li->inInference && li->inferred) {
// XXX: it was inferred in the past, so it's almost valid to re-infer it now
- jl_type_infer(li, 0);
+ jl_type_infer(li, ctx->world, 0);
}
if (!li->inInference && li->inferred && li->code != jl_nothing) {
- jl_compile_linfo(li);
+ jl_compile_linfo(li, ctx->world);
}
}
Value *theFptr = (Value*)li->functionObjectsDecls.functionObject;
@@ -3080,6 +3085,10 @@ static void emit_stmtpos(jl_value_t *expr, jl_codectx_t *ctx)
return;
// fall-through
}
+ if (ctx->linfo->def == NULL) {
+ Value *world = builder.CreateCall(prepare_call(jlgetworld_func));
+ builder.CreateStore(world, ctx->world_age_field);
+ }
(void)emit_expr(expr, ctx);
}
@@ -3506,17 +3515,17 @@ static Function *gen_cfun_wrapper(jl_function_t *ff, jl_value_t *jlrettype, jl_t
const char *name = "cfunction";
// try to look up this function for direct invoking
- jl_lambda_info_t *lam = jl_get_specialization1((jl_tupletype_t*)sigt);
+ jl_lambda_info_t *lam = jl_get_specialization1((jl_tupletype_t*)sigt, jl_world_counter/*FIXME*/);
jl_value_t *astrt = (jl_value_t*)jl_any_type;
// infer it first, if necessary
if (lam && lam->inInference)
lam = NULL; // TODO: use emit_invoke framework to dispatch these
if (lam && (lam->code == jl_nothing || !lam->inferred))
- jl_type_infer(lam, 0);
+ jl_type_infer(lam, jl_world_counter, 0);
if (lam && (lam->inInference || !lam->inferred))
lam = NULL; // TODO: use emit_invoke framework to dispatch these
if (lam != NULL) {
- jl_compile_linfo(lam);
+ jl_compile_linfo(lam, jl_world_counter);
name = jl_symbol_name(lam->def->name);
astrt = lam->rettype;
if (astrt != (jl_value_t*)jl_bottom_type &&
@@ -3555,6 +3564,8 @@ static Function *gen_cfun_wrapper(jl_function_t *ff, jl_value_t *jlrettype, jl_t
jl_codectx_t ctx;
ctx.f = cw;
ctx.linfo = lam;
+ ctx.code = NULL;
+ ctx.world = jl_world_counter;
ctx.sret = false;
ctx.spvals_ptr = NULL;
allocate_gc_frame(b0, &ctx);
@@ -3844,8 +3855,9 @@ static Function *jl_cfunction_object(jl_function_t *ff, jl_value_t *declrt, jl_t
cfunc_sig = (jl_value_t*)jl_apply_tuple_type((jl_svec_t*)cfunc_sig);
// check the cache
+ size_t world = 1;
if (jl_cfunction_list.unknown != jl_nothing) {
- jl_typemap_entry_t *sf = jl_typemap_assoc_by_type(jl_cfunction_list, (jl_tupletype_t*)cfunc_sig, NULL, 1, 0, /*offs*/0);
+ jl_typemap_entry_t *sf = jl_typemap_assoc_by_type(jl_cfunction_list, (jl_tupletype_t*)cfunc_sig, NULL, 1, 0, /*offs*/0, world);
if (sf) {
Function *f = (Function*)jl_unbox_voidpointer(sf->func.value);
if (f) {
@@ -3905,6 +3917,8 @@ static Function *gen_jlcall_wrapper(jl_lambda_info_t *lam, Function *f, bool sre
jl_codectx_t ctx;
ctx.f = w;
ctx.linfo = lam;
+ ctx.code = NULL;
+ ctx.world = 0;
ctx.sret = false;
ctx.spvals_ptr = NULL;
allocate_gc_frame(b0, &ctx);
@@ -3956,7 +3970,7 @@ static Function *gen_jlcall_wrapper(jl_lambda_info_t *lam, Function *f, bool sre
}
// Compile to LLVM IR, using a specialized signature if applicable.
-static std::unique_ptr emit_function(jl_lambda_info_t *lam, jl_llvm_functions_t *declarations)
+static std::unique_ptr emit_function(jl_lambda_info_t *lam, size_t world, jl_llvm_functions_t *declarations)
{
assert(declarations && "Capturing declarations is always required");
@@ -3976,6 +3990,8 @@ static std::unique_ptr emit_function(jl_lambda_info_t *lam, jl_llvm_func
ctx.handlers = &handlers;
ctx.module = lam->def ? lam->def->module : jl_current_module;
ctx.linfo = lam;
+ ctx.code = code;
+ ctx.world = world;
ctx.name = jl_symbol_name(lam->def ? lam->def->name : anonymous_sym);
ctx.funcName = ctx.name;
ctx.vaSlot = -1;
@@ -3983,6 +3999,7 @@ static std::unique_ptr emit_function(jl_lambda_info_t *lam, jl_llvm_func
ctx.inbounds.push_back(false);
ctx.boundsCheck.push_back(false);
ctx.spvals_ptr = NULL;
+ bool toplevel = lam->def == NULL;
// step 2. process var-info lists to see what vars need boxing
int n_ssavalues = jl_is_long(lam->ssavaluetypes) ? jl_unbox_long(lam->ssavaluetypes) : jl_array_len(lam->ssavaluetypes);
@@ -4419,6 +4436,14 @@ static std::unique_ptr emit_function(jl_lambda_info_t *lam, jl_llvm_func
// step 7. set up GC frame
allocate_gc_frame(b0, &ctx);
+ Value *last_age = NULL;
+ if (toplevel) {
+ ctx.world_age_field = builder.CreateGEP(
+ builder.CreateBitCast(ctx.ptlsStates, T_psize),
+ ConstantInt::get(T_size, offsetof(jl_tls_states_t, world_age) / sizeof(size_t)));
+ last_age = tbaa_decorate(tbaa_gcframe, builder.CreateLoad(ctx.world_age_field));
+ }
+
// step 8. allocate space for exception handler contexts
for(i=0; i < stmtslen; i++) {
jl_value_t *stmt = jl_array_ptr_ref(stmts,i);
@@ -4766,6 +4791,8 @@ static std::unique_ptr emit_function(jl_lambda_info_t *lam, jl_llvm_func
retval = NULL;
if (do_malloc_log && lno != -1)
mallocVisitLine(filename, lno);
+ if (toplevel)
+ builder.CreateStore(last_age, ctx.world_age_field);
if (type_is_ghost(retty) || ctx.sret)
builder.CreateRetVoid();
else
@@ -5594,6 +5621,14 @@ static void init_julia_llvm_env(Module *m)
"julia.jlcall_frame_decl", m);
add_named_global(jlcall_frame_func, (void*)NULL, /*dllimport*/false);
+ jlgetworld_func =
+ Function::Create(FunctionType::get(T_size, ArrayRef(), false),
+ Function::ExternalLinkage,
+ "jl_get_world_counter", m);
+ jlgetworld_func->addFnAttr(Attribute::ReadOnly);
+ add_named_global(jlgetworld_func, jl_get_world_counter);
+
+
// set up optimization passes
#ifdef LLVM37
// No DataLayout pass needed anymore.
diff --git a/src/dump.c b/src/dump.c
index bf4a47232a40a..1ea8d60db5907 100644
--- a/src/dump.c
+++ b/src/dump.c
@@ -844,6 +844,8 @@ static void jl_serialize_value_(ios_t *s, jl_value_t *v)
write_int8(s, m->isstaged);
jl_serialize_value(s, (jl_value_t*)m->file);
write_int32(s, m->line);
+ write_int32(s, m->min_world);
+ write_int32(s, m->max_world);
jl_serialize_value(s, (jl_value_t*)m->sig);
jl_serialize_value(s, (jl_value_t*)m->tvars);
if (mode != MODE_MODULE_POSTWORK)
@@ -1457,6 +1459,8 @@ static jl_value_t *jl_deserialize_value_(ios_t *s, jl_value_t *vtag, jl_value_t
m->isstaged = read_int8(s);
m->file = (jl_sym_t*)jl_deserialize_value(s, NULL);
m->line = read_int32(s);
+ m->min_world = read_int32(s);
+ m->max_world = read_int32(s);
m->sig = (jl_tupletype_t*)jl_deserialize_value(s, (jl_value_t**)&m->sig);
jl_gc_wb(m, m->sig);
m->tvars = (jl_svec_t*)jl_deserialize_value(s, (jl_value_t**)&m->tvars);
@@ -1924,6 +1928,7 @@ static void jl_save_system_image_to_stream(ios_t *f)
write_int32(f, jl_get_t_uid_ctr());
write_int32(f, jl_get_gs_ctr());
+ write_int32(f, jl_world_counter);
jl_finalize_serializer(f); // done with f
htable_reset(&backref_table, 0);
@@ -2019,6 +2024,7 @@ static void jl_restore_system_image_from_stream(ios_t *f)
int uid_ctr = read_int32(f);
int gs_ctr = read_int32(f);
+ jl_world_counter = read_int32(f);
jl_module_init_order = jl_finalize_deserializer(f, NULL); // done with f
jl_set_t_uid_ctr(uid_ctr);
diff --git a/src/gc.c b/src/gc.c
index 498f524d0d129..92fd632f5427f 100644
--- a/src/gc.c
+++ b/src/gc.c
@@ -105,7 +105,10 @@ static void run_finalizer(jl_value_t *o, jl_value_t *ff)
else {
jl_value_t *args[2] = {ff,o};
JL_TRY {
+ size_t last_age = jl_get_ptls_states()->world_age;
+ jl_get_ptls_states()->world_age = jl_world_counter;
jl_apply(args, 2);
+ jl_get_ptls_states()->world_age = last_age;
}
JL_CATCH {
jl_printf(JL_STDERR, "error in running finalizer: ");
diff --git a/src/gf.c b/src/gf.c
index a6e9657a783e1..20b1597d4da05 100644
--- a/src/gf.c
+++ b/src/gf.c
@@ -24,7 +24,11 @@
extern "C" {
#endif
-size_t jl_world_counter = 0;
+size_t jl_world_counter = 1;
+JL_DLLEXPORT size_t jl_get_world_counter(void)
+{
+ return jl_world_counter;
+}
JL_DLLEXPORT jl_value_t *jl_invoke(jl_lambda_info_t *meth, jl_value_t **args, uint32_t nargs)
{
@@ -121,30 +125,31 @@ static int8_t jl_cachearg_offset(jl_methtable_t *mt)
JL_DLLEXPORT jl_lambda_info_t *jl_get_specialized(jl_method_t *m, jl_tupletype_t *types, jl_svec_t *sp);
// get or create the LambdaInfo for a specialization
-JL_DLLEXPORT jl_lambda_info_t *jl_specializations_get_linfo(jl_method_t *m, jl_tupletype_t *type, jl_svec_t *sparams)
+JL_DLLEXPORT jl_lambda_info_t *jl_specializations_get_linfo(jl_method_t *m, jl_tupletype_t *type, jl_svec_t *sparams, size_t world)
{
- jl_typemap_entry_t *sf = jl_typemap_assoc_by_type(m->specializations, type, NULL, 1, /*subtype*/0, /*offs*/0);
+ jl_typemap_entry_t *sf = jl_typemap_assoc_by_type(m->specializations, type, NULL, 1, /*subtype*/0, /*offs*/0, world);
if (sf && jl_is_lambda_info(sf->func.value) && ((jl_lambda_info_t*)sf->func.value)->code != jl_nothing)
return (jl_lambda_info_t*)sf->func.value;
jl_lambda_info_t *li = jl_get_specialized(m, type, sparams);
JL_GC_PUSH1(&li);
// TODO: fuse lookup and insert steps
- jl_typemap_insert(&m->specializations, (jl_value_t*)m, type, jl_emptysvec, NULL, jl_emptysvec, (jl_value_t*)li, 0, &tfunc_cache, 1, ~(size_t)0, NULL);
+ assert(world >= m->min_world && world <= m->max_world);
+ jl_typemap_insert(&m->specializations, (jl_value_t*)m, type, jl_emptysvec, NULL, jl_emptysvec, (jl_value_t*)li, 0, &tfunc_cache, m->min_world, m->max_world, NULL);
JL_GC_POP();
return li;
}
-JL_DLLEXPORT jl_value_t *jl_specializations_lookup(jl_method_t *m, jl_tupletype_t *type)
+JL_DLLEXPORT jl_value_t *jl_specializations_lookup(jl_method_t *m, jl_tupletype_t *type, size_t world)
{
- jl_typemap_entry_t *sf = jl_typemap_assoc_by_type(m->specializations, type, NULL, 2, /*subtype*/0, /*offs*/0);
+ jl_typemap_entry_t *sf = jl_typemap_assoc_by_type(m->specializations, type, NULL, 2, /*subtype*/0, /*offs*/0, world);
if (!sf)
return jl_nothing;
return sf->func.value;
}
-JL_DLLEXPORT jl_value_t *jl_methtable_lookup(jl_methtable_t *mt, jl_tupletype_t *type)
+JL_DLLEXPORT jl_value_t *jl_methtable_lookup(jl_methtable_t *mt, jl_tupletype_t *type, size_t world)
{
- jl_typemap_entry_t *sf = jl_typemap_assoc_by_type(mt->defs, type, NULL, 2, /*subtype*/0, /*offs*/0);
+ jl_typemap_entry_t *sf = jl_typemap_assoc_by_type(mt->defs, type, NULL, 2, /*subtype*/0, /*offs*/0, world);
if (!sf)
return jl_nothing;
return sf->func.value;
@@ -208,7 +213,7 @@ jl_lambda_info_t *jl_get_unspecialized(jl_lambda_info_t *method)
if "li" has been inferred before but the IR was deleted, returns a
new LambdaInfo with the IR reconstituted.
*/
-jl_lambda_info_t *jl_type_infer(jl_lambda_info_t *li, int force)
+jl_lambda_info_t *jl_type_infer(jl_lambda_info_t *li, size_t world, int force)
{
#ifdef ENABLE_INFERENCE
jl_module_t *mod = NULL;
@@ -222,15 +227,19 @@ jl_lambda_info_t *jl_type_infer(jl_lambda_info_t *li, int force)
(mod != jl_core_module || !lastIn)))) { // avoid any potential recursion in calling jl_typeinf_func on itself
JL_LOCK(&codegen_lock); // Might GC
assert(li->inInference == 0);
- jl_value_t *fargs[2];
+ jl_value_t *fargs[3];
fargs[0] = (jl_value_t*)jl_typeinf_func;
fargs[1] = (jl_value_t*)li;
+ fargs[2] = jl_box_ulong(world);
#ifdef TRACE_INFERENCE
jl_printf(JL_STDERR,"inference on ");
jl_static_show_func_sig(JL_STDERR, (jl_value_t*)li->specTypes);
jl_printf(JL_STDERR, "\n");
#endif
- li = (jl_lambda_info_t*)jl_apply(fargs, 2);
+ size_t last_age = jl_get_ptls_states()->world_age; // FIXME: should be typeinf age?
+ jl_get_ptls_states()->world_age = jl_world_counter;
+ li = (jl_lambda_info_t*)jl_apply(fargs, 3);
+ jl_get_ptls_states()->world_age = last_age;
assert(li->def || li->inInference == 0); // if this is toplevel expr, make sure inference finished
JL_UNLOCK(&codegen_lock); // Might GC
}
@@ -309,7 +318,7 @@ JL_DLLEXPORT void jl_set_typeinf_func(jl_value_t *f)
jl_reset_mt_caches(jl_main_module, unspec);
size_t i, l;
for (i = 0, l = jl_array_len(unspec); i < l; i++) {
- jl_type_infer((jl_lambda_info_t*)jl_array_ptr_ref(unspec, i), 1);
+ jl_type_infer((jl_lambda_info_t*)jl_array_ptr_ref(unspec, i), jl_world_counter, 1);
}
JL_GC_POP();
}
@@ -390,7 +399,9 @@ static jl_value_t *ml_matches(union jl_typemap_t ml, int offs,
static jl_lambda_info_t *cache_method(jl_methtable_t *mt, union jl_typemap_t *cache, jl_value_t *parent,
jl_tupletype_t *type, // the specialized type signature for type lambda
jl_tupletype_t *tt, // the original tupletype of the signature
- jl_typemap_entry_t *m, jl_svec_t *sparams)
+ jl_typemap_entry_t *m,
+ size_t world,
+ jl_svec_t *sparams)
{
JL_LOCK(&codegen_lock); // Might GC
size_t i;
@@ -639,7 +650,7 @@ static jl_lambda_info_t *cache_method(jl_methtable_t *mt, union jl_typemap_t *ca
}
// here we infer types and specialize the method
- newmeth = jl_specializations_get_linfo(definition, type, sparams);
+ newmeth = jl_specializations_get_linfo(definition, type, sparams, world);
if (cache_with_orig) {
// if there is a need to cache with one of the original signatures,
@@ -677,7 +688,8 @@ static jl_lambda_info_t *cache_method(jl_methtable_t *mt, union jl_typemap_t *ca
}
}
- jl_typemap_insert(cache, parent, origtype, jl_emptysvec, type, guardsigs, (jl_value_t*)newmeth, jl_cachearg_offset(mt), &lambda_cache, 1, ~(size_t)0, NULL);
+ jl_typemap_insert(cache, parent, origtype, jl_emptysvec, type, guardsigs, (jl_value_t*)newmeth, jl_cachearg_offset(mt), &lambda_cache, m->min_world, m->max_world, NULL);
+
JL_UNLOCK(&codegen_lock); // Might GC
if (definition->traced && jl_method_tracer)
jl_call_tracer(jl_method_tracer, (jl_value_t*)newmeth);
@@ -685,7 +697,7 @@ static jl_lambda_info_t *cache_method(jl_methtable_t *mt, union jl_typemap_t *ca
return newmeth;
}
-static jl_lambda_info_t *jl_mt_assoc_by_type(jl_methtable_t *mt, jl_datatype_t *tt, int cache, int inexact)
+static jl_lambda_info_t *jl_mt_assoc_by_type(jl_methtable_t *mt, jl_datatype_t *tt, int cache, int inexact, size_t world)
{
jl_typemap_entry_t *entry = NULL;
jl_svec_t *env = jl_emptysvec;
@@ -693,7 +705,7 @@ static jl_lambda_info_t *jl_mt_assoc_by_type(jl_methtable_t *mt, jl_datatype_t *
jl_tupletype_t *sig = NULL;
JL_GC_PUSH4(&env, &entry, &func, &sig);
- entry = jl_typemap_assoc_by_type(mt->defs, tt, &env, inexact, 1, 0);
+ entry = jl_typemap_assoc_by_type(mt->defs, tt, &env, inexact, 1, 0, world);
if (entry == NULL || entry == INEXACT_ENTRY) {
JL_GC_POP();
return NULL;
@@ -709,7 +721,7 @@ static jl_lambda_info_t *jl_mt_assoc_by_type(jl_methtable_t *mt, jl_datatype_t *
if (!cache)
nf = jl_get_specialized(m, sig, env);
else
- nf = cache_method(mt, &mt->cache, (jl_value_t*)mt, sig, tt, entry, env);
+ nf = cache_method(mt, &mt->cache, (jl_value_t*)mt, sig, tt, entry, world, env);
JL_GC_POP();
return nf;
}
@@ -776,7 +788,7 @@ static int check_ambiguous_visitor(jl_typemap_entry_t *oldentry, struct typemap_
// now we are checking that the reverse is true
if (!jl_args_morespecific((jl_value_t*)(closure->after ? type : sig),
(jl_value_t*)(closure->after ? sig : type))) {
- jl_typemap_entry_t *l = jl_typemap_assoc_by_type(map, (jl_tupletype_t*)isect, NULL, 0, 0, 0);
+ jl_typemap_entry_t *l = jl_typemap_assoc_by_type(map, (jl_tupletype_t*)isect, NULL, 0, 0, 0, closure->newentry->min_world);
if (l != NULL) // ok, intersection is covered
return 1;
jl_method_t *mambig = oldentry->func.method;
@@ -904,7 +916,7 @@ void jl_method_table_insert(jl_methtable_t *mt, jl_method_t *method, jl_tupletyp
JL_GC_PUSH3(&oldvalue, &env.match.env, &env.match.ti);
jl_typemap_entry_t *newentry = jl_typemap_insert(&mt->defs, (jl_value_t*)mt,
type, tvars, simpletype, jl_emptysvec, (jl_value_t*)method, 0, &method_defs,
- ++jl_world_counter, ~(size_t)0, &oldvalue);
+ method->min_world, method->max_world, &oldvalue);
if (oldvalue) {
method->ambig = ((jl_method_t*)oldvalue)->ambig;
method_overwrite(newentry, (jl_method_t*)oldvalue);
@@ -928,8 +940,8 @@ void jl_method_table_insert(jl_methtable_t *mt, jl_method_t *method, jl_tupletyp
env.match.fptr = invalidate_conflicting;
env.match.va = va;
env.match.type = (jl_value_t*)type;
- env.max_world = jl_world_counter - 1;
- jl_typemap_intersection_visitor(mt->cache, 0, &env.match);
+ env.max_world = method->min_world - 1;
+ jl_typemap_intersection_visitor(mt->cache, jl_cachearg_offset(mt), &env.match);
}
JL_GC_POP();
update_max_args(mt, type);
@@ -938,13 +950,8 @@ void jl_method_table_insert(jl_methtable_t *mt, jl_method_t *method, jl_tupletyp
void JL_NORETURN jl_method_error_bare(jl_function_t *f, jl_value_t *args)
{
- jl_value_t *fargs[3] = {
- (jl_value_t*)jl_methoderror_type,
- (jl_value_t*)f,
- args
- };
- if (fargs[0]) {
- jl_throw(jl_apply_generic(fargs, 3));
+ if (jl_methoderror_type) {
+ jl_throw(jl_new_struct(jl_methoderror_type, f, args));
}
else {
jl_printf((JL_STREAM*)STDERR_FILENO, "A method error occurred before the base MethodError type was defined. Aborting...\n");
@@ -1001,33 +1008,33 @@ jl_tupletype_t *arg_type_tuple(jl_value_t **args, size_t nargs)
}
jl_lambda_info_t *jl_method_lookup_by_type(jl_methtable_t *mt, jl_tupletype_t *types,
- int cache, int inexact)
+ int cache, int inexact, size_t world)
{
- jl_typemap_entry_t *entry = jl_typemap_assoc_by_type(mt->cache, types, NULL, 0, 1, jl_cachearg_offset(mt));
+ jl_typemap_entry_t *entry = jl_typemap_assoc_by_type(mt->cache, types, NULL, 0, 1, jl_cachearg_offset(mt), world);
jl_lambda_info_t *sf;
if (entry) {
sf = entry->func.linfo;
}
else {
if (jl_is_leaf_type((jl_value_t*)types)) cache=1;
- sf = jl_mt_assoc_by_type(mt, types, cache, inexact);
+ sf = jl_mt_assoc_by_type(mt, types, cache, inexact, world);
}
return sf;
}
-JL_DLLEXPORT int jl_method_exists(jl_methtable_t *mt, jl_tupletype_t *types)
+JL_DLLEXPORT int jl_method_exists(jl_methtable_t *mt, jl_tupletype_t *types, size_t world)
{
- return jl_method_lookup_by_type(mt, types, 0, 0) != NULL;
+ return jl_method_lookup_by_type(mt, types, 0, 0, world) != NULL;
}
-jl_lambda_info_t *jl_method_lookup(jl_methtable_t *mt, jl_value_t **args, size_t nargs, int cache)
+jl_lambda_info_t *jl_method_lookup(jl_methtable_t *mt, jl_value_t **args, size_t nargs, int cache, size_t world)
{
jl_lambda_info_t *sf;
- jl_typemap_entry_t *entry = jl_typemap_assoc_exact(mt->cache, args, nargs, jl_cachearg_offset(mt));
+ jl_typemap_entry_t *entry = jl_typemap_assoc_exact(mt->cache, args, nargs, jl_cachearg_offset(mt), world);
if (entry == NULL) {
jl_tupletype_t *tt = arg_type_tuple(args, nargs);
JL_GC_PUSH1(&tt);
- sf = jl_mt_assoc_by_type(mt, tt, cache, 0);
+ sf = jl_mt_assoc_by_type(mt, tt, cache, 0, world);
JL_GC_POP();
}
else {
@@ -1039,7 +1046,7 @@ jl_lambda_info_t *jl_method_lookup(jl_methtable_t *mt, jl_value_t **args, size_t
JL_DLLEXPORT jl_value_t *jl_matching_methods(jl_tupletype_t *types, int lim, int include_ambiguous);
-jl_lambda_info_t *jl_compile_for_dispatch(jl_lambda_info_t *li)
+jl_lambda_info_t *jl_compile_for_dispatch(jl_lambda_info_t *li, size_t world)
{
if (li->functionObjectsDecls.functionObject == NULL) {
if (li->inInference || li->inCompile) {
@@ -1052,7 +1059,7 @@ jl_lambda_info_t *jl_compile_for_dispatch(jl_lambda_info_t *li)
if (li->code == jl_nothing ||
(!li->inferred && li->def != NULL && jl_symbol_name(li->def->name)[0] != '@')) {
// don't bother with typeinf on macros or toplevel thunks
- jl_type_infer(li, 0);
+ jl_type_infer(li, world, 0);
}
if (li->functionObjectsDecls.functionObject == NULL) {
if (li->inInference || li->inCompile || li->code == jl_nothing) {
@@ -1064,7 +1071,7 @@ jl_lambda_info_t *jl_compile_for_dispatch(jl_lambda_info_t *li)
}
}
if (li->functionObjectsDecls.functionObject == NULL) { // check again, because jl_type_infer may have compiled it
- jl_compile_linfo(li);
+ jl_compile_linfo(li, world);
}
}
jl_generate_fptr(li);
@@ -1072,7 +1079,7 @@ jl_lambda_info_t *jl_compile_for_dispatch(jl_lambda_info_t *li)
}
// compile-time method lookup
-jl_lambda_info_t *jl_get_specialization1(jl_tupletype_t *types)
+jl_lambda_info_t *jl_get_specialization1(jl_tupletype_t *types, size_t world)
{
assert(jl_nparams(types) > 0);
if (!jl_is_leaf_type((jl_value_t*)types) || jl_has_typevars((jl_value_t*)types))
@@ -1100,7 +1107,7 @@ jl_lambda_info_t *jl_get_specialization1(jl_tupletype_t *types)
// not be the case
JL_GC_PUSH1(&sf);
JL_TRY {
- sf = jl_method_lookup_by_type(mt, types, 1, 1);
+ sf = jl_method_lookup_by_type(mt, types, 1, 1, world);
} JL_CATCH {
sf = NULL;
}
@@ -1114,7 +1121,7 @@ jl_lambda_info_t *jl_get_specialization1(jl_tupletype_t *types)
JL_DLLEXPORT int jl_compile_hint(jl_tupletype_t *types)
{
- jl_lambda_info_t *li = jl_get_specialization1(types);
+ jl_lambda_info_t *li = jl_get_specialization1(types, jl_world_counter);
if (li == NULL)
return 0;
if (li->functionObjectsDecls.functionObject == NULL) {
@@ -1122,17 +1129,17 @@ JL_DLLEXPORT int jl_compile_hint(jl_tupletype_t *types)
if (li->inInference)
return 0;
if (li->code == jl_nothing || !li->inferred)
- jl_type_infer(li, 0);
+ jl_type_infer(li, jl_world_counter, 0);
if (li->inInference || li->code == jl_nothing)
return 0;
- jl_compile_linfo(li);
+ jl_compile_linfo(li, jl_world_counter);
}
return 1;
}
-JL_DLLEXPORT jl_value_t *jl_get_spec_lambda(jl_tupletype_t *types)
+JL_DLLEXPORT jl_value_t *jl_get_spec_lambda(jl_tupletype_t *types, size_t world)
{
- jl_value_t *li = (jl_value_t*)jl_get_specialization1(types);
+ jl_value_t *li = (jl_value_t*)jl_get_specialization1(types, world);
return li ? li : jl_nothing;
}
@@ -1346,7 +1353,7 @@ static void _compile_all_deq(jl_array_t *found)
if (jl_is_method(ml->func.value)) {
// type infer a copy of the template, to avoid modifying the template itself
templ = ml->func.method->lambda_template;
- linfo = jl_specializations_get_linfo(ml->func.method, ml->sig, jl_emptysvec);
+ linfo = jl_specializations_get_linfo(ml->func.method, ml->sig, jl_emptysvec, jl_world_counter);
}
else if (jl_is_lambda_info(ml->func.value)) {
templ = ml->func.linfo;
@@ -1358,7 +1365,7 @@ static void _compile_all_deq(jl_array_t *found)
if (!linfo->inferred || linfo->code == jl_nothing) {
// force this function to be recompiled
- jl_type_infer(linfo, 1);
+ jl_type_infer(linfo, jl_world_counter, 1);
}
// keep track of whether all possible signatures have been cached (and thus whether it can skip trying to compile the template function)
@@ -1370,7 +1377,7 @@ static void _compile_all_deq(jl_array_t *found)
templ->functionID = -1;
}
else {
- jl_compile_linfo(linfo);
+ jl_compile_linfo(linfo, jl_world_counter);
assert(linfo->functionID > 0);
if (linfo != templ) {
// copy the function pointer back to the lambda_template
@@ -1639,6 +1646,7 @@ JL_DLLEXPORT jl_value_t *jl_apply_generic(jl_value_t **args, uint32_t nargs)
if (traceen)
show_call(args[0], &args[1], nargs-1);
#endif
+ size_t world = jl_get_ptls_states()->world_age;
/*
search order:
@@ -1672,7 +1680,7 @@ JL_DLLEXPORT jl_value_t *jl_apply_generic(jl_value_t **args, uint32_t nargs)
// if (entry == NULL) {
// jl_value_t *F = args[0];
// mt = jl_gf_mtable(F);
-// entry = jl_typemap_assoc_exact(mt->cache, args, nargs, jl_cachearg_offset(mt));
+// entry = jl_typemap_assoc_exact(mt->cache, args, nargs, jl_cachearg_offset(mt), world);
// if (entry && entry->isleafsig && entry->simplesig == (void*)jl_nothing && entry->guardsigs == jl_emptysvec) {
// switch (++pick_which[cache_idx1] & 1) {
// case 0:
@@ -1706,7 +1714,7 @@ JL_DLLEXPORT jl_value_t *jl_apply_generic(jl_value_t **args, uint32_t nargs)
//
// jl_value_t *F = args[0];
// mt = jl_gf_mtable(F);
-// entry = jl_typemap_assoc_exact(mt->cache, args, nargs, jl_cachearg_offset(mt));
+// entry = jl_typemap_assoc_exact(mt->cache, args, nargs, jl_cachearg_offset(mt), world);
// if (entry && entry->isleafsig && entry->simplesig == (void*)jl_nothing && entry->guardsigs == jl_emptysvec) {
// switch (++pick_which[cache_idx1] & 3) {
// case 0:
@@ -1745,7 +1753,8 @@ JL_DLLEXPORT jl_value_t *jl_apply_generic(jl_value_t **args, uint32_t nargs)
for (i = 0; i < 4; i++) {
entry = call_cache[cache_idx[i]];
if (entry && nargs == jl_svec_len(entry->sig->parameters) &&
- sig_match_fast(args, jl_svec_data(entry->sig->parameters), 0, nargs)) {
+ sig_match_fast(args, jl_svec_data(entry->sig->parameters), 0, nargs) &&
+ world >= entry->min_world && world <= entry->max_world) {
break;
}
}
@@ -1753,7 +1762,7 @@ JL_DLLEXPORT jl_value_t *jl_apply_generic(jl_value_t **args, uint32_t nargs)
if (i == 4) {
jl_value_t *F = args[0];
mt = jl_gf_mtable(F);
- entry = jl_typemap_assoc_exact(mt->cache, args, nargs, jl_cachearg_offset(mt));
+ entry = jl_typemap_assoc_exact(mt->cache, args, nargs, jl_cachearg_offset(mt), world);
if (entry && entry->isleafsig && entry->simplesig == (void*)jl_nothing && entry->guardsigs == jl_emptysvec) {
// put the entry into the cache if it's valid for a leaftype lookup,
// using pick_which to slightly randomize where it ends up
@@ -1769,7 +1778,7 @@ JL_DLLEXPORT jl_value_t *jl_apply_generic(jl_value_t **args, uint32_t nargs)
// if running inference overwrites this particular method, it becomes
// unreachable from the method table, so root mfunc.
JL_GC_PUSH2(&tt, &mfunc);
- mfunc = jl_mt_assoc_by_type(mt, tt, 1, 0);
+ mfunc = jl_mt_assoc_by_type(mt, tt, 1, 0, world);
if (mfunc == NULL) {
#ifdef JL_TRACE
@@ -1794,11 +1803,11 @@ JL_DLLEXPORT jl_value_t *jl_apply_generic(jl_value_t **args, uint32_t nargs)
return verify_type(res);
}
-JL_DLLEXPORT jl_value_t *jl_gf_invoke_lookup(jl_datatype_t *types)
+JL_DLLEXPORT jl_value_t *jl_gf_invoke_lookup(jl_datatype_t *types, size_t world)
{
jl_methtable_t *mt = ((jl_datatype_t*)jl_tparam0(types))->name->mt;
jl_typemap_entry_t *entry = jl_typemap_assoc_by_type(mt->defs, types, /*don't record env*/NULL,
- /*exact match*/0, /*subtype*/1, /*offs*/0);
+ /*exact match*/0, /*subtype*/1, /*offs*/0, world);
if (!entry)
return jl_nothing;
return (jl_value_t*)entry;
@@ -1815,6 +1824,7 @@ JL_DLLEXPORT jl_value_t *jl_gf_invoke_lookup(jl_datatype_t *types)
// NOTE: assumes argument type is a subtype of the lookup type.
jl_value_t *jl_gf_invoke(jl_tupletype_t *types0, jl_value_t **args, size_t nargs)
{
+ size_t world = jl_get_ptls_states()->world_age;
jl_svec_t *tpenv = jl_emptysvec;
jl_tupletype_t *newsig = NULL;
jl_tupletype_t *tt = NULL;
@@ -1824,7 +1834,7 @@ jl_value_t *jl_gf_invoke(jl_tupletype_t *types0, jl_value_t **args, size_t nargs
jl_value_t *gf = args[0];
types = (jl_datatype_t*)jl_argtype_with_function(gf, (jl_tupletype_t*)types0);
jl_methtable_t *mt = jl_gf_mtable(gf);
- jl_typemap_entry_t *entry = (jl_typemap_entry_t*)jl_gf_invoke_lookup(types);
+ jl_typemap_entry_t *entry = (jl_typemap_entry_t*)jl_gf_invoke_lookup(types, world);
if ((jl_value_t*)entry == jl_nothing) {
jl_method_error_bare(gf, (jl_value_t*)types0);
@@ -1837,7 +1847,7 @@ jl_value_t *jl_gf_invoke(jl_tupletype_t *types0, jl_value_t **args, size_t nargs
jl_lambda_info_t *mfunc = NULL;
jl_typemap_entry_t *tm = NULL;
if (entry->func.method->invokes.unknown != NULL)
- tm = jl_typemap_assoc_exact(entry->func.method->invokes, args, nargs, jl_cachearg_offset(mt));
+ tm = jl_typemap_assoc_exact(entry->func.method->invokes, args, nargs, jl_cachearg_offset(mt), world);
if (tm == NULL) {
tt = arg_type_tuple(args, nargs);
if (entry->tvars != jl_emptysvec) {
@@ -1852,7 +1862,7 @@ jl_value_t *jl_gf_invoke(jl_tupletype_t *types0, jl_value_t **args, size_t nargs
if (func->invokes.unknown == NULL)
func->invokes.unknown = jl_nothing;
- mfunc = cache_method(mt, &func->invokes, entry->func.value, sig, tt, entry, tpenv);
+ mfunc = cache_method(mt, &func->invokes, entry->func.value, sig, tt, entry, world, tpenv);
}
else {
mfunc = tm->func.linfo;
diff --git a/src/init.c b/src/init.c
index 9db6f36df98bc..9764435286a2e 100644
--- a/src/init.c
+++ b/src/init.c
@@ -230,7 +230,10 @@ JL_DLLEXPORT void jl_atexit_hook(int exitcode)
jl_value_t *f = jl_get_global(jl_base_module, jl_symbol("_atexit"));
if (f != NULL) {
JL_TRY {
+ size_t last_age = jl_get_ptls_states()->world_age;
+ jl_get_ptls_states()->world_age = jl_get_world_counter();
jl_apply(&f, 1);
+ jl_get_ptls_states()->world_age = last_age;
}
JL_CATCH {
jl_printf(JL_STDERR, "\natexit hook threw an error: ");
diff --git a/src/interpreter.c b/src/interpreter.c
index 8d83eec54bd65..c8f4ee35dc7df 100644
--- a/src/interpreter.c
+++ b/src/interpreter.c
@@ -28,7 +28,11 @@ int jl_is_toplevel_only_expr(jl_value_t *e);
jl_value_t *jl_interpret_toplevel_expr(jl_value_t *e)
{
- return eval(e, NULL);
+ size_t last_age = jl_get_ptls_states()->world_age;
+ jl_get_ptls_states()->world_age = jl_world_counter;
+ jl_value_t *ret = eval(e, NULL);
+ jl_get_ptls_states()->world_age = last_age;
+ return ret;
}
JL_DLLEXPORT jl_value_t *jl_interpret_toplevel_expr_in(jl_module_t *m, jl_value_t *e,
@@ -439,7 +443,10 @@ static jl_value_t *eval(jl_value_t *e, interpreter_state *s)
jl_value_t *jl_toplevel_eval_body(jl_array_t *stmts)
{
- return eval_body(stmts, NULL, 0, 1);
+ size_t last_age = jl_get_ptls_states()->world_age;
+ jl_value_t *ret = eval_body(stmts, NULL, 0, 1);
+ jl_get_ptls_states()->world_age = last_age;
+ return ret;
}
static jl_value_t *eval_body(jl_array_t *stmts, interpreter_state *s, int start, int toplevel)
@@ -450,15 +457,17 @@ static jl_value_t *eval_body(jl_array_t *stmts, interpreter_state *s, int start,
while (1) {
if (i >= ns)
jl_error("`body` expression must terminate in `return`. Use `block` instead.");
- jl_value_t *stmt = jl_array_ptr_ref(stmts,i);
+ if (toplevel)
+ jl_get_ptls_states()->world_age = jl_world_counter;
+ jl_value_t *stmt = jl_array_ptr_ref(stmts, i);
if (jl_is_gotonode(stmt)) {
- i = jl_gotonode_label(stmt)-1;
+ i = jl_gotonode_label(stmt) - 1;
continue;
}
else if (jl_is_expr(stmt)) {
jl_sym_t *head = ((jl_expr_t*)stmt)->head;
if (head == return_sym) {
- jl_value_t *ex = jl_exprarg(stmt,0);
+ jl_value_t *ex = jl_exprarg(stmt, 0);
if (toplevel && jl_is_toplevel_only_expr(ex))
return jl_toplevel_eval(ex);
else
@@ -466,7 +475,7 @@ static jl_value_t *eval_body(jl_array_t *stmts, interpreter_state *s, int start,
}
else if (head == assign_sym) {
jl_value_t *sym = jl_exprarg(stmt, 0);
- jl_value_t *rhs = eval(jl_exprarg(stmt,1), s);
+ jl_value_t *rhs = eval(jl_exprarg(stmt, 1), s);
if (jl_is_ssavalue(sym)) {
ssize_t genid = ((jl_ssavalue_t*)sym)->id;
if (genid >= jl_linfo_nssavalues(s->lam) || genid < 0)
@@ -485,7 +494,7 @@ static jl_value_t *eval_body(jl_array_t *stmts, interpreter_state *s, int start,
sym = (jl_value_t*)jl_globalref_name(sym);
}
else {
- m = (s==NULL || s->lam==NULL || s->lam->def==NULL) ? jl_current_module : s->lam->def->module;
+ m = (s == NULL || s->lam == NULL || s->lam->def == NULL) ? jl_current_module : s->lam->def->module;
}
assert(jl_is_symbol(sym));
JL_GC_PUSH1(&rhs);
@@ -495,9 +504,9 @@ static jl_value_t *eval_body(jl_array_t *stmts, interpreter_state *s, int start,
}
}
else if (head == goto_ifnot_sym) {
- jl_value_t *cond = eval(jl_exprarg(stmt,0), s);
+ jl_value_t *cond = eval(jl_exprarg(stmt, 0), s);
if (cond == jl_false) {
- i = jl_unbox_long(jl_exprarg(stmt, 1))-1;
+ i = jl_unbox_long(jl_exprarg(stmt, 1)) - 1;
continue;
}
else if (cond != jl_true) {
@@ -506,20 +515,20 @@ static jl_value_t *eval_body(jl_array_t *stmts, interpreter_state *s, int start,
}
else if (head == line_sym) {
if (toplevel)
- jl_lineno = jl_unbox_long(jl_exprarg(stmt,0));
+ jl_lineno = jl_unbox_long(jl_exprarg(stmt, 0));
// TODO: interpreted function line numbers
}
else if (head == enter_sym) {
jl_enter_handler(&__eh);
if (!jl_setjmp(__eh.eh_ctx,1)) {
- return eval_body(stmts, s, i+1, toplevel);
+ return eval_body(stmts, s, i + 1, toplevel);
}
else {
#ifdef _OS_WINDOWS_
if (jl_exception_in_transit == jl_stackovf_exception)
_resetstkoflw();
#endif
- i = jl_unbox_long(jl_exprarg(stmt,0))-1;
+ i = jl_unbox_long(jl_exprarg(stmt, 0)) - 1;
continue;
}
}
@@ -540,11 +549,11 @@ static jl_value_t *eval_body(jl_array_t *stmts, interpreter_state *s, int start,
// TODO: interpreted function line numbers
}
else if (jl_is_newvarnode(stmt)) {
- jl_value_t *var = jl_fieldref(stmt,0);
+ jl_value_t *var = jl_fieldref(stmt, 0);
assert(jl_is_slot(var));
ssize_t n = jl_slot_number(var);
assert(n <= jl_linfo_nslots(s->lam) && n > 0);
- s->locals[n-1] = NULL;
+ s->locals[n - 1] = NULL;
}
else {
eval(stmt, s);
@@ -562,22 +571,27 @@ jl_value_t *jl_interpret_call(jl_lambda_info_t *lam, jl_value_t **args, uint32_t
jl_value_t **locals;
JL_GC_PUSHARGS(locals, jl_linfo_nslots(lam) + jl_linfo_nssavalues(lam));
interpreter_state s;
- s.lam = lam; s.locals = locals; s.sparam_vals = sparam_vals;
+ s.lam = lam;
+ s.locals = locals;
+ s.sparam_vals = sparam_vals;
size_t i;
- for(i=0; i < lam->nargs; i++) {
- if (lam->isva && i == lam->nargs-1)
- locals[i] = jl_f_tuple(NULL, &args[i], nargs-i);
+ for (i = 0; i < lam->nargs; i++) {
+ if (lam->isva && i == lam->nargs - 1)
+ locals[i] = jl_f_tuple(NULL, &args[i], nargs - i);
else
locals[i] = args[i];
}
- jl_value_t *r = eval_body(stmts, &s, 0, lam->nargs==0);
+ jl_value_t *r = eval_body(stmts, &s, 0, lam->def == NULL);
JL_GC_POP();
return r;
}
jl_value_t *jl_interpret_toplevel_thunk(jl_lambda_info_t *lam)
{
- return jl_interpret_call(lam, NULL, 0, NULL);
+ size_t last_age = jl_get_ptls_states()->world_age;
+ jl_value_t *ret = jl_interpret_call(lam, NULL, 0, NULL);
+ jl_get_ptls_states()->world_age = last_age;
+ return ret;
}
#ifdef __cplusplus
diff --git a/src/jl_uv.c b/src/jl_uv.c
index 0e862db4c77cc..43c7a8714ae89 100644
--- a/src/jl_uv.c
+++ b/src/jl_uv.c
@@ -100,8 +100,12 @@ JL_DLLEXPORT void jl_uv_closeHandle(uv_handle_t *handle)
if (handle == (uv_handle_t*)JL_STDERR)
JL_STDERR = (JL_STREAM*)STDERR_FILENO;
// also let the client app do its own cleanup
- if (handle->type != UV_FILE && handle->data)
+ if (handle->type != UV_FILE && handle->data) {
+ size_t last_age = jl_get_ptls_states()->world_age;
+ jl_get_ptls_states()->world_age = jl_world_counter;
jl_uv_call_close_callback((jl_value_t*)handle->data);
+ jl_get_ptls_states()->world_age = last_age;
+ }
if (handle == (uv_handle_t*)&signal_async)
return;
free(handle);
diff --git a/src/jlapi.c b/src/jlapi.c
index a169b8bc302f2..b6cf870734bfc 100644
--- a/src/jlapi.c
+++ b/src/jlapi.c
@@ -56,7 +56,10 @@ JL_DLLEXPORT jl_value_t *jl_eval_string(const char *str)
jl_value_t *ast = jl_parse_input_line(str, strlen(str),
filename, strlen(filename));
JL_GC_PUSH1(&ast);
+ size_t last_age = jl_get_ptls_states()->world_age;
+ jl_get_ptls_states()->world_age = jl_get_world_counter();
r = jl_toplevel_eval(ast);
+ jl_get_ptls_states()->world_age = last_age;
JL_GC_POP();
jl_exception_clear();
}
@@ -121,7 +124,10 @@ JL_DLLEXPORT jl_value_t *jl_call(jl_function_t *f, jl_value_t **args, int32_t na
argv[0] = (jl_value_t*)f;
for(int i=1; iworld_age;
+ jl_get_ptls_states()->world_age = jl_get_world_counter();
v = jl_apply(argv, nargs+1);
+ jl_get_ptls_states()->world_age = last_age;
JL_GC_POP();
jl_exception_clear();
}
@@ -136,7 +142,10 @@ JL_DLLEXPORT jl_value_t *jl_call0(jl_function_t *f)
jl_value_t *v;
JL_TRY {
JL_GC_PUSH1(&f);
+ size_t last_age = jl_get_ptls_states()->world_age;
+ jl_get_ptls_states()->world_age = jl_get_world_counter();
v = jl_apply(&f, 1);
+ jl_get_ptls_states()->world_age = last_age;
JL_GC_POP();
jl_exception_clear();
}
@@ -153,7 +162,10 @@ JL_DLLEXPORT jl_value_t *jl_call1(jl_function_t *f, jl_value_t *a)
jl_value_t **argv;
JL_GC_PUSHARGS(argv, 2);
argv[0] = f; argv[1] = a;
+ size_t last_age = jl_get_ptls_states()->world_age;
+ jl_get_ptls_states()->world_age = jl_get_world_counter();
v = jl_apply(argv, 2);
+ jl_get_ptls_states()->world_age = last_age;
JL_GC_POP();
jl_exception_clear();
}
@@ -170,7 +182,10 @@ JL_DLLEXPORT jl_value_t *jl_call2(jl_function_t *f, jl_value_t *a, jl_value_t *b
jl_value_t **argv;
JL_GC_PUSHARGS(argv, 3);
argv[0] = f; argv[1] = a; argv[2] = b;
+ size_t last_age = jl_get_ptls_states()->world_age;
+ jl_get_ptls_states()->world_age = jl_get_world_counter();
v = jl_apply(argv, 3);
+ jl_get_ptls_states()->world_age = last_age;
JL_GC_POP();
jl_exception_clear();
}
@@ -188,7 +203,10 @@ JL_DLLEXPORT jl_value_t *jl_call3(jl_function_t *f, jl_value_t *a,
jl_value_t **argv;
JL_GC_PUSHARGS(argv, 4);
argv[0] = f; argv[1] = a; argv[2] = b; argv[3] = c;
+ size_t last_age = jl_get_ptls_states()->world_age;
+ jl_get_ptls_states()->world_age = jl_get_world_counter();
v = jl_apply(argv, 4);
+ jl_get_ptls_states()->world_age = last_age;
JL_GC_POP();
jl_exception_clear();
}
diff --git a/src/jltypes.c b/src/jltypes.c
index da0407420ccf7..954730240721b 100644
--- a/src/jltypes.c
+++ b/src/jltypes.c
@@ -3668,13 +3668,15 @@ void jl_init_types(void)
jl_method_type =
jl_new_datatype(jl_symbol("Method"),
jl_any_type, jl_emptysvec,
- jl_svec(15,
+ jl_svec(17,
jl_symbol("name"),
jl_symbol("module"),
jl_symbol("file"),
jl_symbol("line"),
jl_symbol("sig"),
jl_symbol("tvars"),
+ jl_symbol("min-age"),
+ jl_symbol("max-age"),
jl_symbol("ambig"),
jl_symbol("specializations"),
jl_symbol("lambda_template"),
@@ -3684,23 +3686,25 @@ void jl_init_types(void)
jl_symbol("isstaged"),
jl_symbol("needs_sparam_vals_ducttape"),
jl_symbol("")),
- jl_svec(15,
+ jl_svec(17,
jl_sym_type,
jl_module_type,
jl_sym_type,
jl_int32_type,
jl_type_type,
- jl_any_type,
+ jl_any_type, // Union{TypeVar, SimpleVector}
+ jl_long_type,
+ jl_long_type,
jl_any_type, // Union{Array, Void}
- jl_any_type,
- jl_any_type,
+ jl_any_type, // TypeMap
+ jl_any_type, // LambdaInfo
jl_array_any_type,
jl_any_type,
jl_int32_type,
jl_bool_type,
jl_bool_type,
jl_bool_type),
- 0, 1, 8);
+ 0, 1, 11);
jl_lambda_info_type =
jl_new_datatype(jl_symbol("LambdaInfo"),
@@ -3755,7 +3759,7 @@ void jl_init_types(void)
jl_int32_type, jl_int32_type),
0, 1, 7);
jl_svecset(jl_lambda_info_type->types, 9, jl_lambda_info_type);
- jl_svecset(jl_method_type->types, 8, jl_lambda_info_type);
+ jl_svecset(jl_method_type->types, 10, jl_lambda_info_type);
jl_typector_type =
jl_new_datatype(jl_symbol("TypeConstructor"),
diff --git a/src/julia.h b/src/julia.h
index 75defc8201c16..c7316ae81585a 100644
--- a/src/julia.h
+++ b/src/julia.h
@@ -202,10 +202,14 @@ typedef struct _jl_method_t {
jl_sym_t *file;
int32_t line;
- // method's type signature. partly redundant with lambda_template->specTypes
+ // partly redundant with the containing TypeMapEntry
+ // method's type signature
jl_tupletype_t *sig;
- // bound type variables (static parameters). redundant with TypeMapEntry->tvars
+ // bound type variables (static parameters)
jl_svec_t *tvars;
+ size_t min_world;
+ size_t max_world;
+
// list of potentially-ambiguous methods (nothing = none, Vector{Any} of Methods otherwise)
jl_value_t *ambig;
@@ -1031,6 +1035,7 @@ JL_DLLEXPORT jl_value_t *jl_generic_function_def(jl_sym_t *name, jl_value_t **bp
jl_value_t *bp_owner,
jl_binding_t *bnd);
JL_DLLEXPORT void jl_method_def(jl_svec_t *argdata, jl_lambda_info_t *f, jl_value_t *isstaged);
+JL_DLLEXPORT size_t jl_get_world_counter(void);
JL_DLLEXPORT jl_function_t *jl_get_kwsorter(jl_typename_t *tn);
JL_DLLEXPORT jl_value_t *jl_box_bool(int8_t x);
JL_DLLEXPORT jl_value_t *jl_box_int8(int8_t x);
@@ -1419,6 +1424,7 @@ typedef struct _jl_handler_t {
#endif
sig_atomic_t defer_signal;
int finalizers_inhibited;
+ size_t world_age;
} jl_handler_t;
typedef struct _jl_task_t {
@@ -1520,6 +1526,7 @@ STATIC_INLINE void jl_eh_restore_state(jl_handler_t *eh)
locks->len = eh->locks_len;
}
#endif
+ ptls->world_age = eh->world_age;
ptls->defer_signal = eh->defer_signal;
ptls->gc_state = eh->gc_state;
ptls->finalizers_inhibited = eh->finalizers_inhibited;
diff --git a/src/julia_internal.h b/src/julia_internal.h
index b7500f8cf7d16..075dfd812168b 100644
--- a/src/julia_internal.h
+++ b/src/julia_internal.h
@@ -70,11 +70,11 @@ STATIC_INLINE jl_value_t *newstruct(jl_datatype_t *type)
return jv;
}
-jl_lambda_info_t *jl_type_infer(jl_lambda_info_t *li, int force);
+jl_lambda_info_t *jl_type_infer(jl_lambda_info_t *li, size_t world, int force);
void jl_generate_fptr(jl_lambda_info_t *li);
-void jl_compile_linfo(jl_lambda_info_t *li);
+void jl_compile_linfo(jl_lambda_info_t *li, size_t world);
JL_DLLEXPORT int jl_compile_hint(jl_tupletype_t *types);
-jl_lambda_info_t *jl_compile_for_dispatch(jl_lambda_info_t *li);
+jl_lambda_info_t *jl_compile_for_dispatch(jl_lambda_info_t *li, size_t world);
// invoke (compiling if necessary) the jlcall function pointer for a method
jl_lambda_info_t *jl_get_unspecialized(jl_lambda_info_t *method);
@@ -82,7 +82,7 @@ STATIC_INLINE jl_value_t *jl_call_method_internal(jl_lambda_info_t *meth, jl_val
{
jl_lambda_info_t *mfptr = meth;
if (__unlikely(mfptr->fptr == NULL))
- mfptr = jl_compile_for_dispatch(mfptr);
+ mfptr = jl_compile_for_dispatch(mfptr, jl_get_ptls_states()->world_age);
if (mfptr->jlcall_api == 0)
return mfptr->fptr(args[0], &args[1], nargs-1);
else
@@ -201,8 +201,8 @@ int jl_is_toplevel_only_expr(jl_value_t *e);
jl_value_t *jl_call_scm_on_ast(char *funcname, jl_value_t *expr);
jl_lambda_info_t *jl_method_lookup_by_type(jl_methtable_t *mt, jl_tupletype_t *types,
- int cache, int inexact);
-jl_lambda_info_t *jl_method_lookup(jl_methtable_t *mt, jl_value_t **args, size_t nargs, int cache);
+ int cache, int inexact, size_t world);
+jl_lambda_info_t *jl_method_lookup(jl_methtable_t *mt, jl_value_t **args, size_t nargs, int cache, size_t world);
jl_value_t *jl_gf_invoke(jl_tupletype_t *types, jl_value_t **args, size_t nargs);
jl_datatype_t *jl_first_argument_datatype(jl_value_t *argtypes);
@@ -313,7 +313,7 @@ int32_t jl_get_llvm_gv(jl_value_t *p);
void jl_idtable_rehash(jl_array_t **pa, size_t newsz);
JL_DLLEXPORT jl_methtable_t *jl_new_method_table(jl_sym_t *name, jl_module_t *module);
-jl_lambda_info_t *jl_get_specialization1(jl_tupletype_t *types);
+jl_lambda_info_t *jl_get_specialization1(jl_tupletype_t *types, size_t world);
int jl_has_call_ambiguities(jl_tupletype_t *types, jl_method_t *m);
jl_function_t *jl_module_get_initializer(jl_module_t *m);
@@ -606,18 +606,18 @@ jl_typemap_entry_t *jl_typemap_insert(union jl_typemap_t *cache, jl_value_t *par
jl_value_t **overwritten);
jl_typemap_entry_t *jl_typemap_assoc_by_type(union jl_typemap_t ml_or_cache, jl_tupletype_t *types, jl_svec_t **penv,
- int8_t subtype_inexact__sigseq_useenv, int8_t subtype, int8_t offs);
+ int8_t subtype_inexact__sigseq_useenv, int8_t subtype, int8_t offs, size_t world);
static jl_typemap_entry_t *const INEXACT_ENTRY = (jl_typemap_entry_t*)(uintptr_t)-1;
-jl_typemap_entry_t *jl_typemap_level_assoc_exact(jl_typemap_level_t *cache, jl_value_t **args, size_t n, int8_t offs);
-jl_typemap_entry_t *jl_typemap_entry_assoc_exact(jl_typemap_entry_t *mn, jl_value_t **args, size_t n);
-STATIC_INLINE jl_typemap_entry_t *jl_typemap_assoc_exact(union jl_typemap_t ml_or_cache, jl_value_t **args, size_t n, int8_t offs)
+jl_typemap_entry_t *jl_typemap_level_assoc_exact(jl_typemap_level_t *cache, jl_value_t **args, size_t n, int8_t offs, size_t world);
+jl_typemap_entry_t *jl_typemap_entry_assoc_exact(jl_typemap_entry_t *mn, jl_value_t **args, size_t n, size_t world);
+STATIC_INLINE jl_typemap_entry_t *jl_typemap_assoc_exact(union jl_typemap_t ml_or_cache, jl_value_t **args, size_t n, int8_t offs, size_t world)
{
// NOTE: This function is a huge performance hot spot!!
if (jl_typeof(ml_or_cache.unknown) == (jl_value_t*)jl_typemap_entry_type) {
- return jl_typemap_entry_assoc_exact(ml_or_cache.leaf, args, n);
+ return jl_typemap_entry_assoc_exact(ml_or_cache.leaf, args, n, world);
}
else if (jl_typeof(ml_or_cache.unknown) == (jl_value_t*)jl_typemap_level_type) {
- return jl_typemap_level_assoc_exact(ml_or_cache.node, args, n, offs);
+ return jl_typemap_level_assoc_exact(ml_or_cache.node, args, n, offs, world);
}
return NULL;
}
diff --git a/src/module.c b/src/module.c
index 53f7846fcb1ab..05afd794e6ae0 100644
--- a/src/module.c
+++ b/src/module.c
@@ -597,7 +597,6 @@ void jl_module_run_initializer(jl_module_t *m)
jl_get_ptls_states()->world_age = last_age;
}
JL_CATCH {
- jl_get_ptls_states()->world_age = last_age;
if (jl_initerror_type == NULL) {
jl_rethrow();
}
diff --git a/src/task.c b/src/task.c
index eb0bc90b2bfa7..555617aada6d8 100644
--- a/src/task.c
+++ b/src/task.c
@@ -254,6 +254,7 @@ static void NOINLINE JL_NORETURN start_task(void)
jl_gc_wb(t, res);
}
}
+ jl_get_ptls_states()->world_age = jl_world_counter; // TODO
finish_task(t, res);
gc_debug_critical_error();
abort();
diff --git a/src/toplevel.c b/src/toplevel.c
index fe56ab3f0952d..38e746ecd979a 100644
--- a/src/toplevel.c
+++ b/src/toplevel.c
@@ -174,7 +174,6 @@ jl_value_t *jl_eval_module_expr(jl_expr_t *ex)
}
}
JL_CATCH {
- ptls->world_age = last_age;
ptls->current_module = last_module;
ptls->current_task->current_module = task_last_m;
outermost = prev_outermost;
@@ -543,7 +542,7 @@ jl_value_t *jl_toplevel_eval_flex(jl_value_t *e, int fast, int expanded)
thk->specTypes = (jl_tupletype_t*)jl_typeof(jl_emptytuple); // no gc_wb needed
if (ewc) {
- jl_type_infer(thk, 0);
+ jl_type_infer(thk, jl_get_ptls_states()->world_age, 0);
jl_value_t *dummy_f_arg=NULL;
result = jl_call_method_internal(thk, &dummy_f_arg, 1);
}
diff --git a/src/typemap.c b/src/typemap.c
index 1431f05a4bafe..987c30160630b 100644
--- a/src/typemap.c
+++ b/src/typemap.c
@@ -533,11 +533,12 @@ int sigs_eq(jl_value_t *a, jl_value_t *b, int useenv)
there tends to be lots of variation there. The type of the 0th argument
(the function) is always the same for most functions.
*/
-static jl_typemap_entry_t *jl_typemap_assoc_by_type_(jl_typemap_entry_t *ml, jl_tupletype_t *types, int8_t inexact, jl_svec_t **penv)
+static jl_typemap_entry_t *jl_typemap_assoc_by_type_(jl_typemap_entry_t *ml, jl_tupletype_t *types,
+ int8_t inexact, jl_svec_t **penv, size_t world)
{
size_t n = jl_datatype_nfields(types);
for (; ml != (void*)jl_nothing; ml = ml->next) {
- if (ml->max_world != ~(size_t)0)
+ if (world < ml->min_world || world > ml->max_world)
continue; // ignore replaced methods
size_t lensig = jl_datatype_nfields(ml->sig);
if (lensig == n || (ml->va && lensig <= n+1)) {
@@ -623,14 +624,15 @@ static jl_typemap_entry_t *jl_typemap_assoc_by_type_(jl_typemap_entry_t *ml, jl_
return NULL;
}
-static jl_typemap_entry_t *jl_typemap_lookup_by_type_(jl_typemap_entry_t *ml, jl_tupletype_t *types, int8_t useenv)
+static jl_typemap_entry_t *jl_typemap_lookup_by_type_(jl_typemap_entry_t *ml, jl_tupletype_t *types, int8_t useenv, size_t world)
{
- while (ml != (void*)jl_nothing) {
+ for (; ml != (void*)jl_nothing; ml = ml->next) {
+ if (world < ml->min_world || world > ml->max_world)
+ continue;
// TODO: more efficient
if (sigs_eq((jl_value_t*)types, (jl_value_t*)ml->sig, useenv)) {
return ml;
}
- ml = ml->next;
}
return NULL;
}
@@ -639,7 +641,7 @@ static jl_typemap_entry_t *jl_typemap_lookup_by_type_(jl_typemap_entry_t *ml, jl
// this is the general entry point for looking up a type in the cache
// (as a subtype, or with typeseq)
jl_typemap_entry_t *jl_typemap_assoc_by_type(union jl_typemap_t ml_or_cache, jl_tupletype_t *types, jl_svec_t **penv,
- int8_t subtype_inexact__sigseq_useenv, int8_t subtype, int8_t offs)
+ int8_t subtype_inexact__sigseq_useenv, int8_t subtype, int8_t offs, size_t world)
{
if (jl_typeof(ml_or_cache.unknown) == (jl_value_t*)jl_typemap_level_type) {
jl_typemap_level_t *cache = ml_or_cache.node;
@@ -664,7 +666,7 @@ jl_typemap_entry_t *jl_typemap_assoc_by_type(union jl_typemap_t ml_or_cache, jl_
// If there is a type at offs, look in the optimized caches
if (!subtype) {
if (ty && jl_is_any(ty))
- return jl_typemap_assoc_by_type(cache->any, types, penv, subtype_inexact__sigseq_useenv, subtype, offs+1);
+ return jl_typemap_assoc_by_type(cache->any, types, penv, subtype_inexact__sigseq_useenv, subtype, offs+1, world);
if (isva) // in lookup mode, want to match Vararg exactly, not as a subtype
ty = NULL;
}
@@ -675,7 +677,7 @@ jl_typemap_entry_t *jl_typemap_assoc_by_type(union jl_typemap_t ml_or_cache, jl_
union jl_typemap_t ml = mtcache_hash_lookup(cache->targ, a0, 1, offs);
if (ml.unknown != jl_nothing) {
jl_typemap_entry_t *li = jl_typemap_assoc_by_type(ml, types, penv,
- subtype_inexact__sigseq_useenv, subtype, offs+1);
+ subtype_inexact__sigseq_useenv, subtype, offs+1, world);
if (li) return li;
}
}
@@ -685,7 +687,7 @@ jl_typemap_entry_t *jl_typemap_assoc_by_type(union jl_typemap_t ml_or_cache, jl_
union jl_typemap_t ml = mtcache_hash_lookup(cache->arg1, ty, 0, offs);
if (ml.unknown != jl_nothing) {
jl_typemap_entry_t *li = jl_typemap_assoc_by_type(ml, types, penv,
- subtype_inexact__sigseq_useenv, subtype, offs+1);
+ subtype_inexact__sigseq_useenv, subtype, offs+1, world);
if (li) return li;
}
}
@@ -693,51 +695,52 @@ jl_typemap_entry_t *jl_typemap_assoc_by_type(union jl_typemap_t ml_or_cache, jl_
}
// Always check the list (since offs doesn't always start at 0)
if (subtype) {
- jl_typemap_entry_t *li = jl_typemap_assoc_by_type_(cache->linear, types, subtype_inexact__sigseq_useenv, penv);
+ jl_typemap_entry_t *li = jl_typemap_assoc_by_type_(cache->linear, types, subtype_inexact__sigseq_useenv, penv, world);
if (li) return li;
- return jl_typemap_assoc_by_type(cache->any, types, penv, subtype_inexact__sigseq_useenv, subtype, offs+1);
+ return jl_typemap_assoc_by_type(cache->any, types, penv, subtype_inexact__sigseq_useenv, subtype, offs+1, world);
}
else {
- return jl_typemap_lookup_by_type_(cache->linear, types, subtype_inexact__sigseq_useenv);
+ return jl_typemap_lookup_by_type_(cache->linear, types, subtype_inexact__sigseq_useenv, world);
}
}
else {
return subtype ?
- jl_typemap_assoc_by_type_(ml_or_cache.leaf, types, subtype_inexact__sigseq_useenv, penv) :
- jl_typemap_lookup_by_type_(ml_or_cache.leaf, types, subtype_inexact__sigseq_useenv);
+ jl_typemap_assoc_by_type_(ml_or_cache.leaf, types, subtype_inexact__sigseq_useenv, penv, world) :
+ jl_typemap_lookup_by_type_(ml_or_cache.leaf, types, subtype_inexact__sigseq_useenv, world);
}
}
-jl_typemap_entry_t *jl_typemap_entry_assoc_exact(jl_typemap_entry_t *ml, jl_value_t **args, size_t n)
+jl_typemap_entry_t *jl_typemap_entry_assoc_exact(jl_typemap_entry_t *ml, jl_value_t **args, size_t n, size_t world)
{
// some manually-unrolled common special cases
while (ml->simplesig == (void*)jl_nothing && ml->guardsigs == jl_emptysvec && ml->isleafsig) {
// use a tight loop for a long as possible
- if (ml->max_world == ~(size_t)0 && n == jl_datatype_nfields(ml->sig) && jl_typeof(args[0]) == jl_tparam(ml->sig, 0)) {
- if (n == 1)
- return ml;
- if (n == 2) {
- if (jl_typeof(args[1]) == jl_tparam(ml->sig, 1))
- return ml;
- }
- else if (n == 3) {
- if (jl_typeof(args[1]) == jl_tparam(ml->sig, 1) &&
- jl_typeof(args[2]) == jl_tparam(ml->sig, 2))
- return ml;
- }
- else {
- if (sig_match_leaf(args, jl_svec_data(ml->sig->parameters), n))
+ if (world >= ml->min_world && world <= ml->max_world)
+ if (n == jl_datatype_nfields(ml->sig) && jl_typeof(args[0]) == jl_tparam(ml->sig, 0)) {
+ if (n == 1)
return ml;
+ if (n == 2) {
+ if (jl_typeof(args[1]) == jl_tparam(ml->sig, 1))
+ return ml;
+ }
+ else if (n == 3) {
+ if (jl_typeof(args[1]) == jl_tparam(ml->sig, 1) &&
+ jl_typeof(args[2]) == jl_tparam(ml->sig, 2))
+ return ml;
+ }
+ else {
+ if (sig_match_leaf(args, jl_svec_data(ml->sig->parameters), n))
+ return ml;
+ }
}
- }
ml = ml->next;
if (ml == (void*)jl_nothing)
return NULL;
}
- while (ml != (void*)jl_nothing) {
- if (ml->max_world != ~(size_t)0)
- goto nomatch; // ignore replaced methods
+ for (; ml != (void*)jl_nothing; ml = ml->next) {
+ if (world < ml->min_world || world > ml->max_world)
+ continue; // ignore replaced methods
size_t lensig = jl_datatype_nfields(ml->sig);
if (lensig == n || (ml->va && lensig <= n+1)) {
if (ml->simplesig != (void*)jl_nothing) {
@@ -745,24 +748,24 @@ jl_typemap_entry_t *jl_typemap_entry_assoc_exact(jl_typemap_entry_t *ml, jl_valu
int isva = lensimplesig > 0 && jl_is_vararg_type(jl_tparam(ml->simplesig, lensimplesig - 1));
if (lensig == n || (isva && lensimplesig <= n + 1)) {
if (!sig_match_simple(args, n, jl_svec_data(ml->simplesig->parameters), isva, lensimplesig))
- goto nomatch;
+ continue;
}
else {
- goto nomatch;
+ continue;
}
}
if (ml->isleafsig) {
if (!sig_match_leaf(args, jl_svec_data(ml->sig->parameters), n))
- goto nomatch;
+ continue;
}
else if (ml->issimplesig) {
if (!sig_match_simple(args, n, jl_svec_data(ml->sig->parameters), ml->va, lensig))
- goto nomatch;
+ continue;
}
else {
if (!jl_tuple_subtype(args, n, ml->sig, 1))
- goto nomatch;
+ continue;
}
size_t i, l;
@@ -777,14 +780,14 @@ jl_typemap_entry_t *jl_typemap_entry_assoc_exact(jl_typemap_entry_t *ml, jl_valu
}
}
return ml;
- }
nomatch:
- ml = ml->next;
+ continue;
+ }
}
return NULL;
}
-jl_typemap_entry_t *jl_typemap_level_assoc_exact(jl_typemap_level_t *cache, jl_value_t **args, size_t n, int8_t offs)
+jl_typemap_entry_t *jl_typemap_level_assoc_exact(jl_typemap_level_t *cache, jl_value_t **args, size_t n, int8_t offs, size_t world)
{
if (n > offs) {
jl_value_t *a1 = args[offs];
@@ -792,21 +795,21 @@ jl_typemap_entry_t *jl_typemap_level_assoc_exact(jl_typemap_level_t *cache, jl_v
assert(jl_is_datatype(ty));
if (ty == (jl_value_t*)jl_datatype_type && cache->targ != (void*)jl_nothing) {
union jl_typemap_t ml_or_cache = mtcache_hash_lookup(cache->targ, a1, 1, offs);
- jl_typemap_entry_t *ml = jl_typemap_assoc_exact(ml_or_cache, args, n, offs+1);
+ jl_typemap_entry_t *ml = jl_typemap_assoc_exact(ml_or_cache, args, n, offs+1, world);
if (ml) return ml;
}
if (cache->arg1 != (void*)jl_nothing) {
union jl_typemap_t ml_or_cache = mtcache_hash_lookup(cache->arg1, ty, 0, offs);
- jl_typemap_entry_t *ml = jl_typemap_assoc_exact(ml_or_cache, args, n, offs+1);
+ jl_typemap_entry_t *ml = jl_typemap_assoc_exact(ml_or_cache, args, n, offs+1, world);
if (ml) return ml;
}
}
if (jl_typeof(cache->linear) != (jl_value_t*)jl_nothing) {
- jl_typemap_entry_t *ml = jl_typemap_entry_assoc_exact(cache->linear, args, n);
+ jl_typemap_entry_t *ml = jl_typemap_entry_assoc_exact(cache->linear, args, n, world);
if (ml) return ml;
}
if (jl_typeof(cache->any.unknown) != (jl_value_t*)jl_nothing)
- return jl_typemap_assoc_exact(cache->any, args, n, offs+1);
+ return jl_typemap_assoc_exact(cache->any, args, n, offs+1, world);
return NULL;
}
@@ -953,9 +956,9 @@ jl_typemap_entry_t *jl_typemap_insert(union jl_typemap_t *cache, jl_value_t *par
}
if ((jl_value_t*)simpletype == jl_nothing) {
- jl_typemap_entry_t *ml = jl_typemap_assoc_by_type(*cache, type, NULL, 1, 0, offs);
+ jl_typemap_entry_t *ml = jl_typemap_assoc_by_type(*cache, type, NULL, 1, 0, offs, min_world);
if (ml && ml->simplesig == (void*)jl_nothing) {
- if (newvalue == ml->func.value) // no change
+ if (newvalue == ml->func.value) // no change. TODO: involve world in computation
return ml;
if (overwritten != NULL)
*overwritten = ml->func.value;
diff --git a/test/loading.jl b/test/loading.jl
index b7687d65d71e8..cadf484aceb2e 100644
--- a/test/loading.jl
+++ b/test/loading.jl
@@ -8,7 +8,8 @@ using Base.Test
include("test_sourcepath.jl")
thefname = "the fname!//\\&\0\1*"
-@test include_string("include_string_test() = @__FILE__", thefname)() == Base.source_path()
+include_string_test_func = include_string("include_string_test() = @__FILE__", thefname)
+@test include_string_test_func() == Base.source_path()
@test include_string("Base.source_path()", thefname) == Base.source_path()
@test basename(@__FILE__) == "loading.jl"
@test isabspath(@__FILE__)
diff --git a/test/runtests.jl b/test/runtests.jl
index 4fef9b34cfbf2..53114f4cc342a 100644
--- a/test/runtests.jl
+++ b/test/runtests.jl
@@ -77,7 +77,7 @@ cd(dirname(@__FILE__)) do
for t in node1_tests
n > 1 && print("\tFrom worker 1:\t")
- runtests(t)
+ eval(Expr(:call, () -> runtests(t))) # runtests is defined by the include above
end
println(" \033[32;1mSUCCESS\033[0m")
diff --git a/test/staged.jl b/test/staged.jl
index 8f064b56b5e3a..2a2633b96de76 100644
--- a/test/staged.jl
+++ b/test/staged.jl
@@ -154,7 +154,7 @@ end
# @generated functions including inner functions
@generated function _g_f_with_inner(x)
- :(y->y)
+ return y -> y
end
@test (_g_f_with_inner(1))(8) == 8
diff --git a/ui/repl.c b/ui/repl.c
index c7f391a8189b4..2c393695c4900 100644
--- a/ui/repl.c
+++ b/ui/repl.c
@@ -547,7 +547,10 @@ static NOINLINE int true_main(int argc, char *argv[])
(jl_function_t*)jl_get_global(jl_base_module, jl_symbol("_start")) : NULL;
if (start_client) {
+ size_t last_age = jl_get_ptls_states()->world_age;
+ jl_get_ptls_states()->world_age = jl_get_world_counter();
jl_apply(&start_client, 1);
+ jl_get_ptls_states()->world_age = last_age;
return 0;
}