Skip to content

Commit 4a704d2

Browse files
committed
also cache calls that end up getting compiled in local method table
1 parent 96e0194 commit 4a704d2

File tree

3 files changed

+33
-14
lines changed

3 files changed

+33
-14
lines changed

src/construct.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ function prepare_call(@nospecialize(f), allargs; enter_generated = false)
248248
# The generator threw an error. Let's generate the same error by calling it.
249249
f(allargs[2:end]...)
250250
end
251-
isa(ret, Compiled) && return ret
251+
isa(ret, Compiled) && return ret, argtypes
252252
# Typical return
253253
framecode, lenv = ret
254254
if is_generated(method) && enter_generated
@@ -543,7 +543,7 @@ See [`enter_call`](@ref) for a similar approach not based on expressions.
543543
function enter_call_expr(expr; enter_generated = false)
544544
clear_caches()
545545
r = determine_method_for_expr(expr; enter_generated = enter_generated)
546-
if isa(r, Tuple)
546+
if r !== nothing && !isa(r[1], Compiled)
547547
return prepare_frame(r[1:end-1]...)
548548
end
549549
nothing
@@ -597,7 +597,7 @@ function enter_call(@nospecialize(finfo), @nospecialize(args...); kwargs...)
597597
error(f, " is a builtin or intrinsic")
598598
end
599599
r = prepare_call(f, allargs; enter_generated=enter_generated)
600-
if isa(r, Tuple)
600+
if r !== nothing && !isa(r[1], Compiled)
601601
return prepare_frame(r[1:end-1]...)
602602
end
603603
return nothing

src/localmethtable.jl

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ function get_call_framecode(fargs::Vector{Any}, parentframe::FrameCode, idx::Int
1111
nargs = length(fargs) # includes f as the first "argument"
1212
# Determine whether we can look up the appropriate framecode in the local method table
1313
if isassigned(parentframe.methodtables, idx) # if this is the first call, this may not yet be set
14+
# The case where `methodtables[idx]` is a `Compiled` has already been handled in `bypass_builtins`
1415
d_meth = d_meth1 = parentframe.methodtables[idx]::DispatchableMethod
1516
local d_methprev
1617
depth = 1
@@ -20,8 +21,12 @@ function get_call_framecode(fargs::Vector{Any}, parentframe::FrameCode, idx::Int
2021
sig = d_meth.sig.parameters::SimpleVector
2122
if length(sig) == nargs
2223
# If this is generated, match only if `enter_generated` also matches
23-
fi = d_meth.frameinstance::FrameInstance
24-
matches = !is_generated(scopeof(fi.framecode)) || enter_generated == fi.enter_generated
24+
fi = d_meth.frameinstance
25+
if fi isa FrameInstance
26+
matches = !is_generated(scopeof(fi.framecode)) || enter_generated == fi.enter_generated
27+
else
28+
matches = !enter_generated
29+
end
2530
if matches
2631
for i = 1:nargs
2732
if !isa(fargs[i], sig[i])
@@ -38,7 +43,11 @@ function get_call_framecode(fargs::Vector{Any}, parentframe::FrameCode, idx::Int
3843
d_methprev.next = d_meth.next
3944
d_meth.next = d_meth1
4045
end
41-
return fi.framecode, fi.sparam_vals
46+
if fi isa Compiled
47+
return Compiled(), nothing
48+
else
49+
return fi.framecode, fi.sparam_vals
50+
end
4251
end
4352
end
4453
depth += 1
@@ -52,11 +61,16 @@ function get_call_framecode(fargs::Vector{Any}, parentframe::FrameCode, idx::Int
5261
fargs[1] = f = to_function(fargs[1])
5362
ret = prepare_call(f, fargs; enter_generated=enter_generated)
5463
ret === nothing && return f(fargs[2:end]...), nothing
55-
isa(ret, Compiled) && return ret, nothing
56-
framecode, args, env, argtypes = ret
57-
# Store the results of the method lookup in the local method table
58-
fi = FrameInstance(framecode, env, is_generated(scopeof(framecode)) && enter_generated)
59-
d_meth = DispatchableMethod(nothing, fi, argtypes)
64+
is_compiled = isa(ret[1], Compiled)
65+
local framecode
66+
if is_compiled
67+
d_meth = DispatchableMethod(nothing, Compiled(), ret[2])
68+
else
69+
framecode, args, env, argtypes = ret
70+
# Store the results of the method lookup in the local method table
71+
fi = FrameInstance(framecode, env, is_generated(scopeof(framecode)) && enter_generated)
72+
d_meth = DispatchableMethod(nothing, fi, argtypes)
73+
end
6074
if isassigned(parentframe.methodtables, idx)
6175
d_meth.next = parentframe.methodtables[idx]
6276
# Drop the oldest d_meth, if necessary
@@ -74,5 +88,9 @@ function get_call_framecode(fargs::Vector{Any}, parentframe::FrameCode, idx::Int
7488
d_meth.next = nothing
7589
end
7690
parentframe.methodtables[idx] = d_meth
77-
return framecode, env
91+
if is_compiled
92+
return Compiled(), nothing
93+
else
94+
return framecode, env
95+
end
7896
end

src/types.jl

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,10 @@ function breakpointchar(bps::BreakpointState)
5353
return bps.condition === falsecondition ? ' ' : 'd' # no breakpoint : disabled
5454
end
5555

56+
abstract type AbstractFrameInstance end
5657
mutable struct DispatchableMethod
5758
next::Union{Nothing,DispatchableMethod} # linked-list representation
58-
frameinstance::Any # really a FrameInstance but we have a cyclic dependency
59+
frameinstance::Union{Compiled, AbstractFrameInstance} # really a Union{Compiled, FrameInstance} but we have a cyclic dependency
5960
sig::Type # for speed of matching, this is a *concrete* signature. `sig <: frameinstance.framecode.scope.sig`
6061
end
6162

@@ -124,7 +125,7 @@ Fields:
124125
- `framecode`: the [`FrameCode`](@ref) for the method.
125126
- `sparam_vals`: the static parameter values for the method.
126127
"""
127-
struct FrameInstance
128+
struct FrameInstance <: AbstractFrameInstance
128129
framecode::FrameCode
129130
sparam_vals::SimpleVector
130131
enter_generated::Bool

0 commit comments

Comments
 (0)