Skip to content

Commit ca07ee9

Browse files
authored
Merge pull request #60 from JuliaDebug/teh/startup_latency
Reduce startup latency
2 parents 91cd0db + 1bb4283 commit ca07ee9

File tree

5 files changed

+70
-39
lines changed

5 files changed

+70
-39
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
*.jl.mem
44
expected.out
55
failed.out
6-
src/builtins.jl
6+
src/builtins*.jl
77
deps/build.log
88
docs/build/
99
test/results.md

deps/build.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@ using InteractiveUtils
22

33
const srcpath = joinpath(dirname(@__DIR__), "src")
44
include(joinpath(srcpath, "generate_builtins.jl"))
5-
open(joinpath(srcpath, "builtins.jl"), "w") do io
5+
open(joinpath(srcpath, "builtins-julia$(Int(VERSION.major)).$(Int(VERSION.minor)).jl"), "w") do io
66
generate_builtins(io)
77
end

src/JuliaInterpreter.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ const empty_svec = Core.svec()
142142

143143
include("localmethtable.jl")
144144
include("interpret.jl")
145-
include("builtins.jl")
145+
include("builtins-julia$(Int(VERSION.major)).$(Int(VERSION.minor)).jl")
146146

147147
function show_stackloc(io::IO, stack, frame, pc=frame.pc[])
148148
indent = ""

src/generate_builtins.jl

Lines changed: 66 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,63 @@
11
# This file generates builtins.jl.
22

33
function scopedname(f)
4-
fstr = string(f)
4+
io = IOBuffer()
5+
show(io, f)
6+
fstr = String(take!(io))
57
occursin('.', fstr) && return fstr
68
tn = typeof(f).name
79
Base.isexported(tn.module, Symbol(fstr)) && return fstr
8-
return string(tn.module) * '.' * fstr
10+
fsym = Symbol(fstr)
11+
isdefined(tn.module, fsym) && return string(tn.module) * '.' * fstr
12+
return "Base." * fstr
913
end
1014

