From 54404d9e0e98fbb29fe1b6920ac527d0a9263efd Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Mon, 29 Jun 2020 17:03:41 -0500 Subject: [PATCH] Fix some invalidations during Julia's bootstrap (#36427) Also add nospecialize to with_output_color --- base/Base.jl | 1 + base/abstractarray.jl | 5 ++++- base/docs/Docs.jl | 2 +- base/essentials.jl | 2 ++ base/indices.jl | 4 ++++ base/initdefs.jl | 3 +++ base/meta.jl | 2 +- base/multidimensional.jl | 1 - base/shell.jl | 18 +++++++++--------- base/simdloop.jl | 2 +- base/strings/string.jl | 1 - base/strings/util.jl | 2 +- base/util.jl | 2 +- 13 files changed, 28 insertions(+), 17 deletions(-) diff --git a/base/Base.jl b/base/Base.jl index 777e07bd30715b..cc1cf6e68b442e 100644 --- a/base/Base.jl +++ b/base/Base.jl @@ -129,6 +129,7 @@ include("abstractarraymath.jl") include("arraymath.jl") # SIMD loops +@pure sizeof(s::String) = Core.sizeof(s) # needed by gensym as called from simdloop include("simdloop.jl") using .SimdLoop diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 1fdf83cbc504cd..9c81d041975eeb 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -1060,6 +1060,9 @@ function getindex(A::AbstractArray, I...) error_if_canonical_getindex(IndexStyle(A), A, I...) _getindex(IndexStyle(A), A, to_indices(A, I)...) end +# To avoid invalidations from multidimensional.jl: getindex(A::Array, i1::Union{Integer, CartesianIndex}, I::Union{Integer, CartesianIndex}...) +getindex(A::Array, i1::Integer, I::Integer...) = A[to_indices(A, (i1, I...))...] + function unsafe_getindex(A::AbstractArray, I...) @_inline_meta @inbounds r = getindex(A, I...) @@ -2163,7 +2166,7 @@ end # map on collections map(f, A::AbstractArray) = collect_similar(A, Generator(f,A)) -mapany(f, itr) = map!(f, Vector{Any}(undef, length(itr)), itr) # convenient for Expr.args +mapany(f, itr) = map!(f, Vector{Any}(undef, length(itr)::Int), itr) # convenient for Expr.args # default to returning an Array for `map` on general iterators """ diff --git a/base/docs/Docs.jl b/base/docs/Docs.jl index 50a13244451aa7..f5e8b37c5d44c0 100644 --- a/base/docs/Docs.jl +++ b/base/docs/Docs.jl @@ -96,7 +96,7 @@ function signature!(tv, expr::Expr) push!(sig.args[end].args, argtype(arg)) end if isexpr(expr.args[1], :curly) && isempty(tv) - append!(tv, mapany(tvar, expr.args[1].args[2:end])) + append!(tv, mapany(tvar, (expr.args[1]::Expr).args[2:end])) end for i = length(tv):-1:1 push!(sig.args, :(Tuple{$(tv[i].args[1])})) diff --git a/base/essentials.jl b/base/essentials.jl index 3b4b03f91179a8..85c2a146dc5c1c 100644 --- a/base/essentials.jl +++ b/base/essentials.jl @@ -172,6 +172,8 @@ convert(::Type{T}, x::T) where {T} = x convert(::Type{Type}, x::Type) = x # the ssair optimizer is strongly dependent on this method existing to avoid over-specialization # in the absence of inlining-enabled # (due to fields typed as `Type`, which is generally a bad idea) +# These end up being called during bootstrap and then would be invalidated if not for the following: +convert(::Type{String}, x::String) = x """ @eval [mod,] ex diff --git a/base/indices.jl b/base/indices.jl index 37eec4ed6c8176..a223932545651d 100644 --- a/base/indices.jl +++ b/base/indices.jl @@ -320,6 +320,10 @@ not all index types are guaranteed to propagate to `Base.to_index`. """ to_indices(A, I::Tuple) = (@_inline_meta; to_indices(A, axes(A), I)) to_indices(A, I::Tuple{Any}) = (@_inline_meta; to_indices(A, (eachindex(IndexLinear(), A),), I)) +# In simple cases, we know that we don't need to use axes(A), optimize those. +# Having this here avoids invalidations from multidimensional.jl: to_indices(A, I::Tuple{Vararg{Union{Integer, CartesianIndex}}}) +to_indices(A, I::Tuple{}) = () +to_indices(A, I::Tuple{Vararg{Integer}}) = (@_inline_meta; to_indices(A, (), I)) to_indices(A, inds, ::Tuple{}) = () to_indices(A, inds, I::Tuple{Any, Vararg{Any}}) = (@_inline_meta; (to_index(A, I[1]), to_indices(A, _maybetail(inds), tail(I))...)) diff --git a/base/initdefs.jl b/base/initdefs.jl index 5e18028332c596..9fac0d0bf75fc8 100644 --- a/base/initdefs.jl +++ b/base/initdefs.jl @@ -266,6 +266,9 @@ function active_project(search_load_path::Bool=true) project == "@" && continue project = load_path_expand(project) project === nothing && continue + # while this seems well-inferred, nevertheless without the type annotation below + # there are backedges here from abspath(::AbstractString, ::String) + project = project::String if !isfile_casesensitive(project) && basename(project) ∉ project_names project = abspath(project, "Project.toml") end diff --git a/base/meta.jl b/base/meta.jl index 560d66ea37311d..ff2ea563cb3234 100644 --- a/base/meta.jl +++ b/base/meta.jl @@ -155,7 +155,7 @@ function _parse_string(text::AbstractString, filename::AbstractString, if index < 1 || index > ncodeunits(text) + 1 throw(BoundsError(text, index)) end - ex, offset = Core._parse(text, filename, index-1, options) + ex, offset::Int = Core._parse(text, filename, index-1, options) ex, offset+1 end diff --git a/base/multidimensional.jl b/base/multidimensional.jl index 51de7184cb92f6..17e24d7d335eb5 100644 --- a/base/multidimensional.jl +++ b/base/multidimensional.jl @@ -701,7 +701,6 @@ ensure_indexable(I::Tuple{}) = () # In simple cases, we know that we don't need to use axes(A). Optimize those # until Julia gets smart enough to elide the call on its own: -to_indices(A, I::Tuple{}) = () @inline to_indices(A, I::Tuple{Vararg{Union{Integer, CartesianIndex}}}) = to_indices(A, (), I) # But some index types require more context spanning multiple indices # CartesianIndexes are simple; they just splat out diff --git a/base/shell.jl b/base/shell.jl index fcb8b2d2888b67..26775e23a2b9d6 100644 --- a/base/shell.jl +++ b/base/shell.jl @@ -17,7 +17,7 @@ end function shell_parse(str::AbstractString, interpolate::Bool=true; special::AbstractString="") - s::SubString = SubString(str, firstindex(str)) + s = SubString(str, firstindex(str)) s = rstrip_shell(lstrip(s)) # N.B.: This is used by REPLCompletions @@ -37,9 +37,9 @@ function shell_parse(str::AbstractString, interpolate::Bool=true; push!(arg, x) end end - function consume_upto(j) + function consume_upto(s, i, j) update_arg(s[i:prevind(s, j)]) - i = something(peek(st), (lastindex(s)+1,'\0'))[1] + something(peek(st), (lastindex(s)+1,'\0'))[1] end function append_arg() if isempty(arg); arg = Any["",]; end @@ -49,7 +49,7 @@ function shell_parse(str::AbstractString, interpolate::Bool=true; for (j, c) in st if !in_single_quotes && !in_double_quotes && isspace(c) - consume_upto(j) + i = consume_upto(s, i, j) append_arg() while !isempty(st) # We've made sure above that we don't end in whitespace, @@ -59,7 +59,7 @@ function shell_parse(str::AbstractString, interpolate::Bool=true; popfirst!(st) end elseif interpolate && !in_single_quotes && c == '$' - consume_upto(j) + i = consume_upto(s, i, j) isempty(st) && error("\$ right before end of command") stpos, c = popfirst!(st) isspace(c) && error("space not allowed right after \$") @@ -79,21 +79,21 @@ function shell_parse(str::AbstractString, interpolate::Bool=true; else if !in_double_quotes && c == '\'' in_single_quotes = !in_single_quotes - consume_upto(j) + i = consume_upto(s, i, j) elseif !in_single_quotes && c == '"' in_double_quotes = !in_double_quotes - consume_upto(j) + i = consume_upto(s, i, j) elseif c == '\\' if in_double_quotes isempty(st) && error("unterminated double quote") k, c′ = peek(st) if c′ == '"' || c′ == '$' || c′ == '\\' - consume_upto(j) + i = consume_upto(s, i, j) _ = popfirst!(st) end elseif !in_single_quotes isempty(st) && error("dangling backslash") - consume_upto(j) + i = consume_upto(s, i, j) _ = popfirst!(st) end elseif !in_single_quotes && !in_double_quotes && c in special diff --git a/base/simdloop.jl b/base/simdloop.jl index 933a309461d388..e0b6d89d972775 100644 --- a/base/simdloop.jl +++ b/base/simdloop.jl @@ -26,7 +26,7 @@ function check_body!(x::Expr) if x.head === :break || x.head === :continue throw(SimdError("$(x.head) is not allowed inside a @simd loop body")) elseif x.head === :macrocall && x.args[1] === Symbol("@goto") - throw(SimdError("$(x.args[1]) is not allowed inside a @simd loop body")) + throw(SimdError("@goto is not allowed inside a @simd loop body")) end for arg in x.args check_body!(arg) diff --git a/base/strings/string.jl b/base/strings/string.jl index 6825ac29b0930d..1ebb85ff78dd22 100644 --- a/base/strings/string.jl +++ b/base/strings/string.jl @@ -95,7 +95,6 @@ pointer(s::String) = unsafe_convert(Ptr{UInt8}, s) pointer(s::String, i::Integer) = pointer(s)+(i-1) @pure ncodeunits(s::String) = Core.sizeof(s) -@pure sizeof(s::String) = Core.sizeof(s) codeunit(s::String) = UInt8 @inline function codeunit(s::String, i::Integer) diff --git a/base/strings/util.jl b/base/strings/util.jl index e7abfa0bf3f98f..9fd7888fc784be 100644 --- a/base/strings/util.jl +++ b/base/strings/util.jl @@ -224,7 +224,7 @@ julia> lstrip(a) """ function lstrip(f, s::AbstractString) e = lastindex(s) - for (i, c) in pairs(s) + for (i::Int, c::AbstractChar) in pairs(s) !f(c) && return @inbounds SubString(s, i, e) end SubString(s, e+1, e) diff --git a/base/util.jl b/base/util.jl index 8e794c4f1ad95d..e8bb5b8b3a79be 100644 --- a/base/util.jl +++ b/base/util.jl @@ -66,7 +66,7 @@ Printing with the color `:nothing` will print the string without modifications. """ text_colors -function with_output_color(f::Function, color::Union{Int, Symbol}, io::IO, args...; bold::Bool = false) +function with_output_color(@nospecialize(f::Function), color::Union{Int, Symbol}, io::IO, args...; bold::Bool = false) buf = IOBuffer() iscolor = get(io, :color, false)::Bool try f(IOContext(buf, io), args...)