Skip to content

Commit cecdb14

Browse files
authored
Some new inferrability improvements (#422)
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.
1 parent 740e71b commit cecdb14

File tree

5 files changed

+33
-20
lines changed

5 files changed

+33
-20
lines changed

src/builtins.jl

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,8 @@ function maybe_evaluate_builtin(frame, call_expr, expand::Bool)
8080
if !expand
8181
return Some{Any}(Core._apply_iterate(argswrapped...))
8282
end
83-
@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]))"
83+
aw1 = argswrapped[1]::Function
84+
@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))"
8485
new_expr = Expr(:call, argswrapped[2])
8586
popfirst!(argswrapped) # pop the iterate
8687
popfirst!(argswrapped) # pop the function
@@ -214,7 +215,7 @@ function maybe_evaluate_builtin(frame, call_expr, expand::Bool)
214215
return Some{Any}(throw(getargs(args, frame)...))
215216
end
216217
elseif f === tuple
217-
return Some{Any}(ntuple(i->@lookup(frame, args[i+1]), length(args)-1))
218+
return Some{Any}(ntupleany(i->@lookup(frame, args[i+1]), length(args)-1))
218219
elseif f === typeassert
219220
if nargs == 2
220221
return Some{Any}(typeassert(@lookup(frame, args[2]), @lookup(frame, args[3])))

src/construct.jl

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ julia> JuliaInterpreter.prepare_args(mymethod, [mymethod, 1, 2], [:verbose=>true
133133
function prepare_args(@nospecialize(f), allargs, kwargs)
134134
if !isempty(kwargs)
135135
f = Core.kwfunc(f)
136-
allargs = [f, namedtuple(kwargs), allargs...]
136+
allargs = Any[f, namedtuple(kwargs), allargs...]
137137
elseif f === Core._apply
138138
f = to_function(allargs[2])
139139
allargs = append_any((allargs[2],), allargs[3:end]...)
@@ -315,7 +315,7 @@ function prepare_framedata(framecode, argvals::Vector{Any}, lenv::SimpleVector=e
315315
end
316316
end
317317
if islastva
318-
locals[meth_nargs] = (let i=meth_nargs; Some{Any}(ntuple(k->argvals[i+k-1], nargs-i+1)); end)
318+
locals[meth_nargs] = (let i=meth_nargs; Some{Any}(ntupleany(k->argvals[i+k-1], nargs-i+1)); end)
319319
last_reference[meth_nargs] = 1
320320
end
321321
end
@@ -555,7 +555,7 @@ function enter_call_expr(expr; enter_generated = false)
555555
clear_caches()
556556
r = determine_method_for_expr(expr; enter_generated = enter_generated)
557557
if r !== nothing && !isa(r[1], Compiled)
558-
return prepare_frame(r[1:end-1]...)
558+
return prepare_frame(Base.front(r)...)
559559
end
560560
nothing
561561
end
@@ -609,7 +609,7 @@ function enter_call(@nospecialize(finfo), @nospecialize(args...); kwargs...)
609609
end
610610
r = prepare_call(f, allargs; enter_generated=enter_generated)
611611
if r !== nothing && !isa(r[1], Compiled)
612-
return prepare_frame(r[1:end-1]...)
612+
return prepare_frame(Base.front(r)...)
613613
end
614614
return nothing
615615
end
@@ -631,7 +631,7 @@ function extract_args(__module__, ex0)
631631
return Expr(:tuple, :(<:), ex0.args...)
632632
else
633633
return Expr(:tuple,
634-
map(x->isexpr(x,:parameters) ? QuoteNode(x) : x, ex0.args)...)
634+
mapany(x->isexpr(x,:parameters) ? QuoteNode(x) : x, ex0.args)...)
635635
end
636636
end
637637
if isexpr(ex0, :macrocall) # Make @edit @time 1+2 edit the macro by using the types of the *expressions*
@@ -642,14 +642,14 @@ function extract_args(__module__, ex0)
642642
return error("expression is not a function call or symbol")
643643
elseif ex.head === :call
644644
return Expr(:tuple,
645-
map(x->isexpr(x, :parameters) ? QuoteNode(x) : x, ex.args)...)
645+
mapany(x->isexpr(x, :parameters) ? QuoteNode(x) : x, ex.args)...)
646646
elseif ex.head === :body
647647
a1 = ex.args[1]
648648
if isexpr(a1, :call)
649649
a11 = a1.args[1]
650650
if a11 === :setindex!
651651
return Expr(:tuple,
652-
map(x->isexpr(x, :parameters) ? QuoteNode(x) : x, arg.args)...)
652+
mapany(x->isexpr(x, :parameters) ? QuoteNode(x) : x, arg.args)...)
653653
end
654654
end
655655
end

src/interpret.jl

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -308,11 +308,11 @@ function evaluate_structtype(@nospecialize(recurse), frame, node)
308308

