@@ -15,12 +15,12 @@ For `f(x::AbstractArray{T}) where T`, the corresponding `sigsv` is constructed a
15
15
sig = signature(sigsv)
16
16
"""
17
17
function signature (sigsv:: SimpleVector )
18
- sigp, sigtv = sigsv
18
+ sigp:: SimpleVector , sigtv:: SimpleVector = sigsv
19
19
sig = Tuple{sigp... }
20
20
for i = length (sigtv): - 1 : 1
21
21
sig = UnionAll (sigtv[i], sig)
22
22
end
23
- return sig
23
+ return sig:: Union{DataType,UnionAll}
24
24
end
25
25
26
26
"""
@@ -43,8 +43,8 @@ function signature(@nospecialize(recurse), frame::Frame, @nospecialize(stmt), pc
43
43
while ! isexpr (stmt, :method , 3 ) # wait for the 3-arg version
44
44
if isanonymous_typedef (stmt)
45
45
lastpc = pc = step_through_methoddef (recurse, frame, stmt) # define an anonymous function
46
- elseif isexpr (stmt, :call ) && is_quotenode ( stmt. args[1 ], Core. Typeof) &&
47
- (sym = stmt. args[2 ]; isa (sym, Symbol) && ! isdefined (mod, sym))
46
+ elseif isexpr (stmt, :call ) && (q = ( stmt:: Expr ) . args[1 ]; isa (q, QuoteNode) && q . value === Core. Typeof) &&
47
+ (sym = ( stmt:: Expr ) . args[2 ]; isa (sym, Symbol) && ! isdefined (mod, sym))
48
48
return nothing , pc
49
49
else
50
50
lastpc = pc
@@ -53,6 +53,7 @@ function signature(@nospecialize(recurse), frame::Frame, @nospecialize(stmt), pc
53
53
end
54
54
stmt = pc_expr (frame, pc)
55
55
end
56
+ isa (stmt, Expr) || return nothing , pc
56
57
sigsv = @lookup (frame, stmt. args[2 ]):: SimpleVector
57
58
sigt = signature (sigsv)
58
59
return sigt, lastpc
@@ -105,6 +106,13 @@ mutable struct MethodInfo
105
106
end
106
107
MethodInfo (start) = MethodInfo (start, - 1 , Int[])
107
108
109
+ struct SelfCall
110
+ linetop:: Int
111
+ linebody:: Int
112
+ callee:: Symbol
113
+ caller:: Union{Symbol,Bool}
114
+ end
115
+
108
116
"""
109
117
methodinfos, selfcalls = identify_framemethod_calls(frame)
110
118
@@ -122,21 +130,26 @@ which will correspond to a 3-argument `:method` expression containing a `CodeInf
122
130
function identify_framemethod_calls (frame)
123
131
refs = Pair{Symbol,Int}[]
124
132
methodinfos = Dict {Symbol,MethodInfo} ()
125
- selfcalls = NamedTuple{( :linetop , :linebody , :callee , :caller ),Tuple{Int64,Int64,Symbol,Union{Symbol,Bool}}} []
133
+ selfcalls = SelfCall []
126
134
for (i, stmt) in enumerate (frame. framecode. src. code)
127
- if isexpr (stmt, :global , 1 )
128
- key = stmt. args[1 ]
135
+ isa (stmt, Expr) || continue
136
+ if stmt. head === :global && length (stmt. args) == 1
137
+ key = stmt. args[1 ]:: Symbol
129
138
# We don't know for sure if this is a reference to a method, but let's
130
139
# tentatively cue it
131
140
push! (refs, key=> i)
132
- elseif isexpr ( stmt, :thunk , 1 ) && stmt. args[1 ] isa CodeInfo
141
+ elseif stmt. head === :thunk && stmt. args[1 ] isa CodeInfo
133
142
tsrc = stmt. args[1 ]:: CodeInfo
134
143
if length (tsrc. code) == 1
135
144
tstmt = tsrc. code[1 ]
136
- if isexpr (tstmt, :return , 1 )
137
- tex = tstmt. args[1 ]
138
- if isexpr (tex, :method )
139
- push! (refs, tex. args[1 ]=> i)
145
+ if isa (tstmt, Expr)
146
+ if tstmt. head === :return && length (tstmt. args) == 1
147
+ tex = tstmt. args[1 ]
148
+ if isa (tex, Expr)
149
+ if tex. head === :method && (methname = tex. args[1 ]; isa (methname, Symbol))
150
+ push! (refs, methname=> i)
151
+ end
152
+ end
140
153
end
141
154
end
142
155
end
@@ -158,12 +171,14 @@ function identify_framemethod_calls(frame)
158
171
end
159
172
msrc = stmt. args[3 ]
160
173
if msrc isa CodeInfo
174
+ key = key:: Union{Symbol,Bool}
161
175
for (j, mstmt) in enumerate (msrc. code)
162
- if isexpr (mstmt, :call )
176
+ isa (mstmt, Expr) || continue
177
+ if mstmt. head === :call
163
178
mkey = mstmt. args[1 ]
164
179
if isa (mkey, Symbol)
165
180
# Could be a GlobalRef but then it's outside frame
166
- haskey (methodinfos, mkey) && push! (selfcalls, (linetop = i, linebody = j, callee = mkey, caller = key))
181
+ haskey (methodinfos, mkey) && push! (selfcalls, SelfCall ( i, j, mkey, key))
167
182
elseif is_global_ref (mkey, Core, isdefined (Core, :_apply_iterate ) ? :_apply_iterate : :_apply )
168
183
ssaref = mstmt. args[end - 1 ]
169
184
if isa (ssaref, JuliaInterpreter. SSAValue)
@@ -172,14 +187,16 @@ function identify_framemethod_calls(frame)
172
187
end
173
188
mkey = mstmt. args[end - 2 ]
174
189
if isa (mkey, Symbol)
175
- haskey (methodinfos, mkey) && push! (selfcalls, (linetop = i, linebody = j, callee = mkey, caller = key))
190
+ haskey (methodinfos, mkey) && push! (selfcalls, SelfCall ( i, j, mkey, key))
176
191
end
177
192
end
178
- elseif isexpr ( mstmt, :meta ) && mstmt. args[1 ] == :generated
193
+ elseif mstmt. head === :meta && mstmt. args[1 ] = == :generated
179
194
newex = mstmt. args[2 ]
180
- if isexpr (newex, :new ) && length (newex. args) >= 2 && is_global_ref (newex. args[1 ], Core, :GeneratedFunctionStub )
181
- mkey = newex. args[2 ]:: Symbol
182
- haskey (methodinfos, mkey) && push! (selfcalls, (linetop= i, linebody= j, callee= mkey, caller= key))
195
+ if isa (newex, Expr)
196
+ if newex. head === :new && length (newex. args) >= 2 && is_global_ref (newex. args[1 ], Core, :GeneratedFunctionStub )
197
+ mkey = newex. args[2 ]:: Symbol
198
+ haskey (methodinfos, mkey) && push! (selfcalls, SelfCall (i, j, mkey, key))
199
+ end
183
200
end
184
201
end
185
202
end
@@ -261,7 +278,8 @@ function rename_framemethods!(@nospecialize(recurse), frame::Frame, methodinfos,
261
278
@warn " skipping callee $callee (called by $caller ) due to $err "
262
279
end
263
280
end
264
- for (linetop, linebody, callee, caller) in selfcalls
281
+ for sc in selfcalls
282
+ linetop, linebody, callee, caller = sc. linetop, sc. linebody, sc. callee, sc. caller
265
283
cname = get (replacements, callee, nothing )
266
284
if cname != = nothing && cname != = callee
267
285
replacename! ((src. code[linetop]. args[3 ]):: CodeInfo , callee=> cname)
@@ -315,7 +333,7 @@ function find_corrected_name(@nospecialize(recurse), frame, pc, name, parentname
315
333
if stmt. args[1 ] != = name && isa (body, CodeInfo)
316
334
# This might be the GeneratedFunctionStub for a @generated method
317
335
for (i, bodystmt) in enumerate (body. code)
318
- if isexpr (bodystmt, :meta ) && bodystmt. args[1 ] === :generated
336
+ if isexpr (bodystmt, :meta ) && ( bodystmt:: Expr ) . args[1 ] === :generated
319
337
return signature_top (frame, stmt, pc), true
320
338
end
321
339
i >= 5 && break # we should find this early
@@ -351,11 +369,11 @@ function replacename!(args::Vector{Any}, pr)
351
369
replacename! (a, pr)
352
370
elseif isa (a, CodeInfo)
353
371
replacename! (a. code, pr)
354
- elseif isa (a, QuoteNode) && a. value == oldname
372
+ elseif isa (a, QuoteNode) && a. value === oldname
355
373
args[i] = QuoteNode (newname)
356
374
elseif isa (a, Vector{Any})
357
375
replacename! (a, pr)
358
- elseif a == oldname
376
+ elseif a === oldname
359
377
args[i] = newname
360
378
end
361
379
end
@@ -448,7 +466,7 @@ function methoddef!(@nospecialize(recurse), signatures, frame::Frame, @nospecial
448
466
# guard against busted lookup, e.g., https://github.com/JuliaLang/julia/issues/31112
449
467
code = framecode. src
450
468
codeloc = codelocation (code, pc)
451
- loc = code . linetable[ codeloc]
469
+ loc = linetable (code, codeloc)
452
470
ft = Base. unwrap_unionall (Base. unwrap_unionall (sigt). parameters[1 ])
453
471
if ! startswith (String (ft. name. name), " ##" )
454
472
@warn " file $(loc. file) , line $(loc. line) : no method found for $sigt "
@@ -472,7 +490,7 @@ function methoddef!(@nospecialize(recurse), signatures, frame::Frame, @nospecial
472
490
stmt = pc_expr (frame, pc)
473
491
end
474
492
pc3 = pc
475
- name3 = stmt. args[1 ]
493
+ name3 = ( stmt:: Expr ) . args[1 ]
476
494
sigt === nothing && (error (" expected a signature" ); return next_or_nothing (frame, pc)), pc3
477
495
# Methods like f(x::Ref{<:Real}) that use gensymmed typevars will not have the *exact*
478
496
# signature of the active method. So let's get the active signature.
0 commit comments