Skip to content

Commit f09fc63

Browse files
authored
check in the builtins file (#275)
* check in the builtins file * tweak @static usage
1 parent 54bb086 commit f09fc63

File tree

4 files changed

+235
-13
lines changed

4 files changed

+235
-13
lines changed

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
*.jl.cov
22
*.jl.*.cov
33
*.jl.mem
4-
src/builtins*.jl
54
deps/build.log
65
docs/build/
76
test/results.md

src/generate_builtins.jl renamed to bin/generate_builtins.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,4 +236,4 @@ end
236236
""")
237237
end
238238

239-
generate_builtins(joinpath(@__DIR__, "builtins-julia$(Int(VERSION.major)).$(Int(VERSION.minor)).jl"))
239+
generate_builtins(joinpath(@__DIR__, "..", "src", "builtins.jl"))

src/JuliaInterpreter.jl

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,6 @@ module CompiledCalls
2121
# This module is for handling intrinsics that must be compiled (llvmcall)
2222
end
2323

24-
const BUILTIN_FILE = joinpath(@__DIR__, "builtins-julia$(Int(VERSION.major)).$(Int(VERSION.minor)).jl")
25-
26-
@info "Generating builtins for this julia version..."
27-
gen_builtins_file = joinpath(@__DIR__, "generate_builtins.jl")
28-
# Run as separate command to prevent including the generate_builtins into the precompile cache
29-
withenv("JULIA_LOAD_PATH" => joinpath(@__DIR__, "..")) do
30-
run(`$(Base.julia_cmd()) --startup-file=no $gen_builtins_file`)
31-
end
32-
include_dependency(gen_builtins_file)
33-
3424
# "Backport" of https://github.com/JuliaLang/julia/pull/31536
3525
if VERSION < v"1.2.0-DEV.572"
3626
Base.convert(::Type{Some{T}}, x::Some{T}) where {T} = x
@@ -43,7 +33,7 @@ include("utils.jl")
4333
include("construct.jl")
4434
include("localmethtable.jl")
4535
include("interpret.jl")
46-
include(BUILTIN_FILE)
36+
include("builtins.jl")
4737
include("optimize.jl")
4838
include("commands.jl")
4939
include("breakpoints.jl")

src/builtins.jl

Lines changed: 233 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,233 @@
1+
# This file is mostly generated by `generate_builtins.jl` with some additional @static checks
2+
# for recently added builtins.
3+
4+
function getargs(args, frame)
5+
nargs = length(args)-1 # skip f
6+
callargs = resize!(frame.framedata.callargs, nargs)
7+
for i = 1:nargs
8+
callargs[i] = @lookup(frame, args[i+1])
9+
end
10+
return callargs
11+
end
12+
13+
"""
14+
ret = maybe_evaluate_builtin(frame, call_expr, expand::Bool)
15+
16+
If `call_expr` is to a builtin function, evaluate it, returning the result inside a `Some` wrapper.
17+
Otherwise, return `call_expr`.
18+
19+
If `expand` is true, `Core._apply` calls will be resolved as a call to the applied function.
20+
"""
21+
function maybe_evaluate_builtin(frame, call_expr, expand::Bool)
22+
# By having each call appearing statically in the "switch" block below,
23+
# each gets call-site optimized.
24+
args = call_expr.args
25+
nargs = length(args) - 1
26+
fex = args[1]
27+
if isa(fex, QuoteNode)
28+
f = fex.value
29+
else
30+
f = @lookup(frame, fex)
31+
end
32+
# Builtins and intrinsics have empty method tables. We can circumvent
33+
# a long "switch" check by looking for this.
34+
mt = typeof(f).name.mt
35+
if isa(mt, Core.MethodTable)
36+
isempty(mt) || return call_expr
37+
end
38+
# Builtins
39+
if f === <:
40+
if nargs == 2
41+
return Some{Any}(<:(@lookup(frame, args[2]), @lookup(frame, args[3])))
42+
else
43+
return Some{Any}(<:(getargs(args, frame)...))
44+
end
45+
elseif f === ===
46+
if nargs == 2
47+
return Some{Any}(===(@lookup(frame, args[2]), @lookup(frame, args[3])))
48+
else
49+
return Some{Any}(===(getargs(args, frame)...))
50+
end
51+
elseif f === Core._apply
52+
argswrapped = getargs(args, frame)
53+
if !expand
54+
return Some{Any}(Core._apply(argswrapped...))
55+
end
56+
new_expr = Expr(:call, argswrapped[1])
57+
popfirst!(argswrapped)
58+
argsflat = Base.append_any(argswrapped...)
59+
for x in argsflat
60+
push!(new_expr.args, (isa(x, Symbol) || isa(x, Expr) || isa(x, QuoteNode)) ? QuoteNode(x) : x)
61+
end
62+
return new_expr
63+
elseif f === Core._apply_latest
64+
argswrapped = getargs(args, frame)
65+
if !expand
66+
return Some{Any}(Core._apply_latest(argswrapped...))
67+
end
68+
new_expr = Expr(:call, argswrapped[1])
69+
popfirst!(argswrapped)
70+
argsflat = Base.append_any(argswrapped...)
71+
for x in argsflat
72+
push!(new_expr.args, (isa(x, Symbol) || isa(x, Expr) || isa(x, QuoteNode)) ? QuoteNode(x) : x)
73+
end
74+
return new_expr
75+
elseif f === Core._apply_pure
76+
return Some{Any}(Core._apply_pure(getargs(args, frame)...))
77+
elseif f === Core._expr
78+
return Some{Any}(Core._expr(getargs(args, frame)...))
79+
elseif @static isdefined(Core, :_typevar) ? f === Core._typevar : false
80+
if nargs == 3
81+
return Some{Any}(Core._typevar(@lookup(frame, args[2]), @lookup(frame, args[3]), @lookup(frame, args[4])))
82+
else
83+
return Some{Any}(Core._typevar(getargs(args, frame)...))
84+
end
85+
elseif f === Core.apply_type
86+
return Some{Any}(Core.apply_type(getargs(args, frame)...))
87+
elseif f === Core.arrayref
88+
if nargs == 0
89+
return Some{Any}(Core.arrayref())
90+
elseif nargs == 1
91+
return Some{Any}(Core.arrayref(@lookup(frame, args[2])))
92+
elseif nargs == 2
93+
return Some{Any}(Core.arrayref(@lookup(frame, args[2]), @lookup(frame, args[3])))
94+
elseif nargs == 3
95+
return Some{Any}(Core.arrayref(@lookup(frame, args[2]), @lookup(frame, args[3]), @lookup(frame, args[4])))
96+
elseif nargs == 4
97+
return Some{Any}(Core.arrayref(@lookup(frame, args[2]), @lookup(frame, args[3]), @lookup(frame, args[4]), @lookup(frame, args[5])))
98+
elseif nargs == 5
99+
return Some{Any}(Core.arrayref(@lookup(frame, args[2]), @lookup(frame, args[3]), @lookup(frame, args[4]), @lookup(frame, args[5]), @lookup(frame, args[6])))
100+
else
101+
return Some{Any}(Core.arrayref(getargs(args, frame)...))
102+
end
103+
elseif f === Core.arrayset
104+
if nargs == 0
105+
return Some{Any}(Core.arrayset())
106+
elseif nargs == 1
107+
return Some{Any}(Core.arrayset(@lookup(frame, args[2])))
108+
elseif nargs == 2
109+
return Some{Any}(Core.arrayset(@lookup(frame, args[2]), @lookup(frame, args[3])))
110+
elseif nargs == 3
111+
return Some{Any}(Core.arrayset(@lookup(frame, args[2]), @lookup(frame, args[3]), @lookup(frame, args[4])))
112+
elseif nargs == 4
113+
return Some{Any}(Core.arrayset(@lookup(frame, args[2]), @lookup(frame, args[3]), @lookup(frame, args[4]), @lookup(frame, args[5])))
114+
elseif nargs == 5
115+
return Some{Any}(Core.arrayset(@lookup(frame, args[2]), @lookup(frame, args[3]), @lookup(frame, args[4]), @lookup(frame, args[5]), @lookup(frame, args[6])))
116+
elseif nargs == 6
117+
return Some{Any}(Core.arrayset(@lookup(frame, args[2]), @lookup(frame, args[3]), @lookup(frame, args[4]), @lookup(frame, args[5]), @lookup(frame, args[6]), @lookup(frame, args[7])))
118+
else
119+
return Some{Any}(Core.arrayset(getargs(args, frame)...))
120+
end
121+
elseif f === Core.arraysize
122+
if nargs == 2
123+
return Some{Any}(Core.arraysize(@lookup(frame, args[2]), @lookup(frame, args[3])))
124+
else
125+
return Some{Any}(Core.arraysize(getargs(args, frame)...))
126+
end
127+
elseif @static isdefined(Core, :const_arrayref) ? f === Core.const_arrayref : false
128+
return Some{Any}(Core.const_arrayref(getargs(args, frame)...))
129+
elseif f === Core.sizeof
130+
if nargs == 1
131+
return Some{Any}(Core.sizeof(@lookup(frame, args[2])))
132+
else
133+
return Some{Any}(Core.sizeof(getargs(args, frame)...))
134+
end
135+
elseif f === Core.svec
136+
return Some{Any}(Core.svec(getargs(args, frame)...))
137+
elseif f === applicable
138+
return Some{Any}(applicable(getargs(args, frame)...))
139+
elseif f === fieldtype
140+
if nargs == 2
141+
return Some{Any}(fieldtype(@lookup(frame, args[2]), @lookup(frame, args[3])))
142+
elseif nargs == 3
143+
return Some{Any}(fieldtype(@lookup(frame, args[2]), @lookup(frame, args[3]), @lookup(frame, args[4])))
144+
else
145+
return Some{Any}(fieldtype(getargs(args, frame)...))
146+
end
147+
elseif f === getfield
148+
if nargs == 2
149+
return Some{Any}(getfield(@lookup(frame, args[2]), @lookup(frame, args[3])))
150+
elseif nargs == 3
151+
return Some{Any}(getfield(@lookup(frame, args[2]), @lookup(frame, args[3]), @lookup(frame, args[4])))
152+
else
153+
return Some{Any}(getfield(getargs(args, frame)...))
154+
end
155+
elseif f === ifelse
156+
if nargs == 3
157+
return Some{Any}(ifelse(@lookup(frame, args[2]), @lookup(frame, args[3]), @lookup(frame, args[4])))
158+
else
159+
return Some{Any}(ifelse(getargs(args, frame)...))
160+
end
161+
elseif f === invoke
162+
argswrapped = getargs(args, frame)
163+
if !expand
164+
return Some{Any}(invoke(argswrapped...))
165+
end
166+
return Expr(:call, invoke, argswrapped...)
167+
elseif f === isa
168+
if nargs == 2
169+
return Some{Any}(isa(@lookup(frame, args[2]), @lookup(frame, args[3])))
170+
else
171+
return Some{Any}(isa(getargs(args, frame)...))
172+
end
173+
elseif f === isdefined
174+
if nargs == 1
175+
return Some{Any}(isdefined(@lookup(frame, args[2])))
176+
elseif nargs == 2
177+
return Some{Any}(isdefined(@lookup(frame, args[2]), @lookup(frame, args[3])))
178+
else
179+
return Some{Any}(isdefined(getargs(args, frame)...))
180+
end
181+
elseif f === nfields
182+
if nargs == 1
183+
return Some{Any}(nfields(@lookup(frame, args[2])))
184+
else
185+
return Some{Any}(nfields(getargs(args, frame)...))
186+
end
187+
elseif f === setfield!
188+
if nargs == 3
189+
return Some{Any}(setfield!(@lookup(frame, args[2]), @lookup(frame, args[3]), @lookup(frame, args[4])))
190+
else
191+
return Some{Any}(setfield!(getargs(args, frame)...))
192+
end
193+
elseif f === throw
194+
if nargs == 1
195+
return Some{Any}(throw(@lookup(frame, args[2])))
196+
else
197+
return Some{Any}(throw(getargs(args, frame)...))
198+
end
199+
elseif f === tuple
200+
return Some{Any}(ntuple(i->@lookup(frame, args[i+1]), length(args)-1))
201+
elseif f === typeassert
202+
if nargs == 2
203+
return Some{Any}(typeassert(@lookup(frame, args[2]), @lookup(frame, args[3])))
204+
else
205+
return Some{Any}(typeassert(getargs(args, frame)...))
206+
end
207+
elseif f === typeof
208+
if nargs == 1
209+
return Some{Any}(typeof(@lookup(frame, args[2])))
210+
else
211+
return Some{Any}(typeof(getargs(args, frame)...))
212+
end
213+
# Intrinsics
214+
elseif f === Base.cglobal
215+
if nargs == 1
216+
return Some{Any}(Core.eval(moduleof(frame), call_expr))
217+
elseif nargs == 2
218+
call_expr = copy(call_expr)
219+
call_expr.args[3] = @lookup(frame, args[3])
220+
return Some{Any}(Core.eval(moduleof(frame), call_expr))
221+
end
222+
elseif f === Base.llvmcall
223+
return Some{Any}(Base.llvmcall(getargs(args, frame)...))
224+
end
225+
if isa(f, Core.IntrinsicFunction)
226+
cargs = getargs(args, frame)
227+
return Some{Any}(ccall(:jl_f_intrinsic_call, Any, (Any, Ptr{Any}, UInt32), f, cargs, length(cargs)))
228+
end
229+
if isa(f, getfield(Core, Symbol("#kw##invoke")))
230+
return Some{Any}(getfield(Core, Symbol("#kw##invoke"))(getargs(args, frame)...))
231+
end
232+
return call_expr
233+
end

0 commit comments

Comments
 (0)