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