@@ -24,6 +24,7 @@ add_dependencies!(methodinfo::MethodInfo, be::CodeEdges, src, isrequired) = meth
24
24
add_includes! (methodinfo:: MethodInfo , mod:: Module , filename) = methodinfo
25
25
26
26
function is_some_include (@nospecialize (f))
27
+ @assert ! isa (f, Core. SSAValue) && ! isa (f, JuliaInterpreter. SSAValue)
27
28
if isa (f, GlobalRef)
28
29
return f. name === :include
29
30
elseif isa (f, Symbol)
@@ -44,17 +45,21 @@ function is_some_include(@nospecialize(f))
44
45
end
45
46
46
47
# This is not generally used, see `is_method_or_eval` instead
47
- function hastrackedexpr (stmt; heads= LoweredCodeUtils. trackedheads)
48
+ function hastrackedexpr (stmt, code ; heads= LoweredCodeUtils. trackedheads)
48
49
haseval = false
49
50
if isa (stmt, Expr)
50
51
haseval = matches_eval (stmt)
51
52
if stmt. head === :call
52
53
f = stmt. args[1 ]
54
+ while isa (f, Core. SSAValue) || isa (f, JuliaInterpreter. SSAValue)
55
+ f = code[f. id]
56
+ end
53
57
callee_matches (f, Core, :_typebody! ) && return true , haseval
54
58
callee_matches (f, Core, :_setsuper! ) && return true , haseval
55
59
is_some_include (f) && return true , haseval
56
60
elseif stmt. head === :thunk
57
- any (s-> any (hastrackedexpr (s; heads= heads)), (stmt. args[1 ]:: Core.CodeInfo ). code) && return true , haseval
61
+ newcode = (stmt. args[1 ]:: Core.CodeInfo ). code
62
+ any (s-> any (hastrackedexpr (s, newcode; heads= heads)), newcode) && return true , haseval
58
63
elseif stmt. head ∈ heads
59
64
return true , haseval
60
65
end
@@ -70,14 +75,21 @@ function matches_eval(stmt::Expr)
70
75
(isa (f, GlobalRef) && f. name === :eval ) || is_quotenode_egal (f, Core. eval)
71
76
end
72
77
73
- function categorize_stmt (@nospecialize (stmt))
78
+ function categorize_stmt (@nospecialize (stmt), code :: Vector{Any} )
74
79
ismeth, haseval, isinclude, isnamespace, istoplevel = false , false , false , false , false
75
80
if isa (stmt, Expr)
76
81
haseval = matches_eval (stmt)
77
82
ismeth = stmt. head === :method || (stmt. head === :thunk && defines_function (only (stmt. args)))
78
83
istoplevel = stmt. head === :toplevel
79
84
isnamespace = stmt. head === :export || stmt. head === :import || stmt. head === :using
80
- isinclude = stmt. head === :call && is_some_include (stmt. args[1 ])
85
+ isinclude = false
86
+ if stmt. head === :call && length (stmt. args) >= 1
87
+ callee = stmt. args[1 ]
88
+ while isa (callee, Core. SSAValue) || isa (callee, JuliaInterpreter. SSAValue)
89
+ callee = code[callee. id]
90
+ end
91
+ isinclude = is_some_include (callee)
92
+ end
81
93
end
82
94
return ismeth, haseval, isinclude, isnamespace, istoplevel
83
95
end
@@ -112,7 +124,7 @@ function minimal_evaluation!(@nospecialize(predicate), methodinfo, mod::Module,
112
124
evalassign = false
113
125
for (i, stmt) in enumerate (src. code)
114
126
if ! isrequired[i]
115
- isrequired[i], haseval = predicate (stmt):: Tuple{Bool,Bool}
127
+ isrequired[i], haseval = predicate (stmt, src . code ):: Tuple{Bool,Bool}
116
128
if haseval # line `i` may be the equivalent of `f = Core.eval`, so...
117
129
isrequired[edges. succs[i]] .= true # ...require each stmt that calls `eval` via `f(expr)`
118
130
isrequired[i] = true
169
181
minimal_evaluation! (predicate, methodinfo, moduleof (frame), frame. framecode. src, mode)
170
182
171
183
function minimal_evaluation! (methodinfo, frame:: JuliaInterpreter.Frame , mode:: Symbol )
172
- minimal_evaluation! (methodinfo, frame, mode) do @nospecialize (stmt)
173
- ismeth, haseval, isinclude, isnamespace, istoplevel = categorize_stmt (stmt)
184
+ minimal_evaluation! (methodinfo, frame, mode) do @nospecialize (stmt), code
185
+ ismeth, haseval, isinclude, isnamespace, istoplevel = categorize_stmt (stmt, code )
174
186
isreq = ismeth | isinclude | istoplevel
175
187
return mode === :sigs ? (isreq, haseval) : (isreq | isnamespace, haseval)
176
188
end
0 commit comments