Skip to content

Commit 117a11f

Browse files
committed
use our own struct for the local method table instead of TypeMapEntry
1 parent 0c1189b commit 117a11f

File tree

4 files changed

+35
-38
lines changed

4 files changed

+35
-38
lines changed

src/JuliaInterpreter.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ module JuliaInterpreter
22

33
using Base.Meta
44
import Base: +, -, convert, isless
5-
using Core: CodeInfo, TypeMapEntry, SimpleVector, LineInfoNode, GotoNode, Slot,
5+
using Core: CodeInfo, SimpleVector, LineInfoNode, GotoNode, Slot,
66
GeneratedFunctionStub, MethodInstance, NewvarNode, TypeName
77

88
using UUIDs

src/localmethtable.jl

Lines changed: 23 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,17 @@ 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-
tme = tme1 = parentframe.methodtables[idx]::TypeMapEntry
15-
local tmeprev
14+
d_meth = d_meth1 = parentframe.methodtables[idx]::DispatchableMethod
15+
local d_methprev
1616
depth = 1
1717
while true
1818
# TODO: consider using world age bounds to handle cache invalidation
1919
# Determine whether the argument types match the signature
20-
sig = tme.sig.parameters::SimpleVector
20+
sig = d_meth.sig.parameters::SimpleVector
2121
if length(sig) == nargs
2222
# If this is generated, match only if `enter_generated` also matches
23-
mi = tme.func::FrameInstance
24-
matches = !is_generated(scopeof(mi.framecode)) || enter_generated == mi.enter_generated
23+
fi = d_meth.frameinstance::FrameInstance
24+
matches = !is_generated(scopeof(fi.framecode)) || enter_generated == mi.enter_generated
2525
if matches
2626
for i = 1:nargs
2727
if !isa(fargs[i], sig[i])
@@ -34,18 +34,18 @@ function get_call_framecode(fargs::Vector{Any}, parentframe::FrameCode, idx::Int
3434
# Rearrange the list to place this method first
3535
# (if we're in a loop, we'll likely match this one again on the next iteration)
3636
if depth > 1
37-
parentframe.methodtables[idx] = tme
38-
tmeprev.next = tme.next
39-
tme.next = tme1
37+
parentframe.methodtables[idx] = d_meth
38+
d_methprev.next = d_meth.next
39+
d_meth.next = d_meth1
4040
end
41-
return mi.framecode, mi.sparam_vals
41+
return fi.framecode, fi.sparam_vals
4242
end
4343
end
4444
depth += 1
45-
tmeprev = tme
46-
tme = tme.next
47-
tme === nothing && break
48-
tme = tme::TypeMapEntry
45+
d_methprev = d_meth
46+
d_meth = d_meth.next
47+
d_meth === nothing && break
48+
d_meth = d_meth::DispatchableMethod
4949
end
5050
end
5151
# We haven't yet encountered this argtype combination and need to look it up by dispatch
@@ -55,33 +55,24 @@ function get_call_framecode(fargs::Vector{Any}, parentframe::FrameCode, idx::Int
5555
isa(ret, Compiled) && return ret, nothing
5656
framecode, args, env, argtypes = ret
5757
# Store the results of the method lookup in the local method table
58-
mi = FrameInstance(framecode, env, is_generated(scopeof(framecode)) & enter_generated)
59-
# it's sort of odd to call this a TypeMapEntry, then set most of the fields incorrectly
60-
# but since we're just using it as a linked list, it's probably ok
61-
tme = ccall(:jl_new_struct_uninit, Any, (Any,), TypeMapEntry)::TypeMapEntry
62-
tme.func = mi
63-
tme.simplesig = nothing
64-
tme.sig = argtypes
65-
tme.isleafsig = true
66-
tme.issimplesig = false
67-
method = framecode.scope::Method
68-
tme.va = method.isva
58+
fi = FrameInstance(framecode, env, is_generated(scopeof(framecode)) && enter_generated)
59+
d_meth = DispatchableMethod(nothing, fi, argtypes)
6960
if isassigned(parentframe.methodtables, idx)
70-
tme.next = parentframe.methodtables[idx]
71-
# Drop the oldest tme, if necessary
72-
tmetmp = tme.next
61+
d_meth.next = parentframe.methodtables[idx]
62+
# Drop the oldest d_meth, if necessary
63+
d_methtmp = d_meth.next
7364
depth = 2
74-
while isdefined(tmetmp, :next) && tmetmp.next !== nothing
65+
while d_methtmp.next !== nothing
7566
depth += 1
76-
tmetmp = tmetmp.next
67+
d_methtmp = d_methtmp.next
7768
depth >= max_methods && break
7869
end
7970
if depth >= max_methods
80-
tmetmp.next = nothing
71+
d_methtmp.next = nothing
8172
end
8273
else
83-
tme.next = nothing
74+
d_meth.next = nothing
8475
end
85-
parentframe.methodtables[idx] = tme
76+
parentframe.methodtables[idx] = d_meth
8677
return framecode, env
8778
end

src/optimize.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ function optimize!(code::CodeInfo, scope)
232232
code.ssavaluetypes = length(new_code)
233233

234234
# Insert the foreigncall wrappers at the updated idxs
235-
methodtables = Vector{Union{Compiled,TypeMapEntry}}(undef, length(code.code))
235+
methodtables = Vector{Union{Compiled,DispatchableMethod}}(undef, length(code.code))
236236
for idx in foreigncalls_idx
237237
methodtables[ssalookup[idx]] = Compiled()
238238
end

src/types.jl

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

56+
mutable struct DispatchableMethod
57+
next::Union{Nothing,DispatchableMethod} # linked-list representation
58+
frameinstance::Any # really a FrameInstance but we have a cyclic dependency
59+
sig::Type # for speed of matching, this is a *concrete* signature. `sig <: frameinstance.framecode.scope.sig`
60+
end
61+
5662
"""
5763
`FrameCode` holds static information about a method or toplevel code.
5864
One `FrameCode` can be shared by many calling `Frame`s.
@@ -68,7 +74,7 @@ Important fields:
6874
struct FrameCode
6975
scope::Union{Method,Module}
7076
src::CodeInfo
71-
methodtables::Vector{Union{Compiled,TypeMapEntry}} # line-by-line method tables for generic-function :call Exprs
77+
methodtables::Vector{Union{Compiled,DispatchableMethod}} # line-by-line method tables for generic-function :call Exprs
7278
breakpoints::Vector{BreakpointState}
7379
used::BitSet
7480
generator::Bool # true if this is for the expression-generator of a @generated function
@@ -80,7 +86,7 @@ function FrameCode(scope, src::CodeInfo; generator=false, optimize=true)
8086
src, methodtables = optimize!(copy_codeinfo(src), scope)
8187
else
8288
src = replace_coretypes!(copy_codeinfo(src))
83-
methodtables = Vector{Union{Compiled,TypeMapEntry}}(undef, length(src.code))
89+
methodtables = Vector{Union{Compiled,DispatchableMethod}}(undef, length(src.code))
8490
end
8591
breakpoints = Vector{BreakpointState}(undef, length(src.code))
8692
for (i, pc_expr) in enumerate(src.code)
@@ -331,7 +337,7 @@ struct BreakpointSignature <: AbstractBreakpoint
331337
enabled::Ref{Bool}
332338
instances::Vector{BreakpointRef}
333339
end
334-
same_location(bp2::BreakpointSignature, bp::BreakpointSignature) =
340+
same_location(bp2::BreakpointSignature, bp::BreakpointSignature) =
335341
bp2.f == bp.f && bp2.sig == bp.sig && bp2.line == bp.line
336342
function Base.show(io::IO, bp::BreakpointSignature)
337343
print(io, bp.f)
@@ -369,7 +375,7 @@ struct BreakpointFileLocation <: AbstractBreakpoint
369375
enabled::Ref{Bool}
370376
instances::Vector{BreakpointRef}
371377
end
372-
same_location(bp2::BreakpointFileLocation, bp::BreakpointFileLocation) =
378+
same_location(bp2::BreakpointFileLocation, bp::BreakpointFileLocation) =
373379
bp2.path == bp.path && bp2.abspath == bp.abspath && bp2.line == bp.line
374380
function Base.show(io::IO, bp::BreakpointFileLocation)
375381
print(io, bp.path, ':', bp.line)

0 commit comments

Comments
 (0)