diff --git a/base/boot.jl b/base/boot.jl index 65dc5137d34cb..1b68b4529ed5e 100644 --- a/base/boot.jl +++ b/base/boot.jl @@ -239,7 +239,7 @@ function iterate end function Typeof end ccall(:jl_toplevel_eval_in, Any, (Any, Any), Core, quote - (f::typeof(Typeof))(x) = ($(_expr(:meta,:nospecialize,:x)); isa(x,Type) ? Type{x} : typeof(x)) + (f::typeof(Typeof))(x) = ($(_expr(:meta,:inline)); $(_expr(:meta,:nospecialize,:x)); isa(x,Type) ? Type{x} : typeof(x)) end) @@ -436,7 +436,7 @@ end # simple convert for use by constructors of types in Core # note that there is no actual conversion defined here, # so the methods and ccall's in Core aren't permitted to use convert -convert(::Type{Any}, @nospecialize(x)) = x +convert(::Type{Any}, @nospecialize(x)) = (@_inline_meta; x) convert(::Type{T}, x::T) where {T} = x cconvert(::Type{T}, x) where {T} = convert(T, x) unsafe_convert(::Type{T}, x::T) where {T} = x diff --git a/base/compiler/abstractinterpretation.jl b/base/compiler/abstractinterpretation.jl index 41403861499d0..419532d8083d2 100644 --- a/base/compiler/abstractinterpretation.jl +++ b/base/compiler/abstractinterpretation.jl @@ -332,6 +332,14 @@ function abstract_call_method(interp::AbstractInterpreter, method::Method, @nosp add_remark!(interp, sv, "Refusing to infer into `depwarn`") return Any, false, nothing end + if method.nospecialize != 0 && isdefined(method, :source) + declared_inline = ccall(:jl_ir_flag_inlineable, Bool, (Any,), method.source) + if !declared_inline + oldsig = sig + sig = get_nospecialize_sig(method, sig, sparams) + # sig === oldsig || println(oldsig, " => ", sig, " of ", method.sig) + end + end topmost = nothing # Limit argument type tuple growth of functions: # look through the parents list to see if there's a call to the same method diff --git a/base/compiler/utilities.jl b/base/compiler/utilities.jl index e047c7d83fac3..2e6e6f9420683 100644 --- a/base/compiler/utilities.jl +++ b/base/compiler/utilities.jl @@ -142,8 +142,25 @@ function get_compileable_sig(method::Method, @nospecialize(atypes), sparams::Sim isa(atypes, DataType) || return nothing mt = ccall(:jl_method_table_for, Any, (Any,), atypes) mt === nothing && return nothing - return ccall(:jl_normalize_to_compilable_sig, Any, (Any, Any, Any, Any), + atypes = ccall(:jl_normalize_to_compilable_sig, Any, (Any, Any, Any, Any), mt, atypes, sparams, method) + is_compileable = atypes.isdispatchtuple || + ccall(:jl_isa_compileable_sig, Int32, (Any, Any), atypes, method) != 0 + is_compileable || return nothing + return atypes +end + +function get_nospecialize_sig(method::Method, @nospecialize(atypes), sparams::SimpleVector) + if atypes isa UnionAll + ua = unwrap_unionall(atypes) + ua isa DataType || return method.sig + atypes = Tuple{Any[rewrap_unionall(ua.parameters[i], atypes) for i = 1:length(ua.parameters)]...} + end + mt = ccall(:jl_method_table_for, Any, (Any,), atypes) + mt === nothing && return method.sig + atypes = ccall(:jl_normalize_to_compilable_sig, Any, (Any, Any, Any, Any), + mt, atypes, sparams, method) + return atypes end # eliminate UnionAll vars that might be degenerate due to having identical bounds, diff --git a/base/operators.jl b/base/operators.jl index a35c44276a2e4..b8c1c5c7df914 100644 --- a/base/operators.jl +++ b/base/operators.jl @@ -27,7 +27,7 @@ false Supertype operator, equivalent to `T2 <: T1`. """ -(>:)(@nospecialize(a), @nospecialize(b)) = (b <: a) +(>:)(a, b) = (@nospecialize; @_inline_meta; b <: a) """ supertype(T::DataType) @@ -305,7 +305,7 @@ julia> a ≢ a false ``` """ -!==(@nospecialize(x), @nospecialize(y)) = !(x === y) +!==(x, y) = (@nospecialize; @_inline_meta; !(x === y)) const ≢ = !== """ diff --git a/base/promotion.jl b/base/promotion.jl index a6e6d8fdcac4e..1460735142d3c 100644 --- a/base/promotion.jl +++ b/base/promotion.jl @@ -10,7 +10,7 @@ Return the closest common ancestor of `T` and `S`, i.e. the narrowest type from they both inherit. """ typejoin() = Bottom -typejoin(@nospecialize(t)) = t +typejoin(@nospecialize(t)) = (@_pure_meta; t) typejoin(@nospecialize(t), ts...) = (@_pure_meta; typejoin(t, typejoin(ts...))) function typejoin(@nospecialize(a), @nospecialize(b)) @_pure_meta @@ -146,10 +146,11 @@ either a parent of both types, or a `Union` if appropriate. Falls back to [`typejoin`](@ref). """ function promote_typejoin(@nospecialize(a), @nospecialize(b)) + @_inline_meta c = typejoin(_promote_typesubtract(a), _promote_typesubtract(b)) return Union{a, b, c}::Type end -_promote_typesubtract(@nospecialize(a)) = typesplit(a, Union{Nothing, Missing}) +_promote_typesubtract(@nospecialize(a)) = (@_inline_meta; typesplit(a, Union{Nothing, Missing})) # Returns length, isfixed diff --git a/base/tuple.jl b/base/tuple.jl index d0b849f3a9803..4df11fe1085ee 100644 --- a/base/tuple.jl +++ b/base/tuple.jl @@ -21,13 +21,13 @@ _counttuple(::Type) = nothing ## indexing ## -length(@nospecialize t::Tuple) = nfields(t) +length(@nospecialize t::Tuple) = (@_inline_meta; nfields(t)) firstindex(@nospecialize t::Tuple) = 1 -lastindex(@nospecialize t::Tuple) = length(t) -size(@nospecialize(t::Tuple), d::Integer) = (d == 1) ? length(t) : throw(ArgumentError("invalid tuple dimension $d")) -axes(@nospecialize t::Tuple) = (OneTo(length(t)),) -@eval getindex(@nospecialize(t::Tuple), i::Int) = getfield(t, i, $(Expr(:boundscheck))) -@eval getindex(@nospecialize(t::Tuple), i::Real) = getfield(t, convert(Int, i), $(Expr(:boundscheck))) +lastindex(@nospecialize t::Tuple) = (@_inline_meta; length(t)) +size(@nospecialize(t::Tuple), d::Integer) = (@_inline_meta; (d == 1) ? length(t) : throw(ArgumentError("invalid tuple dimension $d"))) +axes(@nospecialize t::Tuple) = (@_inline_meta; (OneTo(length(t)),)) +@eval getindex(@nospecialize(t::Tuple), i::Int) = (@_inline_meta; getfield(t, i, $(Expr(:boundscheck)))) +@eval getindex(@nospecialize(t::Tuple), i::Real) = (@_inline_meta; getfield(t, convert(Int, i), $(Expr(:boundscheck)))) getindex(t::Tuple, r::AbstractArray{<:Any,1}) = (eltype(t)[t[ri] for ri in r]...,) getindex(t::Tuple, b::AbstractArray{Bool,1}) = length(b) == length(t) ? getindex(t, findall(b)) : throw(BoundsError(t, b)) getindex(t::Tuple, c::Colon) = t @@ -47,8 +47,8 @@ true ``` """ function setindex(x::Tuple, v, i::Integer) - @boundscheck 1 <= i <= length(x) || throw(BoundsError(x, i)) @_inline_meta + @boundscheck 1 <= i <= length(x) || throw(BoundsError(x, i)) _setindex(v, i, x...) end @@ -66,7 +66,7 @@ function iterate(@nospecialize(t::Tuple), i::Int=1) return (1 <= i <= length(t)) ? (@inbounds t[i], i + 1) : nothing end -keys(@nospecialize t::Tuple) = OneTo(length(t)) +keys(@nospecialize t::Tuple) = (@_inline_meta; OneTo(length(t))) prevind(@nospecialize(t::Tuple), i::Integer) = Int(i)-1 nextind(@nospecialize(t::Tuple), i::Integer) = Int(i)+1 diff --git a/src/gf.c b/src/gf.c index 343d36fffa1a2..623b5d6200ee0 100644 --- a/src/gf.c +++ b/src/gf.c @@ -2038,10 +2038,8 @@ JL_DLLEXPORT jl_value_t *jl_normalize_to_compilable_sig(jl_methtable_t *mt, jl_t intptr_t nspec = (mt == jl_type_type_mt || mt == jl_nonfunction_mt ? m->nargs + 1 : mt->max_args + 2); jl_compilation_sig(ti, env, m, nspec, &newparams); tt = (newparams ? jl_apply_tuple_type(newparams) : ti); - int is_compileable = ((jl_datatype_t*)ti)->isdispatchtuple || - jl_isa_compileable_sig(tt, m); JL_GC_POP(); - return is_compileable ? (jl_value_t*)tt : jl_nothing; + return (jl_value_t*)tt; } // compile-time method lookup