Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions base/Base.jl
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,36 @@ function replaceproperty!(x, f::Symbol, expected, desired, success_order::Symbol
val = desired isa ty ? desired : convert(ty, desired)
return Core.replacefield!(x, f, expected, val, success_order, fail_order)
end
function setpropertyonce!(x, f::Symbol, desired, success_order::Symbol=:not_atomic, fail_order::Symbol=success_order)
@inline
ty = fieldtype(typeof(x), f)
val = desired isa ty ? desired : convert(ty, desired)
return Core.setfieldonce!(x, f, val, success_order, fail_order)
end

function swapproperty!(x::Module, f::Symbol, v, order::Symbol=:not_atomic)
@inline
ty = Core.get_binding_type(x, f)
val = v isa ty ? v : convert(ty, v)
return Core.swapglobal!(x, f, val, order)
end
function modifyproperty!(x::Module, f::Symbol, op, v, order::Symbol=:not_atomic)
@inline
return Core.modifyglobal!(x, f, op, v, order)
end
function replaceproperty!(x::Module, f::Symbol, expected, desired, success_order::Symbol=:not_atomic, fail_order::Symbol=success_order)
@inline
ty = Core.get_binding_type(x, f)
val = desired isa ty ? desired : convert(ty, desired)
return Core.replaceglobal!(x, f, expected, val, success_order, fail_order)
end
function setpropertyonce!(x::Module, f::Symbol, desired, success_order::Symbol=:not_atomic, fail_order::Symbol=success_order)
@inline
ty = Core.get_binding_type(x, f)
val = desired isa ty ? desired : convert(ty, desired)
return Core.setglobalonce!(x, f, val, success_order, fail_order)
end


convert(::Type{Any}, Core.@nospecialize x) = x
convert(::Type{T}, x::T) where {T} = x
Expand Down
32 changes: 17 additions & 15 deletions base/boot.jl
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
#end

# struct GenericMemoryRef{kind::Symbol, T, AS::AddrSpace}
# mem::Memory{kind, T, AS}
# mem::GenericMemory{kind, T, AS}
# data::Ptr{Cvoid} # make this GenericPtr{addrspace, Cvoid}
#end

Expand Down Expand Up @@ -191,8 +191,8 @@ export
Tuple, Type, UnionAll, TypeVar, Union, Nothing, Cvoid,
AbstractArray, DenseArray, NamedTuple, Pair,
# special objects
Function, Method, Array, Memory, MemoryRef, GenericMemory, GenericMemoryRef,
Module, Symbol, Task, UndefInitializer, undef, WeakRef, VecElement,
Function, Method, Module, Symbol, Task, UndefInitializer, undef, WeakRef, VecElement,
Array, Memory, MemoryRef, AtomicMemory, AtomicMemoryRef, GenericMemory, GenericMemoryRef,
# numeric types
Number, Real, Integer, Bool, Ref, Ptr,
AbstractFloat, Float16, Float32, Float64,
Expand All @@ -209,10 +209,10 @@ export
# AST representation
Expr, QuoteNode, LineNumberNode, GlobalRef,
# object model functions
fieldtype, getfield, setfield!, swapfield!, modifyfield!, replacefield!,
fieldtype, getfield, setfield!, swapfield!, modifyfield!, replacefield!, setfieldonce!,
nfields, throw, tuple, ===, isdefined, eval,
# access to globals
getglobal, setglobal!,
getglobal, setglobal!, swapglobal!, modifyglobal!, replaceglobal!, setglobalonce!,
# ifelse, sizeof # not exported, to avoid conflicting with Base
# type reflection
<:, typeof, isa, typeassert,
Expand Down Expand Up @@ -516,22 +516,24 @@ const undef = UndefInitializer()
(self::Type{GenericMemory{kind,T,addrspace}})(::UndefInitializer, d::NTuple{1,Int}) where {T,kind,addrspace} = self(undef, getfield(d,1))
# empty vector constructor
(self::Type{GenericMemory{kind,T,addrspace}})() where {T,kind,addrspace} = self(undef, 0)
# copy constructors

const Memory{T} = GenericMemory{:not_atomic, T, CPU}
const MemoryRef{T} = GenericMemoryRef{:not_atomic, T, CPU}
GenericMemoryRef(mem::GenericMemory) = memoryref(mem)
GenericMemoryRef(ref::GenericMemoryRef, i::Integer) = memoryref(ref, Int(i), @_boundscheck)
GenericMemoryRef(mem::GenericMemory, i::Integer) = memoryref(memoryref(mem), Int(i), @_boundscheck)
MemoryRef(mem::Memory) = memoryref(mem)
MemoryRef(ref::MemoryRef, i::Integer) = memoryref(ref, Int(i), @_boundscheck)
MemoryRef(mem::Memory, i::Integer) = memoryref(memoryref(mem), Int(i), @_boundscheck)
MemoryRef{T}(mem::Memory{T}) where {T} = memoryref(mem)
MemoryRef{T}(ref::MemoryRef{T}, i::Integer) where {T} = memoryref(ref, Int(i), @_boundscheck)
MemoryRef{T}(mem::Memory{T}, i::Integer) where {T} = memoryref(memoryref(mem), Int(i), @_boundscheck)
GenericMemoryRef{kind,<:Any,AS}(mem::GenericMemory{kind,<:Any,AS}) where {kind,AS} = memoryref(mem)
GenericMemoryRef{kind,<:Any,AS}(ref::GenericMemoryRef{kind,<:Any,AS}, i::Integer) where {kind,AS} = memoryref(ref, Int(i), @_boundscheck)
GenericMemoryRef{kind,<:Any,AS}(mem::GenericMemory{kind,<:Any,AS}, i::Integer) where {kind,AS} = memoryref(memoryref(mem), Int(i), @_boundscheck)
GenericMemoryRef{kind,T,AS}(mem::GenericMemory{kind,T,AS}) where {kind,T,AS} = memoryref(mem)
GenericMemoryRef{kind,T,AS}(ref::GenericMemoryRef{kind,T,AS}, i::Integer) where {kind,T,AS} = memoryref(ref, Int(i), @_boundscheck)
GenericMemoryRef{kind,T,AS}(mem::GenericMemory{kind,T,AS}, i::Integer) where {kind,T,AS} = memoryref(memoryref(mem), Int(i), @_boundscheck)

const Memory{T} = GenericMemory{:not_atomic, T, CPU}
const MemoryRef{T} = GenericMemoryRef{:not_atomic, T, CPU}
const AtomicMemory{T} = GenericMemory{:atomic, T, CPU}
const AtomicMemoryRef{T} = GenericMemoryRef{:atomic, T, CPU}

# construction helpers for Array
new_as_memoryref(self::Type{GenericMemoryRef{isatomic,T,addrspace}}, m::Int) where {T,isatomic,addrspace} = memoryref(fieldtype(self, :mem)(undef, m))
new_as_memoryref(self::Type{GenericMemoryRef{kind,T,addrspace}}, m::Int) where {T,kind,addrspace} = memoryref(fieldtype(self, :mem)(undef, m))

# checked-multiply intrinsic function for dimensions
_checked_mul_dims() = 1, false
Expand Down
10 changes: 5 additions & 5 deletions base/compiler/abstractinterpretation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1113,12 +1113,12 @@ function const_prop_function_heuristic(interp::AbstractInterpreter, @nospecializ
if !still_nothrow || ismutabletype(arrty)
return false
end
elseif ⊑(𝕃ᵢ, arrty, Array)
elseif ⊑(𝕃ᵢ, arrty, Array) || ⊑(𝕃ᵢ, arrty, GenericMemory)
return false
end
elseif istopfunction(f, :iterate)
itrty = argtypes[2]
if ⊑(𝕃ᵢ, itrty, Array)
if ⊑(𝕃ᵢ, itrty, Array) || ⊑(𝕃ᵢ, itrty, GenericMemory)
return false
end
end
Expand Down Expand Up @@ -1501,7 +1501,7 @@ function abstract_iteration(interp::AbstractInterpreter, @nospecialize(itft), @n
# Return Bottom if this is not an iterator.
# WARNING: Changes to the iteration protocol must be reflected here,
# this is not just an optimization.
# TODO: this doesn't realize that Array, SimpleVector, Tuple, and NamedTuple do not use the iterate protocol
# TODO: this doesn't realize that Array, GenericMemory, SimpleVector, Tuple, and NamedTuple do not use the iterate protocol
stateordonet === Bottom && return AbstractIterationResult(Any[Bottom], AbstractIterationInfo(CallMeta[CallMeta(Bottom, Any, call.effects, info)], true))
valtype = statetype = Bottom
ret = Any[]
Expand Down Expand Up @@ -2076,8 +2076,8 @@ function abstract_call_known(interp::AbstractInterpreter, @nospecialize(f),
return abstract_apply(interp, argtypes, si, sv, max_methods)
elseif f === invoke
return abstract_invoke(interp, arginfo, si, sv)
elseif f === modifyfield!
return abstract_modifyfield!(interp, argtypes, si, sv)
elseif f === modifyfield! || f === Core.modifyglobal! || f === Core.memoryrefmodify! || f === atomic_pointermodify
return abstract_modifyop!(interp, f, argtypes, si, sv)
elseif f === Core.finalizer
return abstract_finalizer(interp, argtypes, sv)
elseif f === applicable
Expand Down
22 changes: 15 additions & 7 deletions base/compiler/ssair/inlining.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1286,10 +1286,18 @@ function process_simple!(todo::Vector{Pair{Int,Any}}, ir::IRCode, idx::Int, stat
end
end

if (sig.f !== Core.invoke && sig.f !== Core.finalizer && sig.f !== modifyfield!) &&
is_builtin(optimizer_lattice(state.interp), sig)
# No inlining for builtins (other invoke/apply/typeassert/finalizer)
return nothing
if is_builtin(optimizer_lattice(state.interp), sig)
let f = sig.f
if (f !== Core.invoke &&
f !== Core.finalizer &&
f !== modifyfield! &&
f !== Core.modifyglobal! &&
f !== Core.memoryrefmodify! &&
f !== atomic_pointermodify)
# No inlining defined for most builtins (just invoke/apply/typeassert/finalizer), so attempt an early exit for them
return nothing
end
end
end

# Special case inliners for regular functions
Expand Down Expand Up @@ -1571,7 +1579,7 @@ function handle_opaque_closure_call!(todo::Vector{Pair{Int,Any}},
return nothing
end

function handle_modifyfield!_call!(ir::IRCode, idx::Int, stmt::Expr, info::ModifyFieldInfo, state::InliningState)
function handle_modifyop!_call!(ir::IRCode, idx::Int, stmt::Expr, info::ModifyOpInfo, state::InliningState)
info = info.info
info isa MethodResultPure && (info = info.info)
info isa ConstCallInfo && (info = info.call)
Expand Down Expand Up @@ -1679,8 +1687,8 @@ function assemble_inline_todo!(ir::IRCode, state::InliningState)
# handle special cased builtins
if isa(info, OpaqueClosureCallInfo)
handle_opaque_closure_call!(todo, ir, idx, stmt, info, flag, sig, state)
elseif isa(info, ModifyFieldInfo)
handle_modifyfield!_call!(ir, idx, stmt, info, state)
elseif isa(info, ModifyOpInfo)
handle_modifyop!_call!(ir, idx, stmt, info, state)
elseif isa(info, InvokeCallInfo)
handle_invoke_call!(todo, ir, idx, stmt, info, flag, sig, state)
elseif isa(info, FinalizerInfo)
Expand Down
15 changes: 10 additions & 5 deletions base/compiler/stmtinfo.jl
Original file line number Diff line number Diff line change
Expand Up @@ -222,13 +222,18 @@ struct FinalizerInfo <: CallInfo
end

"""
info::ModifyFieldInfo <: CallInfo
info::ModifyOpInfo <: CallInfo

Represents a resolved all of `modifyfield!(obj, name, op, x, [order])`.
`info.info` wraps the call information of `op(getfield(obj, name), x)`.
Represents a resolved call of one of:
- `modifyfield!(obj, name, op, x, [order])`
- `modifyglobal!(mod, var, op, x, order)`
- `memoryrefmodify!(memref, op, x, order, boundscheck)`
- `Intrinsics.atomic_pointermodify(ptr, op, x, order)`

`info.info` wraps the call information of `op(getval(), x)`.
"""
struct ModifyFieldInfo <: CallInfo
info::CallInfo # the callinfo for the `op(getfield(obj, name), x)` call
struct ModifyOpInfo <: CallInfo
info::CallInfo # the callinfo for the `op(getval(), x)` call
end

@specialize
Loading