11-
# Look up the expected number of arguments in Core.Compiler.tfunc data
12-
function generate_fcall(f, table, id)
15+
function nargs(f, table, id)
16+
# Look up the expected number of arguments in Core.Compiler.tfunc data
1317
if id !== nothing
1418
minarg, maxarg, tfunc = table[id]
1519
else
1620
minarg = 0
1721
maxarg = typemax(Int)
1822
end
19-
# The tfunc tables are wrong for fptoui and fptosi
23+
# The tfunc tables are wrong for fptoui and fptosi (fixed in https://github.com/JuliaLang/julia/pull/30787)
2024
if f == "Base.fptoui" || f == "Base.fptosi"
2125
minarg = 2
2226
end
27+
return minarg, maxarg
28+
end
29+
30+
function generate_fcall_nargs(fname, minarg, maxarg)
2331
# Generate a separate call for each number of arguments
24-
fname = scopedname(f)
25-
if maxarg < typemax(Int)
26-
wrapper = minarg == maxarg ? "" : "if nargs == "
27-
for nargs = minarg:maxarg
28-
if minarg < maxarg
29-
wrapper *= "$nargs\n "
30-
end
31-
argcall = ""
32-
for i = 1:nargs
33-
argcall *= "@lookup(frame, args[$(i+1)])"
34-
if i < nargs
35-
argcall *= ", "
36-
end
37-
end
38-
wrapper *= "return Some{Any}($fname($argcall))"
39-
if nargs < maxarg
40-
wrapper *= "\n elseif nargs == "
32+
maxarg < typemax(Int) || error("call this only for constrained number of arguments")
33+
wrapper = minarg == maxarg ? "" : "if nargs == "
34+
for nargs = minarg:maxarg
35+
if minarg < maxarg
36+
wrapper *= "$nargs\n "
37+
end
38+
argcall = ""
39+
for i = 1:nargs
40+
argcall *= "@lookup(frame, args[$(i+1)])"
41+
if i < nargs
42+
argcall *= ", "
4143
end
4244
end
43-
if minarg < maxarg
44-
wrapper *= "\n end"
45+
wrapper *= "return Some{Any}($fname($argcall))"
46+
if nargs < maxarg
47+
wrapper *= "\n elseif nargs == "
4548
end
46-
return wrapper
49+
end
50+
if minarg < maxarg
51+
wrapper *= "\n end"
52+
end
53+
return wrapper
54+
end
55+
56+
function generate_fcall(f, table, id)
57+
minarg, maxarg = nargs(f, table, id)
58+
fname = scopedname(f)
59+
if maxarg < typemax(Int)
60+
return generate_fcall_nargs(fname, minarg, maxarg)
4761
end
4862
# A built-in with arbitrary or unknown number of arguments.
4963
# This will (unfortunately) use dynamic dispatch.
@@ -124,13 +138,7 @@ function maybe_evaluate_builtin(frame, call_expr)
124138
"""
125139
# Intrinsics
126140
""")
127-
for fsym in names(Core.Intrinsics)
128-
fsym == :Intrinsics && continue
129-
isdefined(Base, fsym) || (println("skipping ", fname); continue)
130-
f = getfield(Base, fsym)
131-
f isa Core.IntrinsicFunction || error("not an intrinsic")
132-
if f == cglobal
133-
print(io,
141+
print(io,
134142
"""
135143
elseif f === Base.cglobal
136144
if nargs == 1
@@ -141,18 +149,40 @@ function maybe_evaluate_builtin(frame, call_expr)
141149
return Some{Any}(Core.eval(moduleof(frame), call_expr))
142150
end
143151
""")
144-
continue
152+
# Extract any intrinsics that support varargs
153+
fva = []
154+
minmin, maxmax = typemax(Int), 0
155+
for fsym in names(Core.Intrinsics)
156+
fsym == :Intrinsics && continue
157+
isdefined(Base, fsym) || continue
158+
f = getfield(Base, fsym)
159+
id = reinterpret(Int32, f) + 1
160+
minarg, maxarg = nargs(f, Core.Compiler.T_IFUNC, id)
161+
if maxarg == typemax(Int)
162+
push!(fva, f)
163+
else
164+
minmin = min(minmin, minarg)
165+
maxmax = max(maxmax, maxarg)
145166
end
167+
end
168+
for f in fva
146169
id = reinterpret(Int32, f) + 1
147-
f = isdefined(Base, fsym) ? "Base.$fsym" :
148-
isdefined(Core, fsym) ? "Core.$fsym" : error("whoops on $f")
170+
fname = scopedname(f)
149171
fcall = generate_fcall(f, Core.Compiler.T_IFUNC, id)
150172
print(io,
151173
"""
152-
elseif f === $f
174+
elseif f === $fname
153175
$fcall
176+
end
154177
""")
155178
end
179+
# Now handle calls with bounded numbers of args
180+
fcall = generate_fcall_nargs("f", minmin, maxmax)
181+
print(io,
182+
"""
183+
if isa(f, Core.IntrinsicFunction)
184+
$fcall
185+
""")
156186
print(io,
157187
"""
158188
end

src/precompile.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ function _precompile_()
2828
precompile(Tuple{typeof(prepare_locals), JuliaFrameCode, Vector{Any}})
2929
precompile(Tuple{typeof(prepare_args), Any, Vector{Any}, Vector{Any}})
3030
precompile(Tuple{typeof(prepare_call), Any, Vector{Any}})
31+
precompile(Tuple{typeof(Core.kwfunc(prepare_call)), NamedTuple{(:enter_generated,),Tuple{Bool}}, typeof(JuliaInterpreter.prepare_call), Function, Vector{Any}})
3132
precompile(Tuple{typeof(build_frame), JuliaFrameCode, Vector{Any}, Core.SimpleVector})
3233
precompile(Tuple{typeof(extract_args), Module, Expr})
3334
precompile(Tuple{typeof(enter_call), Int, Int})

0 commit comments

Comments
 (0)