Skip to content

Commit

Permalink
Some new inferrability improvements (#422)
Browse files Browse the repository at this point in the history
These became visible when working on JuliaLang/julia#37163.
Most are not in a truly performance-critical path (though of course
FrameCode optimization is not entirely uncritical, either), but one of them
is.
  • Loading branch information
timholy authored Aug 23, 2020
1 parent 740e71b commit cecdb14
Show file tree
Hide file tree
Showing 5 changed files with 33 additions and 20 deletions.
5 changes: 3 additions & 2 deletions src/builtins.jl
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,8 @@ function maybe_evaluate_builtin(frame, call_expr, expand::Bool)
if !expand
return Some{Any}(Core._apply_iterate(argswrapped...))
end
@assert argswrapped[1] === Core.iterate || argswrapped[1] === Core.Compiler.iterate || argswrapped[1] === Base.iterate "cannot handle `_apply_iterate` with non iterate as first argument, got $(argswrapped[1]), $(typeof(argswrapped[1]))"
aw1 = argswrapped[1]::Function
@assert aw1 === Core.iterate || aw1 === Core.Compiler.iterate || aw1 === Base.iterate "cannot handle `_apply_iterate` with non iterate as first argument, got $(aw1), $(typeof(aw1))"
new_expr = Expr(:call, argswrapped[2])
popfirst!(argswrapped) # pop the iterate
popfirst!(argswrapped) # pop the function
Expand Down Expand Up @@ -214,7 +215,7 @@ function maybe_evaluate_builtin(frame, call_expr, expand::Bool)
return Some{Any}(throw(getargs(args, frame)...))
end
elseif f === tuple
return Some{Any}(ntuple(i->@lookup(frame, args[i+1]), length(args)-1))
return Some{Any}(ntupleany(i->@lookup(frame, args[i+1]), length(args)-1))
elseif f === typeassert
if nargs == 2
return Some{Any}(typeassert(@lookup(frame, args[2]), @lookup(frame, args[3])))
Expand Down
14 changes: 7 additions & 7 deletions src/construct.jl
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ julia> JuliaInterpreter.prepare_args(mymethod, [mymethod, 1, 2], [:verbose=>true
function prepare_args(@nospecialize(f), allargs, kwargs)
if !isempty(kwargs)
f = Core.kwfunc(f)
allargs = [f, namedtuple(kwargs), allargs...]
allargs = Any[f, namedtuple(kwargs), allargs...]
elseif f === Core._apply
f = to_function(allargs[2])
allargs = append_any((allargs[2],), allargs[3:end]...)
Expand Down Expand Up @@ -315,7 +315,7 @@ function prepare_framedata(framecode, argvals::Vector{Any}, lenv::SimpleVector=e
end
end
if islastva
locals[meth_nargs] = (let i=meth_nargs; Some{Any}(ntuple(k->argvals[i+k-1], nargs-i+1)); end)
locals[meth_nargs] = (let i=meth_nargs; Some{Any}(ntupleany(k->argvals[i+k-1], nargs-i+1)); end)
last_reference[meth_nargs] = 1
end
end
Expand Down Expand Up @@ -555,7 +555,7 @@ function enter_call_expr(expr; enter_generated = false)
clear_caches()
r = determine_method_for_expr(expr; enter_generated = enter_generated)
if r !== nothing && !isa(r[1], Compiled)
return prepare_frame(r[1:end-1]...)
return prepare_frame(Base.front(r)...)
end
nothing
end
Expand Down Expand Up @@ -609,7 +609,7 @@ function enter_call(@nospecialize(finfo), @nospecialize(args...); kwargs...)
end
r = prepare_call(f, allargs; enter_generated=enter_generated)
if r !== nothing && !isa(r[1], Compiled)
return prepare_frame(r[1:end-1]...)
return prepare_frame(Base.front(r)...)
end
return nothing
end
Expand All @@ -631,7 +631,7 @@ function extract_args(__module__, ex0)
return Expr(:tuple, :(<:), ex0.args...)
else
return Expr(:tuple,
map(x->isexpr(x,:parameters) ? QuoteNode(x) : x, ex0.args)...)
mapany(x->isexpr(x,:parameters) ? QuoteNode(x) : x, ex0.args)...)
end
end
if isexpr(ex0, :macrocall) # Make @edit @time 1+2 edit the macro by using the types of the *expressions*
Expand All @@ -642,14 +642,14 @@ function extract_args(__module__, ex0)
return error("expression is not a function call or symbol")
elseif ex.head === :call
return Expr(:tuple,
map(x->isexpr(x, :parameters) ? QuoteNode(x) : x, ex.args)...)
mapany(x->isexpr(x, :parameters) ? QuoteNode(x) : x, ex.args)...)
elseif ex.head === :body
a1 = ex.args[1]
if isexpr(a1, :call)
a11 = a1.args[1]
if a11 === :setindex!
return Expr(:tuple,
map(x->isexpr(x, :parameters) ? QuoteNode(x) : x, arg.args)...)
mapany(x->isexpr(x, :parameters) ? QuoteNode(x) : x, arg.args)...)
end
end
end
Expand Down
10 changes: 6 additions & 4 deletions src/interpret.jl
Original file line number Diff line number Diff line change
Expand Up @@ -308,11 +308,11 @@ function evaluate_structtype(@nospecialize(recurse), frame, node)

name, mod = structname(frame, node)
supertype = lookup_or_eval(recurse, frame, node.args[4])::Type
ismutable = node.args[6]
ninit = node.args[7]
ismutable = node.args[6]::Bool
ninit = node.args[7]::Int
newstructexpr = Expr(:struct_type, name, nothing, nothing, supertype, nothing, ismutable, ninit)
for idx in (2, 3, 5)
ex = newstructexpr.args[idx] = grsvec!(copy(node.args[idx]))
ex = newstructexpr.args[idx] = grsvec!(copy(node.args[idx]::Expr))
for i = 2:length(ex.args)
inplace_lookup!(ex, i, frame)
end
Expand Down Expand Up @@ -371,7 +371,9 @@ function eval_rhs(@nospecialize(recurse), frame, node::Expr)
head = node.head
if head === :new
mod = moduleof(frame)
args = [@lookup(mod, frame, arg) for arg in node.args]
args = let mod=mod
Any[@lookup(mod, frame, arg) for arg in node.args]
end
T = popfirst!(args)
rhs = ccall(:jl_new_structv, Any, (Any, Ptr{Any}, UInt32), T, args, length(args))
return rhs
Expand Down
15 changes: 8 additions & 7 deletions src/optimize.jl
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@ end
function parametric_type_to_expr(t::Type)
t isa Core.TypeofBottom && return t
t isa UnionAll && (t = t.body)
t = t::DataType
if t <: Vararg
return Expr(:(...), t.parameters[1])
end
Expand All @@ -250,7 +251,7 @@ function parametric_type_to_expr(t::Type)
isa(p, TypeVar) ? p.name :
isa(p, DataType) && p.hasfreetypevars ? parametric_type_to_expr(p) : p
end
return Expr(:curly, scopename(t.name), params...)
return Expr(:curly, scopename(t.name), params...)::Expr
end
return t
end
Expand All @@ -260,7 +261,7 @@ function build_compiled_call!(stmt::Expr, fcall, code, idx, nargs::Int, sparams:
TVal = evalmod == Core.Compiler ? Core.Compiler.Val : Val
delete_idx = Int[]
if fcall === :ccall
cfunc, RetType, ArgType = lookup_stmt(code.code, stmt.args[1]), stmt.args[2], stmt.args[3]
cfunc, RetType, ArgType = lookup_stmt(code.code, stmt.args[1]), stmt.args[2], stmt.args[3]::SimpleVector
# The result of this is useful to have next to you when reading this code:
# f(x, y) = ccall(:jl_value_ptr, Ptr{Cvoid}, (Float32,Any), x, y)
# @code_lowered f(2, 3)
Expand All @@ -270,11 +271,11 @@ function build_compiled_call!(stmt::Expr, fcall, code, idx, nargs::Int, sparams:
push!(args, arg)
else
@assert arg isa SSAValue
unsafe_convert_expr = code.code[arg.id]
unsafe_convert_expr = code.code[arg.id]::Expr
push!(delete_idx, arg.id) # delete the unsafe_convert
cconvert_stmt = unsafe_convert_expr.args[3]
push!(delete_idx, cconvert_stmt.id) # delete the cconvert
cconvert_expr = code.code[cconvert_stmt.id]
cconvert_expr = code.code[cconvert_stmt.id]::Expr
push!(args, cconvert_expr.args[3])
end
end
Expand All @@ -290,11 +291,11 @@ function build_compiled_call!(stmt::Expr, fcall, code, idx, nargs::Int, sparams:
if idxstart < idx
while true
pc = step_expr!(Compiled(), frame)
pc == idx && break
pc === idx && break
pc === nothing && error("this should never happen")
end
end
cfunc, RetType, ArgType = @lookup(frame, stmt.args[2]), @lookup(frame, stmt.args[3]), @lookup(frame, stmt.args[4])
cfunc, RetType, ArgType = @lookup(frame, stmt.args[2]), @lookup(frame, stmt.args[3]), @lookup(frame, stmt.args[4])::Type{<:Tuple}
args = stmt.args[5:end]
end
dynamic_ccall = false
Expand All @@ -320,7 +321,7 @@ function build_compiled_call!(stmt::Expr, fcall, code, idx, nargs::Int, sparams:
argnames = Any[Symbol(:arg, i) for i = 1:nargs]
if f === nothing
if fcall == :ccall
ArgType = Expr(:tuple, [parametric_type_to_expr(t) for t in ArgType]...)
ArgType = Expr(:tuple, Any[parametric_type_to_expr(t) for t in ArgType]...)
end
RetType = parametric_type_to_expr(RetType)
# #285: test whether we can evaluate an type constraints on parametric expressions
Expand Down
9 changes: 9 additions & 0 deletions src/packagedef.jl
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,15 @@ else
mapany(f, itr) = map!(f, Vector{Any}(undef, length(itr)::Int), itr) # convenient for Expr.args
end

if isdefined(Base, :ntupleany)
const ntupleany = Base.ntupleany
else
@noinline function ntupleany(f, n)
(n >= 0) || throw(ArgumentError(string("tuple length should be ≥ 0, got ", n)))
(Any[f(i) for i = 1:n]...,)
end
end

include("types.jl")
include("utils.jl")
include("construct.jl")
Expand Down

0 comments on commit cecdb14

Please sign in to comment.