309309
name, mod = structname(frame, node)
310310
supertype = lookup_or_eval(recurse, frame, node.args[4])::Type
311-
ismutable = node.args[6]
312-
ninit = node.args[7]
311+
ismutable = node.args[6]::Bool
312+
ninit = node.args[7]::Int
313313
newstructexpr = Expr(:struct_type, name, nothing, nothing, supertype, nothing, ismutable, ninit)
314314
for idx in (2, 3, 5)
315-
ex = newstructexpr.args[idx] = grsvec!(copy(node.args[idx]))
315+
ex = newstructexpr.args[idx] = grsvec!(copy(node.args[idx]::Expr))
316316
for i = 2:length(ex.args)
317317
inplace_lookup!(ex, i, frame)
318318
end
@@ -371,7 +371,9 @@ function eval_rhs(@nospecialize(recurse), frame, node::Expr)
371371
head = node.head
372372
if head === :new
373373
mod = moduleof(frame)
374-
args = [@lookup(mod, frame, arg) for arg in node.args]
374+
args = let mod=mod
375+
Any[@lookup(mod, frame, arg) for arg in node.args]
376+
end
375377
T = popfirst!(args)
376378
rhs = ccall(:jl_new_structv, Any, (Any, Ptr{Any}, UInt32), T, args, length(args))
377379
return rhs

src/optimize.jl

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,7 @@ end
242242
function parametric_type_to_expr(t::Type)
243243
t isa Core.TypeofBottom && return t
244244
t isa UnionAll && (t = t.body)
245+
t = t::DataType
245246
if t <: Vararg
246247
return Expr(:(...), t.parameters[1])
247248
end
@@ -250,7 +251,7 @@ function parametric_type_to_expr(t::Type)
250251
isa(p, TypeVar) ? p.name :
251252
isa(p, DataType) && p.hasfreetypevars ? parametric_type_to_expr(p) : p
252253
end
253-
return Expr(:curly, scopename(t.name), params...)
254+
return Expr(:curly, scopename(t.name), params...)::Expr
254255
end
255256
return t
256257
end
@@ -260,7 +261,7 @@ function build_compiled_call!(stmt::Expr, fcall, code, idx, nargs::Int, sparams:
260261
TVal = evalmod == Core.Compiler ? Core.Compiler.Val : Val
261262
delete_idx = Int[]
262263
if fcall === :ccall
263-
cfunc, RetType, ArgType = lookup_stmt(code.code, stmt.args[1]), stmt.args[2], stmt.args[3]
264+
cfunc, RetType, ArgType = lookup_stmt(code.code, stmt.args[1]), stmt.args[2], stmt.args[3]::SimpleVector
264265
# The result of this is useful to have next to you when reading this code:
265266
# f(x, y) = ccall(:jl_value_ptr, Ptr{Cvoid}, (Float32,Any), x, y)
266267
# @code_lowered f(2, 3)
@@ -270,11 +271,11 @@ function build_compiled_call!(stmt::Expr, fcall, code, idx, nargs::Int, sparams:
270271
push!(args, arg)
271272
else
272273
@assert arg isa SSAValue
273-
unsafe_convert_expr = code.code[arg.id]
274+
unsafe_convert_expr = code.code[arg.id]::Expr
274275
push!(delete_idx, arg.id) # delete the unsafe_convert
275276
cconvert_stmt = unsafe_convert_expr.args[3]
276277
push!(delete_idx, cconvert_stmt.id) # delete the cconvert
277-
cconvert_expr = code.code[cconvert_stmt.id]
278+
cconvert_expr = code.code[cconvert_stmt.id]::Expr
278279
push!(args, cconvert_expr.args[3])
279280
end
280281
end
@@ -290,11 +291,11 @@ function build_compiled_call!(stmt::Expr, fcall, code, idx, nargs::Int, sparams:
290291
if idxstart < idx
291292
while true
292293
pc = step_expr!(Compiled(), frame)
293-
pc == idx && break
294+
pc === idx && break
294295
pc === nothing && error("this should never happen")
295296
end
296297
end
297-
cfunc, RetType, ArgType = @lookup(frame, stmt.args[2]), @lookup(frame, stmt.args[3]), @lookup(frame, stmt.args[4])
298+
cfunc, RetType, ArgType = @lookup(frame, stmt.args[2]), @lookup(frame, stmt.args[3]), @lookup(frame, stmt.args[4])::Type{<:Tuple}
298299
args = stmt.args[5:end]
299300
end
300301
dynamic_ccall = false
@@ -320,7 +321,7 @@ function build_compiled_call!(stmt::Expr, fcall, code, idx, nargs::Int, sparams:
320321
argnames = Any[Symbol(:arg, i) for i = 1:nargs]
321322
if f === nothing
322323
if fcall == :ccall
323-
ArgType = Expr(:tuple, [parametric_type_to_expr(t) for t in ArgType]...)
324+
ArgType = Expr(:tuple, Any[parametric_type_to_expr(t) for t in ArgType]...)
324325
end
325326
RetType = parametric_type_to_expr(RetType)
326327
# #285: test whether we can evaluate an type constraints on parametric expressions

src/packagedef.jl

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,15 @@ else
3737
mapany(f, itr) = map!(f, Vector{Any}(undef, length(itr)::Int), itr) # convenient for Expr.args
3838
end
3939

40+
if isdefined(Base, :ntupleany)
41+
const ntupleany = Base.ntupleany
42+
else
43+
@noinline function ntupleany(f, n)
44+
(n >= 0) || throw(ArgumentError(string("tuple length should be ≥ 0, got ", n)))
45+
(Any[f(i) for i = 1:n]...,)
46+
end
47+
end
48+
4049
include("types.jl")
4150
include("utils.jl")
4251
include("construct.jl")

0 commit comments

Comments
 (0)