Skip to content

Commit 572a6fe

Browse files
author
Ian Atol
committed
Fixup with latest ImmutableArrays changes
1 parent a4561b0 commit 572a6fe

25 files changed

+815
-138
lines changed

base/abstractarray.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1085,6 +1085,8 @@ function copy(a::AbstractArray)
10851085
copymutable(a)
10861086
end
10871087

1088+
copy(a::Core.ImmutableArray) = a
1089+
10881090
function copyto!(B::AbstractVecOrMat{R}, ir_dest::AbstractRange{Int}, jr_dest::AbstractRange{Int},
10891091
A::AbstractVecOrMat{S}, ir_src::AbstractRange{Int}, jr_src::AbstractRange{Int}) where {R,S}
10901092
if length(ir_dest) != length(ir_src)

base/array.jl

Lines changed: 37 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,36 @@ Union type of [`DenseVector{T}`](@ref) and [`DenseMatrix{T}`](@ref).
118118
"""
119119
const DenseVecOrMat{T} = Union{DenseVector{T}, DenseMatrix{T}}
120120

121+
"""
122+
ImmutableArray{T,N} <: AbstractArray{T,N}
123+
Dynamically allocated, immutable array.
124+
"""
125+
const ImmutableArray = Core.ImmutableArray
126+
127+
"""
128+
ImmutableVector{T} <: AbstractVector{T}
129+
Dynamically allocated, immutable vector.
130+
"""
131+
const ImmutableVector{T} = ImmutableArray{T,1}
132+
133+
"""
134+
IMArray{T,N}
135+
Union type of [`Array{T,N}`](@ref) and [`ImmutableArray{T,N}`](@ref)
136+
"""
137+
const IMArray{T,N} = Union{Array{T, N}, ImmutableArray{T,N}}
138+
139+
"""
140+
IMVector{T}
141+
One-dimensional [`ImmutableArray`](@ref) or [`Array`](@ref) with elements of type `T`. Alias for `IMArray{T, 1}`.
142+
"""
143+
const IMVector{T} = IMArray{T, 1}
144+
145+
"""
146+
IMMatrix{T}
147+
Two-dimensional [`ImmutableArray`](@ref) or [`Array`](@ref) with elements of type `T`. Alias for `IMArray{T,2}`.
148+
"""
149+
const IMMatrix{T} = IMArray{T, 2}
150+
121151
## Basic functions ##
122152

123153
import Core: arraysize, arrayset, arrayref, const_arrayref
@@ -147,18 +177,13 @@ function vect(X...)
147177
return copyto!(Vector{T}(undef, length(X)), X)
148178
end
149179

150-
const ImmutableArray = Core.ImmutableArray
151-
const IMArray{T,N} = Union{Array{T, N}, ImmutableArray{T,N}}
152-
const IMVector{T} = IMArray{T, 1}
153-
const IMMatrix{T} = IMArray{T, 2}
154-
155180
ImmutableArray(a::Array) = Core.arrayfreeze(a)
156181
Array(a::ImmutableArray) = Core.arraythaw(a)
157182

158183
size(a::IMArray, d::Integer) = arraysize(a, convert(Int, d))
159184
size(a::IMVector) = (arraysize(a,1),)
160185
size(a::IMMatrix) = (arraysize(a,1), arraysize(a,2))
161-
size(a::IMArray{<:Any,N}) where {N} = (@_inline_meta; ntuple(M -> size(a, M), Val(N))::Dims)
186+
size(a::IMArray{<:Any,N}) where {N} = (@inline; ntuple(M -> size(a, M), Val(N))::Dims)
162187

163188
asize_from(a::IMArray, n) = n > ndims(a) ? () : (arraysize(a,n), asize_from(a, n+1)...)
164189

@@ -220,24 +245,17 @@ function bitsunionsize(u::Union)
220245
return sz
221246
end
222247

223-
length(a::Array) = arraylen(a)
248+
length(a::IMArray) = arraylen(a)
224249
elsize(@nospecialize _::Type{A}) where {T,A<:Array{T}} = aligned_sizeof(T)
225-
sizeof(a::Array) = Core.sizeof(a)
250+
sizeof(a::IMArray) = Core.sizeof(a)
226251

227-
function isassigned(a::Array, i::Int...)
252+
function isassigned(a::IMArray, i::Int...)
228253
@inline
229254
ii = (_sub2ind(size(a), i...) % UInt) - 1
230255
@boundscheck ii < length(a) % UInt || return false
231256
ccall(:jl_array_isassigned, Cint, (Any, UInt), a, ii) == 1
232257
end
233258

234-
function isassigned(a::ImmutableArray, i::Int...)
235-
@_inline_meta
236-
ii = (_sub2ind(size(a), i...) % UInt) - 1
237-
@boundscheck ii < length(a) % UInt || return false
238-
ccall(:jl_array_isassigned, Cint, (Any, UInt), a, ii) == 1
239-
end
240-
241259
## copy ##
242260

243261
"""
@@ -626,7 +644,7 @@ oneunit(x::AbstractMatrix{T}) where {T} = _one(oneunit(T), x)
626644

