diff --git a/base/boot.jl b/base/boot.jl
index 017114a403d2c..8cc3e66d5945a 100644
--- a/base/boot.jl
+++ b/base/boot.jl
@@ -59,16 +59,40 @@
# name::Symbol
#end
+#type AstInfo
+# ast::Union{Expr, Vector{UInt8}}
+# unspecialized_ducttape::LambdaInfo
+# def::Method
+# pure::Bool
+# called::Int32
+#end
+
#type LambdaInfo
-# ast::Expr
-# sparams::Tuple
+# next::Union{LambdaInfo,Void}
+# sig::Any
+# rettype::Any
+# va::Bool
+# sparam_vals::SimpleVector
+# func
+# ...
+#end
+
+#type Method
+# ast::AstInfo
+# sig::Type
+# tvars::Expr
+# sparam_syms::SimpleVector
# tfunc
# name::Symbol
+# roots::Vector{Any}
+# unspecialized::LambdaInfo
# specializations
-# inferred
-# file::Symbol
-# line::Int
# module::Module
+# file::Symbol
+# line::Int32
+# isstaged::Bool
+# invokes::Union{MethodTable,Void}
+# next::Union{Method,Void}
#end
#abstract Ref{T}
@@ -125,7 +149,7 @@ export
Tuple, Type, TypeConstructor, TypeName, TypeVar, Union, Void,
SimpleVector, AbstractArray, DenseArray,
# special objects
- Box, Function, Builtin, IntrinsicFunction, LambdaInfo, Method, MethodTable,
+ Box, Function, Builtin, IntrinsicFunction, LambdaInfo, AstInfo, Method, MethodTable,
Module, Symbol, Task, Array, WeakRef,
# numeric types
Number, Real, Integer, Bool, Ref, Ptr,
@@ -298,6 +322,7 @@ TypeVar(n::Symbol, lb::ANY, ub::ANY, b::Bool) =
ccall(:jl_new_typevar_, Any, (Any, Any, Any, Any), n, lb::Type, ub::Type, b)::TypeVar
TypeConstructor(p::ANY, t::ANY) = ccall(:jl_new_type_constructor, Any, (Any, Any), p::SimpleVector, t::Type)
+LambdaInfo(m::Method, sparam_vals::SimpleVector, specTypes::DataType) = ccall(:jl_new_lambda_info, Any, (Any, Any, Any), m.ast, sparam_vals, specTypes)
Void() = nothing
@@ -345,5 +370,6 @@ Array{T}(::Type{T}, d::Int...) = Array{T}(d)
Array{T}(::Type{T}, m::Int) = Array{T,1}(m)
Array{T}(::Type{T}, m::Int,n::Int) = Array{T,2}(m,n)
Array{T}(::Type{T}, m::Int,n::Int,o::Int) = Array{T,3}(m,n,o)
+Array{T,N}(::Type{T}, d::NTuple{N,Int}) = Array{T,N}(d)
ccall(:jl_set_istopmod, Void, (Bool,), true)
diff --git a/base/inference.jl b/base/inference.jl
index ab0c60147a9e1..f9d230b116bfb 100644
--- a/base/inference.jl
+++ b/base/inference.jl
@@ -29,9 +29,10 @@ type VarInfo
mod::Module
end
-function VarInfo(linfo::LambdaInfo, ast=linfo.ast)
+function VarInfo(linfo::LambdaInfo, astinfo::AstInfo=linfo.func)
+ ast = astinfo.ast
if !isa(ast,Expr)
- ast = ccall(:jl_uncompress_ast, Any, (Any,Any), linfo, ast)
+ ast = ccall(:jl_uncompress_ast, Any, (Any,Any), astinfo.def, ast)
end
vinflist = ast.args[2][1]::Array{Any,1}
vars = map(vi->vi[1], vinflist)
@@ -43,17 +44,17 @@ function VarInfo(linfo::LambdaInfo, ast=linfo.ast)
gensym_types = Any[ NF for i = 1:(ngs::Int) ]
nl = label_counter(body)+1
if length(linfo.sparam_vals) > 0
- n = length(linfo.sparam_syms)
+ n = length(astinfo.def.sparam_syms)
sp = Array(Any, n*2)
for i = 1:n
- sp[i*2-1] = linfo.sparam_syms[i]
+ sp[i*2-1] = astinfo.def.sparam_syms[i]
sp[i*2 ] = linfo.sparam_vals[i]
end
sp = svec(sp...)
else
sp = svec()
end
- VarInfo(sp, vars, gensym_types, vinflist, nl, ObjectIdDict(), linfo.module)
+ VarInfo(sp, vars, gensym_types, vinflist, nl, ObjectIdDict(), astinfo.def.module)
end
type VarState
@@ -65,7 +66,7 @@ type EmptyCallStack
end
type CallStack
- ast
+ meth::Method
types::Type
recurred::Bool
cycleid::Int
@@ -73,7 +74,7 @@ type CallStack
prev::Union{EmptyCallStack,CallStack}
sv::VarInfo
- CallStack(ast, types::ANY, prev) = new(ast, types, false, 0, Bottom, prev)
+ CallStack(meth, types::ANY, prev) = new(meth, types, false, 0, Bottom, prev)
end
inference_stack = EmptyCallStack()
@@ -648,8 +649,10 @@ end
let stagedcache=Dict{Any,Any}()
global func_for_method
function func_for_method(m::Method, tt, env)
+ spvals = Any[env[i] for i = 2:2:length(env)]
+ _any(sp -> isa(sp, TypeVar), spvals) && empty!(spvals)
if !m.isstaged
- return m.func
+ return LambdaInfo(m, svec(spvals...), tt)
elseif haskey(stagedcache, (m, tt))
return stagedcache[(m, tt)]
else
@@ -659,7 +662,8 @@ let stagedcache=Dict{Any,Any}()
# we can't guarantee that their type behavior is monotonic.
return NF
end
- f = ccall(:jl_instantiate_staged, Any, (Any, Any, Any), m.func, tt, env)
+ f = ccall(:jl_instantiate_staged, Any, (Any, Any, Any), m, tt, env)
+ f = LambdaInfo(f, svec(spvals...), tt)
stagedcache[(m, tt)] = f
return f
end
@@ -730,6 +734,7 @@ function abstract_call_gf_by_type(f::ANY, argtype::ANY, e)
break
end
linfo = linfo::LambdaInfo
+ astinfo = linfo.func::AstInfo
lsig = length(m[3].sig.parameters)
# limit argument type tuple based on size of definition signature.
# for example, given function f(T, Any...), limit to 3 arguments
@@ -738,7 +743,7 @@ function abstract_call_gf_by_type(f::ANY, argtype::ANY, e)
limit = false
# look at the stack to detect recursive calls with growing argument lists
while sp !== EmptyCallStack()
- if linfo.ast === sp.ast && length(argtypes) > length(sp.types.parameters)
+ if astinfo.def === sp.meth && length(argtypes) > length(sp.types.parameters)
limit = true; break
end
sp = sp.prev
@@ -763,7 +768,7 @@ function abstract_call_gf_by_type(f::ANY, argtype::ANY, e)
end
end
#print(m,"\n")
- (_tree,rt) = typeinf(linfo, sig, m[2], linfo)
+ (_tree,rt) = typeinf(linfo, sig, m[2], astinfo.def)
rettype = tmerge(rettype, rt)
if is(rettype,Any)
break
@@ -796,7 +801,7 @@ function invoke_tfunc(f::ANY, types::ANY, argtype::ANY)
if linfo === NF
return Any
end
- return typeinf(linfo::LambdaInfo, ti, env, linfo)[2]
+ return typeinf(linfo::LambdaInfo, ti, env, (linfo.func::AstInfo).def)[2]
end
# `types` is an array of inferred types for expressions in `args`.
@@ -916,9 +921,10 @@ function pure_eval_call(f::ANY, fargs, argtypes::ANY, sv, e)
if linfo === NF
return false
end
- if !linfo.pure
- typeinf(linfo, meth[1], meth[2], linfo)
- if !linfo.pure
+ astinfo = linfo.func::AstInfo
+ if !astinfo.pure
+ typeinf(linfo, meth[1], meth[2], astinfo.def)
+ if !astinfo.pure
return false
end
end
@@ -1381,7 +1387,7 @@ f_argnames(ast) =
is_rest_arg(arg::ANY) = (ccall(:jl_is_rest_arg,Int32,(Any,), arg) != 0)
-function typeinf_ext(linfo, atypes::ANY, def)
+function typeinf_ext(linfo::LambdaInfo, atypes::ANY, def::Method)
global inference_stack
last = inference_stack
inference_stack = EmptyCallStack()
@@ -1390,8 +1396,8 @@ function typeinf_ext(linfo, atypes::ANY, def)
return result
end
-typeinf(linfo,atypes::ANY,sparams::ANY) = typeinf(linfo,atypes,sparams,linfo,true,false)
-typeinf(linfo,atypes::ANY,sparams::ANY,def) = typeinf(linfo,atypes,sparams,def,true,false)
+typeinf(linfo::LambdaInfo,atypes::ANY,sparams::ANY) = typeinf(linfo,atypes,sparams,(linfo.func::AstInfo).def,true,false)
+typeinf(linfo::LambdaInfo,atypes::ANY,sparams::ANY,def::Method) = typeinf(linfo,atypes,sparams,def,true,false)
CYCLE_ID = 1
@@ -1400,8 +1406,8 @@ CYCLE_ID = 1
# def is the original unspecialized version of a method. we aggregate all
# saved type inference data there.
-function typeinf(linfo::LambdaInfo, atypes::ANY, sparams::SimpleVector, def, cop, needtree)
- if linfo.module === Core && isempty(sparams) && isempty(linfo.sparam_vals)
+function typeinf(linfo::LambdaInfo, atypes::ANY, sparams::SimpleVector, def::Method, cop, needtree)
+ if def.module === Core && isempty(sparams) && isempty(linfo.sparam_vals)
atypes = Tuple
end
#dbg =
@@ -1430,19 +1436,19 @@ function typeinf(linfo::LambdaInfo, atypes::ANY, sparams::SimpleVector, def, cop
return (nothing, code)
end
else
- return code # else code is a tuple (ast, type)
+ return code # else code is a tuple (astinfo, type)
end
end
end
end
# TODO: typeinf currently gets stuck without this
- if linfo.name === :abstract_interpret || linfo.name === :tuple_elim_pass || linfo.name === :abstract_call_gf
- return (linfo.ast, Any)
+ if def.name === :abstract_interpret || def.name === :tuple_elim_pass || def.name === :abstract_call_gf
+ return (def.ast, Any)
end
- (fulltree, result, rec) = typeinf_uncached(linfo, atypes, sparams, def, curtype, cop, true)
- if fulltree === ()
- return (fulltree, result::Type)
+ (astinfo, result, rec) = typeinf_uncached(linfo, atypes, sparams, def, curtype, cop, true)
+ if astinfo === ()
+ return (def.ast, result::Type)
end
if !redo
@@ -1464,31 +1470,30 @@ function typeinf(linfo::LambdaInfo, atypes::ANY, sparams::SimpleVector, def, cop
tfarr[idx] = atypes
# in the "rec" state this tree will not be used again, so store
# just the return type in place of it.
- tfarr[idx+1] = rec ? result : (fulltree,result)
+ tfarr[idx+1] = rec ? result : (astinfo,result)
tfarr[idx+2] = rec
else
- def.tfunc[tfunc_idx] = rec ? result : (fulltree,result)
+ def.tfunc[tfunc_idx] = rec ? result : (astinfo,result)
def.tfunc[tfunc_idx+1] = rec
end
- return (fulltree, result::Type)
+ return (astinfo, result::Type)
end
-typeinf_uncached(linfo, atypes::ANY, sparams::ANY; optimize=true) =
- typeinf_uncached(linfo, atypes, sparams, linfo, Bottom, true, optimize)
+typeinf_uncached(linfo::LambdaInfo, atypes::ANY, sparams::ANY; optimize=true) =
+ typeinf_uncached(linfo::LambdaInfo, atypes, sparams, (linfo.func::AstInfo).def, Bottom, true, optimize)
# t[n:end]
tupletype_tail(t::ANY, n) = Tuple{t.parameters[n:end]...}
# compute an inferred (optionally optimized) AST without global effects (i.e. updating the cache)
-function typeinf_uncached(linfo::LambdaInfo, atypes::ANY, sparams::SimpleVector, def, curtype, cop, optimize)
- ast0 = def.ast
+function typeinf_uncached(linfo::LambdaInfo, atypes::ANY, sparams::SimpleVector, def::Method, curtype, cop, optimize)
#if dbg
- # print("typeinf ", linfo.name, " ", object_id(ast0), "\n")
+ # print("typeinf ", def.name, " ", object_id(ast0), "\n")
#end
# if isdefined(:STDOUT)
# write(STDOUT, "typeinf ")
- # write(STDOUT, string(linfo.name))
+ # write(STDOUT, string(def.name))
# write(STDOUT, string(atypes))
# write(STDOUT, '\n')
# end
@@ -1498,7 +1503,7 @@ function typeinf_uncached(linfo::LambdaInfo, atypes::ANY, sparams::SimpleVector,
f = inference_stack
while !isa(f,EmptyCallStack)
- if is(f.ast,ast0)
+ if is(f.meth, def)
# impose limit if we recur and the argument types grow beyond MAX_TYPE_DEPTH
td = type_depth(atypes)
if td > type_depth(f.types)
@@ -1537,7 +1542,7 @@ function typeinf_uncached(linfo::LambdaInfo, atypes::ANY, sparams::SimpleVector,
# check for recursion
f = inference_stack
while !isa(f,EmptyCallStack)
- if (is(f.ast,ast0) || f.ast==ast0) && typeseq(f.types, atypes)
+ if (is(f.meth, def) || f.meth.ast.ast == def.ast.ast) && typeseq(f.types, atypes)
# return best guess so far
(f::CallStack).recurred = true
(f::CallStack).cycleid = CYCLE_ID
@@ -1556,18 +1561,17 @@ function typeinf_uncached(linfo::LambdaInfo, atypes::ANY, sparams::SimpleVector,
end
#if trace_inf
- # print("typeinf ", linfo.name, " ", atypes, " ", linfo.file,":",linfo.line,"\n")
+ # print("typeinf ", def.name, " ", atypes, " ", def.file,":",def.line,"\n")
#end
- #if dbg print("typeinf ", linfo.name, " ", atypes, "\n") end
+ #if dbg print("typeinf ", def.name, " ", atypes, "\n") end
+ astinfo = linfo.func::AstInfo
if cop
- ast = ccall(:jl_prepare_ast, Any, (Any,), linfo)::Expr
- else
- ast = linfo.ast
+ astinfo = ccall(:jl_copy_ast_info, Any, (Any,), astinfo)::AstInfo
end
-
- sv = VarInfo(linfo, ast)
+ ast = astinfo.ast::Expr
+ sv = VarInfo(linfo, astinfo)
if length(linfo.sparam_vals) > 0
# handled by VarInfo constructor
@@ -1577,8 +1581,8 @@ function typeinf_uncached(linfo::LambdaInfo, atypes::ANY, sparams::SimpleVector,
push!(sp, sparams[i].name)
push!(sp, sparams[i+1])
end
- for i = 1:length(linfo.sparam_syms)
- sym = linfo.sparam_syms[i]
+ for i = 1:length(def.sparam_syms)
+ sym = def.sparam_syms[i]
push!(sp, sym)
push!(sp, TypeVar(sym, Any, true))
end
@@ -1602,7 +1606,7 @@ function typeinf_uncached(linfo::LambdaInfo, atypes::ANY, sparams::SimpleVector,
end
# our stack frame
- frame = CallStack(ast0, atypes, inference_stack)
+ frame = CallStack(def, atypes, inference_stack)
frame.sv = sv
inference_stack = frame
frame.result = curtype
@@ -1807,7 +1811,7 @@ function typeinf_uncached(linfo::LambdaInfo, atypes::ANY, sparams::SimpleVector,
# for an example see test/libgit2.jl on 0.5-pre master
# around e.g. commit c072d1ce73345e153e4fddf656cda544013b1219
inference_stack = (inference_stack::CallStack).prev
- return (ast0, Any, false)
+ return (def.ast, Any, false)
end
end
handler_at[l] = cur_hand
@@ -1851,6 +1855,7 @@ function typeinf_uncached(linfo::LambdaInfo, atypes::ANY, sparams::SimpleVector,
rec = false
end
fulltree = type_annotate(ast, s, sv, frame.result, args)
+ astinfo.inferred = true
if !rec
@assert fulltree.args[3].head === :body
@@ -1864,15 +1869,15 @@ function typeinf_uncached(linfo::LambdaInfo, atypes::ANY, sparams::SimpleVector,
tuple_elim_pass(fulltree, sv)
getfield_elim_pass(fulltree.args[3], sv)
end
- linfo.inferred = true
body = Expr(:block)
body.args = fulltree.args[3].args::Array{Any,1}
- linfo.pure = popmeta!(body, :pure)[1]
+ astinfo.pure = popmeta!(body, :pure)[1]
fulltree = ccall(:jl_compress_ast, Any, (Any,Any), def, fulltree)
end
+ astinfo.ast = fulltree
inference_stack = (inference_stack::CallStack).prev
- return (fulltree, frame.result, rec)
+ return (astinfo, frame.result, rec)
end
function record_var_type(e::Symbol, t::ANY, decls)
@@ -2296,7 +2301,7 @@ function inlineable(f::ANY, ft::ANY, e::Expr, atype::ANY, sv::VarInfo, enclosing
if linfo === NF
return NF
end
- methfunc = meth[3].func
+ methfunc = meth[3]
methsig = meth[3].sig
if !(atype <: metharg)
incompletematch = true
@@ -2307,8 +2312,9 @@ function inlineable(f::ANY, ft::ANY, e::Expr, atype::ANY, sv::VarInfo, enclosing
end
end
linfo = linfo::LambdaInfo
+ astinfo = linfo.func::AstInfo
- spnames = Any[s for s in linfo.sparam_syms]
+ spnames = Any[s for s in astinfo.def.sparam_syms]
if length(linfo.sparam_vals) > 0
spvals = Any[x for x in linfo.sparam_vals]
else
@@ -2337,14 +2343,14 @@ function inlineable(f::ANY, ft::ANY, e::Expr, atype::ANY, sv::VarInfo, enclosing
# # check call stack to see if this argument list is growing
# st = inference_stack
# while !isa(st, EmptyCallStack)
- # if st.ast === linfo.def.ast && length(atypes) > length(st.types)
+ # if st.meth === astinfo.def && length(atypes) > length(st.types)
# atypes = limit_tuple_type(atypes)
# meth = _methods(f, atypes, 1)
# if meth === false || length(meth) != 1
# return NF
# end
# meth = meth[1]::Tuple
- # linfo2 = meth[3].func.code
+ # linfo2 = meth[3].code
# if linfo2 !== linfo
# return NF
# end
@@ -2358,13 +2364,14 @@ function inlineable(f::ANY, ft::ANY, e::Expr, atype::ANY, sv::VarInfo, enclosing
methargs = metharg.parameters
nm = length(methargs)
- (ast, ty) = typeinf(linfo, metharg, methsp, linfo, true, true)
- if is(ast,())
+ (astinfo, ty) = typeinf(linfo, metharg, methsp, astinfo.def, true, true)
+ if is(astinfo,())
return NF
end
needcopy = true
+ ast = astinfo.ast
if !isa(ast,Expr)
- ast = ccall(:jl_uncompress_ast, Any, (Any,Any), linfo, ast)
+ ast = ccall(:jl_uncompress_ast, Any, (Any,Any), astinfo.def, ast)
needcopy = false
end
ast = ast::Expr
@@ -3352,6 +3359,6 @@ function replace_getfield!(ast, e::ANY, tupname, vals, sv, i0)
end
end
-#tfunc(f,t) = methods(f,t)[1].func.code.tfunc
+#tfunc(f,t) = methods(f,t)[1].code.tfunc
ccall(:jl_set_typeinf_func, Void, (Any,), typeinf_ext)
diff --git a/base/interactiveutil.jl b/base/interactiveutil.jl
index e29176063d326..7de338f32d37e 100644
--- a/base/interactiveutil.jl
+++ b/base/interactiveutil.jl
@@ -65,8 +65,7 @@ function edit(path::AbstractString, line::Integer=0)
end
function edit(m::Method)
- tv, decls, file, line = arg_decl_parts(m)
- edit(string(file), line)
+ edit(string(m.file), m.line)
end
edit(f) = edit(functionloc(f)...)
@@ -599,7 +598,7 @@ function summarysize(obj::MethodTable, seen, excl)
return size
end
-function summarysize(m::Method, seen, excl)
+function summarysize(m::LambdaInfo, seen, excl)
size::Int = 0
while true
haskey(seen, m) ? (return size) : (seen[m] = true)
@@ -607,11 +606,12 @@ function summarysize(m::Method, seen, excl)
if isdefined(m, :func)
size += summarysize(m.func, seen, excl)::Int
end
+ if isdefined(m, :sparam_vals)
+ size += summarysize(m.sparam_vals, seen, excl)::Int
+ end
size += summarysize(m.sig, seen, excl)::Int
- size += summarysize(m.tvars, seen, excl)::Int
- size += summarysize(m.invokes, seen, excl)::Int
m.next === nothing && break
- m = m.next::Method
+ m = m.next::LambdaInfo
end
return size
end
diff --git a/base/methodshow.jl b/base/methodshow.jl
index f5848e11d8ba0..adc4d3610515a 100644
--- a/base/methodshow.jl
+++ b/base/methodshow.jl
@@ -28,47 +28,50 @@ end
function arg_decl_parts(m::Method)
tv = m.tvars
- if !isa(tv,SimpleVector)
+ if !isa(tv, SimpleVector)
tv = Any[tv]
else
tv = Any[tv...]
end
- li = m.func
- e = uncompressed_ast(li)
+ e = uncompressed_ast(m)
argnames = e.args[1]
s = symbol("?")
decls = [argtype_decl(:tvar_env => tv, get(argnames,i,s), m.sig.parameters[i])
for i = 1:length(m.sig.parameters)]
- return tv, decls, li.file, li.line
+ return tv, decls
end
function show(io::IO, m::Method)
- tv, decls, file, line = arg_decl_parts(m)
- ft = m.sig.parameters[1]
- d1 = decls[1]
- if ft <: Function &&
- isdefined(ft.name.module, ft.name.mt.name) &&
- ft == typeof(getfield(ft.name.module, ft.name.mt.name))
- print(io, ft.name.mt.name)
- elseif isa(ft, DataType) && is(ft.name, Type.name) && isleaftype(ft)
- f = ft.parameters[1]
- if isa(f, DataType) && isempty(f.parameters)
- print(io, f)
+ if isdefined(m, :sig)
+ tv, decls = arg_decl_parts(m)
+ ft = m.sig.parameters[1]
+ d1 = decls[1]
+ if ft <: Function &&
+ isdefined(ft.name.module, ft.name.mt.name) &&
+ ft == typeof(getfield(ft.name.module, ft.name.mt.name))
+ print(io, ft.name.mt.name)
+ elseif isa(ft, DataType) && is(ft.name, Type.name) && isleaftype(ft)
+ f = ft.parameters[1]
+ if isa(f, DataType) && isempty(f.parameters)
+ print(io, f)
+ else
+ print(io, "(", d1[1], "::", d1[2], ")")
+ end
else
print(io, "(", d1[1], "::", d1[2], ")")
end
+ if !isempty(tv)
+ show_delim_array(io, tv, '{', ',', '}', false)
+ end
+ print(io, "(")
+ print_joined(io, [isempty(d[2]) ? d[1] : d[1]*"::"*d[2] for d in decls[2:end]],
+ ", ", ", ")
+ print(io, ")")
else
- print(io, "(", d1[1], "::", d1[2], ")")
- end
- if !isempty(tv)
- show_delim_array(io, tv, '{', ',', '}', false)
+ print(io, m.name, "(?)")
end
- print(io, "(")
- print_joined(io, [isempty(d[2]) ? d[1] : d[1]*"::"*d[2] for d in decls[2:end]],
- ", ", ", ")
- print(io, ")")
- if line > 0
- print(io, " at ", file, ":", line)
+ if m.line > 0
+ print(io, " at ", m.file, ":", m.line)
end
end
@@ -114,10 +117,10 @@ end
fileurl(file) = let f = find_source_file(file); f === nothing ? "" : "file://"*f; end
function url(m::Method)
- M = m.func.module
- (m.func.file == :null || m.func.file == :string) && return ""
- file = string(m.func.file)
- line = m.func.line
+ M = m.module
+ (m.file == :null || m.file == :string) && return ""
+ file = string(m.file)
+ line = m.line
line <= 0 || ismatch(r"In\[[0-9]+\]", file) && return ""
if inbase(M)
if isempty(Base.GIT_VERSION_INFO.commit)
@@ -149,39 +152,43 @@ function url(m::Method)
end
function writemime(io::IO, ::MIME"text/html", m::Method)
- tv, decls, file, line = arg_decl_parts(m)
- ft = m.sig.parameters[1]
- d1 = decls[1]
- if ft <: Function &&
- isdefined(ft.name.module, ft.name.mt.name) &&
- ft == typeof(getfield(ft.name.module, ft.name.mt.name))
- print(io, ft.name.mt.name)
- elseif isa(ft, DataType) && is(ft.name, Type.name) && isleaftype(ft)
- f = ft.parameters[1]
- if isa(f, DataType) && isempty(f.parameters)
- print(io, f)
+ if isdefined(m, :sig)
+ tv, decls = arg_decl_parts(m)
+ ft = m.sig.parameters[1]
+ d1 = decls[1]
+ if ft <: Function &&
+ isdefined(ft.name.module, ft.name.mt.name) &&
+ ft == typeof(getfield(ft.name.module, ft.name.mt.name))
+ print(io, ft.name.mt.name)
+ elseif isa(ft, DataType) && is(ft.name, Type.name) && isleaftype(ft)
+ f = ft.parameters[1]
+ if isa(f, DataType) && isempty(f.parameters)
+ print(io, f)
+ else
+ print(io, "(", d1[1], "::", d1[2], ")")
+ end
else
print(io, "(", d1[1], "::", d1[2], ")")
end
+ if !isempty(tv)
+ print(io,"")
+ show_delim_array(io, tv, '{', ',', '}', false)
+ print(io,"")
+ end
+ print(io, "(")
+ print_joined(io, [isempty(d[2]) ? d[1] : d[1]*"::"*d[2]*""
+ for d in decls[2:end]], ", ", ", ")
+ print(io, ")")
else
- print(io, "(", d1[1], "::", d1[2], ")")
- end
- if !isempty(tv)
- print(io,"")
- show_delim_array(io, tv, '{', ',', '}', false)
- print(io,"")
- end
- print(io, "(")
- print_joined(io, [isempty(d[2]) ? d[1] : d[1]*"::"*d[2]*""
- for d in decls[2:end]], ", ", ", ")
- print(io, ")")
- if line > 0
+ print(io, m.name, "(?)")
+ end
+ if m.line > 0
u = url(m)
if isempty(u)
- print(io, " at ", file, ":", line)
+ print(io, " at ", m.file, ":", m.line)
else
print(io, """ at """,
- file, ":", line, "")
+ m.file, ":", m.line, "")
end
end
end
diff --git a/base/reflection.jl b/base/reflection.jl
index ce74d7d42c72e..57dc5916612a4 100644
--- a/base/reflection.jl
+++ b/base/reflection.jl
@@ -170,8 +170,8 @@ end
tt_cons(t::ANY, tup::ANY) = (@_pure_meta; Tuple{t, (isa(tup, Type) ? tup.parameters : tup)...})
-code_lowered(f, t::ANY=Tuple) = map(m->uncompressed_ast(m.func), methods(f, t))
-function methods(f::ANY,t::ANY)
+code_lowered(f, t::ANY=Tuple) = map(m->uncompressed_ast(m), methods(f, t))
+function methods(f::ANY, t::ANY)
if isa(f,Builtin)
throw(ArgumentError("argument is not a generic function"))
end
@@ -240,12 +240,13 @@ function length(mt::MethodTable)
end
start(mt::MethodTable) = mt.defs
-next(mt::MethodTable, m::Method) = (m,m.next)
+next(mt::MethodTable, m::Method) = (m, m.next)
done(mt::MethodTable, m::Method) = false
done(mt::MethodTable, i::Void) = true
-uncompressed_ast(l::LambdaInfo) =
- isa(l.ast,Expr) ? l.ast : ccall(:jl_uncompress_ast, Any, (Any,Any), l, l.ast)
+uncompressed_ast(l::AstInfo) =
+ isa(l.ast, Expr) ? l.ast : ccall(:jl_uncompress_ast, Any, (Any,Any), l.def, l.ast)
+uncompressed_ast(l::Method) = uncompressed_ast(l.ast)
# Printing code representations in IR and assembly
function _dump_function(f, t::ANY, native, wrapper, strip_ir_metadata, dump_module)
@@ -277,7 +278,7 @@ code_native(f::ANY, types::ANY=Tuple) = code_native(STDOUT, f, types)
# give a decent error message if we try to instantiate a staged function on non-leaf types
function func_for_method_checked(m, types)
- linfo = Core.Inference.func_for_method(m[3],m[1],m[2])
+ linfo = Core.Inference.func_for_method(m[3], m[1], m[2])
if linfo === Core.Inference.NF
error("cannot call @generated function `", m[3], "` ",
"with abstract argument types: ", types)
@@ -291,14 +292,15 @@ function code_typed(f::ANY, types::ANY=Tuple; optimize=true)
for x in _methods(f,types,-1)
linfo = func_for_method_checked(x, types)
if optimize
- (tree, ty) = Core.Inference.typeinf(linfo, x[1], x[2], linfo,
+ (astinfo, ty) = Core.Inference.typeinf(linfo, x[1], x[2], (linfo.func::AstInfo).def,
true, true)
else
- (tree, ty) = Core.Inference.typeinf_uncached(linfo, x[1], x[2],
+ (astinfo, ty) = Core.Inference.typeinf_uncached(linfo, x[1], x[2],
optimize=false)
end
+ tree = astinfo.ast
if !isa(tree, Expr)
- tree = ccall(:jl_uncompress_ast, Any, (Any,Any), linfo, tree)
+ tree = ccall(:jl_uncompress_ast, Any, (Any,Any), astinfo.def, tree)
end
push!(asts, tree)
end
@@ -310,7 +312,7 @@ function return_types(f::ANY, types::ANY=Tuple)
rt = []
for x in _methods(f,types,-1)
linfo = func_for_method_checked(x,types)
- (tree, ty) = Core.Inference.typeinf(linfo, x[1], x[2])
+ (astinfo, ty) = Core.Inference.typeinf(linfo, x[1], x[2])
push!(rt, ty)
end
rt
@@ -346,12 +348,11 @@ function which_module(m::Module, s::Symbol)
end
function functionloc(m::Method)
- lsd = m.func::LambdaInfo
- ln = lsd.line
+ ln = m.line
if ln <= 0
error("could not determine location of method definition")
end
- (find_source_file(string(lsd.file)), ln)
+ (find_source_file(string(m.file)), ln)
end
functionloc(f::ANY, types::ANY) = functionloc(which(f,types))
@@ -375,7 +376,7 @@ function function_module(f, types::ANY)
if isempty(m)
error("no matching methods")
end
- m[1].func.module
+ m[1].module
end
function method_exists(f::ANY, t::ANY)
diff --git a/base/serialize.jl b/base/serialize.jl
index 7c9b28bb5f786..b45701d9290f5 100644
--- a/base/serialize.jl
+++ b/base/serialize.jl
@@ -19,7 +19,7 @@ const TAGS = Any[
#LongSymbol, LongTuple, LongExpr,
Symbol, Tuple, Expr, # dummy entries, intentionally shadowed by earlier ones
LineNumberNode, SymbolNode, LabelNode, GotoNode,
- QuoteNode, TopNode, TypeVar, Box, LambdaInfo,
+ QuoteNode, TopNode, TypeVar, Box, :reserved00,
Module, #=UndefRefTag=#Symbol, Task, ASCIIString, UTF8String,
UTF16String, UTF32String, Float16,
SimpleVector, #=BackrefTag=#Symbol, :reserved11, :reserved12,
@@ -72,7 +72,6 @@ const BACKREF_TAG = Int32(sertag(SimpleVector)+1)
const EXPR_TAG = sertag(Expr)
const LONGEXPR_TAG = Int32(sertag(Expr)+3)
const MODULE_TAG = sertag(Module)
-const LAMBDASTATICDATA_TAG = sertag(LambdaInfo)
const TASK_TAG = sertag(Task)
const DATATYPE_TAG = sertag(DataType)
const TYPENAME_TAG = sertag(TypeName)
@@ -292,41 +291,21 @@ function serialize(s::SerializationState, m::Module)
end
# TODO: make this bidirectional, so objects can be sent back via the same key
-const object_numbers = WeakKeyDict()
-obj_number_salt = 0
-function object_number(l::ANY)
- global obj_number_salt, object_numbers
- if haskey(object_numbers, l)
- return object_numbers[l]
+const type_uid_numbers = WeakKeyDict()
+type_uid_salt = 0
+function type_uid(l::ANY)
+ global type_uid_salt, type_uid_numbers
+ if haskey(type_uid_numbers, l)
+ return type_uid_numbers[l]
end
# a hash function that always gives the same number to the same
# object on the same machine, and is unique over all machines.
- ln = obj_number_salt+(UInt64(myid())<<44)
- obj_number_salt += 1
- object_numbers[l] = ln
+ ln = type_uid_salt+(UInt64(myid())<<44)
+ type_uid_salt += 1
+ type_uid_numbers[l] = ln
return ln
end
-function serialize(s::SerializationState, linfo::LambdaInfo)
- serialize_cycle(s, linfo) && return
- writetag(s.io, LAMBDASTATICDATA_TAG)
- serialize(s, object_number(linfo))
- serialize(s, uncompressed_ast(linfo))
- if isdefined(linfo.def, :roots)
- serialize(s, linfo.def.roots::Vector{Any})
- else
- serialize(s, Any[])
- end
- serialize(s, linfo.sparam_syms)
- serialize(s, linfo.sparam_vals)
- serialize(s, linfo.inferred)
- serialize(s, linfo.module)
- serialize(s, linfo.name)
- serialize(s, linfo.file)
- serialize(s, linfo.line)
- serialize(s, linfo.pure)
-end
-
function serialize(s::SerializationState, t::Task)
serialize_cycle(s, t) && return
if istaskstarted(t) && !istaskdone(t)
@@ -346,7 +325,7 @@ end
function serialize(s::SerializationState, t::TypeName)
serialize_cycle(s, t) && return
writetag(s.io, TYPENAME_TAG)
- serialize(s, object_number(t))
+ serialize(s, type_uid(t))
serialize(s, t.name)
serialize(s, t.module)
serialize(s, t.names)
@@ -541,44 +520,6 @@ function deserialize(s::SerializationState, ::Type{Module})
m
end
-const known_object_data = Dict()
-
-function deserialize(s::SerializationState, ::Type{LambdaInfo})
- lnumber = deserialize(s)
- if haskey(known_object_data, lnumber)
- linfo = known_object_data[lnumber]::LambdaInfo
- makenew = false
- else
- linfo = ccall(:jl_new_lambda_info, Any, (Ptr{Void}, Ptr{Void}, Ptr{Void}, Ptr{Void}), C_NULL, C_NULL, C_NULL, C_NULL)::LambdaInfo
- makenew = true
- end
- deserialize_cycle(s, linfo)
- ast = deserialize(s)::Expr
- roots = deserialize(s)::Vector{Any}
- sparam_syms = deserialize(s)::SimpleVector
- sparam_vals = deserialize(s)::SimpleVector
- infr = deserialize(s)::Bool
- mod = deserialize(s)::Module
- name = deserialize(s)
- file = deserialize(s)
- line = deserialize(s)
- pure = deserialize(s)
- if makenew
- linfo.ast = ast
- linfo.sparam_syms = sparam_syms
- linfo.sparam_vals = sparam_vals
- linfo.inferred = infr
- linfo.module = mod
- linfo.roots = roots
- linfo.name = name
- linfo.file = file
- linfo.line = line
- linfo.pure = pure
- known_object_data[lnumber] = linfo
- end
- return linfo
-end
-
function deserialize_array(s::SerializationState)
d1 = deserialize(s)
if isa(d1,Type)
@@ -643,12 +584,14 @@ end
module __deserialized_types__
end
+const known_types = Dict()
+
function deserialize(s::SerializationState, ::Type{TypeName})
number = deserialize(s)
name = deserialize(s)
mod = deserialize(s)
- if haskey(known_object_data, number)
- tn = known_object_data[number]::TypeName
+ if haskey(known_types, number)
+ tn = known_types[number]::TypeName
name = tn.name
mod = tn.module
makenew = false
@@ -680,7 +623,7 @@ function deserialize(s::SerializationState, ::Type{TypeName})
tn.primary = ccall(:jl_new_datatype, Any, (Any, Any, Any, Any, Any, Cint, Cint, Cint),
tn, super, parameters, names, types,
abstr, mutable, ninitialized)
- known_object_data[number] = tn
+ known_types[number] = tn
ty = tn.primary
ccall(:jl_set_const, Void, (Any, Any, Any), mod, name, ty)
if !isdefined(ty,:instance)
diff --git a/base/stacktraces.jl b/base/stacktraces.jl
index b502f4f01e976..57519a8716a26 100644
--- a/base/stacktraces.jl
+++ b/base/stacktraces.jl
@@ -139,30 +139,26 @@ function show_spec_linfo(io::IO, frame::StackFrame)
print(io, frame.func !== empty_sym ? frame.func : "?")
else
linfo = get(frame.outer_linfo)
- if isdefined(linfo, 8)
- params = linfo.(#=specTypes=#8).parameters
- ft = params[1]
- if ft <: Function && isempty(ft.parameters) &&
- isdefined(ft.name.module, ft.name.mt.name) &&
- ft == typeof(getfield(ft.name.module, ft.name.mt.name))
- print(io, ft.name.mt.name)
- elseif isa(ft, DataType) && is(ft.name, Type.name) && isleaftype(ft)
- f = ft.parameters[1]
- print(io, f)
- else
- print(io, "(::", ft, ")")
- end
- first = true
- print(io, '(')
- for i = 2:length(params)
- first || print(io, ", ")
- first = false
- print(io, "::", params[i])
- end
- print(io, ')')
+ params = linfo.sig.parameters
+ ft = params[1]
+ if ft <: Function && isempty(ft.parameters) &&
+ isdefined(ft.name.module, ft.name.mt.name) &&
+ ft == typeof(getfield(ft.name.module, ft.name.mt.name))
+ print(io, ft.name.mt.name)
+ elseif isa(ft, DataType) && is(ft.name, Type.name) && isleaftype(ft)
+ f = ft.parameters[1]
+ print(io, f)
else
- print(io, linfo.name)
+ print(io, "(::", ft, ")")
end
+ first = true
+ print(io, '(')
+ for i = 2:length(params)
+ first || print(io, ", ")
+ first = false
+ print(io, "::", params[i])
+ end
+ print(io, ')')
end
end
diff --git a/base/sysimg.jl b/base/sysimg.jl
index a26eecb7c23fd..fb213adbe607c 100644
--- a/base/sysimg.jl
+++ b/base/sysimg.jl
@@ -73,7 +73,6 @@ include("array.jl")
(::Type{Matrix})() = Array{Any}(0, 0)
# TODO: possibly turn these into deprecations
-Array{T,N}(::Type{T}, d::NTuple{N,Int}) = Array{T}(d)
Array{T}(::Type{T}, d::Integer...) = Array{T}(convert(Tuple{Vararg{Int}}, d))
Array{T}(::Type{T}, m::Integer) = Array{T}(m)
Array{T}(::Type{T}, m::Integer,n::Integer) = Array{T}(m,n)
diff --git a/src/alloc.c b/src/alloc.c
index 9675c582085b3..51bb022c6b6df 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -43,8 +43,9 @@ jl_datatype_t *jl_newvarnode_type;
jl_datatype_t *jl_topnode_type;
jl_datatype_t *jl_intrinsic_type;
jl_datatype_t *jl_methtable_type;
-jl_datatype_t *jl_method_type;
jl_datatype_t *jl_lambda_info_type;
+jl_datatype_t *jl_ast_info_type;
+jl_datatype_t *jl_method_type;
jl_datatype_t *jl_module_type;
jl_datatype_t *jl_errorexception_type=NULL;
jl_datatype_t *jl_argumenterror_type;
@@ -273,36 +274,61 @@ JL_DLLEXPORT jl_value_t *jl_new_struct_uninit(jl_datatype_t *type)
return jv;
}
-JL_DLLEXPORT
-jl_lambda_info_t *jl_new_lambda_info(jl_value_t *ast, jl_svec_t *tvars, jl_svec_t *sparams,
- jl_module_t *ctx)
-{
- jl_lambda_info_t *li =
- (jl_lambda_info_t*)newobj((jl_value_t*)jl_lambda_info_type,
- NWORDS(sizeof(jl_lambda_info_t)));
- li->ast = ast;
- li->rettype = (jl_value_t*)jl_any_type;
- li->file = null_sym;
- li->line = 0;
- li->pure = 0;
- li->called = 0xff;
+// create a new Method from an expression tree
+JL_DLLEXPORT jl_method_t *jl_new_method(jl_value_t *ast, jl_svec_t *tvars,
+ jl_module_t *ctx)
+{
+ jl_method_t *def =
+ (jl_method_t*)newobj((jl_value_t*)jl_method_type,
+ NWORDS(sizeof(jl_method_t)));
+ def->sig = NULL;
+ def->tvars = NULL;
+ def->next = NULL;
+ def->file = null_sym;
+ def->line = 0;
+ def->isstaged = 0;
+ def->va = 0;
+ def->module = ctx;
+ def->sparam_syms = tvars;
+ def->tfunc = jl_nothing;
+ def->roots = NULL;
+ def->specializations = NULL;
+ def->name = anonymous_sym;
+ def->invokes = (jl_methtable_t*)jl_nothing;
+ def->next = (jl_method_t*)jl_nothing;
+ def->unspecialized = NULL;
+ def->ast = NULL;
+
+ JL_GC_PUSH1(&def);
+ jl_ast_info_t *astinfo =
+ (jl_ast_info_t*)newobj((jl_value_t*)jl_ast_info_type,
+ NWORDS(sizeof(jl_ast_info_t)));
+ astinfo->ast = ast;
+ astinfo->def = def;
+ astinfo->unspecialized_ducttape = NULL;
+ astinfo->called = 0xff;
+ astinfo->pure = 0;
+ astinfo->inferred = 0;
+ astinfo->need_ducttape = (def->sparam_syms != jl_emptysvec);
+ def->ast = astinfo;
+ jl_gc_wb(def, astinfo);
if (ast != NULL && jl_is_expr(ast)) {
- jl_array_t *body = jl_lam_body((jl_expr_t*)ast)->args;
- if (has_meta(body, pure_sym))
- li->pure = 1;
- jl_value_t *body1 = skip_meta(body);
+ jl_expr_t *body = jl_lam_body((jl_expr_t*)ast);
+ if (has_meta(body->args, pure_sym))
+ astinfo->pure = 1;
+ jl_value_t *body1 = skip_meta(body->args);
if (jl_is_linenode(body1)) {
- li->file = jl_linenode_file(body1);
- li->line = jl_linenode_line(body1);
+ def->file = jl_linenode_file(body1);
+ def->line = jl_linenode_line(body1);
}
else if (jl_is_expr(body1) && ((jl_expr_t*)body1)->head == line_sym) {
- li->file = (jl_sym_t*)jl_exprarg(body1, 1);
- li->line = jl_unbox_long(jl_exprarg(body1, 0));
+ def->file = (jl_sym_t*)jl_exprarg(body1, 1);
+ def->line = jl_unbox_long(jl_exprarg(body1, 0));
}
- jl_array_t *vis = jl_lam_vinfo((jl_expr_t*)li->ast);
- jl_array_t *args = jl_lam_args((jl_expr_t*)li->ast);
+ jl_array_t *vis = jl_lam_vinfo((jl_expr_t*)ast);
+ jl_array_t *args = jl_lam_args((jl_expr_t*)ast);
size_t narg = jl_array_len(args);
- uint8_t called=0;
+ astinfo->called=0;
int i, j=0;
for(i=1; i < narg && i <= 8; i++) {
jl_value_t *ai = jl_cellref(args,i);
@@ -313,56 +339,70 @@ jl_lambda_info_t *jl_new_lambda_info(jl_value_t *ast, jl_svec_t *tvars, jl_svec_
} while (jl_cellref(vj,0) != ai);
if (jl_unbox_long(jl_cellref(vj,2))&64)
- called |= (1<<(i-1));
+ astinfo->called |= (1<<(i-1));
}
- li->called = called;
- }
- li->module = ctx;
- li->sparam_syms = tvars;
- li->sparam_vals = sparams;
- li->tfunc = jl_nothing;
- li->fptr = NULL;
- li->jlcall_api = 0;
- li->roots = NULL;
- li->functionObjects.functionObject = NULL;
- li->functionObjects.specFunctionObject = NULL;
- li->functionObjects.cFunctionList = NULL;
- li->functionID = 0;
- li->specFunctionID = 0;
- li->specTypes = NULL;
- li->inferred = 0;
- li->inInference = 0;
- li->inCompile = 0;
- li->unspecialized = NULL;
- li->specializations = NULL;
- li->name = anonymous_sym;
- li->def = li;
- return li;
-}
-
-jl_lambda_info_t *jl_copy_lambda_info(jl_lambda_info_t *linfo)
-{
- jl_lambda_info_t *new_linfo =
- jl_new_lambda_info(linfo->ast, linfo->sparam_syms, linfo->sparam_vals, linfo->module);
- new_linfo->rettype = linfo->rettype;
- new_linfo->tfunc = linfo->tfunc;
- new_linfo->name = linfo->name;
- new_linfo->roots = linfo->roots;
- new_linfo->specTypes = linfo->specTypes;
- new_linfo->unspecialized = linfo->unspecialized;
- new_linfo->specializations = linfo->specializations;
- new_linfo->def = linfo->def;
- new_linfo->file = linfo->file;
- new_linfo->line = linfo->line;
- new_linfo->fptr = linfo->fptr;
- new_linfo->jlcall_api = linfo->jlcall_api;
- new_linfo->functionObjects.functionObject = linfo->functionObjects.functionObject;
- new_linfo->functionObjects.specFunctionObject = linfo->functionObjects.specFunctionObject;
- new_linfo->functionID = linfo->functionID;
- new_linfo->specFunctionID = linfo->specFunctionID;
- return new_linfo;
+ if (astinfo->need_ducttape && !jl_has_intrinsics(astinfo, body, def->module))
+ astinfo->need_ducttape = 0;
+ }
+ JL_GC_POP();
+ return def;
}
+// return a new lambda-info that has some extra static parameters merged in
+JL_DLLEXPORT jl_lambda_info_t *jl_new_lambda_info(jl_value_t *func, jl_svec_t *sp, jl_tupletype_t *types)
+{
+ jl_lambda_info_t *nli =
+ (jl_lambda_info_t*)newobj((jl_value_t*)jl_lambda_info_type,
+ NWORDS(sizeof(jl_lambda_info_t)));
+ nli->next = (jl_lambda_info_t*)jl_nothing;
+ nli->sparam_vals = sp;
+ nli->sig = types;
+ nli->rettype = (jl_value_t*)jl_any_type;
+ nli->va = jl_is_va_tuple(types);
+ nli->func = func;
+ nli->inCompile = 0;
+ jl_llvm_functions_t functionObjects = {0};
+ nli->functionObjects = functionObjects;
+ if (jl_options.compile_enabled == JL_OPTIONS_COMPILE_OFF && func != NULL) {
+ // copy fptr from func
+ while (func) {
+ if (jl_is_ast_info(func)) {
+ jl_ast_info_t *astinfo = (jl_ast_info_t*)func;
+ if (astinfo->unspecialized_ducttape && astinfo->unspecialized_ducttape->functionObjects.fptr)
+ func = (jl_value_t*)astinfo->unspecialized_ducttape;
+ else if (astinfo->def->unspecialized && astinfo->def->unspecialized->functionObjects.fptr)
+ func = (jl_value_t*)astinfo->def->unspecialized;
+ else
+ break;
+ nli->functionObjects = ((jl_lambda_info_t*)func)->functionObjects;
+ nli->rettype = ((jl_lambda_info_t*)func)->rettype;
+ break;
+ }
+ else if (jl_is_lambda_info(func)) {
+ jl_lambda_info_t *linfo = (jl_lambda_info_t*)func;
+ if (linfo->functionObjects.fptr) {
+ nli->functionObjects = linfo->functionObjects;
+ nli->rettype = linfo->rettype;
+ break;
+ }
+ func = linfo->func;
+ }
+ else {
+ assert(0 && "don't know how to codegen this type of object");
+ }
+ }
+ if (nli->functionObjects.fptr == NULL) {
+ JL_GC_PUSH1(&nli);
+ jl_printf(JL_STDERR,"code missing for ");
+ jl_static_show(JL_STDERR, (jl_value_t*)nli);
+ jl_printf(JL_STDERR, " sysimg may not have been built with --compile=all\n");
+ JL_GC_POP();
+ }
+ }
+ return nli;
+}
+
+
// symbols --------------------------------------------------------------------
JL_DEFINE_MUTEX(symbol_table)
@@ -542,8 +582,8 @@ JL_DLLEXPORT jl_methtable_t *jl_new_method_table(jl_sym_t *name, jl_module_t *mo
jl_set_typeof(mt, jl_methtable_type);
mt->name = jl_demangle_typename(name);
mt->module = module;
- mt->defs = (jl_methlist_t*)jl_nothing;
- mt->cache = (jl_methlist_t*)jl_nothing;
+ mt->defs = (jl_method_t*)jl_nothing;
+ mt->cache = (jl_lambda_info_t*)jl_nothing;
mt->cache_arg1 = (jl_array_t*)jl_nothing;
mt->cache_targ = (jl_array_t*)jl_nothing;
mt->max_args = 0;
diff --git a/src/anticodegen.c b/src/anticodegen.c
index 1bce057a0fd1d..8cc4f0ac2b436 100644
--- a/src/anticodegen.c
+++ b/src/anticodegen.c
@@ -43,7 +43,7 @@ void jl_getFunctionInfo(char **name, char **filename, size_t *line,
}
jl_value_t *jl_static_eval(jl_value_t *ex, void *ctx_, jl_module_t *mod,
- jl_lambda_info_t *li, int sparams, int allow_alloc)
+ jl_ast_info_t *ast, jl_lambda_info_t *linfo, int allow_alloc);
{
return NULL;
}
diff --git a/src/ast.c b/src/ast.c
index 4f49995160e31..7c72b8a4a549a 100644
--- a/src/ast.c
+++ b/src/ast.c
@@ -456,7 +456,7 @@ static jl_value_t *scm_to_julia_(fl_context_t *fl_ctx, value_t e, int eo)
jl_expr_t *ex = jl_exprn(lambda_sym, n);
jl_svec_t *tvars = NULL;
jl_array_t *vinf = NULL;
- jl_lambda_info_t *nli = NULL;
+ jl_method_t *nli = NULL;
JL_GC_PUSH4(&ex, &tvars, &vinf, &nli);
e = cdr_(e);
value_t largs = car_(e);
@@ -483,8 +483,8 @@ static jl_value_t *scm_to_julia_(fl_context_t *fl_ctx, value_t e, int eo)
jl_cellset(ex->args, i, scm_to_julia_(fl_ctx, car_(e), eo));
e = cdr_(e);
}
- nli = jl_new_lambda_info((jl_value_t*)ex, tvars, jl_emptysvec, jl_current_module);
- jl_preresolve_globals(nli->ast, nli);
+ nli = jl_new_method((jl_value_t*)ex, tvars, jl_current_module);
+ jl_preresolve_globals(nli->ast->ast, nli);
JL_GC_POP();
return (jl_value_t*)nli;
}
@@ -875,7 +875,7 @@ ssize_t jl_max_jlgensym_in(jl_value_t *v)
}
// wrap expr in a thunk AST
-jl_lambda_info_t *jl_wrap_expr(jl_value_t *expr)
+jl_method_t *jl_wrap_expr(jl_value_t *expr)
{
// `(lambda () (() () () ()) ,expr)
jl_expr_t *le=NULL, *bo=NULL; jl_value_t *vi=NULL;
@@ -895,7 +895,7 @@ jl_lambda_info_t *jl_wrap_expr(jl_value_t *expr)
expr = (jl_value_t*)bo;
}
jl_cellset(le->args, 2, expr);
- jl_lambda_info_t *li = jl_new_lambda_info((jl_value_t*)le, jl_emptysvec, jl_emptysvec, jl_current_module);
+ jl_method_t *li = jl_new_method((jl_value_t*)le, jl_emptysvec, jl_current_module);
JL_GC_POP();
return li;
}
@@ -912,13 +912,11 @@ jl_array_t *jl_lam_args(jl_expr_t *l)
return (jl_array_t*)ae;
}
-jl_sym_t *jl_lam_argname(jl_lambda_info_t *li, int i)
+jl_sym_t *jl_lam_argname(jl_method_t *li, int i)
{
- jl_expr_t *ast;
- if (jl_is_expr(li->ast))
- ast = (jl_expr_t*)li->ast;
- else
- ast = (jl_expr_t*)jl_uncompress_ast(li, li->ast);
+ jl_expr_t *ast = (jl_expr_t*)li->ast->ast;
+ if (!jl_is_expr(ast))
+ ast = (jl_expr_t*)jl_uncompress_ast(li, (jl_value_t*)ast);
// NOTE (gc root): `ast` is not rooted here, but jl_lam_args and jl_cellref
// do not allocate.
return (jl_sym_t*)jl_cellref(jl_lam_args(ast),i);
@@ -1061,7 +1059,7 @@ JL_DLLEXPORT jl_value_t *jl_copy_ast(jl_value_t *expr)
static jl_value_t *dont_copy_ast(jl_value_t *expr)
{
- if (jl_is_symbol(expr) || jl_is_lambda_info(expr)) {
+ if (jl_is_symbol(expr) || jl_is_method(expr)) {
return copy_ast(expr);
}
else if (jl_is_expr(expr)) {
@@ -1085,24 +1083,25 @@ static jl_value_t *dont_copy_ast(jl_value_t *expr)
return expr;
}
-// given a new lambda_info with static parameter values, make a copy
-// of the tree with declared types evaluated and static parameters passed
-// on to all enclosed functions.
-// this tree can then be further mutated by optimization passes.
-JL_DLLEXPORT jl_value_t *jl_prepare_ast(jl_lambda_info_t *li)
+// copy an astinfo tree so it can then be further mutated by optimization passes
+JL_DLLEXPORT jl_ast_info_t *jl_copy_ast_info(jl_ast_info_t *astinfo)
{
- jl_value_t *ast = li->ast;
- if (ast == NULL) return NULL;
+ jl_value_t *ast = astinfo->ast;
JL_GC_PUSH1(&ast);
if (!jl_is_expr(ast)) {
- ast = jl_uncompress_ast(li, ast);
+ ast = jl_uncompress_ast(astinfo->def, ast);
ast = dont_copy_ast(ast);
}
else {
ast = copy_ast(ast);
}
+ jl_ast_info_t *newastinfo =
+ (jl_ast_info_t*)newobj((jl_value_t*)jl_ast_info_type,
+ NWORDS(sizeof(jl_ast_info_t)));
+ *newastinfo = *astinfo;
+ newastinfo->ast = ast;
JL_GC_POP();
- return ast;
+ return newastinfo;
}
JL_DLLEXPORT int jl_is_operator(char *sym)
@@ -1167,15 +1166,15 @@ static int jl_in_sym_svec(jl_svec_t *a, jl_sym_t *v)
return 0;
}
-int jl_local_in_linfo(jl_lambda_info_t *linfo, jl_sym_t *sym)
+int jl_local_in_linfo(jl_method_t *linfo, jl_sym_t *sym)
{
- return jl_in_vinfo_array(jl_lam_vinfo((jl_expr_t*)linfo->ast), sym) ||
+ return jl_in_vinfo_array(jl_lam_vinfo((jl_expr_t*)linfo->ast->ast), sym) ||
jl_in_sym_svec(linfo->sparam_syms, sym);
}
extern jl_value_t *jl_builtin_getfield;
-jl_value_t *jl_preresolve_globals(jl_value_t *expr, jl_lambda_info_t *lam)
+jl_value_t *jl_preresolve_globals(jl_value_t *expr, jl_method_t *lam)
{
if (jl_is_symbol(expr)) {
if (lam->module == NULL)
@@ -1183,9 +1182,9 @@ jl_value_t *jl_preresolve_globals(jl_value_t *expr, jl_lambda_info_t *lam)
if (!jl_local_in_linfo(lam, (jl_sym_t*)expr))
return jl_module_globalref(lam->module, (jl_sym_t*)expr);
}
- else if (jl_is_lambda_info(expr)) {
- jl_lambda_info_t *l = (jl_lambda_info_t*)expr;
- (void)jl_preresolve_globals(l->ast, l);
+ else if (jl_is_method(expr)) {
+ jl_method_t *l = (jl_method_t*)expr;
+ (void)jl_preresolve_globals(l->ast->ast, l);
}
else if (jl_is_expr(expr)) {
jl_expr_t *e = (jl_expr_t*)expr;
@@ -1203,13 +1202,13 @@ jl_value_t *jl_preresolve_globals(jl_value_t *expr, jl_lambda_info_t *lam)
jl_value_t *s = jl_fieldref(jl_exprarg(e,2),0);
jl_value_t *fe = jl_exprarg(e,0);
if (jl_is_symbol(s) && jl_is_topnode(fe)) {
- jl_value_t *f = jl_static_eval(fe, NULL, lam->module, lam, 0, 0);
+ jl_value_t *f = jl_static_eval(fe, NULL, lam->module, NULL, 0, 0);
if (f == jl_builtin_getfield) {
jl_value_t *me = jl_exprarg(e,1);
if (jl_is_topnode(me) ||
(jl_is_symbol(me) && jl_binding_resolved_p(lam->module,(jl_sym_t*)me))) {
jl_value_t *m = jl_static_eval(me, NULL, lam->module,
- lam, 0, 0);
+ NULL, 0, 0);
if (m && jl_is_module(m))
return jl_module_globalref((jl_module_t*)m, (jl_sym_t*)s);
}
diff --git a/src/builtins.c b/src/builtins.c
index d75442e9ee099..c52d52cb0606d 100644
--- a/src/builtins.c
+++ b/src/builtins.c
@@ -1084,11 +1084,8 @@ jl_value_t *jl_mk_builtin_func(const char *name, jl_fptr_t fptr)
{
jl_sym_t *sname = jl_symbol(name);
jl_value_t *f = jl_new_generic_function_with_supertype(sname, jl_core_module, jl_builtin_type, 0);
- jl_lambda_info_t *li = jl_new_lambda_info(jl_nothing, jl_emptysvec, jl_emptysvec, jl_core_module);
- li->fptr = fptr;
- li->name = sname;
- // TODO jb/functions: what should li->ast be?
- li->ast = (jl_value_t*)jl_exprn(lambda_sym,0); jl_gc_wb(li, li->ast);
+ jl_lambda_info_t *li = jl_new_lambda_info(NULL, jl_emptysvec, jl_anytuple_type);
+ li->functionObjects.fptr = fptr;
jl_method_cache_insert(jl_gf_mtable(f), jl_anytuple_type, li);
return f;
}
@@ -1096,7 +1093,7 @@ jl_value_t *jl_mk_builtin_func(const char *name, jl_fptr_t fptr)
jl_fptr_t jl_get_builtin_fptr(jl_value_t *b)
{
assert(jl_subtype(b, (jl_value_t*)jl_builtin_type, 1));
- return jl_gf_mtable(b)->cache->func->fptr;
+ return jl_gf_mtable(b)->cache->functionObjects.fptr;
}
static void add_builtin_func(const char *name, jl_fptr_t fptr)
@@ -1153,7 +1150,6 @@ void jl_init_primitives(void)
add_builtin("SimpleVector", (jl_value_t*)jl_simplevector_type);
add_builtin("Module", (jl_value_t*)jl_module_type);
- add_builtin("Method", (jl_value_t*)jl_method_type);
add_builtin("MethodTable", (jl_value_t*)jl_methtable_type);
add_builtin("Symbol", (jl_value_t*)jl_sym_type);
add_builtin("GenSym", (jl_value_t*)jl_gensym_type);
@@ -1161,6 +1157,8 @@ void jl_init_primitives(void)
add_builtin("Function", (jl_value_t*)jl_function_type);
add_builtin("Builtin", (jl_value_t*)jl_builtin_type);
add_builtin("LambdaInfo", (jl_value_t*)jl_lambda_info_type);
+ add_builtin("AstInfo", (jl_value_t*)jl_ast_info_type);
+ add_builtin("Method", (jl_value_t*)jl_method_type);
add_builtin("Ref", (jl_value_t*)jl_ref_type);
add_builtin("Ptr", (jl_value_t*)jl_pointer_type);
add_builtin("Task", (jl_value_t*)jl_task_type);
@@ -1204,10 +1202,45 @@ static size_t jl_show_svec(JL_STREAM *out, jl_svec_t *t, char *head, char *opn,
return n;
}
-#define MAX_DEPTH 25
+JL_DLLEXPORT size_t jl_static_show_func_sig(JL_STREAM *s, jl_value_t *type)
+{
+ jl_value_t *ftype = jl_first_argument_datatype(type);
+ if (ftype == NULL)
+ return jl_static_show(s, type);
+ size_t n = 0;
+ if (jl_nparams(ftype)==0 || ftype == ((jl_datatype_t*)ftype)->name->primary) {
+ n += jl_printf(s, "%s", jl_symbol_name(((jl_datatype_t*)ftype)->name->mt->name));
+ }
+ else {
+ n += jl_printf(s, "(::");
+ n += jl_static_show(s, ftype);
+ n += jl_printf(s, ")");
+ }
+ size_t tl = jl_nparams(type);
+ n += jl_printf(s, "(");
+ size_t i;
+ for (i = 1; i < tl; i++) {
+ jl_value_t *tp = jl_tparam(type, i);
+ if (i != tl - 1) {
+ n += jl_static_show(s, tp);
+ n += jl_printf(s, ", ");
+ }
+ else {
+ if (jl_is_vararg_type(tp)) {
+ n += jl_static_show(s, jl_tparam0(tp));
+ n += jl_printf(s, "...");
+ }
+ else {
+ n += jl_static_show(s, tp);
+ }
+ }
+ }
+ n += jl_printf(s, ")");
+ return n;
+}
+#define MAX_DEPTH 25
static size_t jl_static_show_x(JL_STREAM *out, jl_value_t *v, int depth);
-
// `v` might be pointing to a field inlined in a structure therefore
// `jl_typeof(v)` may not be the same with `vt` and only `vt` should be
// used to determine the type of the value.
@@ -1229,21 +1262,31 @@ static size_t jl_static_show_x_(JL_STREAM *out, jl_value_t *v,
n += jl_static_show_x(out, (jl_value_t*)vt, depth);
n += jl_printf(out, ">");
}
+ else if (vt == jl_ast_info_type) {
+ jl_ast_info_t *li = (jl_ast_info_t*)v;
+ n += jl_static_show_x(out, (jl_value_t*)li->def->module, depth);
+ n += jl_printf(out, ".%s(...)", jl_symbol_name(li->def->name));
+ // The following is nice for debugging, but allocates memory and generates a lot of output
+ // so it may not be a good idea to to have it active
+ //n += jl_printf(out, " -> ");
+ //n += jl_static_show(out, !jl_is_expr(li->ast) ? jl_uncompress_ast(li->def, li->ast) : li->ast);
+ }
else if (vt == jl_lambda_info_type) {
jl_lambda_info_t *li = (jl_lambda_info_t*)v;
- n += jl_static_show_x(out, (jl_value_t*)li->module, depth);
- if (li->specTypes) {
- n += jl_printf(out, ".");
- n += jl_show_svec(out, li->specTypes->parameters,
- jl_symbol_name(li->name), "(", ")");
+ n += jl_static_show_func_sig(out, (jl_value_t*)li->sig);
+ n += jl_printf(out, " <");
+ n += jl_static_show_x(out, (jl_value_t*)li->sparam_vals, depth);
+ n += jl_printf(out, ">");
+ }
+ else if (vt == jl_method_type) {
+ jl_method_t *li = (jl_method_t*)v;
+ if (li->sig) {
+ n += jl_static_show_func_sig(out, (jl_value_t*)li->sig);
}
else {
+ n += jl_static_show_x(out, (jl_value_t*)li->module, depth);
n += jl_printf(out, ".%s(?)", jl_symbol_name(li->name));
}
- // The following is nice for debugging, but allocates memory and generates a lot of output
- // so it may not be a good idea to to have it active
- //jl_printf(out, " -> ");
- //jl_static_show(out, !jl_is_expr(li->ast) ? jl_uncompress_ast(li, li->ast) : li->ast);
}
else if (vt == jl_simplevector_type) {
n += jl_show_svec(out, (jl_svec_t*)v, "svec", "(", ")");
@@ -1510,43 +1553,6 @@ JL_DLLEXPORT size_t jl_static_show(JL_STREAM *out, jl_value_t *v)
return jl_static_show_x(out, v, 0);
}
-JL_DLLEXPORT size_t jl_static_show_func_sig(JL_STREAM *s, jl_value_t *type)
-{
- jl_value_t *ftype = jl_first_argument_datatype(type);
- if (ftype == NULL)
- return jl_static_show(s, type);
- size_t n = 0;
- if (jl_nparams(ftype)==0 || ftype == ((jl_datatype_t*)ftype)->name->primary) {
- n += jl_printf(s, "%s", jl_symbol_name(((jl_datatype_t*)ftype)->name->mt->name));
- }
- else {
- n += jl_printf(s, "(::");
- n += jl_static_show(s, ftype);
- n += jl_printf(s, ")");
- }
- size_t tl = jl_nparams(type);
- n += jl_printf(s, "(");
- size_t i;
- for (i = 1; i < tl; i++) {
- jl_value_t *tp = jl_tparam(type, i);
- if (i != tl - 1) {
- n += jl_static_show(s, tp);
- n += jl_printf(s, ", ");
- }
- else {
- if (jl_is_vararg_type(tp)) {
- n += jl_static_show(s, jl_tparam0(tp));
- n += jl_printf(s, "...");
- }
- else {
- n += jl_static_show(s, tp);
- }
- }
- }
- n += jl_printf(s, ")");
- return n;
-}
-
JL_DLLEXPORT void jl_(void *jl_value)
{
jl_in_jl_++;
diff --git a/src/ccall.cpp b/src/ccall.cpp
index db4fb386e353e..1697893352e0e 100644
--- a/src/ccall.cpp
+++ b/src/ccall.cpp
@@ -440,7 +440,7 @@ static jl_cgval_t emit_cglobal(jl_value_t **args, size_t nargs, jl_codectx_t *ct
if (nargs == 2) {
JL_TRY {
rt = jl_interpret_toplevel_expr_in(ctx->module, args[2],
- ctx->linfo->sparam_syms,
+ ctx->astinfo->def->sparam_syms,
ctx->linfo->sparam_vals);
}
JL_CATCH {
@@ -505,7 +505,7 @@ static jl_cgval_t emit_llvmcall(jl_value_t **args, size_t nargs, jl_codectx_t *c
{
JL_TRY {
at = jl_interpret_toplevel_expr_in(ctx->module, args[3],
- ctx->linfo->sparam_syms,
+ ctx->astinfo->def->sparam_syms,
ctx->linfo->sparam_vals);
}
JL_CATCH {
@@ -515,7 +515,7 @@ static jl_cgval_t emit_llvmcall(jl_value_t **args, size_t nargs, jl_codectx_t *c
{
JL_TRY {
rt = jl_interpret_toplevel_expr_in(ctx->module, args[2],
- ctx->linfo->sparam_syms,
+ ctx->astinfo->def->sparam_syms,
ctx->linfo->sparam_vals);
}
JL_CATCH {
@@ -525,7 +525,7 @@ static jl_cgval_t emit_llvmcall(jl_value_t **args, size_t nargs, jl_codectx_t *c
{
JL_TRY {
ir = jl_interpret_toplevel_expr_in(ctx->module, args[1],
- ctx->linfo->sparam_syms,
+ ctx->astinfo->def->sparam_syms,
ctx->linfo->sparam_vals);
}
JL_CATCH {
@@ -966,7 +966,7 @@ static jl_cgval_t emit_ccall(jl_value_t **args, size_t nargs, jl_codectx_t *ctx)
else {
JL_TRY {
rt = jl_interpret_toplevel_expr_in(ctx->module, args[2],
- ctx->linfo->sparam_syms,
+ ctx->astinfo->def->sparam_syms,
ctx->linfo->sparam_vals);
}
JL_CATCH {
@@ -1049,7 +1049,7 @@ static jl_cgval_t emit_ccall(jl_value_t **args, size_t nargs, jl_codectx_t *ctx)
{
JL_TRY {
at = jl_interpret_toplevel_expr_in(ctx->module, args[3],
- ctx->linfo->sparam_syms,
+ ctx->astinfo->def->sparam_syms,
ctx->linfo->sparam_vals);
}
JL_CATCH {
diff --git a/src/cgutils.cpp b/src/cgutils.cpp
index c7602e535a52d..a53c1cb950a10 100644
--- a/src/cgutils.cpp
+++ b/src/cgutils.cpp
@@ -849,8 +849,9 @@ static Value *literal_pointer_val(jl_value_t *p)
}
if (jl_is_lambda_info(p)) {
jl_lambda_info_t *linfo = (jl_lambda_info_t*)p;
+ jl_datatype_t *ftype = (jl_datatype_t*)jl_first_argument_datatype((jl_value_t*)linfo->sig);
// Type-inferred functions are prefixed with a -
- return julia_gv("-", linfo->name, linfo->module, p);
+ return ftype ? julia_gv("-", ftype->name->mt->name, ftype->name->mt->module, p) : julia_gv("jl_lambda#", p);
}
if (jl_is_symbol(p)) {
jl_sym_t *addr = (jl_sym_t*)p;
@@ -1498,7 +1499,7 @@ static jl_value_t *expr_type(jl_value_t *e, jl_codectx_t *ctx)
if (jl_is_symbol(e)) {
if (is_global((jl_sym_t*)e, ctx)) {
// look for static parameter
- jl_svec_t *sp = ctx->linfo->sparam_syms;
+ jl_svec_t *sp = ctx->astinfo->def->sparam_syms;
for (size_t i=0; i < jl_svec_len(sp); i++) {
assert(jl_is_symbol(jl_svecref(sp, i)));
if (e == jl_svecref(sp, i)) {
@@ -1532,8 +1533,6 @@ static jl_value_t *expr_type(jl_value_t *e, jl_codectx_t *ctx)
// --- accessing the representations of built-in data types ---
-static void jl_add_linfo_root(jl_lambda_info_t *li, jl_value_t *val);
-
static Value *data_pointer(Value *x)
{
return builder.CreateBitCast(x, T_ppjlvalue);
@@ -1586,7 +1585,7 @@ static bool emit_getfield_unknownidx(jl_cgval_t *ret, const jl_cgval_t &strct, V
jl_value_t *jt = jl_field_type(stt,0);
if (!stt->uid) {
// add root for types not cached
- jl_add_linfo_root(ctx->linfo, (jl_value_t*)stt);
+ jl_add_linfo_root(ctx, (jl_value_t*)stt);
}
Value *idx0 = emit_bounds_check(strct, (jl_value_t*)stt, idx, ConstantInt::get(T_size, nfields), ctx);
if (strct.isghost) {
@@ -2010,7 +2009,7 @@ static Value *boxed(const jl_cgval_t &vinfo, jl_codectx_t *ctx, jl_value_t *jt)
if ((c = dyn_cast(v)) != NULL) {
jl_value_t *s = static_constant_instance(c, jt);
if (s) {
- jl_add_linfo_root(ctx->linfo, s);
+ jl_add_linfo_root(ctx, s);
return literal_pointer_val(s);
}
}
diff --git a/src/codegen.cpp b/src/codegen.cpp
index dda59ed8b42e7..c0f0514ef14dc 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -549,6 +549,7 @@ struct jl_gcinfo_t {
// Keeps tracks of all functions and compile units created during this cycle
// to be able to atomically add them to a module.
+// on the old JIT, jl_cyclectx_t* is used as a bool to track codegen recursion
typedef struct {
std::vector functions;
std::vector CUs;
@@ -569,6 +570,7 @@ typedef struct {
std::map *handlers;
jl_module_t *module;
jl_expr_t *ast;
+ jl_ast_info_t *astinfo;
jl_lambda_info_t *linfo;
Value *spvals_ptr;
Value *argArray;
@@ -698,6 +700,27 @@ static inline jl_cgval_t mark_julia_const(jl_value_t *jv)
return constant;
}
+static void jl_add_linfo_root(jl_codectx_t *ctx, jl_value_t *val)
+{
+ JL_GC_PUSH1(&val);
+ jl_method_t *li = ctx->astinfo->def;
+ if (li->roots == NULL) {
+ li->roots = jl_alloc_cell_1d(1);
+ jl_gc_wb(li, li->roots);
+ jl_cellset(li->roots, 0, val);
+ }
+ else {
+ size_t rlen = jl_array_dim0(li->roots);
+ for(size_t i=0; i < rlen; i++) {
+ if (jl_cellref(li->roots,i) == val) {
+ JL_GC_POP();
+ return;
+ }
+ }
+ jl_cell_1d_push(li->roots, val);
+ }
+ JL_GC_POP();
+}
// --- utilities ---
@@ -748,7 +771,7 @@ static bool store_unboxed_p(jl_sym_t *s, jl_codectx_t *ctx)
jl_varinfo_t &vi = ctx->vars[s];
// only store a variable unboxed if type inference has run, which
// checks that the variable is not referenced undefined.
- return (ctx->linfo->inferred && !vi.usedUndef &&
+ return (ctx->astinfo->inferred && !vi.usedUndef &&
// don't unbox vararg tuples
s != ctx->vaName && store_unboxed_p(vi.value.typ));
}
@@ -828,7 +851,7 @@ static Function *to_function(jl_lambda_info_t *li, jl_cyclectx_t *cyclectx)
{
JL_LOCK(codegen);
JL_SIGATOMIC_BEGIN();
- assert(!li->inInference);
+ assert(jl_is_ast_info(li->func));
BasicBlock *old = nested_compile ? builder.GetInsertBlock() : NULL;
DebugLoc olddl = builder.getCurrentDebugLocation();
bool last_n_c = nested_compile;
@@ -850,16 +873,16 @@ static Function *to_function(jl_lambda_info_t *li, jl_cyclectx_t *cyclectx)
delete newcyclectx;
}
#else
- emit_function(li, &li->functionObjects, &definitions, NULL);
+ emit_function(li, &li->functionObjects, &definitions, (jl_cyclectx_t*)true);
#endif
f = (llvm::Function*)definitions.functionObject;
specf = (llvm::Function*)definitions.specFunctionObject;
- li->functionID = jl_assign_functionID(f, 0);
+ li->functionObjects.functionID = jl_assign_functionID(f, 0);
if (specf)
- li->specFunctionID = jl_assign_functionID(specf, 1);
+ li->functionObjects.specFunctionID = jl_assign_functionID(specf, 1);
if (f->getFunctionType() != jl_func_sig)
// mark the pointer as jl_fptr_sparam_t calling convention
- li->jlcall_api = 1;
+ li->functionObjects.jlcall_api = 1;
//n_emit++;
}
JL_CATCH {
@@ -873,7 +896,7 @@ static Function *to_function(jl_lambda_info_t *li, jl_cyclectx_t *cyclectx)
}
JL_SIGATOMIC_END();
JL_UNLOCK(codegen);
- jl_rethrow_with_add("error compiling %s", jl_symbol_name(li->name));
+ jl_rethrow_with_add("error compiling %s", jl_symbol_name(((jl_ast_info_t*)li->func)->def->name));
}
assert(f != NULL);
const DataLayout &DL =
@@ -884,7 +907,7 @@ static Function *to_function(jl_lambda_info_t *li, jl_cyclectx_t *cyclectx)
#endif
// record that this function name came from this linfo,
// so we can build a reverse mapping for debug-info.
- if (li->name != anonymous_sym) {
+ if (((jl_ast_info_t*)li->func)->def->name != anonymous_sym) {
// but don't remember anonymous symbols because
// they may not be rooted in the gc for the life of the program,
// and the runtime doesn't notify us when the code becomes unreachable :(
@@ -1057,7 +1080,7 @@ extern "C" void jl_generate_fptr(jl_lambda_info_t *li)
JL_LOCK(codegen);
// objective: assign li->fptr
assert(li->functionObjects.functionObject);
- if (li->fptr == NULL) {
+ if (li->functionObjects.fptr == NULL) {
JL_SIGATOMIC_BEGIN();
#ifdef USE_MCJIT
if (imaging_mode) {
@@ -1076,16 +1099,16 @@ extern "C" void jl_generate_fptr(jl_lambda_info_t *li)
}
}
jl_finalize_module(m);
- li->fptr = (jl_fptr_t)jl_ExecutionEngine->getFunctionAddress(((Function*)li->functionObjects.functionObject)->getName());
+ li->functionObjects.fptr = (jl_fptr_t)jl_ExecutionEngine->getFunctionAddress(((Function*)li->functionObjects.functionObject)->getName());
}
else {
- li->fptr = (jl_fptr_t)getAddressForOrCompileFunction((Function*)li->functionObjects.functionObject);
+ li->functionObjects.fptr = (jl_fptr_t)getAddressForOrCompileFunction((Function*)li->functionObjects.functionObject);
}
#else
- li->fptr = (jl_fptr_t)jl_ExecutionEngine->getPointerToFunction((Function*)li->functionObjects.functionObject);
+ li->functionObjects.fptr = (jl_fptr_t)jl_ExecutionEngine->getPointerToFunction((Function*)li->functionObjects.functionObject);
#endif
- assert(li->fptr != NULL);
+ assert(li->functionObjects.fptr != NULL);
#ifndef KEEP_BODIES
if (!imaging_mode)
((Function*)li->functionObjects.functionObject)->deleteBody();
@@ -1127,14 +1150,62 @@ extern "C" void jl_generate_fptr(jl_lambda_info_t *li)
JL_UNLOCK(codegen);
}
-extern "C" void jl_compile_linfo(jl_lambda_info_t *li, void *cyclectx)
+static jl_lambda_info_t *jl_get_unspecialized(jl_method_t *def, jl_lambda_info_t *method)
+{
+ if (!def->ast->need_ducttape) {
+ // one unspecialized version of a function can usually be shared among all cached specializations
+ if (!def->unspecialized) {
+ def->unspecialized = jl_new_lambda_info((jl_value_t*)def->ast, jl_emptysvec, def->sig);
+ jl_gc_wb(def, def->unspecialized);
+ }
+ assert(!def->unspecialized->inCompile);
+ return def->unspecialized;
+ }
+
+ // but if ducttape is required for the compiler, then use it instead
+ assert(jl_is_ast_info(method->func));
+ jl_ast_info_t *ast = (jl_ast_info_t*)method->func;
+ if (!ast->unspecialized_ducttape) {
+ if (ast == ast->def->ast) {
+ ast = jl_copy_ast_info(ast);
+ method->func = (jl_value_t*)ast;
+ jl_gc_wb(method, ast);
+ }
+ ast->unspecialized_ducttape = jl_new_lambda_info((jl_value_t*)def->ast, method->sparam_vals, method->sig);
+ jl_gc_wb(ast, ast->unspecialized_ducttape);
+ }
+ assert(!ast->unspecialized_ducttape->inCompile);
+ return ast->unspecialized_ducttape;
+}
+
+extern "C" jl_lambda_info_t *jl_compile_linfo(jl_lambda_info_t *li, void *cyclectx)
{
+ // objective: return a lambda-info with a functionObject
if (li->functionObjects.functionObject == NULL) {
- // objective: assign li->functionObject
- li->inCompile = 1;
- (void)to_function(li, (jl_cyclectx_t *)cyclectx);
- li->inCompile = 0;
+ if (jl_is_ast_info(li->func)) {
+ jl_ast_info_t *astinfo = (jl_ast_info_t*)li->func;
+ if (li->inCompile) {
+ if (cyclectx != NULL)
+ return NULL;
+ return jl_compile_linfo(jl_get_unspecialized(astinfo->def, li), cyclectx);
+ }
+ assert(!li->inCompile);
+ li->inCompile = 1;
+ to_function(li, (jl_cyclectx_t *)cyclectx);
+ li->inCompile = 0;
+ return li;
+ }
+ else if (jl_is_lambda_info(li->func)) {
+ jl_lambda_info_t *result = jl_compile_linfo((jl_lambda_info_t*)li->func, cyclectx);
+ if (result == (jl_lambda_info_t*)li->func)
+ li->functionObjects = ((jl_lambda_info_t*)li->func)->functionObjects;
+ return result;
+ }
+ else {
+ assert(0 && "don't know how to codegen this type of object");
+ }
}
+ return li;
}
// Get the LLVM Function* for the C-callable entry point for a certain function
@@ -1194,14 +1265,14 @@ static Function *jl_cfunction_object(jl_function_t *f, jl_value_t *rt, jl_tuplet
jl_lambda_info_t *li = jl_get_specialization1((jl_tupletype_t*)sigt, NULL);
if (li != NULL) {
for(i=1; i < nargs+1; i++) {
- jl_value_t *speci = jl_nth_slot_type(li->specTypes, i);
+ jl_value_t *speci = jl_nth_slot_type(li->sig, i);
jl_value_t *sigi = jl_nth_slot_type((jl_tupletype_t*)sigt, i);
if ((isref & (2<<(i-1))) && speci == (jl_value_t*)jl_any_type) {
// specialized for Any => can accept any Ref
}
else if (!jl_types_equal(speci, sigi)) {
jl_errorf("cfunction: type signature of %s does not match specification",
- jl_symbol_name(li->name));
+ jl_symbol_name(jl_gf_mtable(f)->name));
}
}
jl_value_t *astrt = li->rettype;
@@ -1210,12 +1281,12 @@ static Function *jl_cfunction_object(jl_function_t *f, jl_value_t *rt, jl_tuplet
if (rt != (jl_value_t*)jl_void_type) {
// a function that doesn't return can be passed to C as void
jl_errorf("cfunction: %s does not return",
- jl_symbol_name(li->name));
+ jl_symbol_name(jl_gf_mtable(f)->name));
}
}
else if (!jl_subtype(astrt, rt, 0)) {
jl_errorf("cfunction: return type of %s does not match",
- jl_symbol_name(li->name));
+ jl_symbol_name(jl_gf_mtable(f)->name));
}
}
JL_GC_POP(); // kill list: sigt
@@ -1310,20 +1381,12 @@ void *jl_get_llvmf(jl_function_t *f, jl_tupletype_t *tt, bool getwrapper, bool g
linfo = jl_get_specialization1(tt, NULL);
if (linfo == NULL) {
linfo = jl_method_lookup_by_type(jl_gf_mtable(f), tt, 0, 0);
- if (linfo == NULL) {
- JL_GC_POP();
- return NULL;
- }
}
}
if (linfo == NULL) {
JL_GC_POP();
return NULL;
}
- if (!linfo->specTypes) {
- jl_printf(JL_STDERR, "WARNING: Returned code may not match what actually runs.\n");
- linfo = jl_get_unspecialized(linfo);
- }
if (!getdeclarations) {
Function *llvmDecl = nullptr;
@@ -1372,12 +1435,12 @@ void *jl_get_llvmf(jl_function_t *f, jl_tupletype_t *tt, bool getwrapper, bool g
return llvmf;
}
- if (linfo->fptr && !jl_getUnwindInfo((uintptr_t)linfo->fptr)) {
+ if (linfo->functionObjects.fptr && !jl_getUnwindInfo((uintptr_t)linfo->functionObjects.fptr)) {
// Not in in the current ExecutionEngine
// found in the system image: force a recompile
linfo->functionObjects.specFunctionObject = NULL;
linfo->functionObjects.functionObject = NULL;
- linfo->fptr = NULL;
+ linfo->functionObjects.fptr = NULL;
}
if (linfo->functionObjects.functionObject == NULL) {
jl_compile_linfo(linfo, NULL);
@@ -1674,8 +1737,8 @@ extern "C" void jl_write_malloc_log(void)
static void show_source_loc(JL_STREAM *out, jl_codectx_t *ctx)
{
if (ctx == NULL) return;
- jl_printf(out, "in %s at %s", jl_symbol_name(ctx->linfo->name),
- jl_symbol_name(ctx->linfo->file));
+ jl_printf(out, "in %s at %s", jl_symbol_name(ctx->astinfo->def->name),
+ jl_symbol_name(ctx->astinfo->def->file));
}
extern "C" void jl_binding_deprecation_warning(jl_binding_t *b);
@@ -1692,7 +1755,7 @@ static void cg_bdw(jl_binding_t *b, jl_codectx_t *ctx)
// try to statically evaluate, NULL if not possible
extern "C"
jl_value_t *jl_static_eval(jl_value_t *ex, void *ctx_, jl_module_t *mod,
- jl_lambda_info_t *linfo, int sparams, int allow_alloc)
+ jl_ast_info_t *ast, jl_lambda_info_t *linfo, int allow_alloc)
{
jl_codectx_t *ctx = (jl_codectx_t*)ctx_;
if (jl_is_symbolnode(ex))
@@ -1703,16 +1766,16 @@ jl_value_t *jl_static_eval(jl_value_t *ex, void *ctx_, jl_module_t *mod,
if (ctx) {
isglob = is_global(sym, ctx);
}
- else if (linfo) {
- isglob = !jl_local_in_linfo(linfo, sym);
+ else if (ast) {
+ isglob = !jl_local_in_linfo(ast->def, sym);
}
if (isglob) {
- size_t i;
- if (sparams) {
- for (i=0; i < jl_svec_len(linfo->sparam_syms); i++) {
- if (sym == (jl_sym_t*)jl_svecref(linfo->sparam_syms, i)) {
+ if (linfo) {
+ size_t i, l = jl_svec_len(ast->def->sparam_syms);
+ for (i=0; i < l; i++) {
+ if (sym == (jl_sym_t*)jl_svecref(ast->def->sparam_syms, i)) {
// static parameter
- if (jl_svec_len(ctx->linfo->sparam_vals) > 0)
+ if (jl_svec_len(linfo->sparam_vals) > 0)
return jl_svecref(linfo->sparam_vals, i);
else
return NULL;
@@ -1754,11 +1817,11 @@ jl_value_t *jl_static_eval(jl_value_t *ex, void *ctx_, jl_module_t *mod,
if (jl_is_expr(ex)) {
jl_expr_t *e = (jl_expr_t*)ex;
if (e->head == call_sym) {
- jl_value_t *f = jl_static_eval(jl_exprarg(e,0),ctx,mod,linfo,sparams,allow_alloc);
+ jl_value_t *f = jl_static_eval(jl_exprarg(e,0),ctx,mod,ast,linfo,allow_alloc);
if (f) {
if (jl_array_dim0(e->args) == 3 && f==jl_builtin_getfield) {
- m = (jl_module_t*)jl_static_eval(jl_exprarg(e,1),ctx,mod,linfo,sparams,allow_alloc);
- s = (jl_sym_t*)jl_static_eval(jl_exprarg(e,2),ctx,mod,linfo,sparams,allow_alloc);
+ m = (jl_module_t*)jl_static_eval(jl_exprarg(e,1),ctx,mod,ast,linfo,allow_alloc);
+ s = (jl_sym_t*)jl_static_eval(jl_exprarg(e,2),ctx,mod,ast,linfo,allow_alloc);
if (m && jl_is_module(m) && s && jl_is_symbol(s)) {
jl_binding_t *b = jl_get_binding(m, s);
if (b && b->constp) {
@@ -1776,7 +1839,7 @@ jl_value_t *jl_static_eval(jl_value_t *ex, void *ctx_, jl_module_t *mod,
jl_value_t **v;
JL_GC_PUSHARGS(v, n);
for (i = 0; i < n; i++) {
- v[i] = jl_static_eval(jl_exprarg(e,i+1),ctx,mod,linfo,sparams,allow_alloc);
+ v[i] = jl_static_eval(jl_exprarg(e,i+1),ctx,mod,ast,linfo,allow_alloc);
if (v[i] == NULL) {
JL_GC_POP();
return NULL;
@@ -1805,8 +1868,8 @@ jl_value_t *jl_static_eval(jl_value_t *ex, void *ctx_, jl_module_t *mod,
static jl_value_t *static_eval(jl_value_t *ex, jl_codectx_t *ctx, bool sparams,
bool allow_alloc)
{
- return jl_static_eval(ex, ctx, ctx->module, ctx->linfo,
- sparams, allow_alloc);
+ return jl_static_eval(ex, ctx, ctx->module, ctx->astinfo,
+ sparams ? ctx->linfo : NULL, allow_alloc);
}
static bool is_constant(jl_value_t *ex, jl_codectx_t *ctx, bool sparams=true)
@@ -2088,30 +2151,6 @@ static jl_cgval_t emit_boxed_rooted(jl_value_t *e, jl_codectx_t *ctx) // TODO: m
return v;
}
-// --- lambda ---
-
-static void jl_add_linfo_root(jl_lambda_info_t *li, jl_value_t *val)
-{
- JL_GC_PUSH1(&val);
- li = li->def;
- if (li->roots == NULL) {
- li->roots = jl_alloc_cell_1d(1);
- jl_gc_wb(li, li->roots);
- jl_cellset(li->roots, 0, val);
- }
- else {
- size_t rlen = jl_array_dim0(li->roots);
- for(size_t i=0; i < rlen; i++) {
- if (jl_cellref(li->roots,i) == val) {
- JL_GC_POP();
- return;
- }
- }
- jl_cell_1d_push(li->roots, val);
- }
- JL_GC_POP();
-}
-
// --- generating function calls ---
static jl_cgval_t emit_getfield(jl_value_t *expr, jl_sym_t *name, jl_codectx_t *ctx)
@@ -2495,7 +2534,7 @@ static bool emit_builtin_call(jl_cgval_t *ret, jl_value_t *f, jl_value_t **args,
JL_GC_POP();
return true;
}
- if (ctx->linfo->inferred) {
+ if (ctx->astinfo->inferred) {
rt1 = expr_type(expr, ctx);
if (jl_is_tuple_type(rt1) && jl_is_leaf_type(rt1) && nargs == jl_datatype_nfields(rt1)) {
*ret = emit_new_struct(rt1, nargs+1, args, ctx);
@@ -2829,7 +2868,7 @@ static bool emit_builtin_call(jl_cgval_t *ret, jl_value_t *f, jl_value_t **args,
if (ty!=NULL && jl_is_leaf_type(ty)) {
if (jl_has_typevars(ty)) {
// add root for types not cached. issue #7065
- jl_add_linfo_root(ctx->linfo, ty);
+ jl_add_linfo_root(ctx, ty);
}
*ret = mark_julia_const(ty);
JL_GC_POP();
@@ -2880,6 +2919,8 @@ static jl_cgval_t emit_call_function_object(jl_lambda_info_t *li, const jl_cgval
{
if (li->functionObjects.specFunctionObject != NULL) {
// emit specialized call site
+ while (jl_is_lambda_info(li->func))
+ li = (jl_lambda_info_t*)li->func;
jl_value_t *jlretty = li->rettype;
bool retboxed;
(void)julia_type_to_llvm(jlretty, &retboxed);
@@ -2901,7 +2942,7 @@ static jl_cgval_t emit_call_function_object(jl_lambda_info_t *li, const jl_cgval
}
for(size_t i=0; i < nargs+1; i++) {
Type *at = cft->getParamType(idx);
- jl_value_t *jt = jl_nth_slot_type(li->specTypes,i);
+ jl_value_t *jt = jl_nth_slot_type(li->sig,i);
bool isboxed;
Type *et = julia_type_to_llvm(jt, &isboxed);
if (type_is_ghost(et)) {
@@ -2997,7 +3038,7 @@ static jl_cgval_t emit_call(jl_value_t **args, size_t arglen, jl_codectx_t *ctx,
}
}
- if (ctx->linfo->inferred) {
+ if (ctx->astinfo->inferred) {
aty = (jl_value_t*)call_arg_types(args, arglen, ctx);
// attempt compile-time specialization for inferred types
if (aty != NULL) {
@@ -3017,7 +3058,7 @@ static jl_cgval_t emit_call(jl_value_t **args, size_t arglen, jl_codectx_t *ctx,
if (!jl_is_globalref(args[0]) &&
!(jl_is_symbol(args[0]) && is_global((jl_sym_t*)args[0],ctx)) &&
!jl_is_leaf_type(f)) {
- jl_add_linfo_root(ctx->linfo, f);
+ jl_add_linfo_root(ctx, f);
}
fval = mark_julia_const((jl_value_t*)f);
}
@@ -3141,7 +3182,7 @@ static jl_cgval_t emit_var(jl_sym_t *sym, jl_codectx_t *ctx, bool isboxed)
bool isglobal = is_global(sym, ctx);
if (isglobal) {
// look for static parameter
- jl_svec_t *sp = ctx->linfo->sparam_syms;
+ jl_svec_t *sp = ctx->astinfo->def->sparam_syms;
for(size_t i=0; i < jl_svec_len(sp); i++) {
assert(jl_is_symbol(jl_svecref(sp, i)));
if (sym == (jl_sym_t*)jl_svecref(sp, i)) {
@@ -3470,7 +3511,7 @@ static jl_cgval_t emit_expr(jl_value_t *expr, jl_codectx_t *ctx, bool isboxed, b
}
}
if (needroot) {
- jl_add_linfo_root(ctx->linfo, expr);
+ jl_add_linfo_root(ctx, expr);
}
return mark_julia_const(expr);
}
@@ -3576,7 +3617,7 @@ static jl_cgval_t emit_expr(jl_value_t *expr, jl_codectx_t *ctx, bool isboxed, b
extype = (jl_value_t*)jl_any_type;
}
if (jl_is_tuple_type(extype))
- jl_add_linfo_root(ctx->linfo, extype);
+ jl_add_linfo_root(ctx, extype);
return mark_julia_const(extype);
}
else if (head == new_sym) {
@@ -3708,13 +3749,13 @@ static jl_cgval_t emit_expr(jl_value_t *expr, jl_codectx_t *ctx, bool isboxed, b
if (!strcmp(jl_symbol_name(head), "$"))
jl_error("syntax: prefix \"$\" in non-quoted expression");
if (jl_is_toplevel_only_expr(expr) &&
- ctx->linfo->name == anonymous_sym &&
+ ctx->astinfo->def->name == anonymous_sym &&
(ctx->vars.empty() || ((jl_expr_t*)expr)->head == thunk_sym) &&
- ctx->linfo->module == jl_current_module) {
+ ctx->astinfo->def->module == jl_current_module) {
// call interpreter to run a toplevel expr from inside a
// compiled toplevel thunk.
builder.CreateCall(prepare_call(jltopeval_func), literal_pointer_val(expr));
- jl_add_linfo_root(ctx->linfo, expr);
+ jl_add_linfo_root(ctx, expr);
return ghostValue(jl_void_type);
}
// some expression types are metadata and can be ignored
@@ -3726,7 +3767,7 @@ static jl_cgval_t emit_expr(jl_value_t *expr, jl_codectx_t *ctx, bool isboxed, b
else {
jl_errorf("unsupported or misplaced expression \"%s\" in function %s",
jl_symbol_name(head),
- jl_symbol_name(ctx->linfo->name));
+ jl_symbol_name(ctx->astinfo->def->name));
}
}
}
@@ -3867,7 +3908,7 @@ static Function *gen_cfun_wrapper(jl_lambda_info_t *lam, jl_function_t *ff, jl_v
size_t i;
size_t nargs = jl_nparams(argt);
for(i=1; i < nargs+1; i++) {
- jl_value_t *tti = jl_nth_slot_type(lam->specTypes,i);
+ jl_value_t *tti = jl_nth_slot_type(lam->sig,i);
if (tti == (jl_value_t*)jl_pointer_type) {
jl_error("cfunction: argument type Ptr should have an element type, Ptr{T}");
}
@@ -3892,11 +3933,11 @@ static Function *gen_cfun_wrapper(jl_lambda_info_t *lam, jl_function_t *ff, jl_v
jl_compile_linfo(lam, NULL);
if (!lam->functionObjects.functionObject) {
jl_errorf("error compiling %s while creating cfunction",
- jl_symbol_name(lam->name));
+ jl_symbol_name(jl_gf_mtable(ff)->name));
}
std::stringstream funcName;
- funcName << "jlcapi_" << jl_symbol_name(lam->name) << "_" << globalUnique++;
+ funcName << "jlcapi_" << jl_symbol_name(jl_gf_mtable(ff)->name) << "_" << globalUnique++;
// Backup the info for the nested compile
JL_SIGATOMIC_BEGIN(); // no errors expected beyond this point
@@ -3924,6 +3965,8 @@ static Function *gen_cfun_wrapper(jl_lambda_info_t *lam, jl_function_t *ff, jl_v
jl_codectx_t ctx;
ctx.f = cw;
ctx.linfo = lam;
+ ctx.astinfo = NULL;
+ ctx.ast = NULL;
ctx.sret = false;
ctx.spvals_ptr = NULL;
allocate_gc_frame(0, b0, &ctx);
@@ -3974,7 +4017,7 @@ static Function *gen_cfun_wrapper(jl_lambda_info_t *lam, jl_function_t *ff, jl_v
for (size_t i = 0; i < nargs; i++) {
Value *val = &*AI++;
- jl_value_t *jargty = jl_nth_slot_type(lam->specTypes, i+1); // +1 because argt excludes function
+ jl_value_t *jargty = jl_nth_slot_type(lam->sig, i+1); // +1 because argt excludes function
bool isboxed, argboxed;
Type *t = julia_type_to_llvm(jargty, &isboxed);
(void)julia_struct_to_llvm(jargty, &argboxed);
@@ -4150,6 +4193,8 @@ static Function *gen_jlcall_wrapper(jl_lambda_info_t *lam, jl_expr_t *ast, Funct
jl_codectx_t ctx;
ctx.f = w;
ctx.linfo = lam;
+ ctx.astinfo = NULL;
+ ctx.ast = NULL;
ctx.sret = false;
ctx.spvals_ptr = NULL;
allocate_gc_frame(0, b0, &ctx);
@@ -4165,7 +4210,7 @@ static Function *gen_jlcall_wrapper(jl_lambda_info_t *lam, jl_expr_t *ast, Funct
idx++;
}
for(size_t i=0; i < nargs; i++) {
- jl_value_t *ty = jl_nth_slot_type(lam->specTypes, i);
+ jl_value_t *ty = jl_nth_slot_type(lam->sig, i);
bool isboxed;
Type *lty = julia_type_to_llvm(ty, &isboxed);
if (lty != NULL && type_is_ghost(lty))
@@ -4208,10 +4253,11 @@ static void emit_function(jl_lambda_info_t *lam, jl_llvm_functions_t *declaratio
assert(definitions && "Capturing definitions is always required");
// step 1. unpack AST and allocate codegen context for this function
- jl_expr_t *ast = (jl_expr_t*)lam->ast;
+ jl_ast_info_t *astinfo = (jl_ast_info_t*)lam->func;
+ jl_expr_t *ast = (jl_expr_t*)astinfo->ast;
JL_GC_PUSH1(&ast);
if (!jl_is_expr(ast)) {
- ast = (jl_expr_t*)jl_uncompress_ast(lam, (jl_value_t*)ast);
+ ast = (jl_expr_t*)jl_uncompress_ast(astinfo->def, (jl_value_t*)ast);
}
assert(jl_is_expr(ast));
//jl_static_show(JL_STDOUT, (jl_value_t*)ast);
@@ -4223,10 +4269,11 @@ static void emit_function(jl_lambda_info_t *lam, jl_llvm_functions_t *declaratio
ctx.arrayvars = &arrayvars;
ctx.labels = &labels;
ctx.handlers = &handlers;
- ctx.module = lam->module;
+ ctx.module = astinfo->def->module;
ctx.ast = ast;
+ ctx.astinfo = astinfo;
ctx.linfo = lam;
- ctx.funcName = jl_symbol_name(lam->name);
+ ctx.funcName = jl_symbol_name(astinfo->def->name);
ctx.vaName = NULL;
ctx.vaStack = false;
ctx.inbounds.push_back(false);
@@ -4244,11 +4291,6 @@ static void emit_function(jl_lambda_info_t *lam, jl_llvm_functions_t *declaratio
size_t nreq = largslen;
int va = 0;
- assert(lam->specTypes); // this could happen if the user tries to compile a generic-function
- // without specializing (or unspecializing) it first
- // compiling this would cause all specializations to inherit
- // this code and could create an broken compile / function cache
-
if (nreq > 0 && jl_is_rest_arg(jl_cellref(largs,nreq-1))) {
nreq--;
va = 1;
@@ -4265,7 +4307,7 @@ static void emit_function(jl_lambda_info_t *lam, jl_llvm_functions_t *declaratio
if (argname == unused_sym) continue;
jl_varinfo_t &varinfo = ctx.vars[argname];
varinfo.isArgument = true;
- jl_value_t *ty = jl_nth_slot_type(lam->specTypes, i);
+ jl_value_t *ty = jl_nth_slot_type(lam->sig, i);
varinfo.value = mark_julia_type((Value*)NULL, false, ty);
}
if (va && ctx.vaName) {
@@ -4283,7 +4325,7 @@ static void emit_function(jl_lambda_info_t *lam, jl_llvm_functions_t *declaratio
varinfo.isAssigned = (jl_vinfo_assigned(vi)!=0);
varinfo.escapes = false;
varinfo.isSA = (jl_vinfo_sa(vi)!=0);
- varinfo.usedUndef = (jl_vinfo_usedundef(vi)!=0) || (!varinfo.isArgument && !lam->inferred);
+ varinfo.usedUndef = (jl_vinfo_usedundef(vi)!=0) || (!varinfo.isArgument && !astinfo->inferred);
jl_value_t *typ = jl_cellref(vi,1);
if (!jl_is_type(typ))
typ = (jl_value_t*)jl_any_type;
@@ -4304,16 +4346,16 @@ static void emit_function(jl_lambda_info_t *lam, jl_llvm_functions_t *declaratio
Function *f = NULL;
bool specsig = false;
- bool needsparams = jl_svec_len(lam->sparam_syms) != jl_svec_len(lam->sparam_vals);
- if (!va && !needsparams && lam->specTypes != jl_anytuple_type && lam->inferred) {
+ bool needsparams = jl_svec_len(astinfo->def->sparam_syms) != jl_svec_len(lam->sparam_vals);
+ if (!va && !needsparams && lam->sig != jl_anytuple_type && astinfo->inferred) {
// not vararg, consider specialized signature
- for(size_t i=0; i < jl_nparams(lam->specTypes); i++) {
- if (isbits_spec(jl_tparam(lam->specTypes, i))) { // assumes !va
+ for(size_t i=0; i < jl_nparams(lam->sig); i++) {
+ if (isbits_spec(jl_tparam(lam->sig, i))) { // assumes !va
specsig = true;
break;
}
}
- if (jl_nparams(lam->specTypes) == 0)
+ if (jl_nparams(lam->sig) == 0)
specsig = true;
if (isbits_spec(jlrettype))
specsig = true;
@@ -4323,7 +4365,7 @@ static void emit_function(jl_lambda_info_t *lam, jl_llvm_functions_t *declaratio
std::stringstream funcName;
// try to avoid conflicts in the global symbol table
- funcName << "julia_" << jl_symbol_name(lam->name);
+ funcName << "julia_" << jl_symbol_name(astinfo->def->name);
Function *fwrap = NULL;
funcName << "_" << globalUnique++;
@@ -4345,8 +4387,8 @@ static void emit_function(jl_lambda_info_t *lam, jl_llvm_functions_t *declaratio
fsig.push_back(rt->getPointerTo());
rt = T_void;
}
- for(size_t i=0; i < jl_nparams(lam->specTypes); i++) {
- Type *ty = julia_type_to_llvm(jl_tparam(lam->specTypes,i));
+ for(size_t i=0; i < jl_nparams(lam->sig); i++) {
+ Type *ty = julia_type_to_llvm(jl_tparam(lam->sig,i));
if (type_is_ghost(ty))
continue;
if (ty->isAggregateType()) // aggregate types are passed by pointer
@@ -4410,12 +4452,12 @@ static void emit_function(jl_lambda_info_t *lam, jl_llvm_functions_t *declaratio
ctx.f = f;
// step 5. set up debug info context and create first basic block
- bool in_user_code = !jl_is_submodule(lam->module, jl_base_module) && !jl_is_submodule(lam->module, jl_core_module);
+ bool in_user_code = !jl_is_submodule(astinfo->def->module, jl_base_module) && !jl_is_submodule(astinfo->def->module, jl_core_module);
bool do_coverage = jl_options.code_coverage == JL_LOG_ALL || (jl_options.code_coverage == JL_LOG_USER && in_user_code);
bool do_malloc_log = jl_options.malloc_log == JL_LOG_ALL || (jl_options.malloc_log == JL_LOG_USER && in_user_code);
jl_value_t *stmt = skip_meta(stmts);
std::string filename = "no file";
- char *dbgFuncName = jl_symbol_name(lam->name);
+ char *dbgFuncName = jl_symbol_name(astinfo->def->name);
int lno = -1;
// look for initial (line num filename [funcname]) node, [funcname] for kwarg methods.
if (jl_is_linenode(stmt)) {
@@ -4495,10 +4537,10 @@ static void emit_function(jl_lambda_info_t *lam, jl_llvm_functions_t *declaratio
#else
std::vector ditypes(0);
#endif
- for(size_t i=0; i < jl_nparams(lam->specTypes); i++) { // assumes !va
+ for(size_t i=0; i < jl_nparams(lam->sig); i++) { // assumes !va
if (ctx.vars[jl_decl_var(jl_cellref(largs,i))].value.isghost)
continue;
- ditypes.push_back(julia_type_to_di(jl_tparam(lam->specTypes,i),ctx.dbuilder,false));
+ ditypes.push_back(julia_type_to_di(jl_tparam(lam->sig,i),ctx.dbuilder,false));
}
#ifdef LLVM38
subrty = ctx.dbuilder->createSubroutineType(ctx.dbuilder->getOrCreateTypeArray(ditypes));
@@ -4794,7 +4836,7 @@ static void emit_function(jl_lambda_info_t *lam, jl_llvm_functions_t *declaratio
AI++; // skip sret slot
for(i=0; i < nreq; i++) {
jl_sym_t *s = jl_decl_var(jl_cellref(largs,i));
- jl_value_t *argType = jl_nth_slot_type(lam->specTypes, i);
+ jl_value_t *argType = jl_nth_slot_type(lam->sig, i);
bool isboxed;
Type *llvmArgType = julia_type_to_llvm(argType, &isboxed);
if (s == unused_sym) {
@@ -5147,17 +5189,23 @@ static Function *jlcall_func_to_llvm(const std::string &cname, void *addr, Modul
return f;
}
-extern "C" void jl_fptr_to_llvm(void *fptr, jl_lambda_info_t *lam, int specsig)
+extern "C" jl_lambda_info_t *jl_fptr_to_llvm(void *fptr, jl_lambda_info_t *lam, int specsig)
{
- if (imaging_mode) {
- if (!specsig) {
- lam->fptr = (jl_fptr_t)fptr; // in imaging mode, it's fine to use the fptr, but we don't want it in the shadow_module
- }
+ if (jl_is_lambda_info(lam->func)) {
+ jl_lambda_info_t *base = jl_fptr_to_llvm(fptr, (jl_lambda_info_t*)lam->func, specsig);
+ lam->functionObjects = base->functionObjects;
+ return base;
+ }
+ else if (imaging_mode) {
+ if (!specsig)
+ lam->functionObjects.fptr = (jl_fptr_t)fptr; // in imaging mode, it's fine to use the fptr, but we don't want it in the shadow_module
}
else {
+ if (specsig ? lam->functionObjects.specFunctionObject != NULL : lam->functionObjects.fptr != NULL) // already assigned fptr for this lam
+ return lam;
// this assigns a function pointer (from loading the system image), to the function object
- std::string funcName = jl_symbol_name(lam->name);
- funcName = "julia_" + funcName;
+ jl_datatype_t *ftype = (jl_datatype_t*)jl_first_argument_datatype((jl_value_t*)lam->sig);
+ std::string funcName = (ftype && ftype->name->mt) ? Twine("julia_", StringRef(jl_symbol_name(ftype->name->mt->name))).str() : "julia_anon";
if (specsig) { // assumes !va
std::vector fsig(0);
jl_value_t *jlrettype = lam->rettype;
@@ -5176,8 +5224,8 @@ extern "C" void jl_fptr_to_llvm(void *fptr, jl_lambda_info_t *lam, int specsig)
fsig.push_back(rt->getPointerTo());
rt = T_void;
}
- for (size_t i=0; i < jl_nparams(lam->specTypes); i++) {
- Type *ty = julia_type_to_llvm(jl_tparam(lam->specTypes,i));
+ for (size_t i=0; i < jl_nparams(lam->sig); i++) {
+ Type *ty = julia_type_to_llvm(jl_tparam(lam->sig,i));
if (type_is_ghost(ty))
continue;
if (ty->isAggregateType()) // aggregate types are passed by pointer
@@ -5195,20 +5243,21 @@ extern "C" void jl_fptr_to_llvm(void *fptr, jl_lambda_info_t *lam, int specsig)
add_named_global(f, (void*)fptr);
}
else {
- if (lam->jlcall_api == 1) { // jl_func_sig_sparams -- don't bother emitting the FunctionObject (since can't be used right now)
- assert(lam->fptr == NULL);
- lam->fptr = (jl_fptr_t)fptr;
+ if (lam->functionObjects.jlcall_api == 1) { // jl_func_sig_sparams -- don't bother emitting the FunctionObject (since can't be used right now)
+ assert(lam->functionObjects.fptr == NULL);
+ lam->functionObjects.fptr = (jl_fptr_t)fptr;
}
else {
Function *f = jlcall_func_to_llvm(funcName, fptr, shadow_module);
if (lam->functionObjects.functionObject == NULL) {
lam->functionObjects.functionObject = (void*)f;
- assert(lam->fptr == NULL);
- lam->fptr = (jl_fptr_t)fptr;
+ assert(lam->functionObjects.fptr == NULL);
+ lam->functionObjects.fptr = (jl_fptr_t)fptr;
}
}
}
}
+ return lam;
}
#if LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR == 3 && defined(SYSTEM_LLVM)
diff --git a/src/dump.c b/src/dump.c
index 9ab2f575ce3be..c95df223c9b76 100644
--- a/src/dump.c
+++ b/src/dump.c
@@ -433,15 +433,11 @@ static void jl_update_all_fptrs(void)
for (i = 0; i < delayed_fptrs_n; i++) {
jl_lambda_info_t *li = delayed_fptrs[i].li;
int32_t func = delayed_fptrs[i].func - 1;
- if (func >= 0) {
- jl_fptr_to_llvm(fvars[func], li, 0);
- linfos[func] = li;
- }
int32_t cfunc = delayed_fptrs[i].cfunc - 1;
- if (cfunc >= 0) {
- jl_fptr_to_llvm(fvars[cfunc], li, 1);
- linfos[cfunc] = li;
- }
+ if (func >= 0)
+ linfos[func] = jl_fptr_to_llvm(fvars[func], li, 0);
+ if (cfunc >= 0)
+ linfos[cfunc] = jl_fptr_to_llvm(fvars[cfunc], li, 1);
}
jl_register_fptrs(sysimage_base, fvars, linfos, sysimg_fvars_max);
delayed_fptrs_n = 0;
@@ -611,11 +607,11 @@ static void jl_serialize_module(ios_t *s, jl_module_t *m)
static int is_ast_node(jl_value_t *v)
{
- if (jl_is_lambda_info(v)) {
- jl_lambda_info_t *li = (jl_lambda_info_t*)v;
- if (jl_is_expr(li->ast)) {
- li->ast = jl_compress_ast(li, li->ast);
- jl_gc_wb(li, li->ast);
+ if (jl_is_ast_info(v)) {
+ jl_ast_info_t *astinfo = (jl_ast_info_t*)v;
+ if (jl_is_expr(astinfo->ast)) {
+ astinfo->ast = jl_compress_ast(astinfo->def, astinfo->ast);
+ jl_gc_wb(astinfo, astinfo->ast);
}
return 0;
}
@@ -791,13 +787,13 @@ static void jl_serialize_value_(ios_t *s, jl_value_t *v)
jl_serialize_value(s, ((jl_tvar_t*)v)->ub);
write_int8(s, ((jl_tvar_t*)v)->bound);
}
- else if (jl_is_lambda_info(v)) {
- writetag(s, jl_lambda_info_type);
- jl_lambda_info_t *li = (jl_lambda_info_t*)v;
+ else if (jl_is_method(v)) {
+ writetag(s, jl_method_type);
+ jl_method_t *li = (jl_method_t*)v;
jl_serialize_value(s, li->ast);
- jl_serialize_value(s, li->rettype);
+ jl_serialize_value(s, li->sig);
+ jl_serialize_value(s, li->tvars);
jl_serialize_value(s, (jl_value_t*)li->sparam_syms);
- jl_serialize_value(s, (jl_value_t*)li->sparam_vals);
// don't save cached type info for code in the Core module, because
// it might reference types in the old Base module.
if (li->module == jl_core_module) {
@@ -824,23 +820,32 @@ static void jl_serialize_value_(ios_t *s, jl_value_t *v)
jl_serialize_value(s, (jl_value_t*)li->tfunc);
}
jl_serialize_value(s, (jl_value_t*)li->name);
- jl_serialize_value(s, (jl_value_t*)li->specTypes);
+ jl_serialize_value(s, (jl_value_t*)li->roots);
+ jl_serialize_value(s, (jl_value_t*)li->unspecialized);
jl_serialize_value(s, (jl_value_t*)li->specializations);
- write_int8(s, li->inferred);
- write_int8(s, li->pure);
- write_int8(s, li->called);
+ jl_serialize_value(s, (jl_value_t*)li->module);
jl_serialize_value(s, (jl_value_t*)li->file);
write_int32(s, li->line);
- jl_serialize_value(s, (jl_value_t*)li->module);
- jl_serialize_value(s, (jl_value_t*)li->roots);
- jl_serialize_value(s, (jl_value_t*)li->def);
- jl_serialize_value(s, (jl_value_t*)li->unspecialized);
- jl_serialize_fptr(s, li->fptr);
+ write_int8(s, li->isstaged);
+ write_int8(s, li->va);
+ jl_serialize_value(s, (jl_value_t*)li->invokes);
+ jl_serialize_value(s, (jl_value_t*)li->next);
+ }
+ else if (jl_is_lambda_info(v)) {
+ writetag(s, jl_lambda_info_type);
+ jl_lambda_info_t *li = (jl_lambda_info_t*)v;
+ jl_serialize_value(s, (jl_value_t*)li->sig);
+ jl_serialize_value(s, li->rettype);
+ write_int8(s, li->va);
+ jl_serialize_value(s, (jl_value_t*)li->sparam_vals);
+ jl_serialize_value(s, li->func);
// save functionObject pointers
- write_int32(s, li->functionID);
- write_int32(s, li->specFunctionID);
- if (li->functionID)
- write_int8(s, li->jlcall_api);
+ jl_serialize_fptr(s, li->functionObjects.fptr);
+ write_int32(s, li->functionObjects.functionID);
+ write_int32(s, li->functionObjects.specFunctionID);
+ if (li->functionObjects.functionID)
+ write_int8(s, li->functionObjects.jlcall_api);
+ jl_serialize_value(s, li->next);
}
else if (jl_typeis(v, jl_module_type)) {
jl_serialize_module(s, (jl_module_t*)v);
@@ -927,16 +932,16 @@ static void jl_serialize_methtable_from_mod(ios_t *s, jl_methtable_t *mt, int8_t
assert(!mt->kwsorter);
}
assert(mt->module);
- jl_methlist_t *ml = mt->defs;
- while (ml != (void*)jl_nothing) {
- if (module_in_worklist(ml->func->module)) {
+ jl_method_t *ml = mt->defs;
+ while (ml != (jl_method_t*)jl_nothing) {
+ if (module_in_worklist(ml->module)) {
jl_serialize_value(s, mt->module);
jl_serialize_value(s, name);
write_int8(s, iskw);
- jl_serialize_value(s, ml->sig);
- jl_serialize_value(s, ml->func);
- jl_serialize_value(s, ml->tvars);
- write_int8(s, ml->isstaged);
+ jl_method_t *next = ml->next;
+ ml->next = (jl_method_t*)jl_nothing;
+ jl_serialize_value(s, ml);
+ ml->next = next;
}
ml = ml->next;
}
@@ -1082,24 +1087,25 @@ static int type_has_replaced_module(jl_value_t *t)
return 0;
}
-static void remove_specializations_from_replaced_modules(jl_methlist_t *l)
+static void remove_specializations_from_replaced_modules(jl_method_t *l)
{
- while (l != (void*)jl_nothing) {
- jl_array_t *a = l->func->specializations;
+ while (l != (jl_method_t*)jl_nothing) {
+ jl_array_t *a = l->specializations;
if (a) {
size_t len = jl_array_len(a);
size_t i, insrt=0;
for(i=0; i < len; i++) {
jl_lambda_info_t *li = (jl_lambda_info_t*)jl_cellref(a, i);
- if (!(li->rettype && type_has_replaced_module(li->rettype)) &&
- !(li->specTypes && type_has_replaced_module((jl_value_t*)li->specTypes))) {
+ assert(li->sig && li->rettype);
+ if (!type_has_replaced_module(li->rettype) &&
+ !type_has_replaced_module((jl_value_t*)li->sig)) {
jl_cellset(a, insrt, li);
insrt++;
}
}
- jl_array_del_end(a, len-insrt);
+ jl_array_del_end(a, len - insrt);
}
- a = l->func->roots;
+ a = l->roots;
if (a) {
size_t len = jl_array_len(a);
size_t i;
@@ -1113,12 +1119,27 @@ static void remove_specializations_from_replaced_modules(jl_methlist_t *l)
}
}
-static void remove_methods_from_replaced_modules_from_list(jl_methlist_t **pl)
+static void remove_methods_from_replaced_modules_from_list(jl_lambda_info_t **pl)
+{
+ jl_lambda_info_t *l = *pl;
+ while (l != (jl_lambda_info_t*)jl_nothing) {
+ if (type_has_replaced_module((jl_value_t*)l->sig))
+ *pl = l->next;
+ else if (l->func == NULL)
+ pl = &l->next;
+ else
+ pl = &l->next;
+ l = l->next;
+ }
+}
+
+static void remove_methods_from_replaced_modules_from_defs(jl_method_t **pl)
{
- jl_methlist_t *l = *pl;
- while (l != (void*)jl_nothing) {
- if ((l->func && is_module_replaced(l->func->module)) ||
- type_has_replaced_module((jl_value_t*)l->sig))
+ jl_method_t *l = *pl;
+ while (l != (jl_method_t*)jl_nothing) {
+ if (type_has_replaced_module((jl_value_t*)l->sig))
+ *pl = l->next;
+ else if (is_module_replaced(l->module))
*pl = l->next;
else
pl = &l->next;
@@ -1126,19 +1147,22 @@ static void remove_methods_from_replaced_modules_from_list(jl_methlist_t **pl)
}
}
+
static void remove_methods_from_replaced_modules_from_cache(jl_array_t *a)
{
jl_value_t **data;
size_t i, l = jl_array_len(a); data = (jl_value_t**)jl_array_data(a);
for(i=0; i < l; i++) {
if (data[i] != NULL)
- remove_methods_from_replaced_modules_from_list((jl_methlist_t**)&data[i]);
+ remove_methods_from_replaced_modules_from_list((jl_lambda_info_t**)&data[i]);
}
}
static void remove_methods_from_replaced_modules(jl_methtable_t *mt)
{
- remove_methods_from_replaced_modules_from_list(&mt->defs);
+ // note: this is probably completely gc-invalid,
+ // but it's unlikely gc will be called again
+ remove_methods_from_replaced_modules_from_defs(&mt->defs);
remove_methods_from_replaced_modules_from_list(&mt->cache);
if ((jl_value_t*)mt->cache_arg1 != jl_nothing)
remove_methods_from_replaced_modules_from_cache(mt->cache_arg1);
@@ -1416,56 +1440,72 @@ static jl_value_t *jl_deserialize_value_(ios_t *s, jl_value_t *vtag, jl_value_t
tv->bound = read_int8(s);
return (jl_value_t*)tv;
}
- else if (vtag == (jl_value_t*)jl_lambda_info_type) {
- jl_lambda_info_t *li =
- (jl_lambda_info_t*)newobj((jl_value_t*)jl_lambda_info_type,
- NWORDS(sizeof(jl_lambda_info_t)));
+ else if (vtag == (jl_value_t*)jl_method_type) {
+ jl_method_t *li =
+ (jl_method_t*)newobj((jl_value_t*)jl_method_type,
+ NWORDS(sizeof(jl_method_t)));
if (usetable)
arraylist_push(&backref_list, li);
- li->ast = jl_deserialize_value(s, &li->ast);
+ li->ast = (jl_ast_info_t*)jl_deserialize_value(s, (jl_value_t**)&li->ast);
jl_gc_wb(li, li->ast);
- li->rettype = jl_deserialize_value(s, &li->rettype);
- jl_gc_wb(li, li->rettype);
+ li->sig = (jl_tupletype_t*)jl_deserialize_value(s, (jl_value_t**)&li->sig);
+ jl_gc_wb(li, li->sig);
+ li->tvars = (jl_svec_t*)jl_deserialize_value(s, (jl_value_t**)&li->tvars);
+ jl_gc_wb(li, li->tvars);
li->sparam_syms = (jl_svec_t*)jl_deserialize_value(s, (jl_value_t**)&li->sparam_syms);
jl_gc_wb(li, li->sparam_syms);
- li->sparam_vals = (jl_svec_t*)jl_deserialize_value(s, (jl_value_t**)&li->sparam_vals);
- jl_gc_wb(li, li->sparam_vals);
li->tfunc = jl_deserialize_value(s, (jl_value_t**)&li->tfunc);
jl_gc_wb(li, li->tfunc);
li->name = (jl_sym_t*)jl_deserialize_value(s, NULL);
jl_gc_wb(li, li->name);
- li->specTypes = (jl_tupletype_t*)jl_deserialize_value(s, (jl_value_t**)&li->specTypes);
- if (li->specTypes) jl_gc_wb(li, li->specTypes);
+ li->roots = (jl_array_t*)jl_deserialize_value(s, (jl_value_t**)&li->roots);
+ if (li->roots) jl_gc_wb(li, li->roots);
+ li->unspecialized = (jl_lambda_info_t*)jl_deserialize_value(s, (jl_value_t**)&li->unspecialized);
+ if (li->unspecialized) jl_gc_wb(li, li->unspecialized);
li->specializations = (jl_array_t*)jl_deserialize_value(s, (jl_value_t**)&li->specializations);
if (li->specializations) jl_gc_wb(li, li->specializations);
- li->inferred = read_int8(s);
- li->pure = read_int8(s);
- li->called = read_int8(s);
+ li->module = (jl_module_t*)jl_deserialize_value(s, (jl_value_t**)&li->module);
+ jl_gc_wb(li, li->module);
li->file = (jl_sym_t*)jl_deserialize_value(s, NULL);
jl_gc_wb(li, li->file);
li->line = read_int32(s);
- li->module = (jl_module_t*)jl_deserialize_value(s, (jl_value_t**)&li->module);
- jl_gc_wb(li, li->module);
- li->roots = (jl_array_t*)jl_deserialize_value(s, (jl_value_t**)&li->roots);
- if (li->roots) jl_gc_wb(li, li->roots);
- li->def = (jl_lambda_info_t*)jl_deserialize_value(s, (jl_value_t**)&li->def);
- jl_gc_wb(li, li->def);
- li->fptr = NULL;
+ li->isstaged = read_int8(s);
+ li->va = read_int8(s);
+ li->invokes = (jl_methtable_t*)jl_deserialize_value(s, (jl_value_t**)&li->invokes);
+ jl_gc_wb(li, li->invokes);
+ li->next = (jl_method_t*)jl_deserialize_value(s, (jl_value_t**)&li->next);
+ jl_gc_wb(li, li->next);
+ return (jl_value_t*)li;
+ }
+ else if (vtag == (jl_value_t*)jl_lambda_info_type) {
+ jl_lambda_info_t *li =
+ (jl_lambda_info_t*)newobj((jl_value_t*)jl_lambda_info_type,
+ NWORDS(sizeof(jl_lambda_info_t)));
+ if (usetable)
+ arraylist_push(&backref_list, li);
+ li->sig = (jl_tupletype_t*)jl_deserialize_value(s, (jl_value_t**)&li->sig);
+ jl_gc_wb(li, li->sig);
+ li->rettype = jl_deserialize_value(s, &li->rettype);
+ jl_gc_wb(li, li->rettype);
+ li->va = read_int8(s);
+ li->sparam_vals = (jl_svec_t*)jl_deserialize_value(s, (jl_value_t**)&li->sparam_vals);
+ jl_gc_wb(li, li->sparam_vals);
+ li->func = jl_deserialize_value(s, &li->func);
+ jl_gc_wb(li, li->func);
+ li->inCompile = 0;
li->functionObjects.functionObject = NULL;
li->functionObjects.cFunctionList = NULL;
li->functionObjects.specFunctionObject = NULL;
- li->inInference = 0;
- li->inCompile = 0;
- li->unspecialized = (jl_lambda_info_t*)jl_deserialize_value(s, (jl_value_t**)&li->unspecialized);
- if (li->unspecialized) jl_gc_wb(li, li->unspecialized);
- li->fptr = jl_deserialize_fptr(s);
- li->functionID = 0;
- li->specFunctionID = 0;
+ li->functionObjects.functionID = 0;
+ li->functionObjects.specFunctionID = 0;
int32_t cfunc_llvm, func_llvm;
+ li->functionObjects.fptr = jl_deserialize_fptr(s);
func_llvm = read_int32(s);
cfunc_llvm = read_int32(s);
jl_delayed_fptrs(li, func_llvm, cfunc_llvm);
- li->jlcall_api = func_llvm ? read_int8(s) : 0;
+ li->functionObjects.jlcall_api = func_llvm ? read_int8(s) : 0;
+ li->next = jl_deserialize_value(s, &li->next);
+ jl_gc_wb(li, li->next);
return (jl_value_t*)li;
}
else if (vtag == (jl_value_t*)jl_module_type) {
@@ -1652,11 +1692,9 @@ static void jl_deserialize_lambdas_from_mod(ios_t *s)
int8_t iskw = read_int8(s);
if (iskw)
gf = jl_get_kwsorter(((jl_datatype_t*)jl_typeof(gf))->name);
- jl_tupletype_t *types = (jl_tupletype_t*)jl_deserialize_value(s, NULL);
- jl_lambda_info_t *meth = (jl_lambda_info_t*)jl_deserialize_value(s, NULL);
- jl_svec_t *tvars = (jl_svec_t*)jl_deserialize_value(s, NULL);
- int8_t isstaged = read_int8(s);
- jl_method_table_insert(jl_gf_mtable(gf), types, meth, tvars, isstaged);
+
+ jl_method_t *meth = (jl_method_t*)jl_deserialize_value(s, NULL);
+ jl_method_table_insert(jl_gf_mtable(gf), meth);
}
}
@@ -2028,7 +2066,7 @@ JL_DLLEXPORT void jl_restore_system_image_data(const char *buf, size_t len)
JL_SIGATOMIC_END();
}
-JL_DLLEXPORT jl_value_t *jl_compress_ast(jl_lambda_info_t *li, jl_value_t *ast)
+JL_DLLEXPORT jl_value_t *jl_compress_ast(jl_method_t *li, jl_value_t *ast)
{
JL_SIGATOMIC_BEGIN();
JL_LOCK(dump); // Might GC
@@ -2039,12 +2077,13 @@ JL_DLLEXPORT jl_value_t *jl_compress_ast(jl_lambda_info_t *li, jl_value_t *ast)
jl_array_t *last_tlv = tree_literal_values;
jl_module_t *last_tem = tree_enclosing_module;
int en = jl_gc_enable(0); // Might GC
+ assert(jl_is_method(li));
- if (li->def->roots == NULL) {
- li->def->roots = jl_alloc_cell_1d(0);
- jl_gc_wb(li->def, li->def->roots);
+ if (li->roots == NULL) {
+ li->roots = jl_alloc_cell_1d(0);
+ jl_gc_wb(li, li->roots);
}
- tree_literal_values = li->def->roots;
+ tree_literal_values = li->roots;
tree_enclosing_module = li->module;
jl_serialize_value(&dest, ast);
@@ -2052,7 +2091,7 @@ JL_DLLEXPORT jl_value_t *jl_compress_ast(jl_lambda_info_t *li, jl_value_t *ast)
jl_value_t *v = (jl_value_t*)jl_takebuf_array(&dest);
if (jl_array_len(tree_literal_values) == 0 && last_tlv == NULL) {
- li->def->roots = NULL;
+ li->roots = NULL;
}
tree_literal_values = last_tlv;
tree_enclosing_module = last_tem;
@@ -2063,15 +2102,16 @@ JL_DLLEXPORT jl_value_t *jl_compress_ast(jl_lambda_info_t *li, jl_value_t *ast)
return v;
}
-JL_DLLEXPORT jl_value_t *jl_uncompress_ast(jl_lambda_info_t *li, jl_value_t *data)
+JL_DLLEXPORT jl_value_t *jl_uncompress_ast(jl_method_t *li, jl_value_t *data)
{
JL_SIGATOMIC_BEGIN();
JL_LOCK(dump); // Might GC
+ assert(jl_is_method(li));
assert(jl_is_array(data));
DUMP_MODES last_mode = mode;
mode = MODE_AST;
jl_array_t *bytes = (jl_array_t*)data;
- tree_literal_values = li->def->roots;
+ tree_literal_values = li->roots;
tree_enclosing_module = li->module;
ios_t src;
ios_mem(&src, 0);
@@ -2283,7 +2323,7 @@ static jl_array_t *_jl_restore_incremental(ios_t *f)
jl_deserialize_lambdas_from_mod(f); // hook up methods of external generic functions
init_order = jl_finalize_deserializer(f); // done with f
- // Resort the internal method tables
+ // Rehash the internal method tables
size_t i;
for (i = 0; i < methtable_list.len; i++) {
jl_methtable_t *mt = (jl_methtable_t*)methtable_list.items[i];
@@ -2291,24 +2331,22 @@ static jl_array_t *_jl_restore_incremental(ios_t *f)
jl_array_t *cache_arg1 = mt->cache_arg1;
mt->cache_targ = (jl_array_t*)jl_nothing;
mt->cache_arg1 = (jl_array_t*)jl_nothing;
- if (cache_targ != (void*)jl_nothing) {
+ if (cache_targ != (jl_array_t*)jl_nothing) {
size_t j, l = jl_array_len(cache_targ);
for (j = 0; j < l; j++) {
- jl_methlist_t *ml = (jl_methlist_t*)jl_cellref(cache_targ, j);
- while (ml != NULL && ml != (void*)jl_nothing) {
- assert(!ml->isstaged);
- jl_method_cache_insert(mt, ml->sig, ml->func);
+ jl_lambda_info_t *ml = (jl_lambda_info_t*)jl_cellref(cache_targ, j);
+ while (ml != NULL && ml != (jl_lambda_info_t*)jl_nothing) {
+ jl_method_cache_insert(mt, ml->sig, ml);
ml = ml->next;
}
}
}
- if (cache_arg1 != (void*)jl_nothing) {
+ if (cache_arg1 != (jl_array_t*)jl_nothing) {
size_t j, l = jl_array_len(cache_arg1);
for (j = 0; j < l; j++) {
- jl_methlist_t *ml = (jl_methlist_t*)jl_cellref(cache_arg1, j);
- while (ml != NULL && ml != (void*)jl_nothing) {
- assert(!ml->isstaged);
- jl_method_cache_insert(mt, ml->sig, ml->func);
+ jl_lambda_info_t *ml = (jl_lambda_info_t*)jl_cellref(cache_arg1, j);
+ while (ml != NULL && ml != (jl_lambda_info_t*)jl_nothing) {
+ jl_method_cache_insert(mt, ml->sig, ml);
ml = ml->next;
}
}
@@ -2368,7 +2406,7 @@ void jl_init_serializer(void)
(void*)LongExpr_tag, (void*)LiteralVal_tag,
(void*)SmallInt64_tag, (void*)SmallDataType_tag,
(void*)Int32_tag, (void*)Array1d_tag, (void*)Singleton_tag,
- jl_module_type, jl_tvar_type, jl_lambda_info_type,
+ jl_module_type, jl_tvar_type, jl_lambda_info_type, jl_method_type, jl_ast_info_type,
(void*)CommonSym_tag, (void*)NearbyGlobal_tag, jl_globalref_type,
// everything above here represents a class of object rather only than a literal
@@ -2424,7 +2462,7 @@ void jl_init_serializer(void)
jl_densearray_type, jl_void_type, jl_function_type,
jl_typector_type, jl_typename_type, jl_builtin_type,
jl_task_type, jl_uniontype_type, jl_typetype_type, jl_typetype_tvar,
- jl_ANY_flag, jl_array_any_type, jl_intrinsic_type, jl_method_type,
+ jl_ANY_flag, jl_array_any_type, jl_intrinsic_type,
jl_methtable_type, jl_voidpointer_type, jl_newvarnode_type,
jl_array_symbol_type, jl_anytuple_type, jl_tparam0(jl_anytuple_type),
jl_typeof(jl_emptytuple),
@@ -2432,9 +2470,10 @@ void jl_init_serializer(void)
jl_ref_type->name, jl_pointer_type->name, jl_simplevector_type->name,
jl_datatype_type->name, jl_uniontype_type->name, jl_array_type->name,
jl_expr_type->name, jl_typename_type->name, jl_type_type->name,
- jl_methtable_type->name, jl_method_type->name, jl_tvar_type->name,
+ jl_methtable_type->name, jl_tvar_type->name,
jl_ntuple_type->name, jl_abstractarray_type->name, jl_vararg_type->name,
jl_densearray_type->name, jl_void_type->name, jl_lambda_info_type->name,
+ jl_ast_info_type->name, jl_method_type->name,
jl_module_type->name, jl_function_type->name,
jl_typector_type->name, jl_intrinsic_type->name, jl_task_type->name,
jl_labelnode_type->name, jl_linenumbernode_type->name, jl_builtin_type->name,
diff --git a/src/gf.c b/src/gf.c
index 2c33318e88994..0c210fec7f6bb 100644
--- a/src/gf.c
+++ b/src/gf.c
@@ -113,17 +113,17 @@ static inline int cache_match(jl_value_t **args, size_t n, jl_value_t **sig,
}
static inline
-jl_methlist_t *mtcache_hash_lookup(jl_array_t *a, jl_value_t *ty, int8_t tparam, int8_t offs)
+jl_lambda_info_t *mtcache_hash_lookup(jl_array_t *a, jl_value_t *ty, int8_t tparam, int8_t offs)
{
uintptr_t uid = ((jl_datatype_t*)ty)->uid;
- jl_methlist_t *ml = (jl_methlist_t*)jl_cellref(a, uid & (a->nrows-1));
+ jl_lambda_info_t *ml = (jl_lambda_info_t*)jl_cellref(a, uid & (a->nrows-1));
if (ml && ml!=(void*)jl_nothing) {
jl_value_t *t = jl_field_type(ml->sig, offs);
if (tparam) t = jl_tparam0(t);
if (t == ty)
return ml;
}
- return (jl_methlist_t*)jl_nothing;
+ return (jl_lambda_info_t*)jl_nothing;
}
static void mtcache_rehash(jl_array_t **pa, jl_value_t *parent, int8_t offs)
@@ -134,8 +134,8 @@ static void mtcache_rehash(jl_array_t **pa, jl_value_t *parent, int8_t offs)
jl_value_t **nd = (jl_value_t**)n->data;
size_t i;
for(i=0; i < len; i++) {
- jl_methlist_t *ml = (jl_methlist_t*)d[i];
- if (ml && ml!=(jl_methlist_t*)jl_nothing) {
+ jl_lambda_info_t *ml = (jl_lambda_info_t*)d[i];
+ if (ml && ml!=(jl_lambda_info_t*)jl_nothing) {
jl_value_t *t = jl_field_type(ml->sig, offs);
if (jl_is_type_type(t))
t = jl_tparam0(t);
@@ -147,15 +147,15 @@ static void mtcache_rehash(jl_array_t **pa, jl_value_t *parent, int8_t offs)
*pa = n;
}
-static jl_methlist_t **mtcache_hash_bp(jl_array_t **pa, jl_value_t *ty,
+static jl_lambda_info_t **mtcache_hash_bp(jl_array_t **pa, jl_value_t *ty,
int8_t tparam, int8_t offs, jl_value_t *parent)
{
uintptr_t uid;
if (jl_is_datatype(ty) && (uid = ((jl_datatype_t*)ty)->uid)) {
while (1) {
- jl_methlist_t **pml = &((jl_methlist_t**)jl_array_data(*pa))[uid & ((*pa)->nrows-1)];
- if (*pml == NULL || *pml == (jl_methlist_t*)jl_nothing) {
- *pml = (jl_methlist_t*)jl_nothing;
+ jl_lambda_info_t **pml = &((jl_lambda_info_t**)jl_array_data(*pa))[uid & ((*pa)->nrows-1)];
+ if (*pml == NULL || *pml == (jl_lambda_info_t*)jl_nothing) {
+ *pml = (jl_lambda_info_t*)jl_nothing;
return pml;
}
jl_value_t *t = jl_field_type((*pml)->sig, offs);
@@ -182,14 +182,14 @@ static jl_lambda_info_t *jl_method_table_assoc_exact_by_type(jl_methtable_t *mt,
{
// called object is the primary key for constructors, otherwise first argument
int8_t offs = (mt == jl_type_type->name->mt) ? 0 : 1;
- jl_methlist_t *ml = (jl_methlist_t*)jl_nothing;
+ jl_lambda_info_t *ml = (jl_lambda_info_t*)jl_nothing;
if (jl_datatype_nfields(types) > offs) {
jl_value_t *ty = jl_tparam(types, offs);
if (jl_is_type_type(ty)) {
jl_value_t *a0 = jl_tparam0(ty);
if (mt->cache_targ != (void*)jl_nothing && jl_is_datatype(a0)) {
ml = mtcache_hash_lookup(mt->cache_targ, a0, 1, offs);
- if (ml!=(jl_methlist_t*)jl_nothing)
+ if (ml!=(jl_lambda_info_t*)jl_nothing)
goto mt_assoc_bt_lkup;
}
}
@@ -204,10 +204,10 @@ static jl_lambda_info_t *jl_method_table_assoc_exact_by_type(jl_methtable_t *mt,
if (cache_match_by_type(jl_svec_data(types->parameters),
jl_datatype_nfields(types),
ml->sig, ml->va)) {
- return ml->func;
+ return ml;
}
// see corresponding code in jl_method_table_assoc_exact
- if (ml->func == NULL && jl_subtype((jl_value_t*)types, (jl_value_t*)ml->sig, 0))
+ if (ml->sparam_vals == NULL && jl_subtype((jl_value_t*)types, (jl_value_t*)ml->sig, 0))
return NULL;
ml = ml->next;
}
@@ -218,7 +218,7 @@ static jl_lambda_info_t *jl_method_table_assoc_exact(jl_methtable_t *mt, jl_valu
{
// NOTE: This function is a huge performance hot spot!!
int8_t offs = (mt == jl_type_type->name->mt) ? 0 : 1;
- jl_methlist_t *ml = (jl_methlist_t*)jl_nothing;
+ jl_lambda_info_t *ml = (jl_lambda_info_t*)jl_nothing;
if (n > offs) {
jl_value_t *a1 = args[offs];
jl_value_t *ty = (jl_value_t*)jl_typeof(a1);
@@ -235,21 +235,21 @@ static jl_lambda_info_t *jl_method_table_assoc_exact(jl_methtable_t *mt, jl_valu
jl_value_t *t0 = (jl_value_t*)jl_typeof(a0);
if (ml->next==(void*)jl_nothing && n==2 && jl_datatype_nfields(ml->sig)==2 &&
jl_tparam(ml->sig,1-offs)==t0)
- return ml->func;
+ return ml;
if (n==3) {
// some manually-unrolled common special cases
jl_value_t *a2 = args[2];
if (!jl_is_tuple(a2)) { // issue #6426
- jl_methlist_t *mn = ml;
+ jl_lambda_info_t *mn = ml;
if (jl_datatype_nfields(mn->sig)==3 &&
jl_tparam(mn->sig,1-offs)==t0 &&
jl_tparam(mn->sig,2)==(jl_value_t*)jl_typeof(a2))
- return mn->func;
+ return mn;
mn = mn->next;
if (mn!=(void*)jl_nothing && jl_datatype_nfields(mn->sig)==3 &&
jl_tparam(mn->sig,1-offs)==t0 &&
jl_tparam(mn->sig,2)==(jl_value_t*)jl_typeof(a2))
- return mn->func;
+ return mn;
}
}
}
@@ -262,12 +262,12 @@ static jl_lambda_info_t *jl_method_table_assoc_exact(jl_methtable_t *mt, jl_valu
size_t lensig = jl_datatype_nfields(ml->sig);
if (lensig == n || (ml->va && lensig <= n+1)) {
if (cache_match(args, n, jl_svec_data(ml->sig->parameters), ml->va, lensig)) {
- return ml->func;
+ return ml;
}
// if we hit a guard entry (ml->func == NULL), do a more
// expensive subtype check, since guard entries added for ANY might be
// abstract. this fixed issue #12967.
- if (ml->func == NULL && jl_tuple_subtype(args, n, ml->sig, 1))
+ if (ml->sparam_vals == NULL && jl_tuple_subtype(args, n, ml->sig, 1))
return NULL;
}
ml = ml->next;
@@ -275,98 +275,14 @@ static jl_lambda_info_t *jl_method_table_assoc_exact(jl_methtable_t *mt, jl_valu
return NULL;
}
-// return a new lambda-info that has some extra static parameters merged in.
-static jl_lambda_info_t *jl_add_static_parameters(jl_lambda_info_t *l, jl_svec_t *sp, jl_tupletype_t *types)
-{
- JL_GC_PUSH1(&sp);
- assert(jl_svec_len(l->sparam_syms) == jl_svec_len(sp) || sp == jl_emptysvec);
- assert(l->sparam_vals == jl_emptysvec);
- assert(l->specTypes == NULL);
- jl_lambda_info_t *nli = jl_copy_lambda_info(l);
- nli->unspecialized = l;
- nli->sparam_vals = sp; // no gc_wb needed
- nli->tfunc = jl_nothing;
- nli->specializations = NULL;
- nli->specTypes = types;
- if (types) jl_gc_wb(nli, types);
-
- /* "method" itself should never get compiled,
- for example, if an unspecialized method is needed,
- the slow compiled code should be associated with
- method->unspecialized, not method */
- assert(!nli->ast ||
- (nli->fptr == NULL &&
- nli->jlcall_api == 0 &&
- nli->functionObjects.functionObject == NULL &&
- nli->functionObjects.specFunctionObject == NULL &&
- nli->functionObjects.cFunctionList == NULL &&
- nli->functionID == 0 &&
- nli->specFunctionID == 0));
- if (jl_options.compile_enabled == JL_OPTIONS_COMPILE_OFF) {
- // copy fptr from the unspecialized method definition
- jl_lambda_info_t *unspec = l->unspecialized;
- if (unspec != NULL) {
- nli->fptr = unspec->fptr;
- nli->jlcall_api = unspec->jlcall_api;
- nli->functionObjects.functionObject = unspec->functionObjects.functionObject;
- nli->functionObjects.specFunctionObject = unspec->functionObjects.specFunctionObject;
- nli->functionID = unspec->functionID;
- nli->specFunctionID = unspec->functionID;
- }
- if (nli->fptr == NULL) {
- jl_printf(JL_STDERR,"code missing for ");
- jl_static_show(JL_STDERR, (jl_value_t*)nli);
- jl_printf(JL_STDERR, " sysimg may not have been built with --compile=all\n");
- }
- }
- JL_GC_POP();
- return nli;
-}
+static void jl_method_list_insert(jl_lambda_info_t **pml, jl_tupletype_t *type,
+ jl_lambda_info_t *method, jl_value_t *parent);
-jl_lambda_info_t *jl_get_unspecialized(jl_lambda_info_t *method)
-{
- // one unspecialized version of a function can be shared among all cached specializations
- jl_lambda_info_t *def = method;
- if (def->specTypes) {
- // a method is a specialization iff it has specTypes
- // but method->unspecialized points to the definition in that case
- // and definition->unspecialized points to the thing to call
- def = def->unspecialized;
- }
- if (__unlikely(def->unspecialized == NULL)) {
- int need_sparams = 0; // if there are intrinsics, probably require the sparams to compile successfully
- if (method->sparam_vals != jl_emptysvec) {
- jl_value_t *ast = def->ast;
- JL_GC_PUSH1(&ast);
- if (!jl_is_expr(ast))
- ast = jl_uncompress_ast(def, ast);
- if (jl_has_intrinsics(method, jl_lam_body((jl_expr_t*)ast), method->module))
- need_sparams = 1;
- JL_GC_POP();
- }
- if (need_sparams) {
- method->unspecialized = jl_add_static_parameters(def, method->sparam_vals, method->specTypes);
- jl_gc_wb(method, method->unspecialized);
- method->unspecialized->unspecialized = method->unspecialized;
- def = method;
- }
- else {
- def->unspecialized = jl_add_static_parameters(def, jl_emptysvec, jl_anytuple_type);
- jl_gc_wb(def, def->unspecialized);
- }
- }
- return def->unspecialized;
-}
-
-static jl_methlist_t *jl_method_list_insert(jl_methlist_t **pml, jl_tupletype_t *type,
- jl_lambda_info_t *method, jl_svec_t *tvars,
- int check_amb, int8_t isstaged, jl_value_t *parent);
-
-jl_lambda_info_t *jl_method_cache_insert(jl_methtable_t *mt, jl_tupletype_t *type,
- jl_lambda_info_t *method)
+void jl_method_cache_insert(jl_methtable_t *mt, jl_tupletype_t *type,
+ jl_lambda_info_t *method)
{
int8_t offs = (mt == jl_type_type->name->mt) ? 0 : 1;
- jl_methlist_t **pml = &mt->cache;
+ jl_lambda_info_t **pml = &mt->cache;
jl_value_t *cache_array = NULL;
if (jl_datatype_nfields(type) > offs) {
jl_value_t *t1 = jl_tparam(type, offs);
@@ -400,7 +316,7 @@ jl_lambda_info_t *jl_method_cache_insert(jl_methtable_t *mt, jl_tupletype_t *typ
}
}
ml_do_insert:
- return jl_method_list_insert(pml, type, method, jl_emptysvec, 0, 0, cache_array ? cache_array : (jl_value_t*)mt)->func;
+ jl_method_list_insert(pml, type, method, cache_array ? cache_array : (jl_value_t*)mt);
}
/*
@@ -409,7 +325,7 @@ jl_lambda_info_t *jl_method_cache_insert(jl_methtable_t *mt, jl_tupletype_t *typ
can be equal to "li" if not applicable.
*/
int jl_in_inference = 0;
-void jl_type_infer(jl_lambda_info_t *li, jl_lambda_info_t *def)
+void jl_type_infer(jl_lambda_info_t *li)
{
JL_LOCK(codegen); // Might GC
int last_ii = jl_in_inference;
@@ -418,29 +334,28 @@ void jl_type_infer(jl_lambda_info_t *li, jl_lambda_info_t *def)
// TODO: this should be done right before code gen, so if it is
// interrupted we can try again the next time the function is
// called
- assert(li->inInference == 0);
- li->inInference = 1;
+ jl_ast_info_t *astinfo = (jl_ast_info_t*)li->func;
+ assert(jl_is_ast_info(astinfo));
+ assert(li->inCompile == 0);
+ li->inCompile = 1;
jl_value_t *fargs[4];
fargs[0] = (jl_value_t*)jl_typeinf_func;
fargs[1] = (jl_value_t*)li;
- fargs[2] = (jl_value_t*)li->specTypes;
- fargs[3] = (jl_value_t*)def;
+ fargs[2] = (jl_value_t*)li->sig;
+ fargs[3] = (jl_value_t*)astinfo->def;
#ifdef TRACE_INFERENCE
jl_printf(JL_STDERR,"inference on ");
- jl_static_show_func_sig(JL_STDERR, (jl_value_t*)argtypes);
+ jl_static_show_func_sig(JL_STDERR, (jl_value_t*)li->sig);
jl_printf(JL_STDERR, "\n");
#endif
#ifdef ENABLE_INFERENCE
jl_value_t *newast = jl_apply(fargs, 4);
- jl_value_t *defast = def->ast;
- li->ast = jl_fieldref(newast, 0);
- jl_gc_wb(li, li->ast);
+ li->func = jl_fieldref(newast, 0);
+ jl_gc_wb(li, li->func);
li->rettype = jl_fieldref(newast, 1);
jl_gc_wb(li, li->rettype);
- // if type inference bails out it returns def->ast
- li->inferred = li->ast != defast;
#endif
- li->inInference = 0;
+ li->inCompile = 0;
}
jl_in_inference = last_ii;
JL_UNLOCK(codegen);
@@ -474,11 +389,11 @@ static int is_kind(jl_value_t *v)
v==(jl_value_t*)jl_typector_type);
}
-static jl_value_t *ml_matches(jl_methlist_t *ml, jl_value_t *type,
- jl_sym_t *name, int lim);
+static jl_value_t *method_matches(jl_method_t *ml, jl_value_t *type,
+ jl_sym_t *name, int lim);
static jl_lambda_info_t *cache_method(jl_methtable_t *mt, jl_tupletype_t *type,
- jl_lambda_info_t *method, jl_tupletype_t *decl,
+ jl_method_t *method, jl_tupletype_t *decl,
jl_svec_t *sparams, int8_t isstaged)
{
JL_LOCK(codegen); // Might GC
@@ -500,11 +415,11 @@ static jl_lambda_info_t *cache_method(jl_methtable_t *mt, jl_tupletype_t *type,
jl_value_t *decl_i = jl_nth_slot_type(decl,i);
if (!isstaged && jl_is_type_type(elt) && jl_is_tuple_type(jl_tparam0(elt)) &&
!(jl_subtype(decl_i, (jl_value_t*)jl_type_type, 0) && !is_kind(decl_i))) {
- jl_methlist_t *curr = mt->defs;
+ jl_method_t *curr = mt->defs;
int ok=1;
- while (curr != (void*)jl_nothing) {
+ while (curr != (jl_method_t*)jl_nothing) {
jl_value_t *slottype = jl_nth_slot_type(curr->sig, i);
- if (slottype && curr->func!=method) {
+ if (slottype && curr != method) {
if (jl_is_type_type(slottype) &&
jl_type_intersection(slottype, decl_i) != jl_bottom_type) {
ok=0;
@@ -520,7 +435,7 @@ static jl_lambda_info_t *cache_method(jl_methtable_t *mt, jl_tupletype_t *type,
}
int set_to_any = 0;
- int notcalled_func = (i>0 && i<=8 && !(method->called&(1<<(i-1))) &&
+ int notcalled_func = (i>0 && i<=8 && !(method->ast->called&(1<<(i-1))) &&
jl_subtype(elt,(jl_value_t*)jl_function_type,0));
if (decl_i == jl_ANY_flag ||
(notcalled_func && (decl_i == (jl_value_t*)jl_any_type ||
@@ -534,12 +449,12 @@ static jl_lambda_info_t *cache_method(jl_methtable_t *mt, jl_tupletype_t *type,
temp2 = (jl_value_t*)jl_svec_copy(newparams);
temp2 = (jl_value_t*)jl_apply_tuple_type((jl_svec_t*)temp2);
int nintr=0;
- jl_methlist_t *curr = mt->defs;
+ jl_method_t *curr = mt->defs;
int specific_decl =
decl_i != (jl_value_t*)jl_any_type && decl_i != (jl_value_t*)jl_ANY_flag;
// if this method is the only match even with the current slot
// set to Any, then it is safe to cache it that way.
- while (curr != (void*)jl_nothing && (curr->func != method || specific_decl)) {
+ while (curr != (jl_method_t*)jl_nothing && (curr != method || specific_decl)) {
if (jl_type_intersection((jl_value_t*)curr->sig, (jl_value_t*)temp2) !=
(jl_value_t*)jl_bottom_type) {
nintr++;
@@ -637,11 +552,11 @@ static jl_lambda_info_t *cache_method(jl_methtable_t *mt, jl_tupletype_t *type,
type.
*/
int ok=1, kindslot=0;
- jl_methlist_t *curr = mt->defs;
+ jl_method_t *curr = mt->defs;
jl_value_t *kind = (jl_value_t*)jl_typeof(jl_tparam0(elt));
- while (curr != (void*)jl_nothing) {
+ while (curr != (jl_method_t*)jl_nothing) {
jl_value_t *slottype = jl_nth_slot_type(curr->sig, i);
- if (slottype && curr->func!=method) {
+ if (slottype && curr != method) {
if (slottype == kind) {
ok=0;
break;
@@ -657,9 +572,9 @@ static jl_lambda_info_t *cache_method(jl_methtable_t *mt, jl_tupletype_t *type,
}
else {
curr = mt->defs;
- while (curr != (void*)jl_nothing) {
+ while (curr != (jl_method_t*)jl_nothing) {
jl_value_t *slottype = jl_nth_slot_type(curr->sig, i);
- if (slottype && curr->func!=method) {
+ if (slottype && curr != method) {
if (!very_general_type(slottype) &&
jl_type_intersection(slottype, (jl_value_t*)jl_type_type) !=
(jl_value_t*)jl_bottom_type) {
@@ -680,11 +595,11 @@ static jl_lambda_info_t *cache_method(jl_methtable_t *mt, jl_tupletype_t *type,
// if a slot is specialized for a particular kind, it can be
// considered a reflective method and so only needs to be
// specialized for type representation, not type extent.
- jl_methlist_t *curr = mt->defs;
+ jl_method_t *curr = mt->defs;
int ok=1;
- while (curr != (void*)jl_nothing) {
+ while (curr != (jl_method_t*)jl_nothing) {
jl_value_t *slottype = jl_nth_slot_type(curr->sig, i);
- if (slottype && curr->func!=method) {
+ if (slottype && curr != method) {
if (jl_is_type_type(slottype) &&
jl_type_intersection(slottype, decl_i) != jl_bottom_type) {
ok=0;
@@ -758,13 +673,13 @@ static jl_lambda_info_t *cache_method(jl_methtable_t *mt, jl_tupletype_t *type,
}
if (need_guard_entries) {
- temp = ml_matches(mt->defs, (jl_value_t*)type, lambda_sym, -1);
+ temp = method_matches(mt->defs, (jl_value_t*)type, lambda_sym, -1);
int unmatched_tvars = 0;
for(i=0; i < jl_array_len(temp); i++) {
jl_value_t *m = jl_cellref(temp, i);
- jl_value_t *env = jl_svecref(m,1);
+ jl_value_t *env = jl_svecref(m, 1);
for(int k=1; k < jl_svec_len(env); k+=2) {
- if (jl_is_typevar(jl_svecref(env,k))) {
+ if (jl_is_typevar(jl_svecref(env, k))) {
unmatched_tvars = 1; break;
}
}
@@ -778,7 +693,7 @@ static jl_lambda_info_t *cache_method(jl_methtable_t *mt, jl_tupletype_t *type,
if (!unmatched_tvars) {
for(i=0; i < jl_array_len(temp); i++) {
jl_value_t *m = jl_cellref(temp, i);
- if (((jl_methlist_t*)jl_svecref(m,2))->func != method) {
+ if ((jl_method_t*)jl_svecref(m, 2) != method) {
jl_method_cache_insert(mt, (jl_tupletype_t*)jl_svecref(m, 0), NULL);
}
}
@@ -796,34 +711,37 @@ static jl_lambda_info_t *cache_method(jl_methtable_t *mt, jl_tupletype_t *type,
int k;
for(k=0; k < lilist->nrows; k++) {
li = (jl_lambda_info_t*)jl_cellref(lilist, k);
- if (jl_types_equal((jl_value_t*)li->specTypes, (jl_value_t*)type))
+ if (jl_types_equal((jl_value_t*)li->sig, (jl_value_t*)type))
break;
}
if (k == lilist->nrows) lilist=NULL;
}
- if (lilist != NULL && !li->inInference) {
+ if (lilist != NULL) {
assert(li);
- newmeth = li;
+ temp = (jl_value_t*)li;
if (cache_as_orig)
- (void)jl_method_cache_insert(mt, origtype, newmeth);
+ newmeth = jl_new_lambda_info((jl_value_t*)li, li->sparam_vals, origtype);
else
- (void)jl_method_cache_insert(mt, type, newmeth);
+ newmeth = li;
+ jl_method_cache_insert(mt, newmeth->sig, newmeth);
JL_GC_POP();
JL_UNLOCK(codegen);
- return newmeth;
+ return li;
}
- jl_svec_t *sparam_vals = jl_svec_len(sparams) == 0 ? jl_emptysvec : jl_alloc_svec_uninit(jl_svec_len(sparams)/2);
- for (int i = 0; i < jl_svec_len(sparam_vals); i++) {
- jl_svecset(sparam_vals, i, jl_svecref(sparams, i * 2 + 1));
+ newparams = jl_svec_len(sparams) == 0 ? jl_emptysvec : jl_alloc_svec_uninit(jl_svec_len(sparams)/2);
+ for (int i = 0; i < jl_svec_len(newparams); i++) {
+ jl_svecset(newparams, i, jl_svecref(sparams, i * 2 + 1));
}
- newmeth = jl_add_static_parameters(method, sparam_vals, type);
+ newmeth = jl_new_lambda_info((jl_value_t*)method->ast, newparams, type);
if (cache_as_orig)
- (void)jl_method_cache_insert(mt, origtype, newmeth);
+ li = jl_new_lambda_info((jl_value_t*)newmeth, newmeth->sparam_vals, origtype);
else
- (void)jl_method_cache_insert(mt, type, newmeth);
+ li = newmeth;
+ temp = (jl_value_t*)li;
+ jl_method_cache_insert(mt, li->sig, li);
- if (newmeth->ast != NULL) {
+ if (newmeth->func != NULL) {
jl_array_t *spe = method->specializations;
if (spe == NULL) {
spe = jl_alloc_cell_1d(1);
@@ -835,8 +753,8 @@ static jl_lambda_info_t *cache_method(jl_methtable_t *mt, jl_tupletype_t *type,
method->specializations = spe;
jl_gc_wb(method, method->specializations);
if (jl_options.compile_enabled != JL_OPTIONS_COMPILE_OFF) // don't bother with typeinf if compile is off
- if (jl_symbol_name(newmeth->name)[0] != '@') // don't bother with typeinf on macros
- jl_type_infer(newmeth, method);
+ if (jl_symbol_name(method->name)[0] != '@') // don't bother with typeinf on macros
+ jl_type_infer(newmeth);
}
JL_GC_POP();
JL_UNLOCK(codegen);
@@ -899,40 +817,23 @@ static jl_value_t *lookup_match(jl_value_t *a, jl_value_t *b, jl_svec_t **penv,
}
// invoke (compiling if necessary) the jlcall function pointer for an unspecialized method
-static jl_value_t *jl_call_unspecialized(jl_svec_t *sparam_vals, jl_lambda_info_t *meth,
- jl_value_t **args, uint32_t nargs)
-{
- if (__unlikely(meth->fptr == NULL)) {
- jl_compile_linfo(meth, NULL);
- jl_generate_fptr(meth);
- }
- assert(jl_svec_len(meth->sparam_syms) == jl_svec_len(sparam_vals));
- if (__likely(meth->jlcall_api == 0))
- return meth->fptr(args[0], &args[1], nargs-1);
- else
- return ((jl_fptr_sparam_t)meth->fptr)(sparam_vals, args[0], &args[1], nargs-1);
-}
-
-JL_DLLEXPORT jl_lambda_info_t *jl_instantiate_staged(jl_lambda_info_t *generator, jl_tupletype_t *tt, jl_svec_t *env)
+JL_DLLEXPORT jl_method_t *jl_instantiate_staged(jl_method_t *generator, jl_tupletype_t *tt, jl_svec_t *env)
{
jl_expr_t *ex = NULL;
jl_value_t *linenum = NULL;
jl_svec_t *sparam_vals = NULL;
- JL_GC_PUSH3(&ex, &linenum, &sparam_vals);
+ jl_lambda_info_t *li = NULL;
+ JL_GC_PUSH4(&ex, &linenum, &sparam_vals, &li);
sparam_vals = jl_svec_len(env) == 0 ? jl_emptysvec : jl_alloc_svec_uninit(jl_svec_len(env)/2);
for (int i = 0; i < jl_svec_len(sparam_vals); i++) {
jl_svecset(sparam_vals, i, jl_svecref(env, i * 2 + 1));
}
- assert(generator->sparam_vals == jl_emptysvec);
assert(jl_svec_len(generator->sparam_syms) == jl_svec_len(sparam_vals));
- assert(generator->unspecialized == NULL && generator->specTypes == jl_anytuple_type);
- //if (!generated->inferred)
- // jl_type_infer(generator, generator); // this doesn't help all that much
ex = jl_exprn(lambda_sym, 2);
- jl_expr_t *generatorast = (jl_expr_t*)generator->ast;
+ jl_expr_t *generatorast = (jl_expr_t*)generator->ast->ast;
if (!jl_is_expr(generatorast))
generatorast = (jl_expr_t*)jl_uncompress_ast(generator, (jl_value_t*)generatorast);
jl_array_t *argnames = jl_lam_args(generatorast);
@@ -952,7 +853,8 @@ JL_DLLEXPORT jl_lambda_info_t *jl_instantiate_staged(jl_lambda_info_t *generator
assert(jl_nparams(tt) == jl_array_len(argnames) ||
(jl_is_rest_arg(jl_cellref(argnames, jl_array_len(argnames)-1)) &&
(jl_nparams(tt) >= jl_array_len(argnames) - 1)));
- jl_cellset(body->args, 1, jl_call_unspecialized(sparam_vals, generator, jl_svec_data(tt->parameters), jl_nparams(tt)));
+ li = jl_new_lambda_info((jl_value_t*)generator->unspecialized, sparam_vals, jl_anytuple_type);
+ jl_cellset(body->args, 1, jl_call_method_internal(li, jl_svec_data(tt->parameters), jl_nparams(tt)));
if (generator->sparam_syms != jl_emptysvec) {
// mark this function as having the same static parameters as the generator
@@ -965,25 +867,34 @@ JL_DLLEXPORT jl_lambda_info_t *jl_instantiate_staged(jl_lambda_info_t *generator
ex = newast;
}
// need to eval macros in the right module, but not give a warning for the `eval` call unless that results in a call to `eval`
- jl_lambda_info_t *func = (jl_lambda_info_t*)jl_toplevel_eval_in_warn(generator->module, (jl_value_t*)ex, 1);
+ jl_method_t *func = (jl_method_t*)jl_toplevel_eval_in_warn(generator->module, (jl_value_t*)ex, 1);
+
func->name = generator->name;
+ func->sig = tt;
+ jl_gc_wb(func, tt);
+ func->tvars = generator->tvars;
+ jl_gc_wb(func, generator->tvars);
+ func->va = jl_is_va_tuple(tt);
+ func->isstaged = 0;
+ func->invokes = (struct _jl_methtable_t *)jl_nothing;
+
JL_GC_POP();
return func;
}
static jl_lambda_info_t *jl_mt_assoc_by_type(jl_methtable_t *mt, jl_datatype_t *tt, int cache, int inexact)
{
- jl_methlist_t *m = mt->defs;
+ jl_method_t *m = mt->defs;
size_t nargs = jl_nparams(tt);
size_t i;
jl_value_t *ti=(jl_value_t*)jl_bottom_type;
jl_tupletype_t *newsig=NULL;
jl_svec_t *env = jl_emptysvec;
- jl_lambda_info_t *func = NULL;
- JL_GC_PUSH3(&env, &newsig, &func);
+ jl_svec_t *sparam_vals = NULL;
+ JL_GC_PUSH4(&env, &newsig, &m, &sparam_vals);
- while (m != (void*)jl_nothing) {
- if (m->tvars!=jl_emptysvec) {
+ while (m != (jl_method_t*)jl_nothing) {
+ if (m->tvars != jl_emptysvec) {
ti = lookup_match((jl_value_t*)tt, (jl_value_t*)m->sig, &env, m->tvars);
if (ti != (jl_value_t*)jl_bottom_type) {
// parametric methods only match if all typevars are matched by
@@ -1013,18 +924,23 @@ static jl_lambda_info_t *jl_mt_assoc_by_type(jl_methtable_t *mt, jl_datatype_t *
}
if (ti == (jl_value_t*)jl_bottom_type) {
- if (m != (void*)jl_nothing) {
- func = m->func;
- if (m->isstaged)
- func = jl_instantiate_staged(func, tt, env);
+ if (m != (jl_method_t*)jl_nothing) {
+ int isstaged = m->isstaged;
+ if (isstaged)
+ m = jl_instantiate_staged(m, tt, env);
if (!cache) {
+ sparam_vals = jl_svec_len(env) == 0 ? jl_emptysvec : jl_alloc_svec_uninit(jl_svec_len(env)/2);
+ for (int i = 0; i < jl_svec_len(sparam_vals); i++) {
+ jl_svecset(sparam_vals, i, jl_svecref(env, i * 2 + 1));
+ }
+ jl_lambda_info_t *nf = jl_new_lambda_info((jl_value_t*)m->ast, sparam_vals, tt);
JL_GC_POP();
- return func;
+ return nf;
}
// make sure the argument is rooted in `cache_method`
// in case another thread changed it.
newsig = m->sig;
- jl_lambda_info_t *res = cache_method(mt, tt, func, m->sig, jl_emptysvec, m->isstaged);
+ jl_lambda_info_t *res = cache_method(mt, tt, m, m->sig, jl_emptysvec, isstaged);
JL_GC_POP();
return res;
}
@@ -1033,7 +949,6 @@ static jl_lambda_info_t *jl_mt_assoc_by_type(jl_methtable_t *mt, jl_datatype_t *
}
assert(jl_is_svec(env));
- func = m->func;
if (inexact && !jl_types_equal(ti, (jl_value_t*)tt)) {
// the compiler might attempt jl_get_specialization on e.g.
@@ -1044,8 +959,9 @@ static jl_lambda_info_t *jl_mt_assoc_by_type(jl_methtable_t *mt, jl_datatype_t *
return NULL;
}
- if (m->isstaged)
- func = jl_instantiate_staged(func, tt, env);
+ int isstaged = m->isstaged;
+ if (isstaged)
+ m = jl_instantiate_staged(m, tt, env);
// don't bother computing this if no arguments are tuples
for(i=0; i < jl_nparams(tt); i++) {
@@ -1062,10 +978,16 @@ static jl_lambda_info_t *jl_mt_assoc_by_type(jl_methtable_t *mt, jl_datatype_t *
}
assert(jl_is_tuple_type(newsig));
jl_lambda_info_t *nf;
- if (!cache)
- nf = func;
- else
- nf = cache_method(mt, tt, func, newsig, env, m->isstaged);
+ if (!cache) {
+ sparam_vals = jl_svec_len(env) == 0 ? jl_emptysvec : jl_alloc_svec_uninit(jl_svec_len(env)/2);
+ for (int i = 0; i < jl_svec_len(sparam_vals); i++) {
+ jl_svecset(sparam_vals, i, jl_svecref(env, i * 2 + 1));
+ }
+ nf = jl_new_lambda_info((jl_value_t*)m->ast, sparam_vals, newsig);
+ }
+ else {
+ nf = cache_method(mt, tt, m, newsig, env, isstaged);
+ }
JL_GC_POP();
return nf;
}
@@ -1115,7 +1037,7 @@ JL_DLLEXPORT int jl_args_morespecific(jl_value_t *a, jl_value_t *b)
return msp;
}
-void print_func_loc(JL_STREAM *s, jl_lambda_info_t *li);
+void print_func_loc(JL_STREAM *s, jl_method_t *li);
/*
warn about ambiguous method priorities
@@ -1135,9 +1057,9 @@ void print_func_loc(JL_STREAM *s, jl_lambda_info_t *li);
To check this, jl_types_equal_generic needs to be more sophisticated
so (T,T) is not equivalent to (Any,Any). (TODO)
*/
-static void check_ambiguous(jl_methlist_t *ml, jl_tupletype_t *type,
- jl_methlist_t *oldmeth, jl_sym_t *fname,
- jl_lambda_info_t *linfo)
+static void check_ambiguous(jl_method_t *ml, jl_tupletype_t *type,
+ jl_method_t *oldmeth, jl_sym_t *fname,
+ jl_method_t *linfo)
{
jl_tupletype_t *sig = oldmeth->sig;
size_t tl = jl_nparams(type);
@@ -1160,9 +1082,9 @@ static void check_ambiguous(jl_methlist_t *ml, jl_tupletype_t *type,
JL_GC_POP();
return;
}
- jl_methlist_t *l = ml;
+ jl_method_t *l = ml;
JL_STREAM *s;
- while (l != (void*)jl_nothing) {
+ while (l != (jl_method_t*)jl_nothing) {
if (sigs_eq(isect, (jl_value_t*)l->sig, 0))
goto done_chk_amb; // ok, intersection is covered
l = l->next;
@@ -1173,7 +1095,7 @@ static void check_ambiguous(jl_methlist_t *ml, jl_tupletype_t *type,
print_func_loc(s, linfo);
jl_printf(s, "\nis ambiguous with: \n ");
jl_static_show_func_sig(s, (jl_value_t*)sig);
- print_func_loc(s, oldmeth->func);
+ print_func_loc(s, oldmeth);
jl_printf(s, ".\nTo fix, define \n ");
jl_static_show_func_sig(s, isect);
jl_printf(s, "\nbefore the new definition.\n");
@@ -1194,124 +1116,162 @@ static int has_unions(jl_tupletype_t *type)
return 0;
}
-static
-jl_methlist_t *jl_method_list_insert(jl_methlist_t **pml, jl_tupletype_t *type,
- jl_lambda_info_t *method, jl_svec_t *tvars,
- int check_amb, int8_t isstaged, jl_value_t *parent)
+// if this contains Union types, methods after it might actually be
+// more specific than it. we need to re-sort them.
+// this method sorts newitem into the pml singly-linked list owned by gc-root parent
+// using the accessors ml_pnext (returns &ml->next) and ml_sig (returns ml->sig)
+static void union_sorter(jl_value_t **pml, jl_value_t *newitem, jl_value_t *parent,
+ jl_value_t**(*ml_pnext)(jl_value_t*), jl_value_t*(*ml_sig)(jl_value_t*))
{
- jl_methlist_t *l, **pl;
+ jl_value_t *next_parent = NULL;
+ jl_value_t *item_parent = newitem;
+ jl_value_t **pitem = ml_pnext(newitem);
+ jl_value_t *item = *pitem;
+ while (item != (jl_value_t*)jl_nothing) {
+ jl_value_t **pl = pml, *l = *pml, *pa = parent;
+ jl_value_t **pnext = ml_pnext(item);
+ jl_value_t *next = *pnext;
+ next_parent = item;
+ while (l != *ml_pnext(newitem)) {
+ if (jl_args_morespecific(ml_sig(item),
+ ml_sig(l))) {
+ // reinsert item earlier in the list
+ *pitem = next;
+ jl_gc_wb(item_parent, next);
+ *ml_pnext(item) = l;
+ jl_gc_wb(item, l);
+ *pl = item;
+ jl_gc_wb(pa, item);
+ pnext = pitem;
+ next_parent = item_parent;
+ break;
+ }
+ pa = l;
+ pl = ml_pnext(l);
+ l = *pl;
+ }
+ item = next;
+ pitem = pnext;
+ item_parent = next_parent;
+ }
+}
+static jl_value_t **mi_pnext(jl_value_t* m) { return (jl_value_t**)&((jl_method_t*)m)->next; }
+static jl_value_t *mi_sig(jl_value_t* m) { return (jl_value_t*)((jl_method_t*)m)->sig; }
+static jl_value_t **ml_pnext(jl_value_t* m) { return (jl_value_t**)&((jl_lambda_info_t*)m)->next; }
+static jl_value_t *ml_sig(jl_value_t* m) { return (jl_value_t*)((jl_lambda_info_t*)m)->sig; }
+
+static void jl_method_add(jl_method_t **pml,
+ jl_method_t *method,
+ jl_value_t *parent)
+{
+ jl_method_t *l, **pl;
+ jl_value_t *pa;
+ jl_tupletype_t *type = method->sig;
assert(jl_is_tuple_type(type));
- l = *pml;
- while (l != (void*)jl_nothing) {
- if (((l->tvars==jl_emptysvec) == (tvars==jl_emptysvec)) &&
+ pl = pml; l = *pml; pa = parent;
+ while (l != (jl_method_t*)jl_nothing) {
+ if (((l->tvars==jl_emptysvec) == (method->tvars==jl_emptysvec)) &&
sigs_eq((jl_value_t*)type, (jl_value_t*)l->sig, 1)) {
- if (method == NULL) // don't overwrite with guard entries
- return l;
// method overwritten
- if (check_amb && l->func && method) {
- jl_module_t *newmod = method->module;
- jl_module_t *oldmod = l->func->module;
- JL_STREAM *s = JL_STDERR;
- jl_printf(s, "WARNING: Method definition ");
- jl_static_show_func_sig(s, (jl_value_t*)type);
- jl_printf(s, " in module %s", jl_symbol_name(oldmod->name));
- print_func_loc(s, l->func);
- jl_printf(s, " overwritten");
- if (oldmod != newmod)
- jl_printf(s, " in module %s", jl_symbol_name(newmod->name));
- print_func_loc(s, method);
- jl_printf(s, ".\n");
- }
- JL_SIGATOMIC_BEGIN();
- l->sig = type;
- jl_gc_wb(l, l->sig);
- l->tvars = tvars;
- jl_gc_wb(l, l->tvars);
- l->va = jl_is_va_tuple(type);
- l->isstaged = isstaged;
- l->invokes = (struct _jl_methtable_t *)jl_nothing;
- // TODO: `l->func` or `l->func->roots` might need to be rooted
- l->func = method;
- if (l->func)
- jl_gc_wb(l, l->func);
- JL_SIGATOMIC_END();
- return l;
+ jl_module_t *newmod = method->module;
+ jl_module_t *oldmod = l->module;
+ JL_STREAM *s = JL_STDERR;
+ jl_printf(s, "WARNING: Method definition ");
+ jl_static_show_func_sig(s, (jl_value_t*)type);
+ jl_printf(s, " in module %s", jl_symbol_name(oldmod->name));
+ print_func_loc(s, l);
+ jl_printf(s, " overwritten");
+ if (oldmod != newmod)
+ jl_printf(s, " in module %s", jl_symbol_name(newmod->name));
+ print_func_loc(s, method);
+ jl_printf(s, ".\n");
+ method->next = l->next;
+ jl_gc_wb(method, method->next);
+ *pl = method;
+ jl_gc_wb(pa, method);
+ return;
}
+ pl = &l->next;
+ pa = (jl_value_t*)l;
l = l->next;
}
- pl = pml;
- l = *pml;
- jl_value_t *pa = parent;
- while (l != (void*)jl_nothing) {
+
+ pl = pml; l = *pml; pa = parent;
+ while (l != (jl_method_t*)jl_nothing) {
if (jl_args_morespecific((jl_value_t*)type, (jl_value_t*)l->sig))
break;
- if (check_amb) {
- check_ambiguous(*pml, type, l, method->name, method);
- }
+ check_ambiguous(*pml, type, l, method->name, method);
pl = &l->next;
pa = (jl_value_t*)l;
l = l->next;
}
- jl_methlist_t *newrec = (jl_methlist_t*)jl_gc_allocobj(sizeof(jl_methlist_t));
- jl_set_typeof(newrec, jl_method_type);
- newrec->sig = type;
- newrec->tvars = tvars;
- newrec->va = jl_is_va_tuple(type);
- newrec->isstaged = isstaged;
- newrec->func = method;
- newrec->invokes = (struct _jl_methtable_t*)jl_nothing;
- newrec->next = l;
+
JL_SIGATOMIC_BEGIN();
- JL_GC_PUSH1(&newrec);
- *pl = newrec;
- jl_gc_wb(pa, newrec);
- // if this contains Union types, methods after it might actually be
- // more specific than it. we need to re-sort them.
- if (has_unions(type)) {
- jl_value_t *item_parent = (jl_value_t*)newrec;
- jl_value_t *next_parent = 0;
- jl_methlist_t *item = newrec->next, *next;
- jl_methlist_t **pitem = &newrec->next, **pnext;
- while (item != (void*)jl_nothing) {
- pl = pml;
- l = *pml;
- pa = parent;
- next = item->next;
- pnext = &item->next;
- next_parent = (jl_value_t*)item;
- while (l != newrec->next) {
- if (jl_args_morespecific((jl_value_t*)item->sig,
- (jl_value_t*)l->sig)) {
- // reinsert item earlier in the list
- *pitem = next;
- jl_gc_wb(item_parent, next);
- item->next = l;
- jl_gc_wb(item, item->next);
- *pl = item;
- jl_gc_wb(pa, item);
- pnext = pitem;
- next_parent = item_parent;
- break;
- }
- pl = &l->next;
- pa = (jl_value_t*)l;
- l = l->next;
- }
- item = next;
- pitem = pnext;
- item_parent = next_parent;
+ method->next = l;
+ *pl = method;
+ jl_gc_wb(pa, method);
+ if (has_unions(type))
+ union_sorter((jl_value_t**)pml, (jl_value_t*)method, parent, mi_pnext, mi_sig);
+ JL_SIGATOMIC_END();
+}
+
+static void jl_method_list_insert(jl_lambda_info_t **pml, jl_tupletype_t *type,
+ jl_lambda_info_t *method, jl_value_t *parent)
+{
+ jl_lambda_info_t *l, **pl;
+ jl_value_t *pa;
+
+ assert(jl_is_tuple_type(type));
+ pl = pml; l = *pml; pa = parent;
+ while (l != (jl_lambda_info_t*)jl_nothing) {
+ if (sigs_eq((jl_value_t*)type, (jl_value_t*)l->sig, 1)) {
+ // cache entry overwritten
+ if (method == NULL) // don't overwrite with guard entries
+ return;
+ method->next = l->next;
+ jl_gc_wb(method, method->next);
+ *pl = method;
+ jl_gc_wb(pa, method);
+ return;
}
+ pl = &l->next;
+ pa = (jl_value_t*)l;
+ l = l->next;
+ }
+
+ pl = pml; l = *pml; pa = parent;
+ while (l != (jl_lambda_info_t*)jl_nothing) {
+ if (jl_args_morespecific((jl_value_t*)type, (jl_value_t*)l->sig))
+ break;
+ pl = &l->next;
+ pa = (jl_value_t*)l;
+ l = l->next;
+ }
+ if (method == NULL) // need to allocate the guard entry object now
+ method = jl_new_lambda_info(NULL, NULL, type);
+ method->next = l;
+ jl_gc_wb(method, l);
+
+ if (has_unions(type)) {
+ JL_SIGATOMIC_BEGIN();
+ *pl = method;
+ jl_gc_wb(pa, method);
+ JL_GC_PUSH1(&method);
+ union_sorter((jl_value_t**)pml, (jl_value_t*)method, parent, ml_pnext, ml_sig);
+ JL_GC_POP();
+ JL_SIGATOMIC_END();
+ }
+ else {
+ *pl = method;
+ jl_gc_wb(pa, method);
}
- JL_GC_POP();
- JL_SIGATOMIC_END();
- return newrec;
}
-static void remove_conflicting(jl_methlist_t **pl, jl_value_t *type)
+static void remove_conflicting(jl_lambda_info_t **pl, jl_value_t *type)
{
- jl_methlist_t *l = *pl;
- while (l != (void*)jl_nothing) {
+ jl_lambda_info_t *l = *pl;
+ while (l != (jl_lambda_info_t*)jl_nothing) {
if (jl_type_intersection(type, (jl_value_t*)l->sig) !=
(jl_value_t*)jl_bottom_type) {
*pl = l->next;
@@ -1332,34 +1292,28 @@ static void update_max_args(jl_methtable_t *mt, jl_tupletype_t *type)
mt->max_args = na;
}
-jl_methlist_t *jl_method_table_insert(jl_methtable_t *mt, jl_tupletype_t *type,
- jl_lambda_info_t *method, jl_svec_t *tvars,
- int8_t isstaged)
+void jl_method_table_insert(jl_methtable_t *mt,
+ jl_method_t *method)
{
- if (jl_svec_len(tvars) == 1)
- tvars = (jl_svec_t*)jl_svecref(tvars,0);
- if (isstaged) // staged function definitions will be compiled directly. mark them accordingly.
- method->specTypes = jl_anytuple_type;
- else // otherwise, the method will be compiled via unspecialized or the method cache, never directly
- assert(!method->specTypes);
JL_SIGATOMIC_BEGIN();
- jl_methlist_t *ml = jl_method_list_insert(&mt->defs,type,method,tvars,1,isstaged,(jl_value_t*)mt);
+ jl_method_add(&mt->defs, method, (jl_value_t*)mt);
// invalidate cached methods that overlap this definition
+ jl_tupletype_t *type = method->sig;
remove_conflicting(&mt->cache, (jl_value_t*)type);
jl_gc_wb(mt, mt->cache);
- if (mt->cache_arg1 != (void*)jl_nothing) {
+ if (mt->cache_arg1 != (jl_array_t*)jl_nothing) {
for(int i=0; i < jl_array_len(mt->cache_arg1); i++) {
- jl_methlist_t **pl = &((jl_methlist_t**)jl_array_data(mt->cache_arg1))[i];
- if (*pl && *pl != (void*)jl_nothing) {
+ jl_lambda_info_t **pl = &((jl_lambda_info_t**)jl_array_data(mt->cache_arg1))[i];
+ if (*pl && *pl != (jl_lambda_info_t*)jl_nothing) {
remove_conflicting(pl, (jl_value_t*)type);
jl_gc_wb(mt->cache_arg1, jl_cellref(mt->cache_arg1,i));
}
}
}
- if (mt->cache_targ != (void*)jl_nothing) {
+ if (mt->cache_targ != (jl_array_t*)jl_nothing) {
for(int i=0; i < jl_array_len(mt->cache_targ); i++) {
- jl_methlist_t **pl = &((jl_methlist_t**)jl_array_data(mt->cache_targ))[i];
- if (*pl && *pl != (void*)jl_nothing) {
+ jl_lambda_info_t **pl = &((jl_lambda_info_t**)jl_array_data(mt->cache_targ))[i];
+ if (*pl && *pl != (jl_lambda_info_t*)jl_nothing) {
remove_conflicting(pl, (jl_value_t*)type);
jl_gc_wb(mt->cache_targ, jl_cellref(mt->cache_targ,i));
}
@@ -1367,7 +1321,6 @@ jl_methlist_t *jl_method_table_insert(jl_methtable_t *mt, jl_tupletype_t *type,
}
update_max_args(mt, type);
JL_SIGATOMIC_END();
- return ml;
}
void JL_NORETURN jl_no_method_error_bare(jl_function_t *f, jl_value_t *args)
@@ -1435,7 +1388,7 @@ jl_lambda_info_t *jl_method_lookup_by_type(jl_methtable_t *mt, jl_tupletype_t *t
int cache, int inexact)
{
jl_lambda_info_t *sf = jl_method_table_assoc_exact_by_type(mt, types);
- if (sf == NULL) {
+ if (sf == NULL || sf->sparam_vals == NULL) {
if (jl_is_leaf_type((jl_value_t*)types)) cache=1;
sf = jl_mt_assoc_by_type(mt, types, cache, inexact);
}
@@ -1450,7 +1403,7 @@ JL_DLLEXPORT int jl_method_exists(jl_methtable_t *mt, jl_tupletype_t *types)
jl_lambda_info_t *jl_method_lookup(jl_methtable_t *mt, jl_value_t **args, size_t nargs, int cache)
{
jl_lambda_info_t *sf = jl_method_table_assoc_exact(mt, args, nargs);
- if (sf == NULL) {
+ if (sf == NULL || sf->sparam_vals == NULL) {
jl_tupletype_t *tt = arg_type_tuple(args, nargs);
JL_GC_PUSH1(&tt);
sf = jl_mt_assoc_by_type(mt, tt, cache, 0);
@@ -1494,12 +1447,12 @@ jl_lambda_info_t *jl_get_specialization1(jl_tupletype_t *types, void *cyclectx)
} JL_CATCH {
goto not_found;
}
- if (sf == NULL || sf->ast == NULL || sf->inInference)
+ if (sf == NULL)
goto not_found;
if (sf->functionObjects.functionObject == NULL) {
- if (sf->fptr != NULL)
+ if (sf->functionObjects.fptr != NULL)
goto not_found;
- jl_compile_linfo(sf, cyclectx);
+ sf = jl_compile_linfo(sf, cyclectx);
}
JL_GC_POP();
return sf;
@@ -1537,7 +1490,7 @@ static int tupletype_any_bottom(jl_value_t *sig)
return 0;
}
-static int _compile_all_tvar_union(jl_methlist_t *meth, jl_tupletype_t *methsig)
+static int _compile_all_tvar_union(jl_method_t *meth, jl_tupletype_t *methsig)
{
// f{<:Union{...}}(...) is a common pattern
// and expanding the Union may give a leaf function
@@ -1556,11 +1509,6 @@ static int _compile_all_tvar_union(jl_methlist_t *meth, jl_tupletype_t *methsig)
// if the signature is already a leaftype
jl_lambda_info_t *spec = jl_get_specialization1(methsig, NULL);
if (spec) {
- if (methsig == meth->sig) {
- // replace unspecialized func with newly specialized version
- meth->func->unspecialized = spec;
- jl_gc_wb(meth->func, spec);
- }
return 1;
}
}
@@ -1629,7 +1577,7 @@ static int _compile_all_tvar_union(jl_methlist_t *meth, jl_tupletype_t *methsig)
return complete;
}
-static int _compile_all_union(jl_methlist_t *meth)
+static int _compile_all_union(jl_method_t *meth)
{
// f(::Union{...}, ...) is a common pattern
// and expanding the Union may give a leaf function
@@ -1701,75 +1649,75 @@ static void _compile_all_deq(jl_array_t *found)
jl_printf(JL_STDERR, "found %d uncompiled methods for compile-all\n", (int)found_l);
for (found_i = 0; found_i < found_l; found_i++) {
jl_printf(JL_STDERR, " %zd / %zd\r", found_i + 1, found_l);
- jl_methlist_t *meth = (jl_methlist_t*)jl_cellref(found, found_i);
- jl_lambda_info_t *linfo = meth->func;
-
- if (!linfo)
- return; // XXX: how does this happen
- if (!linfo->specTypes)
- linfo = jl_get_unspecialized(linfo);
- if (!linfo->inferred) {
- // force this function to be recompiled
- jl_type_infer(linfo, linfo);
- linfo->functionObjects.functionObject = NULL;
- linfo->functionObjects.specFunctionObject = NULL;
- linfo->functionObjects.cFunctionList = NULL;
- linfo->functionID = 0;
- linfo->specFunctionID = 0;
- }
-
- // keep track of whether all possible signatures have been cached (and thus whether it can skip trying to compile the unspecialized function)
- // this is necessary because many intrinsics try to call static_eval and thus are not compilable unspecialized
- int complete = _compile_all_union(meth);
- if (complete) {
- if (!linfo->functionID)
- // indicate that this method doesn't need a functionID because it was fully covered above
- linfo->functionID = -1;
+ jl_value_t *meth = jl_cellref(found, found_i);
+
+ jl_lambda_info_t *linfo;
+ if (jl_is_method(meth)) {
+ // method definition -- compile via unspecialized field
+ jl_method_t *m = (jl_method_t*)meth;
+ int complete = _compile_all_union(m);
+ linfo = m->unspecialized;
+ if (complete) {
+ // keep track of whether all possible signatures have been cached (and thus whether it can skip trying to compile the unspecialized function)
+ // this is necessary because many intrinsics try to call static_eval and thus are not compilable unspecialized
+ if (!linfo->functionObjects.functionID)
+ // indicate that this method doesn't need a functionID because it was fully covered above
+ linfo->functionObjects.functionID = -1;
+ continue;
+ }
}
else {
- jl_compile_linfo(linfo, NULL);
- assert(linfo->functionID > 0);
+ linfo = (jl_lambda_info_t*)meth;
}
+
+ jl_type_infer(linfo);
+ jl_compile_linfo(linfo, NULL);
+ assert(linfo->functionObjects.functionID > 0);
}
jl_printf(JL_STDERR, "\n");
}
+static void _compile_all_enq_linfo(jl_lambda_info_t *linfo, jl_array_t *found)
+{
+ while (linfo != NULL && (jl_value_t*)linfo != jl_nothing) {
+ if (linfo->func != NULL) {
+ if (jl_is_lambda_info(linfo->func))
+ _compile_all_enq_linfo((jl_lambda_info_t*)linfo->func, found);
+ else if (!linfo->functionObjects.functionID)
+ // found a lambda specialization (not a placeholder guard)
+ // and it still needs to be compiled
+ jl_cell_1d_push(found, (jl_value_t*)linfo);
+ }
+ linfo = linfo->next;
+ }
+}
+
static void _compile_all_enq_mt(jl_methtable_t *mt, jl_array_t *found);
-static void _compile_all_enq_ml(jl_methlist_t *ml, jl_array_t *found)
+static void _compile_all_enq_methods(jl_method_t *ml, jl_array_t *found)
{
while (ml != NULL && (jl_value_t*)ml != jl_nothing) {
- if (ml->func != NULL) {
- // found a method (not a placeholder guard)
- jl_lambda_info_t *linfo = ml->func;
- if (!linfo->specTypes) {
- // method definition -- compile via unspecialized field
- if (linfo->fptr != NULL)
- return; // builtin function
- linfo = jl_get_unspecialized(linfo);
- }
- if (!linfo->functionID || !linfo->inferred) {
- // and it still needs to be compiled
- if (!ml->isstaged)
- jl_cell_1d_push(found, (jl_value_t*)ml);
- }
+ if (!ml->isstaged) {
+ // method definitions -- compile unspecialized field
+ _compile_all_enq_linfo(ml->unspecialized, found);
}
_compile_all_enq_mt(ml->invokes, found);
ml = ml->next;
}
}
+
static void _compile_all_enq_mt(jl_methtable_t *mt, jl_array_t *found)
{
jl_array_t *a;
if (mt == NULL || (jl_value_t*)mt == jl_nothing) return;
- _compile_all_enq_ml(mt->defs, found);
- _compile_all_enq_ml(mt->cache, found);
+ _compile_all_enq_methods(mt->defs, found);
+ _compile_all_enq_linfo(mt->cache, found);
a = mt->cache_arg1;
if ((jl_value_t*)a != jl_nothing) {
size_t i, l = jl_array_len(a);
for (i = 0; i < l; i++) {
- _compile_all_enq_ml((jl_methlist_t*)jl_cellref(a, i), found);
+ _compile_all_enq_linfo((jl_lambda_info_t*)jl_cellref(a, i), found);
}
}
@@ -1777,7 +1725,7 @@ static void _compile_all_enq_mt(jl_methtable_t *mt, jl_array_t *found)
if ((jl_value_t*)a != jl_nothing) {
size_t i, l = jl_array_len(a);
for (i = 0; i < l; i++) {
- _compile_all_enq_ml((jl_methlist_t*)jl_cellref(a, i), found);
+ _compile_all_enq_linfo((jl_lambda_info_t*)jl_cellref(a, i), found);
}
}
}
@@ -1785,7 +1733,7 @@ static void _compile_all_enq_mt(jl_methtable_t *mt, jl_array_t *found)
static void _compile_all_enq_module(jl_module_t *m, jl_array_t *found)
{
// scan through all types reachable from 'v' and
- // record all jl_lambda_info_t objects and signatures in their method tables
+ // record all jl_method_t and jl_lambda_info_t objects in the system
size_t i, sz = m->bindings.size;
for(i=1; i < sz; i+=2) {
if (m->bindings.table[i] != HT_NOTFOUND) {
@@ -1794,7 +1742,7 @@ static void _compile_all_enq_module(jl_module_t *m, jl_array_t *found)
jl_value_t *v = b->value;
if (jl_is_datatype(v)) {
jl_typename_t *tn = ((jl_datatype_t*)v)->name;
- if (tn->module == m && tn->name == b->name) {
+ if (tn->module == m && tn->name == b->name && !jl_subtype(v, (jl_value_t*)jl_builtin_type, 0)) {
_compile_all_enq_mt(tn->mt, found);
}
}
@@ -1877,17 +1825,11 @@ JL_DLLEXPORT jl_value_t *jl_apply_generic(jl_value_t **args, uint32_t nargs)
*/
jl_lambda_info_t *mfunc = jl_method_table_assoc_exact(mt, args, nargs);
- if (mfunc != NULL) {
+ if (mfunc != NULL && mfunc->sparam_vals != NULL) {
#ifdef JL_TRACE
if (traceen)
jl_printf(JL_STDOUT, " at %s:%d\n", jl_symbol_name(mfunc->file), mfunc->line);
#endif
- if (mfunc->inInference || mfunc->inCompile) {
- // if inference is running on this function, return a copy
- // of the function to be compiled without inference and run.
- return verify_type(jl_call_unspecialized(mfunc->sparam_vals, jl_get_unspecialized(mfunc), args, nargs));
- }
- assert(!mfunc->inInference);
return verify_type(jl_call_method_internal(mfunc, args, nargs));
}
@@ -1911,20 +1853,19 @@ JL_DLLEXPORT jl_value_t *jl_apply_generic(jl_value_t **args, uint32_t nargs)
if (traceen)
jl_printf(JL_STDOUT, " at %s:%d\n", jl_symbol_name(mfunc->file), mfunc->line);
#endif
- assert(!mfunc->inInference);
jl_value_t *res = jl_call_method_internal(mfunc, args, nargs);
JL_GC_POP();
return verify_type(res);
}
-JL_DLLEXPORT jl_value_t *jl_gf_invoke_lookup(jl_datatype_t *types)
+JL_DLLEXPORT jl_method_t *jl_gf_invoke_lookup(jl_datatype_t *types)
{
jl_methtable_t *mt = ((jl_datatype_t*)jl_tparam0(types))->name->mt;
- jl_methlist_t *m = mt->defs;
+ jl_method_t *m = mt->defs;
size_t typelen = jl_nparams(types);
- while (m != (void*)jl_nothing) {
- if (m->tvars!=jl_emptysvec) {
+ while (m != (jl_method_t*)jl_nothing) {
+ if (m->tvars != jl_emptysvec) {
if (jl_type_match((jl_value_t*)types,
(jl_value_t*)m->sig) != (jl_value_t*)jl_false)
break;
@@ -1935,9 +1876,7 @@ JL_DLLEXPORT jl_value_t *jl_gf_invoke_lookup(jl_datatype_t *types)
m = m->next;
}
- if (m == (void*)jl_nothing)
- return jl_nothing;
- return (jl_value_t*)m;
+ return m;
}
// invoke()
@@ -1951,16 +1890,17 @@ 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)
{
- jl_svec_t *tpenv=jl_emptysvec;
- jl_tupletype_t *newsig=NULL;
- jl_tupletype_t *tt=NULL;
- jl_tupletype_t *types=NULL;
- JL_GC_PUSH4(&types, &tpenv, &newsig, &tt);
+ size_t i;
+ jl_svec_t *tpenv = jl_emptysvec;
+ jl_tupletype_t *newsig = NULL;
+ jl_tupletype_t *tt = NULL;
+ jl_tupletype_t *types = NULL;
+ jl_method_t *m = NULL;
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_methlist_t *m = (jl_methlist_t*)jl_gf_invoke_lookup(types);
- size_t i;
+ JL_GC_PUSH5(&types, &tpenv, &newsig, &tt, &m);
+ types = (jl_datatype_t*)jl_argtype_with_function(gf, (jl_tupletype_t*)types0);
+ m = jl_gf_invoke_lookup(types);
if ((jl_value_t*)m == jl_nothing) {
jl_no_method_error_bare(gf, (jl_value_t*)types0);
@@ -1975,22 +1915,18 @@ jl_value_t *jl_gf_invoke(jl_tupletype_t *types0, jl_value_t **args, size_t nargs
mfunc = NULL;
else
mfunc = jl_method_table_assoc_exact(m->invokes, args, nargs);
- if (mfunc != NULL) {
- if (mfunc->inInference || mfunc->inCompile) {
- // if inference is running on this function, return a copy
- // of the function to be compiled without inference and run.
- JL_GC_POP();
- return jl_call_unspecialized(mfunc->sparam_vals, jl_get_unspecialized(mfunc), args, nargs);
- }
- }
- else {
+ if (mfunc == NULL || mfunc->sparam_vals == NULL) {
tt = arg_type_tuple(args, nargs);
- if (m->invokes == (void*)jl_nothing) {
- m->invokes = jl_new_method_table(mt->name, mt->module);
- jl_gc_wb(m, m->invokes);
- update_max_args(m->invokes, tt);
+ jl_methtable_t *invokes = m->invokes;
+ if (invokes == (jl_methtable_t*)jl_nothing) {
+ invokes = jl_new_method_table(mt->name, mt->module);
+ m->invokes = invokes;
+ jl_gc_wb(m, invokes);
+ update_max_args(invokes, tt);
// this private method table has just this one definition
- jl_method_list_insert(&m->invokes->defs,m->sig,m->func,m->tvars,0,m->isstaged,(jl_value_t*)m->invokes);
+ // FIXME: jwn this is going to copy jl_method_t and break the link to unspecialized
+ // perhaps this should go directly into a method cache, instead of through a method table
+ m = jl_add_method_to_table(invokes, m->sig, m, m->tvars, m->isstaged);
}
newsig = m->sig;
@@ -2011,18 +1947,19 @@ jl_value_t *jl_gf_invoke(jl_tupletype_t *types0, jl_value_t **args, size_t nargs
jl_svec_len(tpenv)/2);
}
}
- jl_lambda_info_t *func = m->func;
- if (m->isstaged)
- func = jl_instantiate_staged(func, tt, tpenv);
- mfunc = cache_method(m->invokes, tt, func, newsig, tpenv, m->isstaged);
+ int isstaged = m->isstaged;
+ if (isstaged)
+ m = jl_instantiate_staged(m, tt, tpenv);
+
+ mfunc = cache_method(invokes, tt, m, newsig, tpenv, isstaged);
}
JL_GC_POP();
return jl_call_method_internal(mfunc, args, nargs);
}
-void print_func_loc(JL_STREAM *s, jl_lambda_info_t *li)
+void print_func_loc(JL_STREAM *s, jl_method_t *li)
{
long lno = li->line;
if (lno > 0) {
@@ -2075,29 +2012,41 @@ JL_DLLEXPORT jl_function_t *jl_new_generic_function(jl_sym_t *name, jl_module_t
return jl_new_generic_function_with_supertype(name, module, jl_function_type, 0);
}
-void jl_add_method_to_table(jl_methtable_t *mt, jl_tupletype_t *types, jl_lambda_info_t *meth,
- jl_svec_t *tvars, int8_t isstaged)
+jl_method_t *jl_add_method_to_table(jl_methtable_t *mt, jl_tupletype_t *types, jl_method_t *meth,
+ jl_svec_t *tvars, int8_t isstaged)
{
assert(jl_is_tuple_type(types));
- assert(jl_is_lambda_info(meth));
+ assert(jl_is_method(meth));
assert(jl_is_mtable(mt));
JL_GC_PUSH1(&meth);
jl_sym_t *n = mt->name;
- if (meth->name != anonymous_sym && meth->name != n) {
- // already used by another GF; make a copy (issue #10373)
- assert(meth->sparam_vals == jl_emptysvec);
- meth = jl_add_static_parameters(meth, jl_emptysvec, NULL);
- meth->unspecialized = NULL;
+ if (meth->sig) {
+ // already used by another GF; make a duplicate (issue #10373)
+ jl_method_t *newmeth =
+ (jl_method_t*)newobj((jl_value_t*)jl_method_type,
+ NWORDS(sizeof(jl_method_t)));
+ *newmeth = *meth;
+ newmeth->unspecialized = NULL;
+ meth = newmeth;
}
meth->name = n;
- (void)jl_method_table_insert(mt, types, meth, tvars, isstaged);
+ meth->sig = types;
+ jl_gc_wb(meth, types);
+ if (jl_svec_len(tvars) == 1)
+ tvars = (jl_svec_t*)jl_svecref(tvars, 0);
+ meth->tvars = tvars;
+ jl_gc_wb(meth, tvars);
+ meth->va = jl_is_va_tuple(types);
+ if (isstaged) {
+ meth->isstaged = 1;
+ meth->unspecialized = jl_new_lambda_info((jl_value_t*)meth->ast, jl_emptysvec, jl_anytuple_type);
+ jl_gc_wb(meth, meth->unspecialized);
+ }
+ meth->invokes = (struct _jl_methtable_t *)jl_nothing;
+
+ jl_method_table_insert(mt, meth);
JL_GC_POP();
-}
-
-void jl_add_method(jl_function_t *gf, jl_tupletype_t *types, jl_lambda_info_t *meth,
- jl_svec_t *tvars, int8_t isstaged)
-{
- jl_add_method_to_table(jl_gf_mtable(gf), types, meth, tvars, isstaged);
+ return meth;
}
JL_DLLEXPORT jl_svec_t *jl_match_method(jl_value_t *type, jl_value_t *sig,
@@ -2136,9 +2085,9 @@ static int tvar_exists_at_top_level(jl_value_t *tv, jl_tupletype_t *sig, int att
return 0;
}
-// returns a match as (argtypes, static_params, Method)
-static jl_value_t *ml_matches(jl_methlist_t *ml, jl_value_t *type,
- jl_sym_t *name, int lim)
+// returns a match as (argtypes, static_params, MethodInfo)
+static jl_value_t *method_matches(jl_method_t *ml, jl_value_t *type,
+ jl_sym_t *name, int lim)
{
jl_array_t *t = (jl_array_t*)jl_an_empty_cell;
jl_svec_t *matc=NULL;
@@ -2146,7 +2095,7 @@ static jl_value_t *ml_matches(jl_methlist_t *ml, jl_value_t *type,
jl_value_t *ti=NULL;
JL_GC_PUSH4(&t, &matc, &env, &ti);
int len=0, i;
- while (ml != (void*)jl_nothing) {
+ while (ml != (jl_method_t*)jl_nothing) {
// a method is shadowed if type <: S <: m->sig where S is the
// signature of another applicable method
/*
@@ -2156,7 +2105,6 @@ static jl_value_t *ml_matches(jl_methlist_t *ml, jl_value_t *type,
env = jl_emptysvec;
ti = lookup_match(type, (jl_value_t*)ml->sig, &env, ml->tvars);
if (ti != (jl_value_t*)jl_bottom_type) {
- assert(ml->func);
assert(jl_is_svec(env));
int skip = 0;
@@ -2238,10 +2186,9 @@ static jl_value_t *ml_matches(jl_methlist_t *ml, jl_value_t *type,
}
// return a cell array of svecs, each describing a method match:
-// {svec(t, spvals, li, cenv), ...}
+// {svec(t, spvals, ml), ...}
// t is the intersection of the type argument and the method signature,
-// spvals is any matched static parameter values, li is the LambdaInfo,
-// and cenv is the closure environment or ().
+// spvals is any matched static parameter values, ml is the MethodInfo,
//
// lim is the max # of methods to return. if there are more return jl_false.
// -1 for no limit.
@@ -2252,7 +2199,7 @@ JL_DLLEXPORT jl_value_t *jl_matching_methods(jl_value_t *types, int lim)
jl_methtable_t *mt = ((jl_datatype_t*)jl_tparam0(types))->name->mt;
if (mt == NULL)
return (jl_value_t*)jl_alloc_cell_1d(0);
- return ml_matches(mt->defs, types, mt->name, lim);
+ return method_matches(mt->defs, types, mt->name, lim);
}
#ifdef __cplusplus
diff --git a/src/interpreter.c b/src/interpreter.c
index af2dc188af829..b8e01bd87c108 100644
--- a/src/interpreter.c
+++ b/src/interpreter.c
@@ -267,7 +267,7 @@ static jl_value_t *eval(jl_value_t *e, jl_value_t **locals, size_t nl, size_t ng
JL_GC_PUSH2(&atypes, &meth);
atypes = eval(args[1], locals, nl, ngensym);
meth = eval(args[2], locals, nl, ngensym);
- jl_method_def((jl_svec_t*)atypes, (jl_lambda_info_t*)meth, args[3]);
+ jl_method_def((jl_svec_t*)atypes, (jl_method_t*)meth, args[3]);
JL_GC_POP();
return jl_nothing;
}
@@ -555,10 +555,10 @@ static jl_value_t *eval_body(jl_array_t *stmts, jl_value_t **locals, size_t nl,
return NULL;
}
-jl_value_t *jl_interpret_toplevel_thunk_with(jl_lambda_info_t *lam,
+jl_value_t *jl_interpret_toplevel_thunk_with(jl_method_t *lam,
jl_value_t **loc, size_t nl)
{
- jl_expr_t *ast = (jl_expr_t*)lam->ast;
+ jl_expr_t *ast = (jl_expr_t*)lam->ast->ast;
jl_array_t *stmts = jl_lam_body(ast)->args;
size_t nargs = jl_array_len(jl_lam_args(ast));
jl_array_t *l = jl_lam_vinfo(ast);
@@ -583,7 +583,7 @@ jl_value_t *jl_interpret_toplevel_thunk_with(jl_lambda_info_t *lam,
return r;
}
-jl_value_t *jl_interpret_toplevel_thunk(jl_lambda_info_t *lam)
+jl_value_t *jl_interpret_toplevel_thunk(jl_method_t *lam)
{
return jl_interpret_toplevel_thunk_with(lam, NULL, 0);
}
diff --git a/src/intrinsics.cpp b/src/intrinsics.cpp
index bf5adcda34b51..88c2c5c53a7d8 100644
--- a/src/intrinsics.cpp
+++ b/src/intrinsics.cpp
@@ -360,7 +360,7 @@ static jl_value_t *staticeval_bitstype(jl_value_t *targ, const char *fname, jl_c
else {
JL_TRY { // TODO: change this to an actual call to staticeval rather than actually executing code
bt = jl_interpret_toplevel_expr_in(ctx->module, targ,
- ctx->linfo->sparam_syms,
+ ctx->astinfo->def->sparam_syms,
ctx->linfo->sparam_vals);
}
JL_CATCH {
@@ -402,7 +402,7 @@ static jl_cgval_t generic_box(jl_value_t *targ, jl_value_t *x, jl_codectx_t *ctx
// Examine the first argument //
jl_value_t *bt = static_eval(targ, ctx, true, true);
if (bt && !jl_is_leaf_type(bt)) {
- jl_add_linfo_root(ctx->linfo, bt);
+ jl_add_linfo_root(ctx, bt);
}
if (!bt || !jl_is_bitstype(bt)) {
diff --git a/src/jltypes.c b/src/jltypes.c
index d591bb899e29b..29e3a524376bb 100644
--- a/src/jltypes.c
+++ b/src/jltypes.c
@@ -3381,16 +3381,6 @@ void jl_init_types(void)
jl_false = jl_box8(jl_bool_type, 0);
jl_true = jl_box8(jl_bool_type, 1);
- jl_method_type =
- jl_new_datatype(jl_symbol("Method"), jl_any_type, jl_emptysvec,
- jl_svec(7, jl_symbol("sig"), jl_symbol("va"), jl_symbol("isstaged"),
- jl_symbol("tvars"), jl_symbol("func"),
- jl_symbol("invokes"), jl_symbol("next")),
- jl_svec(7, jl_type_type, jl_bool_type, jl_bool_type,
- jl_any_type, jl_any_type,
- jl_any_type, jl_any_type),
- 0, 1, 4);
-
jl_function_type = jl_new_abstracttype((jl_value_t*)jl_symbol("Function"), jl_any_type, jl_emptysvec);
jl_builtin_type = jl_new_abstracttype((jl_value_t*)jl_symbol("Builtin"), jl_function_type, jl_emptysvec);
@@ -3479,29 +3469,82 @@ void jl_init_types(void)
jl_svecset(jl_methtable_type->types, 7, jl_module_type);
jl_lambda_info_type =
- jl_new_datatype(jl_symbol("LambdaInfo"),
- jl_any_type, jl_emptysvec,
- jl_svec(16, jl_symbol("ast"), jl_symbol("rettype"),
- jl_symbol("sparam_syms"), jl_symbol("sparam_vals"),
- jl_symbol("tfunc"), jl_symbol("name"),
- jl_symbol("roots"),
- /* jl_symbol("specTypes"),
- jl_symbol("unspecialized"),
- jl_symbol("specializations")*/
+ jl_new_datatype(jl_symbol("LambdaInfo"), jl_any_type, jl_emptysvec,
+ jl_svec(14, jl_symbol("next"),
+ jl_symbol("sig"),
+ jl_symbol("rettype"),
+ jl_symbol("va"),
+ jl_symbol("sparam_vals"),
+ jl_symbol("func"),
jl_symbol(""), jl_symbol(""), jl_symbol(""),
- jl_symbol("module"), jl_symbol("def"),
- jl_symbol("file"), jl_symbol("line"),
- jl_symbol("inferred"),
- jl_symbol("pure")),
- jl_svec(16, jl_any_type, jl_any_type,
- jl_simplevector_type, jl_simplevector_type,
- jl_any_type, jl_sym_type,
- jl_any_type, jl_any_type,
- jl_any_type, jl_array_any_type,
- jl_module_type, jl_any_type,
- jl_sym_type, jl_int32_type,
+ jl_symbol(""), jl_symbol(""), jl_symbol("fptr"),
+ jl_symbol("jlcall_api"), jl_symbol("inCompile")),
+ jl_svec(14, jl_any_type,
+ jl_type_type,
+ jl_type_type,
+ jl_bool_type,
+ jl_simplevector_type,
+ jl_any_type,
+ jl_any_type, jl_any_type, jl_any_type,
+ jl_int32_type, jl_int32_type, jl_any_type,
jl_bool_type, jl_bool_type),
- 0, 1, 5);
+ 0, 1, 4);
+
+ jl_ast_info_type =
+ jl_new_datatype(jl_symbol("AstInfo"),
+ jl_any_type, jl_emptysvec,
+ jl_svec(7, jl_symbol("ast"),
+ jl_symbol("def"),
+ jl_symbol("unspecialized_ducttape"),
+ jl_symbol("called"),
+ jl_symbol("pure"),
+ jl_symbol("inferred"),
+ jl_symbol("need_ducttape")),
+ jl_svec(7, jl_any_type,
+ jl_any_type,
+ jl_lambda_info_type,
+ jl_int32_type,
+ jl_bool_type,
+ jl_bool_type,
+ jl_bool_type),
+ 0, 1, 2);
+
+ jl_method_type =
+ jl_new_datatype(jl_symbol("Method"),
+ jl_any_type, jl_emptysvec,
+ jl_svec(16, jl_symbol("ast"),
+ jl_symbol("sig"),
+ jl_symbol("tvars"),
+ jl_symbol("sparam_syms"),
+ jl_symbol("tfunc"),
+ jl_symbol("name"),
+ jl_symbol("roots"),
+ jl_symbol("unspecialized"),
+ jl_symbol("specializations"),
+ jl_symbol("module"),
+ jl_symbol("file"),
+ jl_symbol("line"),
+ jl_symbol("isstaged"),
+ jl_symbol("va"),
+ jl_symbol("invokes"),
+ jl_symbol("next")),
+ jl_svec(16, jl_ast_info_type,
+ jl_type_type,
+ jl_any_type,
+ jl_simplevector_type,
+ jl_any_type,
+ jl_sym_type,
+ jl_array_any_type,
+ jl_lambda_info_type,
+ jl_array_any_type,
+ jl_module_type,
+ jl_sym_type,
+ jl_int32_type,
+ jl_bool_type,
+ jl_bool_type,
+ jl_any_type,
+ jl_any_type),
+ 0, 1, 1);
jl_typector_type =
jl_new_datatype(jl_symbol("TypeConstructor"),
@@ -3549,12 +3592,15 @@ void jl_init_types(void)
jl_svecset(jl_simplevector_type->types, 0, jl_long_type);
jl_svecset(jl_typename_type->types, 6, jl_long_type);
jl_svecset(jl_methtable_type->types, 5, jl_long_type);
+ jl_svecset(jl_lambda_info_type->types, 6, jl_voidpointer_type);
+ jl_svecset(jl_lambda_info_type->types, 7, jl_voidpointer_type);
+ jl_svecset(jl_lambda_info_type->types, 8, jl_voidpointer_type);
+ jl_svecset(jl_lambda_info_type->types, 11, jl_voidpointer_type);
jl_compute_field_offsets(jl_datatype_type);
jl_compute_field_offsets(jl_typename_type);
jl_compute_field_offsets(jl_uniontype_type);
jl_compute_field_offsets(jl_tvar_type);
- jl_compute_field_offsets(jl_method_type);
jl_compute_field_offsets(jl_methtable_type);
jl_compute_field_offsets(jl_expr_type);
jl_compute_field_offsets(jl_linenumbernode_type);
@@ -3564,6 +3610,8 @@ void jl_init_types(void)
jl_compute_field_offsets(jl_topnode_type);
jl_compute_field_offsets(jl_module_type);
jl_compute_field_offsets(jl_lambda_info_type);
+ jl_compute_field_offsets(jl_ast_info_type);
+ jl_compute_field_offsets(jl_method_type);
jl_compute_field_offsets(jl_typector_type);
jl_compute_field_offsets(jl_simplevector_type);
jl_simplevector_type->pointerfree = 0;
diff --git a/src/julia.h b/src/julia.h
index e6099d7c27a22..9c394d1fe5ad1 100644
--- a/src/julia.h
+++ b/src/julia.h
@@ -278,57 +278,80 @@ typedef jl_value_t *(*jl_fptr_sparam_t)(jl_svec_t*, jl_value_t*, jl_value_t**, u
typedef struct _jl_datatype_t jl_tupletype_t;
-typedef struct _jl_llvm_functions_t {
- void *functionObject; // jlcall llvm Function
- void *cFunctionList; // c callable llvm Functions
-
- // specialized llvm Function (common core for the other two)
- void *specFunctionObject;
-} jl_llvm_functions_t;
-
-typedef struct _jl_lambda_info_t {
+typedef struct _jl_method_t {
JL_DATA_TYPE
- // this holds the static data for a function:
- // a syntax tree, static parameters, and (if it has been compiled)
- // a function pointer.
+ // this holds the static data for a method definition
+ // a syntax tree, static parameter names
// this is the stuff that's shared among different instantiations
// (different environments) of a closure.
- jl_value_t *ast;
- jl_value_t *rettype;
- // sparams is a vector of values indexed by symbols
+ struct _jl_ast_info_t *ast;
+ jl_tupletype_t *sig;
+ // sparam_syms is a svec of the names of the tvars
+ jl_svec_t *tvars;
jl_svec_t *sparam_syms;
- jl_svec_t *sparam_vals;
jl_value_t *tfunc;
jl_sym_t *name; // for error reporting
jl_array_t *roots; // pointers in generated code
- jl_tupletype_t *specTypes; // argument types this will be compiled for
// a slower-but-works version of this function as a fallback
struct _jl_lambda_info_t *unspecialized;
// array of all lambda infos with code generated from this one
jl_array_t *specializations;
struct _jl_module_t *module;
- struct _jl_lambda_info_t *def; // original this is specialized from
jl_sym_t *file;
int32_t line;
- int8_t inferred;
- int8_t pure;
- uint8_t called; // bit flags: whether each of the first 8 arguments is called
+ uint8_t isstaged;
+ uint8_t va;
- // hidden fields:
- uint8_t jlcall_api : 1; // the c-abi for fptr; 0 = jl_fptr_t, 1 = jl_fptr_sparam_t
- uint8_t inInference : 1; // flags to tell if inference is running on this function
- // used to avoid infinite recursion
- uint8_t inCompile : 1;
- jl_fptr_t fptr; // jlcall entry point
+ // cache of specializations of this method for invoke(), i.e.
+ // cases where this method was called even though it was not necessarily
+ // the most specific for the argument types.
+ struct _jl_methtable_t *invokes;
+ struct _jl_method_t *next;
+} jl_method_t;
+
+typedef struct _jl_ast_info_t {
+ JL_DATA_TYPE
+ // this holds the static data for a (possibly inferred) syntax tree
+ jl_value_t *ast;
+ jl_method_t *def; // method this is specialized from
+ // a slower-but-works version of this function as a fallback
+ // this keeps codegen happy if the method contains intrinsics that depend on an sparam
+ struct _jl_lambda_info_t *unspecialized_ducttape;
+ uint32_t called; // bit flags: whether each of the first 8 arguments is called
+ uint8_t pure;
+ uint8_t inferred;
+ uint8_t need_ducttape; // whether this function has sparams and intrinsics,
+ // signaling that it probably can't be compiled via unspecialized
+ // (until the interpreter / runtime-intrinsics are fully functional)
+} jl_ast_info_t;
+typedef struct _jl_llvm_functions_t {
// On the old JIT, handles to all Functions generated for this linfo
// For the new JITs, handles to declarations in the shadow module
// with the same name as the generated functions for this linfo, suitable
// for referencing in LLVM IR
- jl_llvm_functions_t functionObjects;
+ void *functionObject; // jlcall llvm Function
+ void *cFunctionList; // c callable llvm Functions
+ void *specFunctionObject; // specialized llvm Function (common core for the other two)
+ int32_t functionID; // index that this function will have in the codegen table
+ int32_t specFunctionID; // index that this specFunction will have in the codegen table
+ jl_fptr_t fptr; // jlcall entry point
+ uint8_t jlcall_api; // the c-abi for fptr; 0 = jl_fptr_t, 1 = jl_fptr_sparam_t
+} jl_llvm_functions_t;
- int32_t functionID; // index that this function will have in the codegen table
- int32_t specFunctionID; // index that this specFunction will have in the codegen table
+typedef struct _jl_lambda_info_t {
+ JL_DATA_TYPE
+ // this holds the data for a executable thunk that maps sig -> rettype
+ struct _jl_lambda_info_t *next;
+ jl_tupletype_t *sig; // aka specTypes
+ jl_value_t *rettype;
+ uint8_t va; // sig has Vararg
+ uint8_t inCompile; // flags to tell if inference is running on this function
+ // used to avoid infinite recursion
+ // sparam_vals is the closure data (a vector of values indexed by func->def->sparam_syms)
+ jl_svec_t *sparam_vals; // NULL if this is a guard entry
+ jl_value_t *func; // where this function came from, NULL if there isn't an associated definition
+ jl_llvm_functions_t functionObjects;
} jl_lambda_info_t;
typedef jl_value_t jl_function_t;
@@ -443,27 +466,11 @@ typedef struct _jl_module_t {
uint32_t counter;
} jl_module_t;
-typedef struct _jl_methlist_t {
- JL_DATA_TYPE
- jl_tupletype_t *sig;
- int8_t va;
- int8_t isstaged;
- jl_svec_t *tvars;
- jl_lambda_info_t *func;
- // cache of specializations of this method for invoke(), i.e.
- // cases where this method was called even though it was not necessarily
- // the most specific for the argument types.
- struct _jl_methtable_t *invokes;
- // TODO: pointer from specialized to original method
- //jl_function_t *orig_method;
- struct _jl_methlist_t *next;
-} jl_methlist_t;
-
typedef struct _jl_methtable_t {
JL_DATA_TYPE
jl_sym_t *name;
- jl_methlist_t *defs;
- jl_methlist_t *cache;
+ jl_method_t *defs;
+ jl_lambda_info_t *cache;
jl_array_t *cache_arg1;
jl_array_t *cache_targ;
intptr_t max_args; // max # of non-vararg arguments in a signature
@@ -510,6 +517,8 @@ extern JL_DLLEXPORT jl_datatype_t *jl_datatype_type;
extern JL_DLLEXPORT jl_value_t *jl_bottom_type;
extern JL_DLLEXPORT jl_datatype_t *jl_lambda_info_type;
+extern JL_DLLEXPORT jl_datatype_t *jl_ast_info_type;
+extern JL_DLLEXPORT jl_datatype_t *jl_method_type;
extern JL_DLLEXPORT jl_datatype_t *jl_module_type;
extern JL_DLLEXPORT jl_datatype_t *jl_abstractarray_type;
extern JL_DLLEXPORT jl_datatype_t *jl_densearray_type;
@@ -573,7 +582,6 @@ extern JL_DLLEXPORT jl_datatype_t *jl_newvarnode_type;
extern JL_DLLEXPORT jl_datatype_t *jl_topnode_type;
extern JL_DLLEXPORT jl_datatype_t *jl_intrinsic_type;
extern JL_DLLEXPORT jl_datatype_t *jl_methtable_type;
-extern JL_DLLEXPORT jl_datatype_t *jl_method_type;
extern JL_DLLEXPORT jl_svec_t *jl_emptysvec;
extern JL_DLLEXPORT jl_value_t *jl_emptytuple;
@@ -891,6 +899,8 @@ static inline uint32_t jl_fielddesc_size(int8_t fielddesc_type)
#define jl_is_topnode(v) jl_typeis(v,jl_topnode_type)
#define jl_is_linenode(v) jl_typeis(v,jl_linenumbernode_type)
#define jl_is_lambda_info(v) jl_typeis(v,jl_lambda_info_type)
+#define jl_is_ast_info(v) jl_typeis(v,jl_ast_info_type)
+#define jl_is_method(v) jl_typeis(v,jl_method_type)
#define jl_is_module(v) jl_typeis(v,jl_module_type)
#define jl_is_mtable(v) jl_typeis(v,jl_methtable_type)
#define jl_is_task(v) jl_typeis(v,jl_task_type)
@@ -1039,12 +1049,12 @@ JL_DLLEXPORT jl_value_t *jl_new_struct(jl_datatype_t *type, ...);
JL_DLLEXPORT jl_value_t *jl_new_structv(jl_datatype_t *type, jl_value_t **args,
uint32_t na);
JL_DLLEXPORT jl_value_t *jl_new_struct_uninit(jl_datatype_t *type);
-JL_DLLEXPORT jl_function_t *jl_new_closure(jl_fptr_t proc, jl_value_t *env,
- jl_lambda_info_t *li);
-JL_DLLEXPORT jl_lambda_info_t *jl_new_lambda_info(jl_value_t *ast,
- jl_svec_t *tvars,
- jl_svec_t *sparams,
- jl_module_t *ctx);
+JL_DLLEXPORT jl_lambda_info_t *jl_new_lambda_info(jl_value_t *func,
+ jl_svec_t *sp,
+ jl_tupletype_t *sig);
+JL_DLLEXPORT jl_method_t *jl_new_method(jl_value_t *ast,
+ jl_svec_t *tvars,
+ jl_module_t *ctx);
JL_DLLEXPORT jl_svec_t *jl_svec(size_t n, ...);
JL_DLLEXPORT jl_svec_t *jl_svec1(void *a);
JL_DLLEXPORT jl_svec_t *jl_svec2(void *a, void *b);
@@ -1064,7 +1074,7 @@ JL_DLLEXPORT jl_value_t *jl_generic_function_def(jl_sym_t *name, jl_value_t **bp
jl_binding_t *bnd);
JL_DLLEXPORT jl_function_t *jl_new_generic_function(jl_sym_t *name, jl_module_t *module);
JL_DLLEXPORT jl_function_t *jl_new_generic_function_with_supertype(jl_sym_t *name, jl_module_t *module, jl_datatype_t *st, int iskw);
-JL_DLLEXPORT void jl_method_def(jl_svec_t *argdata, jl_lambda_info_t *f, jl_value_t *isstaged);
+JL_DLLEXPORT void jl_method_def(jl_svec_t *argdata, jl_method_t *f, jl_value_t *isstaged);
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);
@@ -1342,11 +1352,11 @@ JL_DLLEXPORT jl_module_t *jl_base_relative_to(jl_module_t *m);
// AST access
JL_DLLEXPORT int jl_is_rest_arg(jl_value_t *ex);
-JL_DLLEXPORT jl_value_t *jl_prepare_ast(jl_lambda_info_t *li);
JL_DLLEXPORT jl_value_t *jl_copy_ast(jl_value_t *expr);
+JL_DLLEXPORT jl_ast_info_t *jl_copy_ast_info(jl_ast_info_t *astinfo);
-JL_DLLEXPORT jl_value_t *jl_compress_ast(jl_lambda_info_t *li, jl_value_t *ast);
-JL_DLLEXPORT jl_value_t *jl_uncompress_ast(jl_lambda_info_t *li, jl_value_t *data);
+JL_DLLEXPORT jl_value_t *jl_compress_ast(jl_method_t *li, jl_value_t *ast);
+JL_DLLEXPORT jl_value_t *jl_uncompress_ast(jl_method_t *li, jl_value_t *data);
JL_DLLEXPORT int jl_is_operator(char *sym);
JL_DLLEXPORT int jl_operator_precedence(char *sym);
diff --git a/src/julia_internal.h b/src/julia_internal.h
index 7c255a166d104..3a044e4abee96 100644
--- a/src/julia_internal.h
+++ b/src/julia_internal.h
@@ -56,19 +56,20 @@ STATIC_INLINE jl_value_t *newstruct(jl_datatype_t *type)
}
void jl_generate_fptr(jl_lambda_info_t *li);
-void jl_compile_linfo(jl_lambda_info_t *li, void *cyclectx);
+jl_lambda_info_t *jl_compile_linfo(jl_lambda_info_t *li, void *cyclectx);
// invoke (compiling if necessary) the jlcall function pointer for a method
STATIC_INLINE jl_value_t *jl_call_method_internal(jl_lambda_info_t *meth, jl_value_t **args, uint32_t nargs)
{
- if (__unlikely(meth->fptr == NULL)) {
- jl_compile_linfo(meth, NULL);
- jl_generate_fptr(meth);
+ jl_lambda_info_t *thk = meth;
+ if (__unlikely(thk->functionObjects.fptr == NULL)) {
+ thk = jl_compile_linfo(meth, NULL);
+ jl_generate_fptr(thk);
}
- if (meth->jlcall_api == 0)
- return meth->fptr(args[0], &args[1], nargs-1);
+ if (thk->functionObjects.jlcall_api == 0)
+ return thk->functionObjects.fptr(args[0], &args[1], nargs-1);
else
- return ((jl_fptr_sparam_t)meth->fptr)(meth->sparam_vals, args[0], &args[1], nargs-1);
+ return ((jl_fptr_sparam_t)thk->functionObjects.fptr)(meth->sparam_vals, args[0], &args[1], nargs-1);
}
jl_tupletype_t *jl_argtype_with_function(jl_function_t *f, jl_tupletype_t *types);
@@ -151,11 +152,10 @@ jl_value_t *jl_type_match_morespecific(jl_value_t *a, jl_value_t *b);
int jl_types_equal_generic(jl_value_t *a, jl_value_t *b, int useenv);
jl_datatype_t *jl_inst_concrete_tupletype_v(jl_value_t **p, size_t np);
jl_datatype_t *jl_inst_concrete_tupletype(jl_svec_t *p);
-jl_lambda_info_t *jl_method_cache_insert(jl_methtable_t *mt, jl_tupletype_t *type,
- jl_lambda_info_t *method);
-jl_methlist_t *jl_method_table_insert(jl_methtable_t *mt, jl_tupletype_t *type,
- jl_lambda_info_t *method, jl_svec_t *tvars,
- int8_t isstaged);
+void jl_method_cache_insert(jl_methtable_t *mt, jl_tupletype_t *type,
+ jl_lambda_info_t *method);
+void jl_method_table_insert(jl_methtable_t *mt,
+ jl_method_t *method);
int jl_is_type(jl_value_t *v);
jl_value_t *jl_type_intersection_matching(jl_value_t *a, jl_value_t *b,
jl_svec_t **penv, jl_svec_t *tvars);
@@ -169,29 +169,26 @@ jl_datatype_t *jl_wrap_vararg(jl_value_t *t);
void jl_assign_bits(void *dest, jl_value_t *bits);
jl_expr_t *jl_exprn(jl_sym_t *head, size_t n);
jl_function_t *jl_new_generic_function(jl_sym_t *name, jl_module_t *module);
-void jl_add_method(jl_function_t *gf, jl_tupletype_t *types, jl_lambda_info_t *meth,
- jl_svec_t *tvars, int8_t isstaged);
-void jl_add_method_to_table(jl_methtable_t *mt, jl_tupletype_t *types, jl_lambda_info_t *meth,
- jl_svec_t *tvars, int8_t isstaged);
+jl_method_t *jl_add_method_to_table(jl_methtable_t *mt, jl_tupletype_t *types, jl_method_t *meth,
+ jl_svec_t *tvars, int8_t isstaged);
jl_function_t *jl_module_call_func(jl_module_t *m);
int jl_is_submodule(jl_module_t *child, jl_module_t *parent);
jl_value_t *jl_toplevel_eval_flex(jl_value_t *e, int fast);
-jl_lambda_info_t *jl_wrap_expr(jl_value_t *expr);
+jl_method_t *jl_wrap_expr(jl_value_t *expr);
jl_value_t *jl_eval_global_var(jl_module_t *m, jl_sym_t *e);
jl_value_t *jl_parse_eval_all(const char *fname, size_t len,
const char *content, size_t contentlen);
-jl_value_t *jl_interpret_toplevel_thunk(jl_lambda_info_t *lam);
-jl_value_t *jl_interpret_toplevel_thunk_with(jl_lambda_info_t *lam,
+jl_value_t *jl_interpret_toplevel_thunk(jl_method_t *lam);
+jl_value_t *jl_interpret_toplevel_thunk_with(jl_method_t *lam,
jl_value_t **loc, size_t nl);
jl_value_t *jl_interpret_toplevel_expr(jl_value_t *e);
jl_value_t *jl_static_eval(jl_value_t *ex, void *ctx_, jl_module_t *mod,
- jl_lambda_info_t *li, int sparams, int allow_alloc);
+ jl_ast_info_t *ast, jl_lambda_info_t *linfo, int allow_alloc);
int jl_is_toplevel_only_expr(jl_value_t *e);
-void jl_type_infer(jl_lambda_info_t *li, jl_lambda_info_t *def);
+void jl_type_infer(jl_lambda_info_t *li);
-jl_lambda_info_t *jl_get_unspecialized(jl_lambda_info_t *method);
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);
@@ -203,19 +200,18 @@ jl_array_t *jl_lam_vinfo(jl_expr_t *l);
jl_array_t *jl_lam_capt(jl_expr_t *l);
jl_value_t *jl_lam_gensyms(jl_expr_t *l);
jl_array_t *jl_lam_staticparams(jl_expr_t *l);
-jl_sym_t *jl_lam_argname(jl_lambda_info_t *li, int i);
+jl_sym_t *jl_lam_argname(jl_method_t *li, int i);
int jl_lam_vars_captured(jl_expr_t *ast);
jl_expr_t *jl_lam_body(jl_expr_t *l);
-int jl_local_in_linfo(jl_lambda_info_t *linfo, jl_sym_t *sym);
+int jl_local_in_linfo(jl_method_t *linfo, jl_sym_t *sym);
jl_value_t *jl_first_argument_datatype(jl_value_t *argtypes);
-jl_value_t *jl_preresolve_globals(jl_value_t *expr, jl_lambda_info_t *lam);
-int jl_has_intrinsics(jl_lambda_info_t *li, jl_expr_t *e, jl_module_t *m);
+jl_value_t *jl_preresolve_globals(jl_value_t *expr, jl_method_t *lam);
+int jl_has_intrinsics(jl_ast_info_t *ast, jl_expr_t *e, jl_module_t *m);
jl_value_t *jl_nth_slot_type(jl_tupletype_t *sig, size_t i);
void jl_compute_field_offsets(jl_datatype_t *st);
jl_array_t *jl_new_array_for_deserialization(jl_value_t *atype, uint32_t ndims, size_t *dims,
int isunboxed, int elsz);
-jl_lambda_info_t *jl_copy_lambda_info(jl_lambda_info_t *linfo);
extern jl_array_t *jl_module_init_order;
#ifdef JL_USE_INTEL_JITEVENTS
@@ -264,7 +260,7 @@ JL_DLLEXPORT jl_methtable_t *jl_new_method_table(jl_sym_t *name, jl_module_t *mo
jl_lambda_info_t *jl_get_specialization1(jl_tupletype_t *types, void *cyclectx);
jl_function_t *jl_module_get_initializer(jl_module_t *m);
uint32_t jl_module_next_counter(jl_module_t *m);
-void jl_fptr_to_llvm(void *fptr, jl_lambda_info_t *lam, int specsig);
+jl_lambda_info_t *jl_fptr_to_llvm(void *fptr, jl_lambda_info_t *lam, int specsig);
jl_tupletype_t *arg_type_tuple(jl_value_t **args, size_t nargs);
jl_value_t *skip_meta(jl_array_t *body);
diff --git a/src/signal-handling.c b/src/signal-handling.c
index f8f7b3f019e92..fa2f132c121c8 100644
--- a/src/signal-handling.c
+++ b/src/signal-handling.c
@@ -57,7 +57,7 @@ static void jl_critical_error(int sig, bt_context_t context, intptr_t *bt_data,
if (context)
*bt_size = n = rec_backtrace_ctx(bt_data, JL_MAX_BT_SIZE, context);
for(size_t i=0; i < n; i++)
- jl_gdblookup(bt_data[i]);
+ jl_gdblookup(bt_data[i] - 1);
gc_debug_print_status();
gc_debug_critical_error();
}
diff --git a/src/task.c b/src/task.c
index 6dccb83e0789a..a166cd1fdb310 100644
--- a/src/task.c
+++ b/src/task.c
@@ -820,7 +820,7 @@ JL_DLLEXPORT void jlbacktrace(void)
{
size_t n = jl_bt_size; // jl_bt_size > 40 ? 40 : jl_bt_size;
for (size_t i=0; i < n; i++)
- jl_gdblookup(jl_bt_data[i]);
+ jl_gdblookup(jl_bt_data[i] - 1);
}
JL_DLLEXPORT void jl_gdbbacktrace(void)
diff --git a/src/toplevel.c b/src/toplevel.c
index 06340be0b5094..b4a09e14dcd73 100644
--- a/src/toplevel.c
+++ b/src/toplevel.c
@@ -240,21 +240,21 @@ JL_DLLEXPORT jl_module_t *jl_base_relative_to(jl_module_t *m)
return jl_top_module;
}
-int jl_has_intrinsics(jl_lambda_info_t *li, jl_expr_t *e, jl_module_t *m)
+int jl_has_intrinsics(jl_ast_info_t *ast, jl_expr_t *e, jl_module_t *m)
{
if (jl_array_len(e->args) == 0)
return 0;
if (e->head == static_typeof_sym) return 1;
jl_value_t *e0 = jl_exprarg(e,0);
if (e->head == call_sym) {
- jl_value_t *sv = jl_static_eval(e0, NULL, m, li, 0, 0);
+ jl_value_t *sv = jl_static_eval(e0, NULL, m, ast, NULL, 0);
if (sv && jl_typeis(sv, jl_intrinsic_type))
return 1;
}
int i;
for(i=0; i < jl_array_len(e->args); i++) {
jl_value_t *a = jl_exprarg(e,i);
- if (jl_is_expr(a) && jl_has_intrinsics(li, (jl_expr_t*)a, m))
+ if (jl_is_expr(a) && jl_has_intrinsics(ast, (jl_expr_t*)a, m))
return 1;
}
return 0;
@@ -262,7 +262,7 @@ int jl_has_intrinsics(jl_lambda_info_t *li, jl_expr_t *e, jl_module_t *m)
// heuristic for whether a top-level input should be evaluated with
// the compiler or the interpreter.
-static int jl_eval_with_compiler_p(jl_lambda_info_t *li, jl_expr_t *expr, int compileloops, jl_module_t *m)
+static int jl_eval_with_compiler_p(jl_expr_t *expr, int compileloops, jl_module_t *m)
{
assert(jl_is_expr(expr));
if (expr->head==body_sym && compileloops) {
@@ -306,7 +306,7 @@ static int jl_eval_with_compiler_p(jl_lambda_info_t *li, jl_expr_t *expr, int co
}
}
}
- if (jl_has_intrinsics(li, expr, m)) return 1;
+ if (jl_has_intrinsics(NULL, expr, m)) return 1;
return 0;
}
@@ -491,7 +491,7 @@ jl_value_t *jl_toplevel_eval_flex(jl_value_t *e, int fast)
jl_value_t *thunk=NULL;
jl_value_t *result;
- jl_lambda_info_t *thk=NULL;
+ jl_method_t *thk=NULL;
int ewc = 0;
JL_GC_PUSH3(&thunk, &thk, &ex);
@@ -512,16 +512,17 @@ jl_value_t *jl_toplevel_eval_flex(jl_value_t *e, int fast)
}
if (head == thunk_sym) {
- thk = (jl_lambda_info_t*)jl_exprarg(ex,0);
- assert(jl_is_lambda_info(thk));
- if (!jl_is_expr(thk->ast)) {
- thk->ast = jl_uncompress_ast(thk, thk->ast);
- jl_gc_wb(thk, thk->ast);
+ thk = (jl_method_t*)jl_exprarg(ex,0);
+ assert(jl_is_method(thk));
+ if (!jl_is_expr(thk->ast->ast)) {
+ thk->ast->ast = jl_uncompress_ast(thk, thk->ast->ast);
+ jl_gc_wb(thk->ast, thk->ast->ast);
}
- ewc = jl_eval_with_compiler_p(thk, jl_lam_body((jl_expr_t*)thk->ast), fast, jl_current_module);
+ assert(jl_svec_len(thk->sparam_syms) == 0);
+ ewc = jl_eval_with_compiler_p(jl_lam_body((jl_expr_t*)thk->ast->ast), fast, jl_current_module);
}
else {
- if (head && jl_eval_with_compiler_p(NULL, (jl_expr_t*)ex, fast, jl_current_module)) {
+ if (head && jl_eval_with_compiler_p((jl_expr_t*)ex, fast, jl_current_module)) {
thk = jl_wrap_expr((jl_value_t*)ex);
ewc = 1;
}
@@ -540,13 +541,16 @@ jl_value_t *jl_toplevel_eval_flex(jl_value_t *e, int fast)
}
}
- thk->specTypes = (jl_tupletype_t*)jl_typeof(jl_emptytuple); // no gc_wb needed
if (ewc) {
- if (!jl_in_inference) {
- jl_type_infer(thk, thk);
+ thk->sig = (jl_tupletype_t*)jl_typeof(jl_emptytuple);
+ if (!thk->unspecialized) {
+ thk->unspecialized = jl_new_lambda_info((jl_value_t*)thk->ast, jl_emptysvec, thk->sig);
+ jl_gc_wb(thk, thk->unspecialized);
+ if (!jl_in_inference)
+ jl_type_infer(thk->unspecialized);
}
- jl_value_t *dummy_f_arg=NULL;
- result = jl_call_method_internal(thk, &dummy_f_arg, 1);
+ jl_value_t *dummy_f_arg = NULL;
+ result = jl_call_method_internal(thk->unspecialized, &dummy_f_arg, 1);
}
else {
result = jl_interpret_toplevel_thunk(thk);
@@ -609,15 +613,15 @@ static int type_contains(jl_value_t *ty, jl_value_t *x)
return 0;
}
-void print_func_loc(JL_STREAM *s, jl_lambda_info_t *li);
+void print_func_loc(JL_STREAM *s, jl_method_t *li);
-void jl_check_static_parameter_conflicts(jl_lambda_info_t *li, jl_svec_t *t, jl_sym_t *fname)
+void jl_check_static_parameter_conflicts(jl_method_t *li, jl_svec_t *t, jl_sym_t *fname)
{
jl_array_t *vinfo;
size_t nvars;
- if (li->ast && jl_is_expr(li->ast)) {
- vinfo = jl_lam_vinfo((jl_expr_t*)li->ast);
+ if (li->ast->ast && jl_is_expr(li->ast->ast)) {
+ vinfo = jl_lam_vinfo((jl_expr_t*)li->ast->ast);
nvars = jl_array_len(vinfo);
for(size_t i=0; i < jl_svec_len(t); i++) {
for(size_t j=0; j < nvars; j++) {
@@ -703,7 +707,7 @@ jl_value_t *jl_first_argument_datatype(jl_value_t *argtypes)
return (jl_value_t*)first_arg_datatype(argtypes, 0);
}
-static jl_lambda_info_t *expr_to_lambda(jl_lambda_info_t *f)
+static jl_method_t *expr_to_lambda_ast(jl_method_t *f)
{
// this occurs when there is a closure being added to an out-of-scope function
// the user should only do this at the toplevel
@@ -721,14 +725,14 @@ static jl_lambda_info_t *expr_to_lambda(jl_lambda_info_t *f)
for (i = 0; i < l; i++) {
jl_svecset(tvar_syms, i, jl_arrayref(tvar_syms_arr, i));
}
- // wrap in a LambdaInfo
- f = jl_new_lambda_info((jl_value_t*)f, tvar_syms, jl_emptysvec, jl_current_module);
- jl_preresolve_globals(f->ast, f);
+ // wrap in a Method
+ f = jl_new_method((jl_value_t*)f, tvar_syms, jl_current_module);
+ jl_preresolve_globals(f->ast->ast, f);
JL_GC_POP();
return f;
}
-JL_DLLEXPORT void jl_method_def(jl_svec_t *argdata, jl_lambda_info_t *f, jl_value_t *isstaged)
+JL_DLLEXPORT void jl_method_def(jl_svec_t *argdata, jl_method_t *f, jl_value_t *isstaged)
{
// argdata is svec({types...}, svec(typevars...))
jl_tupletype_t *argtypes = (jl_tupletype_t*)jl_svecref(argdata,0);
@@ -737,10 +741,10 @@ JL_DLLEXPORT void jl_method_def(jl_svec_t *argdata, jl_lambda_info_t *f, jl_valu
jl_sym_t *name;
JL_GC_PUSH1(&f);
- if (!jl_is_lambda_info(f))
- f = expr_to_lambda(f);
+ if (!jl_is_method(f))
+ f = expr_to_lambda_ast(f);
- assert(jl_is_lambda_info(f));
+ assert(jl_is_method(f));
assert(jl_is_tuple_type(argtypes));
assert(jl_is_svec(tvars));
assert(jl_nparams(argtypes)>0);
@@ -788,10 +792,10 @@ JL_DLLEXPORT void jl_method_def(jl_svec_t *argdata, jl_lambda_info_t *f, jl_valu
}
}
- jl_add_method_to_table(mt, argtypes, f, tvars, isstaged == jl_true);
- if (jl_boot_file_loaded && f->ast && jl_is_expr(f->ast)) {
- f->ast = jl_compress_ast(f, f->ast);
- jl_gc_wb(f, f->ast);
+ f = jl_add_method_to_table(mt, argtypes, f, tvars, isstaged == jl_true);
+ if (jl_boot_file_loaded && f->ast->ast && jl_is_expr(f->ast->ast)) {
+ f->ast->ast = jl_compress_ast(f, f->ast->ast);
+ jl_gc_wb(f->ast, f->ast->ast);
}
JL_GC_POP();
}
diff --git a/test/core.jl b/test/core.jl
index 101bec0ebf2cb..c6673cf972de4 100644
--- a/test/core.jl
+++ b/test/core.jl
@@ -2383,10 +2383,10 @@ let f
(::typeof(f))(x::newtype10373) = println("$f")
end
end
-@test methods(f10373).defs.func.name == :f10373
-@test methods(f10373).defs.next.func.name == :f10373
-@test methods(g10373).defs.func.name == :g10373
-@test methods(g10373).defs.next.func.name == :g10373
+@test methods(f10373).defs.name == :f10373
+@test methods(f10373).defs.next.name == :f10373
+@test methods(g10373).defs.name == :g10373
+@test methods(g10373).defs.next.name == :g10373
# issue #7221
f7221{T<:Number}(::T) = 1