Skip to content

Commit 958bd73

Browse files
authored
proper support for interpreting opaque closures (#593)
* proper support for interpreting opaque closures * correctly handle `getfield` on #self# * don't error on older versions * move oc -> oc.captures transform to prepare_frame * don't interpret inferred * remove diffractor test
1 parent f3a34a3 commit 958bd73

File tree

4 files changed

+40
-9
lines changed

4 files changed

+40
-9
lines changed

bin/generate_builtins.jl

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -132,10 +132,15 @@ function maybe_evaluate_builtin(frame, call_expr, expand::Bool)
132132
f = @lookup(frame, fex)
133133
end
134134
135-
@static if isdefined(Core, :OpaqueClosure)
136-
if f isa Core.OpaqueClosure
137-
return Some{Any}(f(args...))
135+
if @static isdefined(Core, :OpaqueClosure) && f isa Core.OpaqueClosure
136+
if expand
137+
if !Core.Compiler.uncompressed_ir(f.source).inferred
138+
return Expr(:call, f, args[2:end]...)
139+
else
140+
@debug "not interpreting opaque closure \$f since it contains inferred code"
141+
end
138142
end
143+
return Some{Any}(f(args...))
139144
end
140145
if !(isa(f, Core.Builtin) || isa(f, Core.IntrinsicFunction))
141146
return call_expr

src/builtins.jl

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,15 @@ function maybe_evaluate_builtin(frame, call_expr, expand::Bool)
3838
f = @lookup(frame, fex)
3939
end
4040

41-
@static if isdefined(Core, :OpaqueClosure)
42-
if f isa Core.OpaqueClosure
43-
return Some{Any}(f(args...))
41+
if @static isdefined(Core, :OpaqueClosure) && f isa Core.OpaqueClosure
42+
if expand
43+
if !Core.Compiler.uncompressed_ir(f.source).inferred
44+
return Expr(:call, f, args[2:end]...)
45+
else
46+
@debug "not interpreting opaque closure $f since it contains inferred code"
47+
end
4448
end
49+
return Some{Any}(f(args...))
4550
end
4651
if !(isa(f, Core.Builtin) || isa(f, Core.IntrinsicFunction))
4752
return call_expr

src/construct.jl

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,16 @@ function prepare_call(@nospecialize(f), allargs; enter_generated = false)
241241
end
242242
argtypesv = Any[_Typeof(a) for a in allargs]
243243
argtypes = Tuple{argtypesv...}
244-
method = whichtt(argtypes)
244+
if @static isdefined(Core, :OpaqueClosure) && f isa Core.OpaqueClosure
245+
method = f.source
246+
# don't try to interpret optimized ir
247+
if Core.Compiler.uncompressed_ir(method).inferred
248+
@debug "not interpreting opaque closure $f since it contains inferred code"
249+
return nothing
250+
end
251+
else
252+
method = whichtt(argtypes)
253+
end
245254
if method === nothing
246255
# Call it to generate the exact error
247256
return f(allargs[2:end]...)
@@ -298,7 +307,10 @@ function prepare_framedata(framecode, argvals::Vector{Any}, lenv::SimpleVector=e
298307
nargs, meth_nargs = length(argvals), Int(meth.nargs)
299308
islastva = meth.isva && nargs >= meth_nargs
300309
for i = 1:meth_nargs-islastva
301-
if nargs >= i
310+
# for OCs #self# actually refers to the captures instead
311+
if @static isdefined(Core, :OpaqueClosure) && i == 1 && (oc = argvals[1]) isa Core.OpaqueClosure
312+
locals[i], last_reference[i] = Some{Any}(oc.captures), 1
313+
elseif i <= nargs
302314
locals[i], last_reference[i] = Some{Any}(argvals[i]), 1
303315
else
304316
locals[i] = Some{Any}(())

test/interpret.jl

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -944,7 +944,16 @@ end
944944
@test @interpret foo_536(UInt8('A'))
945945

946946
@static if isdefined(Base.Experimental, Symbol("@opaque"))
947-
@test @interpret (Base.Experimental.@opaque x->3*x)(4) == 12
947+
@testset "opaque closures" begin
948+
g(x) = 3x
949+
f = Base.Experimental.@opaque x -> g(x)
950+
@test @interpret f(4) == 12
951+
952+
# test stepping into opaque closures
953+
@breakpoint g(1)
954+
fr = JuliaInterpreter.enter_call_expr(Expr(:call, f, 4))
955+
@test JuliaInterpreter.finish_and_return!(fr) isa JuliaInterpreter.BreakpointRef
956+
end
948957
end
949958

950959
# CassetteOverlay, issue #552

0 commit comments

Comments
 (0)