627645
## Conversions ##
628646

629-
convert(::Type{T}, a::AbstractArray) where {T<:Array} = a isa T ? a : T(a)
647+
convert(T::Type{<:IMArray}, a::AbstractArray) = a isa T ? a : T(a)
630648
convert(::Type{Union{}}, a::AbstractArray) = throw(MethodError(convert, (Union{}, a)))
631649

632650
promote_rule(a::Type{Array{T,n}}, b::Type{Array{S,n}}) where {T,n,S} = el_same(promote_type(T,S), a, b)
@@ -637,6 +655,7 @@ if nameof(@__MODULE__) === :Base # avoid method overwrite
637655
# constructors should make copies
638656
Array{T,N}(x::AbstractArray{S,N}) where {T,N,S} = copyto_axcheck!(Array{T,N}(undef, size(x)), x)
639657
AbstractArray{T,N}(A::AbstractArray{S,N}) where {T,N,S} = copyto_axcheck!(similar(A,T), A)
658+
ImmutableArray{T,N}(Ar::AbstractArray{S,N}) where {T,N,S} = Core.arrayfreeze(copyto_axcheck!(Array{T,N}(undef, size(Ar)), Ar))
640659
end
641660

642661
## copying iterators to containers
@@ -937,7 +956,7 @@ function getindex end
937956
@eval getindex(A::Array, i1::Int, i2::Int, I::Int...) = (@inline; arrayref($(Expr(:boundscheck)), A, i1, i2, I...))
938957

939958
@eval getindex(A::ImmutableArray, i1::Int) = arrayref($(Expr(:boundscheck)), A, i1)
940-
@eval getindex(A::ImmutableArray, i1::Int, i2::Int, I::Int...) = (@_inline_meta; arrayref($(Expr(:boundscheck)), A, i1, i2, I...))
959+
@eval getindex(A::ImmutableArray, i1::Int, i2::Int, I::Int...) = (@inline; arrayref($(Expr(:boundscheck)), A, i1, i2, I...))
941960

942961
# Faster contiguous indexing using copyto! for UnitRange and Colon
943962
function getindex(A::Array, I::AbstractUnitRange{<:Integer})

base/broadcast.jl

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1345,4 +1345,17 @@ function Base.show(io::IO, op::BroadcastFunction)
13451345
end
13461346
Base.show(io::IO, ::MIME"text/plain", op::BroadcastFunction) = show(io, op)
13471347

