Skip to content

Commit d27b979

Browse files
authored
Add hasbox to check for Core.Box (#29)
1 parent 1916295 commit d27b979

File tree

2 files changed

+48
-0
lines changed

2 files changed

+48
-0
lines changed

src/MethodAnalysis.jl

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ using Base.Meta: isexpr
88

99
export visit, call_type, methodinstance, methodinstances, worlds # findcallers is exported from its own file
1010
export visit_backedges, all_backedges, with_all_backedges, terminal_backedges, direct_backedges
11+
export hasbox
1112

1213
include("visit.jl")
1314
include("backedges.jl")
@@ -189,6 +190,29 @@ function methodinstances(@nospecialize(types::Type))
189190
return methodinstances(f, types)
190191
end
191192

193+
if isdefined(Base, :code_typed_by_type)
194+
function hasbox(mi::MethodInstance)
195+
try
196+
srcs = Base.code_typed_by_type(mi.specTypes)
197+
for (ci, rt) in srcs
198+
(any(==(Core.Box), ci.slottypes) || any(==(Core.Box), ci.ssavaluetypes)) && return true
199+
end
200+
return false
201+
catch
202+
return false
203+
end
204+
end
205+
else
206+
hasbox(mi::MethodInstance) = error("hasbox requires at least Julia 1.6")
207+
end
208+
209+
"""
210+
hasbox(mi::MethodInstance)
211+
212+
Return `true` if the code for `mi` has a `Core.Box`. This often arises from a limitation in Julia's type-inference,
213+
see https://docs.julialang.org/en/v1/manual/performance-tips/#man-performance-captured.
214+
"""
215+
hasbox
192216

193217
if isdefined(Core, :MethodMatch)
194218
include("findcallers.jl")

test/runtests.jl

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,30 @@ end
198198
end
199199
end
200200

201+
@testset "hasbox" begin
202+
function abmult(r::Int)
203+
if r < 0
204+
r = -r
205+
end
206+
f = x -> x * r
207+
return f
208+
end
209+
function abmult2(r::Int)
210+
f = x -> x * abs(r)
211+
return f
212+
end
213+
abmult(1)
214+
mi = methodinstance(abmult, (Int,))
215+
abmult2(1)
216+
mi2 = methodinstance(abmult2, (Int,))
217+
if isdefined(Base, :code_typed_by_type)
218+
@test hasbox(mi)
219+
@test !hasbox(mi2)
220+
else
221+
@test_throws ErrorException("hasbox requires at least Julia 1.6") hasbox(mi)
222+
end
223+
end
224+
201225
module Callers
202226

203227
f(x) = rand()

0 commit comments

Comments
 (0)