Ai
21 Star 49 Fork 0

Gitee 极速下载/julia-language

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
此仓库是为了提升国内下载速度的镜像仓库,每日同步一次。 原始仓库: https://github.com/JuliaLang/julia
克隆/下载
utilities.jl 11.05 KB
一键复制 编辑 原始数据 按行查看 历史
# This file is a part of Julia. License is MIT: https://julialang.org/license
###########
# generic #
###########
if !@isdefined(var"@zone")
# This is designed to allow inserting timers when loading a second copy
# of inference for performing performance experiments.
macro timeit(args...)
esc(args[end])
end
end
function contains_is(itr, @nospecialize(x))
for y in itr
if y === x
return true
end
end
return false
end
anymap(f::Function, a::Vector{Any}) = Any[ f(a[i]) for i in 1:length(a) ]
############
# inlining #
############
const MAX_INLINE_CONST_SIZE = 256
function count_const_size(@nospecialize(x), count_self::Bool = true)
(x isa Type || x isa Core.TypeName || x isa Symbol) && return 0
if ismutable(x)
# No definite size
(isa(x, GenericMemory) || isa(x, String) || isa(x, SimpleVector)) &&
return MAX_INLINE_CONST_SIZE + 1
if isa(x, Module) || isa(x, Method) || isa(x, CodeInstance)
# We allow modules, methods and CodeInstance, because we already assume they are externally
# rooted, so we count their contents as 0 size.
return sizeof(Ptr{Cvoid})
end
# We allow mutable types with no mutable fields (i.e. those mutable
# types used for identity only). The intent of this function is to
# prevent the rooting of large amounts of data that may have been
# speculatively computed. If the struct can get mutated later, we
# cannot assess how much data we might end up rooting. However, if
# the struct is mutable only for identity, the query still works.
for i = 1:nfields(x)
if !isconst(typeof(x), i)
return MAX_INLINE_CONST_SIZE + 1
end
end
end
isbits(x) && return Core.sizeof(x)
dt = typeof(x)
sz = count_self ? sizeof(dt) : 0
sz > MAX_INLINE_CONST_SIZE && return MAX_INLINE_CONST_SIZE + 1
dtfd = DataTypeFieldDesc(dt)
for i = 1:Int(datatype_nfields(dt))
isdefined(x, i) || continue
f = getfield(x, i)
if !dtfd[i].isptr && datatype_pointerfree(typeof(f))
continue
end
sz += count_const_size(f, dtfd[i].isptr)
sz > MAX_INLINE_CONST_SIZE && return MAX_INLINE_CONST_SIZE + 1
end
return sz
end
function is_inlineable_constant(@nospecialize(x))
return count_const_size(x) <= MAX_INLINE_CONST_SIZE
end
###########################
# MethodInstance/CodeInfo #
###########################
invoke_api(li::CodeInstance) = ccall(:jl_invoke_api, Cint, (Any,), li)
use_const_api(li::CodeInstance) = invoke_api(li) == 2
function get_staged(mi::MethodInstance, world::UInt)
may_invoke_generator(mi) || return nothing
cache_ci = (mi.def::Method).generator isa Core.CachedGenerator ?
RefValue{CodeInstance}() : nothing
try
return call_get_staged(mi, world, cache_ci)
catch # user code might throw errors – ignore them
return nothing
end
end
# enable caching of unoptimized generated code if the generator is `CachedGenerator`
function call_get_staged(mi::MethodInstance, world::UInt, cache_ci::RefValue{CodeInstance})
token = @_gc_preserve_begin cache_ci
cache_ci_ptr = pointer_from_objref(cache_ci)
src = ccall(:jl_code_for_staged, Ref{CodeInfo}, (Any, UInt, Ptr{CodeInstance}), mi, world, cache_ci_ptr)
@_gc_preserve_end token
return src
end
function call_get_staged(mi::MethodInstance, world::UInt, ::Nothing)
return ccall(:jl_code_for_staged, Ref{CodeInfo}, (Any, UInt, Ptr{Cvoid}), mi, world, C_NULL)
end
function get_cached_uninferred(mi::MethodInstance, world::UInt)
ccall(:jl_cached_uninferred, Any, (Any, UInt), mi.cache, world)::CodeInstance
end
function retrieve_code_info(mi::MethodInstance, world::UInt)
def = mi.def
if !isa(def, Method)
ci = get_cached_uninferred(mi, world)
src = ci.inferred
# Inference may corrupt the src, which is fine, because this is a
# (short-lived) top-level thunk, but set it to NULL anyway, so we
# can catch it if somebody tries to read it again by accident.
# @atomic ci.inferred = C_NULL
return src
end
c = hasgenerator(def) ? get_staged(mi, world) : nothing
if c === nothing && isdefined(def, :source)
src = def.source
if src === nothing
# can happen in images built with --strip-ir
return nothing
elseif isa(src, String)
c = ccall(:jl_uncompress_ir, Ref{CodeInfo}, (Any, Ptr{Cvoid}, Any), def, C_NULL, src)
else
c = copy(src::CodeInfo)
end
if (def.did_scan_source & 0x1) == 0x0
# This scan must happen:
# 1. After method definition
# 2. Before any code instances that may have relied on information
# from implicit GlobalRefs for this method are added to the cache
# 3. Preferably while the IR is already uncompressed
# 4. As late as possible, as early adding of the backedges may cause
# spurious invalidations.
#
# At the moment we do so here, because
# 1. It's reasonably late
# 2. It has easy access to the uncompressed IR
# 3. We necessarily pass through here before relying on any
# information obtained from implicit GlobalRefs.
#
# However, the exact placement of this scan is not as important as
# long as the above conditions are met.
ccall(:jl_scan_method_source_now, Cvoid, (Any, Any), def, c)
end
end
if c isa CodeInfo
c.parent = mi
return c
end
return nothing
end
function get_compileable_sig(method::Method, @nospecialize(atype), sparams::SimpleVector)
isa(atype, DataType) || return nothing
return ccall(:jl_normalize_to_compilable_sig, Any, (Any, Any, Any, Cint),
atype, sparams, method, #=int return_if_compileable=#1)
end
isa_compileable_sig(@nospecialize(atype), sparams::SimpleVector, method::Method) =
!iszero(ccall(:jl_isa_compileable_sig, Int32, (Any, Any, Any), atype, sparams, method))
isa_compileable_sig(m::MethodInstance) = (def = m.def; !isa(def, Method) || isa_compileable_sig(m.specTypes, m.sparam_vals, def))
isa_compileable_sig(::ABIOverride) = false
has_typevar(@nospecialize(t), v::TypeVar) = ccall(:jl_has_typevar, Cint, (Any, Any), t, v) != 0
"""
is_declared_inline(method::Method)::Bool
Check if `method` is declared as `@inline`.
"""
is_declared_inline(method::Method) = _is_declared_inline(method, true)
"""
is_declared_noinline(method::Method)::Bool
Check if `method` is declared as `@noinline`.
"""
is_declared_noinline(method::Method) = _is_declared_inline(method, false)
function _is_declared_inline(method::Method, inline::Bool)
isdefined(method, :source) || return false
src = method.source
isa(src, MaybeCompressed) || return false
return (inline ? is_declared_inline : is_declared_noinline)(src)
end
"""
is_aggressive_constprop(method::Union{Method,CodeInfo})::Bool
Check if `method` is declared as `Base.@constprop :aggressive`.
"""
is_aggressive_constprop(method::Union{Method,CodeInfo}) = method.constprop == 0x01
"""
is_no_constprop(method::Union{Method,CodeInfo})::Bool
Check if `method` is declared as `Base.@constprop :none`.
"""
is_no_constprop(method::Union{Method,CodeInfo}) = method.constprop == 0x02
#########
# types #
#########
@nospecializeinfer function singleton_type(@nospecialize(ft))
ft = widenslotwrapper(ft)
if isa(ft, Const)
return ft.val
elseif isconstType(ft)
return ft.parameters[1]
elseif issingletontype(ft)
return ft.instance
end
return nothing
end
@nospecializeinfer function maybe_singleton_const(@nospecialize(t))
if isa(t, DataType)
if issingletontype(t)
return Const(t.instance)
elseif isconstType(t)
return Const(t.parameters[1])
end
end
return t
end
###################
# SSAValues/Slots #
###################
function ssamap(f, @nospecialize(stmt))
urs = userefs(stmt)
for op in urs
val = op[]
if isa(val, SSAValue)
op[] = f(val)
end
end
return urs[]
end
function foreachssa(@specialize(f), @nospecialize(stmt))
urs = userefs(stmt)
for op in urs
val = op[]
if isa(val, SSAValue)
f(val)
end
end
end
function foreach_anyssa(@specialize(f), @nospecialize(stmt))
urs = userefs(stmt)
for op in urs
val = op[]
if isa(val, AnySSAValue)
f(val)
end
end
end
function find_ssavalue_uses(body::Vector{Any}, nvals::Int)
uses = BitSet[ BitSet() for _ = 1:nvals ]
for line in 1:length(body)
e = body[line]
if isa(e, ReturnNode)
isdefined(e, :val) || continue
e = e.val
elseif isa(e, GotoIfNot)
e = e.cond
end
if isa(e, SSAValue)
push!(uses[e.id], line)
elseif isa(e, Expr)
find_ssavalue_uses!(uses, e, line)
elseif isa(e, PhiNode)
find_ssavalue_uses!(uses, e, line)
end
end
return uses
end
function find_ssavalue_uses!(uses::Vector{BitSet}, e::Expr, line::Int)
head = e.head
is_meta_expr_head(head) && return
skiparg = (head === :(=))
for a in e.args
if skiparg
skiparg = false
elseif isa(a, SSAValue)
push!(uses[a.id], line)
elseif isa(a, Expr)
find_ssavalue_uses!(uses, a, line)
end
end
end
function find_ssavalue_uses!(uses::Vector{BitSet}, e::PhiNode, line::Int)
values = e.values
for i = 1:length(values)
isassigned(values, i) || continue
val = values[i]
if isa(val, SSAValue)
push!(uses[val.id], line)
end
end
end
# using a function to ensure we can infer this
@inline function slot_id(s)
isa(s, SlotNumber) && return s.id
return (s::Argument).n
end
###########
# options #
###########
inlining_enabled() = (JLOptions().can_inline == 1)
function instrumentation_enabled(m::Module, only_if_affects_optimizer::Bool)
generating_output() && return false # don't alter caches
cov = JLOptions().code_coverage
if cov == 1 # user
m = moduleroot(m)
m === Core && return false
isdefined(Main, :Base) && m === Main.Base && return false
return true
elseif cov == 2 # all
return true
end
if !only_if_affects_optimizer
log = JLOptions().malloc_log
if log == 1 # user
m = moduleroot(m)
m === Core && return false
isdefined(Main, :Base) && m === Main.Base && return false
return true
elseif log == 2 # all
return true
end
end
return false
end
function inbounds_option()
opt_check_bounds = JLOptions().check_bounds
opt_check_bounds == 0 && return :default
opt_check_bounds == 1 && return :on
return :off
end
is_asserts() = ccall(:jl_is_assertsbuild, Cint, ()) == 1
_time_ns() = ccall(:jl_hrtime, UInt64, ())
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
C++
1
https://gitee.com/mirrors/julia-language.git
git@gitee.com:mirrors/julia-language.git
mirrors
julia-language
julia-language
master

搜索帮助