Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Backports 1.12 #57408

Merged
merged 21 commits into from
Feb 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
27f16b5
Compiler: fix unsoundness of getfield_tfunc on Tuple Types (#57275)
vtjnash Feb 13, 2025
6f4c220
print admonition for auto-import only once per module (#57378)
vtjnash Feb 13, 2025
94108c5
[LateLowerGCFrame] fix PlaceGCFrameReset for returns_twice (#57392)
vtjnash Feb 14, 2025
77e7199
lowering: Only try to define the method once (#57346)
Keno Feb 12, 2025
f63f36d
bpart: When backdating replace the entire bpart chain (#57341)
Keno Feb 12, 2025
92eb8ba
staticdata: Set min validation world to require world (#57381)
Keno Feb 13, 2025
ff12d71
Only implicitly `using` Base, not Core (#57357)
Keno Feb 13, 2025
f572662
staticdata: Fix typo in recursive edge revalidation (#57383)
Keno Feb 13, 2025
149a5f4
bpart: Move kind enum into its intended place (#57385)
Keno Feb 13, 2025
5e4a7fb
Bump JuliaSyntax to v1.0.2 (#57388)
lgoettgens Feb 14, 2025
22021d9
🤖 [master] Bump the Statistics stdlib from d49c2bf to 77bd570 (#57266)
DilumAluthgeBot Feb 14, 2025
1152e9b
lowering: fix has_fcall computation (#57395)
vtjnash Feb 14, 2025
5e45856
Clarify mathematical definition of `gcd` (#57204)
LilithHafner Feb 14, 2025
69f1a81
internals: add _defaultctor function for defining ctors (#57317)
vtjnash Feb 14, 2025
5918d42
Make `Pairs` public (#56794)
LilithHafner Feb 14, 2025
9002fe5
staticdata: corrected implementation of jl_collect_new_roots (#57407)
vtjnash Feb 14, 2025
67eb453
bpart: Also partition the export flag (#57405)
Keno Feb 15, 2025
0a7da08
Compiler: Fix check for IRShow definedness (#57420)
Keno Feb 15, 2025
41e0464
fix `(-Inf)^-1` inconsistency (#55875)
oscardssmith Feb 15, 2025
423cb56
bpart: Ignore guard bindings for ambiguity purposes (#57406)
Keno Feb 15, 2025
5da257d
Allow for :foreigncall to transition to GC safe automatically (#49933)
vchuravy Feb 15, 2025
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
2 changes: 1 addition & 1 deletion Compiler/src/abstractinterpretation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3409,7 +3409,7 @@ function abstract_eval_foreigncall(interp::AbstractInterpreter, e::Expr, sstate:
abstract_eval_value(interp, x, sstate, sv)
end
cconv = e.args[5]
if isa(cconv, QuoteNode) && (v = cconv.value; isa(v, Tuple{Symbol, UInt16}))
if isa(cconv, QuoteNode) && (v = cconv.value; isa(v, Tuple{Symbol, UInt16, Bool}))
override = decode_effects_override(v[2])
effects = override_effects(effects, override)
end
Expand Down
8 changes: 5 additions & 3 deletions Compiler/src/ssair/verify.jl
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# This file is a part of Julia. License is MIT: https://julialang.org/license

irshow_was_loaded() = invokelatest(isdefined, Compiler.IRShow, :debuginfo_firstline)
function maybe_show_ir(ir::IRCode)
if isdefined(Core, :Main) && isdefined(Core.Main, :Base)
if irshow_was_loaded()
# ensure we use I/O that does not yield, as this gets called during compilation
invokelatest(Core.Main.Base.show, Core.stdout, "text/plain", ir)
else
Expand Down Expand Up @@ -104,15 +105,16 @@ function count_int(val::Int, arr::Vector{Int})
n
end

_debuginfo_firstline(debuginfo::Union{DebugInfo,DebugInfoStream}) = IRShow.debuginfo_firstline(debuginfo)
function verify_ir(ir::IRCode, print::Bool=true,
allow_frontend_forms::Bool=false,
𝕃ₒ::AbstractLattice = SimpleInferenceLattice.instance,
mi::Union{Nothing,MethodInstance}=nothing)
function raise_error()
error_args = Any["IR verification failed."]
if isdefined(Core, :Main) && isdefined(Core.Main, :Base)
if irshow_was_loaded()
# ensure we use I/O that does not yield, as this gets called during compilation
firstline = invokelatest(IRShow.debuginfo_firstline, ir.debuginfo)
firstline = invokelatest(_debuginfo_firstline, ir.debuginfo)
else
firstline = nothing
end
Expand Down
1 change: 1 addition & 0 deletions Compiler/src/typeinfer.jl
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ being used for this purpose alone.
"""
module Timings

using ..Core
using ..Compiler: -, +, :, Vector, length, first, empty!, push!, pop!, @inline,
@inbounds, copy, backtrace

Expand Down
10 changes: 2 additions & 8 deletions Compiler/src/typeutils.jl
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,8 @@ function isTypeDataType(@nospecialize t)
isType(t) && return false
# Could be Union{} at runtime
t === Core.TypeofBottom && return false
if t.name === Tuple.name
# If we have a Union parameter, could have been redistributed at runtime,
# e.g. `Tuple{Union{Int, Float64}, Int}` is a DataType, but
# `Union{Tuple{Int, Int}, Tuple{Float64, Int}}` is typeequal to it and
# is not.
return all(isTypeDataType, t.parameters)
end
return true
# Return true if `t` is not covariant
return t.name !== Tuple.name
end

has_extended_info(@nospecialize x) = (!isa(x, Type) && !isvarargtype(x)) || isType(x)
Expand Down
2 changes: 1 addition & 1 deletion Compiler/src/validation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const VALID_EXPR_HEADS = IdDict{Symbol,UnitRange{Int}}(
:meta => 0:typemax(Int),
:global => 1:1,
:globaldecl => 1:2,
:foreigncall => 5:typemax(Int), # name, RT, AT, nreq, (cconv, effects), args..., roots...
:foreigncall => 5:typemax(Int), # name, RT, AT, nreq, (cconv, effects, gc_safe), args..., roots...
:cfunction => 5:5,
:isdefined => 1:2,
:code_coverage_effect => 0:0,
Expand Down
1 change: 1 addition & 0 deletions Compiler/test/inline.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1769,6 +1769,7 @@ let getfield_tfunc(@nospecialize xs...) =
Compiler.getfield_tfunc(Compiler.fallback_lattice, xs...)
@test getfield_tfunc(Type, Core.Const(:parameters)) !== Union{}
@test !isa(getfield_tfunc(Type{Tuple{Union{Int, Float64}, Int}}, Core.Const(:name)), Core.Const)
@test !isa(getfield_tfunc(Type{Tuple{Any}}, Core.Const(:name)), Core.Const)
end
@test fully_eliminated(Base.ismutable, Tuple{Base.RefValue})

Expand Down
1 change: 1 addition & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ New language features
* Support for Unicode 16 ([#56925]).
* `Threads.@spawn` now takes a `:samepool` argument to specify the same threadpool as the caller.
`Threads.@spawn :samepool foo()` which is shorthand for `Threads.@spawn Threads.threadpool() foo()` ([#57109]).
* The `@ccall` macro can now take a `gc_safe` argument, that if set to true allows the runtime to run garbage collection concurrently to the `ccall`

Language changes
----------------
Expand Down
5 changes: 4 additions & 1 deletion base/Base_compiler.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

baremodule Base

using Core
using Core.Intrinsics, Core.IR

# to start, we're going to use a very simple definition of `include`
Expand Down Expand Up @@ -135,14 +136,16 @@ include("coreio.jl")

import Core: @doc, @__doc__, WrappedException, @int128_str, @uint128_str, @big_str, @cmd

# Export list
include("exports.jl")

# core docsystem
include("docs/core.jl")
Core.atdoc!(CoreDocs.docm)

eval(x) = Core.eval(Base, x)
eval(m::Module, x) = Core.eval(m, x)

include("exports.jl")
include("public.jl")

if false
Expand Down
5 changes: 3 additions & 2 deletions base/boot.jl
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,9 @@ export
# method reflection
applicable, invoke,
# constants
nothing, Main
nothing, Main,
# backwards compatibility
arrayref, arrayset, arraysize, const_arrayref

const getproperty = getfield # TODO: use `getglobal` for modules instead
const setproperty! = setfield!
Expand Down Expand Up @@ -1040,7 +1042,6 @@ const_arrayref(inbounds::Bool, A::Array, i::Int...) = Main.Base.getindex(A, i...
arrayset(inbounds::Bool, A::Array{T}, x::Any, i::Int...) where {T} = Main.Base.setindex!(A, x::T, i...)
arraysize(a::Array) = a.size
arraysize(a::Array, i::Int) = sle_int(i, nfields(a.size)) ? getfield(a.size, i) : 1
export arrayref, arrayset, arraysize, const_arrayref
const check_top_bit = check_sign_bit

# For convenience
Expand Down
50 changes: 43 additions & 7 deletions base/c.jl
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,31 @@ The above input outputs this:

(:printf, :Cvoid, [:Cstring, :Cuint], ["%d", :value])
"""
function ccall_macro_parse(expr::Expr)
function ccall_macro_parse(exprs)
gc_safe = false
expr = nothing
if exprs isa Expr
expr = exprs
elseif length(exprs) == 1
expr = exprs[1]
elseif length(exprs) == 2
gc_expr = exprs[1]
expr = exprs[2]
if gc_expr.head == :(=) && gc_expr.args[1] == :gc_safe
if gc_expr.args[2] == true
gc_safe = true
elseif gc_expr.args[2] == false
gc_safe = false
else
throw(ArgumentError("gc_safe must be true or false"))
end
else
throw(ArgumentError("@ccall option must be `gc_safe=true` or `gc_safe=false`"))
end
else
throw(ArgumentError("@ccall needs a function signature with a return type"))
end

# setup and check for errors
if !isexpr(expr, :(::))
throw(ArgumentError("@ccall needs a function signature with a return type"))
Expand Down Expand Up @@ -328,12 +352,11 @@ function ccall_macro_parse(expr::Expr)
pusharg!(a)
end
end

return func, rettype, types, args, nreq
return func, rettype, types, args, gc_safe, nreq
end


function ccall_macro_lower(convention, func, rettype, types, args, nreq)
function ccall_macro_lower(convention, func, rettype, types, args, gc_safe, nreq)
statements = []

# if interpolation was used, ensure the value is a function pointer at runtime.
Expand All @@ -351,9 +374,15 @@ function ccall_macro_lower(convention, func, rettype, types, args, nreq)
else
func = esc(func)
end
cconv = nothing
if convention isa Tuple
cconv = Expr(:cconv, (convention..., gc_safe), nreq)
else
cconv = Expr(:cconv, (convention, UInt16(0), gc_safe), nreq)
end

return Expr(:block, statements...,
Expr(:call, :ccall, func, Expr(:cconv, convention, nreq), esc(rettype),
Expr(:call, :ccall, func, cconv, esc(rettype),
Expr(:tuple, map(esc, types)...), map(esc, args)...))
end

Expand Down Expand Up @@ -404,9 +433,16 @@ Example using an external library:

The string literal could also be used directly before the function
name, if desired `"libglib-2.0".g_uri_escape_string(...`

It's possible to declare the ccall as `gc_safe` by using the `gc_safe = true` option:
@ccall gc_safe=true strlen(s::Cstring)::Csize_t
This allows the garbage collector to run concurrently with the ccall, which can be useful whenever
the `ccall` may block outside of julia.
WARNING: This option should be used with caution, as it can lead to undefined behavior if the ccall
calls back into the julia runtime. (`@cfunction`/`@ccallables` are safe however)
"""
macro ccall(expr)
return ccall_macro_lower(:ccall, ccall_macro_parse(expr)...)
macro ccall(exprs...)
return ccall_macro_lower((:ccall), ccall_macro_parse(exprs)...)
end

macro ccall_effects(effects::UInt16, expr)
Expand Down
39 changes: 39 additions & 0 deletions base/exports.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,44 @@
# This file is a part of Julia. License is MIT: https://julialang.org/license

# Re-exports from `Core`
export Core,
# key types
Any, DataType, Vararg, NTuple,
Tuple, Type, UnionAll, TypeVar, Union, Nothing, Cvoid,
AbstractArray, DenseArray, NamedTuple, Pair,
# special objects
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,
Signed, Int, Int8, Int16, Int32, Int64, Int128,
Unsigned, UInt, UInt8, UInt16, UInt32, UInt64, UInt128,
# string types
AbstractChar, Char, AbstractString, String, IO,
# errors
ErrorException, BoundsError, DivideError, DomainError, Exception,
InterruptException, InexactError, OutOfMemoryError, ReadOnlyMemoryError,
OverflowError, StackOverflowError, SegmentationFault, UndefRefError, UndefVarError,
TypeError, ArgumentError, MethodError, AssertionError, LoadError, InitError,
UndefKeywordError, ConcurrencyViolationError, FieldError,
# AST representation
Expr, QuoteNode, LineNumberNode, GlobalRef,
# object model functions
fieldtype, getfield, setfield!, swapfield!, modifyfield!, replacefield!, setfieldonce!,
nfields, throw, tuple, ===, isdefined,
# access to globals
getglobal, setglobal!, swapglobal!, modifyglobal!, replaceglobal!, setglobalonce!, isdefinedglobal,
# ifelse, sizeof # not exported, to avoid conflicting with Base
# type reflection
<:, typeof, isa, typeassert,
# method reflection
applicable, invoke,
# constants
nothing, Main,
# backwards compatibility
arrayref, arrayset, arraysize, const_arrayref

export
# Modules
Meta,
Expand Down
3 changes: 3 additions & 0 deletions base/intfuncs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
Greatest common (positive) divisor (or zero if all arguments are zero).
The arguments may be integer and rational numbers.
``a`` is a divisor of ``b`` if there exists an integer ``m`` such
that ``ma=b``.
!!! compat "Julia 1.4"
Rational arguments require Julia 1.4 or later.
Expand Down
51 changes: 24 additions & 27 deletions base/invalidation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -113,39 +113,36 @@ function invalidate_method_for_globalref!(gr::GlobalRef, method::Method, invalid
end
end

const BINDING_FLAG_EXPORTP = 0x2

function invalidate_code_for_globalref!(b::Core.Binding, invalidated_bpart::Core.BindingPartition, new_bpart::Union{Core.BindingPartition, Nothing}, new_max_world::UInt)
gr = b.globalref
if is_some_guard(binding_kind(invalidated_bpart))
if !is_some_guard(binding_kind(invalidated_bpart))
# TODO: We may want to invalidate for these anyway, since they have performance implications
return
end
foreach_module_mtable(gr.mod, new_max_world) do mt::Core.MethodTable
for method in MethodList(mt)
invalidate_method_for_globalref!(gr, method, invalidated_bpart, new_max_world)
foreach_module_mtable(gr.mod, new_max_world) do mt::Core.MethodTable
for method in MethodList(mt)
invalidate_method_for_globalref!(gr, method, invalidated_bpart, new_max_world)
end
return true
end
return true
end
if isdefined(b, :backedges)
for edge in b.backedges
if isa(edge, CodeInstance)
ccall(:jl_invalidate_code_instance, Cvoid, (Any, UInt), edge, new_max_world)
elseif isa(edge, Core.Binding)
isdefined(edge, :partitions) || continue
latest_bpart = edge.partitions
latest_bpart.max_world == typemax(UInt) || continue
is_some_imported(binding_kind(latest_bpart)) || continue
partition_restriction(latest_bpart) === b || continue
invalidate_code_for_globalref!(edge, latest_bpart, nothing, new_max_world)
else
invalidate_method_for_globalref!(gr, edge::Method, invalidated_bpart, new_max_world)
if isdefined(b, :backedges)
for edge in b.backedges
if isa(edge, CodeInstance)
ccall(:jl_invalidate_code_instance, Cvoid, (Any, UInt), edge, new_max_world)
elseif isa(edge, Core.Binding)
isdefined(edge, :partitions) || continue
latest_bpart = edge.partitions
latest_bpart.max_world == typemax(UInt) || continue
is_some_imported(binding_kind(latest_bpart)) || continue
partition_restriction(latest_bpart) === b || continue
invalidate_code_for_globalref!(edge, latest_bpart, nothing, new_max_world)
else
invalidate_method_for_globalref!(gr, edge::Method, invalidated_bpart, new_max_world)
end
end
end
end
if (b.flags & BINDING_FLAG_EXPORTP) != 0
if (invalidated_bpart.kind & BINDING_FLAG_EXPORTED != 0) || (new_bpart !== nothing && (new_bpart.kind & BINDING_FLAG_EXPORTED != 0))
# This binding was exported - we need to check all modules that `using` us to see if they
# have an implicit binding to us.
# have a binding that is affected by this change.
usings_backedges = ccall(:jl_get_module_usings_backedges, Any, (Any,), gr.mod)
if usings_backedges !== nothing
for user in usings_backedges::Vector{Any}
Expand All @@ -154,8 +151,8 @@ function invalidate_code_for_globalref!(b::Core.Binding, invalidated_bpart::Core
isdefined(user_binding, :partitions) || continue
latest_bpart = user_binding.partitions
latest_bpart.max_world == typemax(UInt) || continue
is_some_imported(binding_kind(latest_bpart)) || continue
partition_restriction(latest_bpart) === b || continue
binding_kind(latest_bpart) in (BINDING_KIND_IMPLICIT, BINDING_KIND_FAILED, BINDING_KIND_GUARD) || continue
@atomic :release latest_bpart.max_world = new_max_world
invalidate_code_for_globalref!(convert(Core.Binding, user_binding), latest_bpart, nothing, new_max_world)
end
end
Expand Down
4 changes: 2 additions & 2 deletions base/loading.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3157,11 +3157,11 @@ This can be used to reduce package load times. Cache files are stored in
`DEPOT_PATH[1]/compiled`. See [Module initialization and precompilation](@ref)
for important notes.
"""
function compilecache(pkg::PkgId, internal_stderr::IO = stderr, internal_stdout::IO = stdout; flags::Cmd=``, reasons::Union{Dict{String,Int},Nothing}=Dict{String,Int}(), loadable_exts::Union{Vector{PkgId},Nothing}=nothing)
function compilecache(pkg::PkgId, internal_stderr::IO = stderr, internal_stdout::IO = stdout; flags::Cmd=``, cacheflags::CacheFlags=CacheFlags(), reasons::Union{Dict{String,Int},Nothing}=Dict{String,Int}(), loadable_exts::Union{Vector{PkgId},Nothing}=nothing)
@nospecialize internal_stderr internal_stdout
path = locate_package(pkg)
path === nothing && throw(ArgumentError("$(repr("text/plain", pkg)) not found during precompilation"))
return compilecache(pkg, path, internal_stderr, internal_stdout; flags, reasons, loadable_exts)
return compilecache(pkg, path, internal_stderr, internal_stdout; flags, cacheflags, reasons, loadable_exts)
end

const MAX_NUM_PRECOMPILE_FILES = Ref(10)
Expand Down
3 changes: 2 additions & 1 deletion base/math.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1217,7 +1217,8 @@ end
# this method is only reliable for -2^20 < n < 2^20 (cf. #53881 #53886)
@assume_effects :terminates_locally @noinline function pow_body(x::Float64, n::Integer)
y = 1.0
xnlo = ynlo = 0.0
xnlo = -0.0
ynlo = 0.0
n == 3 && return x*x*x # keep compatibility with literal_pow
if n < 0
rx = inv(x)
Expand Down
2 changes: 1 addition & 1 deletion base/meta.jl
Original file line number Diff line number Diff line change
Expand Up @@ -427,7 +427,7 @@ function _partially_inline!(@nospecialize(x), slot_replacements::Vector{Any},
elseif i == 4
@assert isa(x.args[4], Int)
elseif i == 5
@assert isa((x.args[5]::QuoteNode).value, Union{Symbol, Tuple{Symbol, UInt8}})
@assert isa((x.args[5]::QuoteNode).value, Union{Symbol, Tuple{Symbol, UInt16, Bool}})
else
x.args[i] = _partially_inline!(x.args[i], slot_replacements,
type_signature, static_param_values,
Expand Down
1 change: 1 addition & 0 deletions base/public.jl
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public
Generator,
ImmutableDict,
OneTo,
Pairs,
LogRange,
UUID,

Expand Down
2 changes: 2 additions & 0 deletions base/runtime_internals.jl
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,8 @@ const BINDING_KIND_GUARD = 0x8
const BINDING_KIND_UNDEF_CONST = 0x9
const BINDING_KIND_BACKDATED_CONST = 0xa

const BINDING_FLAG_EXPORTED = 0x10

is_defined_const_binding(kind::UInt8) = (kind == BINDING_KIND_CONST || kind == BINDING_KIND_CONST_IMPORT || kind == BINDING_KIND_BACKDATED_CONST)
is_some_const_binding(kind::UInt8) = (is_defined_const_binding(kind) || kind == BINDING_KIND_UNDEF_CONST)
is_some_imported(kind::UInt8) = (kind == BINDING_KIND_IMPLICIT || kind == BINDING_KIND_EXPLICIT || kind == BINDING_KIND_IMPORTED)
Expand Down
Loading