1348+
struct IMArrayStyle <: Broadcast.AbstractArrayStyle{Any} end
1349+
BroadcastStyle(::Type{<:Core.ImmutableArray}) = IMArrayStyle()
1350+
1351+
#similar has to return mutable array
1352+
function Base.similar(bc::Broadcasted{IMArrayStyle}, ::Type{ElType}) where ElType
1353+
similar(Array{ElType}, axes(bc))
1354+
end
1355+
1356+
@inline function copy(bc::Broadcasted{IMArrayStyle})
1357+
ElType = combine_eltypes(bc.f, bc.args)
1358+
return Core.ImmutableArray(copyto!(similar(bc, ElType), bc))
1359+
end
1360+
13481361
end # module

base/compiler/ssair/EscapeAnalysis/EscapeAnalysis.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1608,7 +1608,7 @@ function escape_builtin!(::typeof(arrayref), astate::AnalysisState, pc::Int, arg
16081608
argtypes = Any[argextype(args[i], astate.ir) for i in 2:length(args)]
16091609
boundcheckt = argtypes[1]
16101610
aryt = argtypes[2]
1611-
if !array_builtin_common_typecheck(boundcheckt, aryt, argtypes, 3)
1611+
if !array_builtin_common_typecheck(Array, boundcheckt, aryt, argtypes, 3)
16121612
add_thrown_escapes!(astate, pc, args, 2)
16131613
end
16141614
ary = args[3]
@@ -1670,7 +1670,7 @@ function escape_builtin!(::typeof(arrayset), astate::AnalysisState, pc::Int, arg
16701670
boundcheckt = argtypes[1]
16711671
aryt = argtypes[2]
16721672
valt = argtypes[3]
1673-
if !(array_builtin_common_typecheck(boundcheckt, aryt, argtypes, 4) &&
1673+
if !(array_builtin_common_typecheck(Array, boundcheckt, aryt, argtypes, 4) &&
16741674
arrayset_typecheck(aryt, valt))
16751675
add_thrown_escapes!(astate, pc, args, 2)
16761676
end

base/compiler/tfuncs.jl

Lines changed: 50 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -461,8 +461,10 @@ add_tfunc(Core._typevar, 3, 3, typevar_tfunc, 100)
461461
add_tfunc(applicable, 1, INT_INF, (@nospecialize(f), args...)->Bool, 100)
462462
add_tfunc(Core.Intrinsics.arraylen, 1, 1, @nospecialize(x)->Int, 4)
463463

464+
const Arrayish = Union{Array,ImmutableArray}
465+
464466
function arraysize_tfunc(@nospecialize(ary), @nospecialize(dim))
465-
hasintersect(widenconst(ary), Array) || return Bottom
467+
hasintersect(widenconst(ary), Arrayish) || return Bottom
466468
hasintersect(widenconst(dim), Int) || return Bottom
467469
return Int
468470
end
@@ -472,7 +474,7 @@ function arraysize_nothrow(argtypes::Vector{Any})
472474
length(argtypes) == 2 || return false
473475
ary = argtypes[1]
474476
dim = argtypes[2]
475-
ary Array || return false
477+
widenconst(ary) <: Arrayish || return false
476478
if isa(dim, Const)
477479
dimval = dim.val
478480
return isa(dimval, Int) && dimval > 0
@@ -1535,27 +1537,27 @@ function tuple_tfunc(argtypes::Vector{Any})
15351537
end
15361538

15371539
arrayref_tfunc(@nospecialize(boundscheck), @nospecialize(ary), @nospecialize idxs...) =
1538-
_arrayref_tfunc(boundscheck, ary, idxs)
1539-
function _arrayref_tfunc(@nospecialize(boundscheck), @nospecialize(ary),
1540-
@nospecialize idxs::Tuple)
1540+
_arrayref_tfunc(Arrayish, boundscheck, ary, idxs)
1541+
function _arrayref_tfunc(@nospecialize(Arytype),
1542+
@nospecialize(boundscheck), @nospecialize(ary), @nospecialize idxs::Tuple)
15411543
isempty(idxs) && return Bottom
1542-
array_builtin_common_errorcheck(boundscheck, ary, idxs) || return Bottom
1543-
return array_elmtype(ary)
1544+
array_builtin_common_errorcheck(Arytype, boundscheck, ary, idxs) || return Bottom
1545+
return array_elmtype(Arytype, ary)
15441546
end
15451547
add_tfunc(arrayref, 3, INT_INF, arrayref_tfunc, 20)
15461548
add_tfunc(const_arrayref, 3, INT_INF, arrayref_tfunc, 20)
15471549

15481550
function arrayset_tfunc(@nospecialize(boundscheck), @nospecialize(ary), @nospecialize(item),
15491551
@nospecialize idxs...)
1550-
hasintersect(widenconst(item), _arrayref_tfunc(boundscheck, ary, idxs)) || return Bottom
1552+
hasintersect(widenconst(item), _arrayref_tfunc(Array, boundscheck, ary, idxs)) || return Bottom
15511553
return ary
15521554
end
15531555
add_tfunc(arrayset, 4, INT_INF, arrayset_tfunc, 20)
15541556

1555-
function array_builtin_common_errorcheck(@nospecialize(boundscheck), @nospecialize(ary),
1556-
@nospecialize idxs::Tuple)
1557+
function array_builtin_common_errorcheck(@nospecialize(Arytype),
1558+
@nospecialize(boundscheck), @nospecialize(ary), @nospecialize idxs::Tuple)
15571559
hasintersect(widenconst(boundscheck), Bool) || return false
1558-
hasintersect(widenconst(ary), Array) || return false
1560+
hasintersect(widenconst(ary), Arytype) || return false
15591561
for i = 1:length(idxs)
15601562
idx = getfield(idxs, i)
15611563
idx = isvarargtype(idx) ? unwrapva(idx) : widenconst(idx)
@@ -1564,9 +1566,9 @@ function array_builtin_common_errorcheck(@nospecialize(boundscheck), @nospeciali
15641566
return true
15651567
end
15661568

1567-
function array_elmtype(@nospecialize ary)
1569+
function array_elmtype(@nospecialize(Arytype), @nospecialize ary)
15681570
a = widenconst(ary)
1569-
if !has_free_typevars(a) && a <: Array
1571+
if !has_free_typevars(a) && a <: Arytype
15701572
a0 = a
15711573
if isa(a, UnionAll)
15721574
a = unwrap_unionall(a0)
@@ -1580,6 +1582,32 @@ function array_elmtype(@nospecialize ary)
15801582
return Any
15811583
end
15821584

1585+
# the ImmutableArray operations might involve copies and so their computation costs can be high,
1586+
# nevertheless we assign smaller inlining costs to them here, since the escape analysis
1587+
# at this moment isn't able to propagate array escapes interprocedurally
1588+
# and it will fail to optimize most cases without inlining
1589+
1590+
arrayfreeze_tfunc(@nospecialize a) = immutable_array_tfunc(Array, ImmutableArray, a)
1591+
add_tfunc(Core.arrayfreeze, 1, 1, arrayfreeze_tfunc, 20)
1592+
1593+
mutating_arrayfreeze_tfunc(@nospecialize a) = immutable_array_tfunc(Array, ImmutableArray, a)
1594+
add_tfunc(Core.mutating_arrayfreeze, 1, 1, mutating_arrayfreeze_tfunc, 10)
1595+
1596+
arraythaw_tfunc(@nospecialize a) = immutable_array_tfunc(ImmutableArray, Array, a)
1597+
add_tfunc(Core.arraythaw, 1, 1, arraythaw_tfunc, 20)
1598+
1599+
function immutable_array_tfunc(@nospecialize(at), @nospecialize(rt), @nospecialize(a))
1600+
a = widenconst(a)
1601+
hasintersect(a, at) || return Bottom
1602+
if a <: at
1603+
unw = unwrap_unionall(a)
1604+
if isa(unw, DataType)
1605+
return rewrap_unionall(rt{unw.parameters[1], unw.parameters[2]}, a)
1606+
end
1607+
end
1608+
return rt
1609+
end
1610+
15831611
function _opaque_closure_tfunc(@nospecialize(arg), @nospecialize(isva),
15841612
@nospecialize(lb), @nospecialize(ub), @nospecialize(source), env::Vector{Any},
15851613
linfo::MethodInstance)
@@ -1613,11 +1641,12 @@ function array_type_undefable(@nospecialize(arytype))
16131641
end
16141642
end
16151643

1616-
function array_builtin_common_nothrow(argtypes::Vector{Any}, first_idx_idx::Int)
1644+
function array_builtin_common_nothrow(@nospecialize(Arytype),
1645+
argtypes::Vector{Any}, first_idx_idx::Int)
16171646
length(argtypes) >= 4 || return false
16181647
boundscheck = argtypes[1]
16191648
arytype = argtypes[2]
1620-
array_builtin_common_typecheck(boundscheck, arytype, argtypes, first_idx_idx) || return false
1649+
array_builtin_common_typecheck(Arytype, boundscheck, arytype, argtypes, first_idx_idx) || return false
16211650
# If we could potentially throw undef ref errors, bail out now.
16221651
arytype = widenconst(arytype)
16231652
array_type_undefable(arytype) && return false
@@ -1632,12 +1661,12 @@ function array_builtin_common_nothrow(argtypes::Vector{Any}, first_idx_idx::Int)
16321661
return false
16331662
end
16341663

1635-
function array_builtin_common_typecheck(
1664+
function array_builtin_common_typecheck(@nospecialize(Arytype),
16361665
@nospecialize(boundscheck), @nospecialize(arytype),
16371666
argtypes::Vector{Any}, first_idx_idx::Int)
1638-
(boundscheck Bool && arytype Array) || return false
1667+
(widenconst(boundscheck) <: Bool && widenconst(arytype) <: Arytype) || return false
16391668
for i = first_idx_idx:length(argtypes)
1640-
argtypes[i] Int || return false
1669+
widenconst(argtypes[i]) <: Int || return false
16411670
end
16421671
return true
16431672
end
@@ -1656,11 +1685,11 @@ end
16561685
# Query whether the given builtin is guaranteed not to throw given the argtypes
16571686
function _builtin_nothrow(@nospecialize(f), argtypes::Array{Any,1}, @nospecialize(rt))
16581687
if f === arrayset
1659-
array_builtin_common_nothrow(argtypes, 4) || return true
1688+
array_builtin_common_nothrow(Array, argtypes, 4) || return true
16601689
# Additionally check element type compatibility
16611690
return arrayset_typecheck(argtypes[2], argtypes[3])
16621691
elseif f === arrayref || f === const_arrayref
1663-
return array_builtin_common_nothrow(argtypes, 3)
1692+
return array_builtin_common_nothrow(Arrayish, argtypes, 3)
16641693
elseif f === arraysize
16651694
return arraysize_nothrow(argtypes)
16661695
elseif f === Core._expr
@@ -1818,8 +1847,7 @@ function builtin_tfunction(interp::AbstractInterpreter, @nospecialize(f), argtyp
18181847
end
18191848
end
18201849
return rt
1821-
end
1822-
if isa(f, IntrinsicFunction)
1850+
elseif isa(f, IntrinsicFunction)
18231851
if is_pure_intrinsic_infer(f) && _all(@nospecialize(a) -> isa(a, Const), argtypes)
18241852
argvals = anymap(@nospecialize(a) -> (a::Const).val, argtypes)
18251853
try

base/compiler/types.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ struct NativeInterpreter <: AbstractInterpreter
261261
end
262262

263263
# If they didn't pass typemax(UInt) but passed something more subtly
264-
# incorrect, fail out loudly.
264+
# incorrect, fail out loud.
265265
@assert world <= get_world_counter()
266266

267267

base/exports.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ export
2222
AbstractVector,
2323
AbstractVecOrMat,
2424
Array,
25+
ImmutableArray,
2526
AbstractMatch,
2627
AbstractPattern,
2728
AbstractDict,
@@ -96,6 +97,7 @@ export
9697
Val,
9798
VecOrMat,
9899
Vector,
100+
ImmutableVector,
99101
VersionNumber,
100102
WeakKeyDict,
101103

base/indices.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ IndexStyle(A::AbstractArray) = IndexStyle(typeof(A))
9595
IndexStyle(::Type{Union{}}) = IndexLinear()
9696
IndexStyle(::Type{<:AbstractArray}) = IndexCartesian()
9797
IndexStyle(::Type{<:Array}) = IndexLinear()
98+
IndexStyle(::Type{<:Core.ImmutableArray}) = IndexLinear()
9899
IndexStyle(::Type{<:AbstractRange}) = IndexLinear()
99100

100101
IndexStyle(A::AbstractArray, B::AbstractArray) = IndexStyle(IndexStyle(A), IndexStyle(B))

base/pointer.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ cconvert(::Type{Ptr{UInt8}}, s::AbstractString) = String(s)
6363
cconvert(::Type{Ptr{Int8}}, s::AbstractString) = String(s)
6464

6565
unsafe_convert(::Type{Ptr{T}}, a::Array{T}) where {T} = ccall(:jl_array_ptr, Ptr{T}, (Any,), a)
66+
unsafe_convert(::Type{Ptr{T}}, a::Core.ImmutableArray{T}) where {T} = ccall(:jl_array_ptr, Ptr{T}, (Any,), a)
6667
unsafe_convert(::Type{Ptr{S}}, a::AbstractArray{T}) where {S,T} = convert(Ptr{S}, unsafe_convert(Ptr{T}, a))
6768
unsafe_convert(::Type{Ptr{T}}, a::AbstractArray{T}) where {T} = error("conversion to pointer not defined for $(typeof(a))")
6869

src/builtins.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1741,7 +1741,7 @@ JL_CALLABLE(jl_f_set_binding_type)
17411741

17421742
JL_CALLABLE(jl_f_arrayfreeze)
17431743
{
1744-
JL_NARGSV(arrayfreeze, 1);
1744+
JL_NARGS(arrayfreeze, 1, 1);
17451745
JL_TYPECHK(arrayfreeze, array, args[0]);
17461746
jl_array_t *a = (jl_array_t*)args[0];
17471747
jl_datatype_t *it = (jl_datatype_t *)jl_apply_type2((jl_value_t*)jl_immutable_array_type,
@@ -1760,7 +1760,7 @@ JL_CALLABLE(jl_f_mutating_arrayfreeze)
17601760
// N.B.: These error checks pretend to be arrayfreeze since this is a drop
17611761
// in replacement and we don't want to change the visible error type in the
17621762
// optimizer
1763-
JL_NARGSV(arrayfreeze, 1);
1763+
JL_NARGS(arrayfreeze, 1, 1);
17641764
JL_TYPECHK(arrayfreeze, array, args[0]);
17651765
jl_array_t *a = (jl_array_t*)args[0];
17661766
jl_datatype_t *it = (jl_datatype_t *)jl_apply_type2((jl_value_t*)jl_immutable_array_type,
@@ -1771,7 +1771,7 @@ JL_CALLABLE(jl_f_mutating_arrayfreeze)
17711771

17721772
JL_CALLABLE(jl_f_arraythaw)
17731773
{
1774-
JL_NARGSV(arraythaw, 1);
1774+
JL_NARGS(arraythaw, 1, 1);
17751775
if (((jl_datatype_t*)jl_typeof(args[0]))->name != jl_immutable_array_typename) {
17761776
jl_type_error("arraythaw", (jl_value_t*)jl_immutable_array_type, args[0]);
17771777
}

0 commit comments

Comments
 (0)