diff --git a/Make.inc b/Make.inc index 51186cfefe8eb9..5d58454c80333e 100644 --- a/Make.inc +++ b/Make.inc @@ -1392,7 +1392,7 @@ endif ifeq ($(OS), WINNT) HAVE_SSP := 1 OSLIBS += -Wl,--export-all-symbols -Wl,--version-script=$(BUILDROOT)/src/julia.expmap \ - $(NO_WHOLE_ARCHIVE) -lpsapi -lkernel32 -lws2_32 -liphlpapi -lwinmm -ldbghelp -luserenv -lsecur32 -latomic + $(NO_WHOLE_ARCHIVE) -lpsapi -lkernel32 -lws2_32 -liphlpapi -lwinmm -ldbghelp -luserenv -lsecur32 -latomic -lole32 JLDFLAGS += -Wl,--stack,8388608 ifeq ($(ARCH),i686) JLDFLAGS += -Wl,--large-address-aware diff --git a/NEWS.md b/NEWS.md index ca4fb51b37fa0f..2da8a7bad8b23b 100644 --- a/NEWS.md +++ b/NEWS.md @@ -54,6 +54,7 @@ Compiler/Runtime improvements * A new `LazyLibrary` type is exported from `Libdl` for use in building chained lazy library loads, primarily to be used within JLLs ([#50074]). * Added support for annotating `Base.@assume_effects` on code blocks ([#52400]). +* The libuv library has been updated from a base of v1.44.2 to v1.48.0 ([#49937]). Command-line option changes --------------------------- @@ -86,6 +87,7 @@ New library functions * `Sys.username()` can be used to return the current user's username ([#51897]). * `wrap(Array, m::Union{MemoryRef{T}, Memory{T}}, dims)` is the safe counterpart to `unsafe_wrap` ([#52049]). * `GC.logging_enabled()` can be used to test whether GC logging has been enabled via `GC.enable_logging` ([#51647]). +* `IdSet` is now exported from Base and considered public ([#53262]). New library features -------------------- diff --git a/base/abstractdict.jl b/base/abstractdict.jl index f73b518930a077..62a5b3ee9e1b03 100644 --- a/base/abstractdict.jl +++ b/base/abstractdict.jl @@ -416,7 +416,7 @@ end Update `d`, removing elements for which `f` is `false`. The function `f` is passed `key=>value` pairs. -# Example +# Examples ```jldoctest julia> d = Dict(1=>"a", 2=>"b", 3=>"c") Dict{Int64, String} with 3 entries: diff --git a/base/boot.jl b/base/boot.jl index ed26536b961ff7..8ca6d392ead671 100644 --- a/base/boot.jl +++ b/base/boot.jl @@ -483,13 +483,13 @@ eval(Core, quote end) function CodeInstance( - mi::MethodInstance, @nospecialize(rettype), @nospecialize(exctype), @nospecialize(inferred_const), + mi::MethodInstance, owner, @nospecialize(rettype), @nospecialize(exctype), @nospecialize(inferred_const), @nospecialize(inferred), const_flags::Int32, min_world::UInt, max_world::UInt, ipo_effects::UInt32, effects::UInt32, @nospecialize(analysis_results), relocatability::UInt8) return ccall(:jl_new_codeinst, Ref{CodeInstance}, - (Any, Any, Any, Any, Any, Int32, UInt, UInt, UInt32, UInt32, Any, UInt8), - mi, rettype, exctype, inferred_const, inferred, const_flags, min_world, max_world, + (Any, Any, Any, Any, Any, Any, Int32, UInt, UInt, UInt32, UInt32, Any, UInt8), + mi, owner, rettype, exctype, inferred_const, inferred, const_flags, min_world, max_world, ipo_effects, effects, analysis_results, relocatability) end diff --git a/base/cartesian.jl b/base/cartesian.jl index decc01cbc3e5f1..ca0fc0aac0cfcf 100644 --- a/base/cartesian.jl +++ b/base/cartesian.jl @@ -115,7 +115,7 @@ Generate a function call expression with keyword arguments `kw...`. As in the case of [`@ncall`](@ref), `sym` represents any number of function arguments, the last of which may be an anonymous-function expression and is expanded into `N` arguments. -# Example +# Examples ```jldoctest julia> using Base.Cartesian diff --git a/base/cmd.jl b/base/cmd.jl index 0e4ec119109f16..202527abdf6444 100644 --- a/base/cmd.jl +++ b/base/cmd.jl @@ -3,9 +3,10 @@ abstract type AbstractCmd end # libuv process option flags -const UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS = UInt8(1 << 2) -const UV_PROCESS_DETACHED = UInt8(1 << 3) -const UV_PROCESS_WINDOWS_HIDE = UInt8(1 << 4) +const UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS = UInt32(1 << 2) +const UV_PROCESS_DETACHED = UInt32(1 << 3) +const UV_PROCESS_WINDOWS_HIDE = UInt32(1 << 4) +const UV_PROCESS_WINDOWS_DISABLE_EXACT_NAME = UInt32(1 << 7) struct Cmd <: AbstractCmd exec::Vector{String} diff --git a/base/compiler/cicache.jl b/base/compiler/cicache.jl index 8332777e6d5bc9..a6ed18fe5105f3 100644 --- a/base/compiler/cicache.jl +++ b/base/compiler/cicache.jl @@ -7,15 +7,16 @@ Internally, each `MethodInstance` keep a unique global cache of code instances that have been created for the given method instance, stratified by world age ranges. This struct abstracts over access to this cache. """ -struct InternalCodeCache end +struct InternalCodeCache + owner::Any # `jl_egal` is used for comparison +end function setindex!(cache::InternalCodeCache, ci::CodeInstance, mi::MethodInstance) + @assert ci.owner === cache.owner ccall(:jl_mi_cache_insert, Cvoid, (Any, Any), mi, ci) return cache end -const GLOBAL_CI_CACHE = InternalCodeCache() - struct WorldRange min_world::UInt max_world::UInt @@ -49,11 +50,11 @@ WorldView(wvc::WorldView, wr::WorldRange) = WorldView(wvc.cache, wr) WorldView(wvc::WorldView, args...) = WorldView(wvc.cache, args...) function haskey(wvc::WorldView{InternalCodeCache}, mi::MethodInstance) - return ccall(:jl_rettype_inferred, Any, (Any, UInt, UInt), mi, first(wvc.worlds), last(wvc.worlds)) !== nothing + return ccall(:jl_rettype_inferred, Any, (Any, Any, UInt, UInt), wvc.cache.owner, mi, first(wvc.worlds), last(wvc.worlds)) !== nothing end function get(wvc::WorldView{InternalCodeCache}, mi::MethodInstance, default) - r = ccall(:jl_rettype_inferred, Any, (Any, UInt, UInt), mi, first(wvc.worlds), last(wvc.worlds)) + r = ccall(:jl_rettype_inferred, Any, (Any, Any, UInt, UInt), wvc.cache.owner, mi, first(wvc.worlds), last(wvc.worlds)) if r === nothing return default end @@ -70,3 +71,9 @@ function setindex!(wvc::WorldView{InternalCodeCache}, ci::CodeInstance, mi::Meth setindex!(wvc.cache, ci, mi) return wvc end + +function code_cache(interp::AbstractInterpreter) + cache = InternalCodeCache(cache_owner(interp)) + worlds = WorldRange(get_inference_world(interp)) + return WorldView(cache, worlds) +end diff --git a/base/compiler/typeinfer.jl b/base/compiler/typeinfer.jl index e9edd04e59d407..e30c6e5f96fcb0 100644 --- a/base/compiler/typeinfer.jl +++ b/base/compiler/typeinfer.jl @@ -326,7 +326,7 @@ function CodeInstance(interp::AbstractInterpreter, result::InferenceResult, end end # relocatability = isa(inferred_result, String) ? inferred_result[end] : UInt8(0) - return CodeInstance(result.linfo, + return CodeInstance(result.linfo, cache_owner(interp), widenconst(result_type), widenconst(result.exc_result), rettype_const, inferred_result, const_flags, first(valid_worlds), last(valid_worlds), # TODO: Actually do something with non-IPO effects diff --git a/base/compiler/types.jl b/base/compiler/types.jl index cdf90a3a6e78ca..642a7ac5516621 100644 --- a/base/compiler/types.jl +++ b/base/compiler/types.jl @@ -14,7 +14,7 @@ the following methods to satisfy the `AbstractInterpreter` API requirement: - `OptimizationParams(interp::NewInterpreter)` - return an `OptimizationParams` instance - `get_inference_world(interp::NewInterpreter)` - return the world age for this interpreter - `get_inference_cache(interp::NewInterpreter)` - return the local inference cache -- `code_cache(interp::NewInterpreter)` - return the global inference cache +- `cache_owner(interp::NewInterpreter)` - return the owner of any new cache entries """ :(AbstractInterpreter) @@ -404,7 +404,7 @@ InferenceParams(interp::NativeInterpreter) = interp.inf_params OptimizationParams(interp::NativeInterpreter) = interp.opt_params get_inference_world(interp::NativeInterpreter) = interp.world get_inference_cache(interp::NativeInterpreter) = interp.inf_cache -code_cache(interp::NativeInterpreter) = WorldView(GLOBAL_CI_CACHE, get_inference_world(interp)) +cache_owner(interp::NativeInterpreter) = nothing """ already_inferred_quick_test(::AbstractInterpreter, ::MethodInstance) diff --git a/base/compiler/utilities.jl b/base/compiler/utilities.jl index 00c7ea40e3db91..7d554e46a1744b 100644 --- a/base/compiler/utilities.jl +++ b/base/compiler/utilities.jl @@ -321,25 +321,6 @@ function iterate(iter::BackedgeIterator, i::Int=1) return BackedgePair(item, backedges[i+1]::MethodInstance), i+2 # `invoke` calls end -""" - add_invalidation_callback!(callback, mi::MethodInstance) - -Register `callback` to be triggered upon the invalidation of `mi`. -`callback` should a function taking two arguments, `callback(replaced::MethodInstance, max_world::UInt32)`, -and it will be recursively invoked on `MethodInstance`s within the invalidation graph. -""" -function add_invalidation_callback!(@nospecialize(callback), mi::MethodInstance) - if !isdefined(mi, :callbacks) - callbacks = mi.callbacks = Any[callback] - else - callbacks = mi.callbacks::Vector{Any} - if !any(@nospecialize(cb)->cb===callback, callbacks) - push!(callbacks, callback) - end - end - return callbacks -end - ######### # types # ######### diff --git a/base/complex.jl b/base/complex.jl index f14b7f2f5336fa..8ac126d2c65328 100644 --- a/base/complex.jl +++ b/base/complex.jl @@ -1097,7 +1097,7 @@ second is used for rounding the imaginary components. which rounds to the nearest integer, with ties (fractional values of 0.5) being rounded to the nearest even integer. -# Example +# Examples ```jldoctest julia> round(3.14 + 4.5im) 3.0 + 4.0im diff --git a/base/essentials.jl b/base/essentials.jl index 8e329c4f7c4d9e..9c156fb1b8f6df 100644 --- a/base/essentials.jl +++ b/base/essentials.jl @@ -90,7 +90,7 @@ f(y) = [x for x in y] standard ones) on type-inference. Use [`Base.@nospecializeinfer`](@ref) together with `@nospecialize` to additionally suppress inference. -# Example +# Examples ```julia julia> f(A::AbstractArray) = g(A) diff --git a/base/experimental.jl b/base/experimental.jl index c599d973b0a762..8dbdcacd65376b 100644 --- a/base/experimental.jl +++ b/base/experimental.jl @@ -254,7 +254,7 @@ When issuing a hint, the output should typically start with `\\n`. If you define custom exception types, your `showerror` method can support hints by calling [`Experimental.show_error_hints`](@ref). -# Example +# Examples ``` julia> module Hinter diff --git a/base/exports.jl b/base/exports.jl index b1b84539c07a36..fbb5b449719d66 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -65,6 +65,7 @@ export Missing, NTuple, IdDict, + IdSet, OrdinalRange, Pair, PartialQuickSort, diff --git a/base/expr.jl b/base/expr.jl index 39da1408a77b37..b90f75e75a76f4 100644 --- a/base/expr.jl +++ b/base/expr.jl @@ -831,7 +831,7 @@ end Tells the compiler to infer `f` using the declared types of `@nospecialize`d arguments. This can be used to limit the number of compiler-generated specializations during inference. -# Example +# Examples ```julia julia> f(A::AbstractArray) = g(A) diff --git a/base/gcutils.jl b/base/gcutils.jl index 25f098e4072235..3b8c4cf4ede10a 100644 --- a/base/gcutils.jl +++ b/base/gcutils.jl @@ -70,7 +70,6 @@ end A finalizer may be registered at object construction. In the following example note that we implicitly rely on the finalizer returning the newly created mutable struct `x`. -# Example ```julia mutable struct MyMutableStruct bar diff --git a/base/iddict.jl b/base/iddict.jl index 0b12ae86b2c6a9..9c133d5ba23c69 100644 --- a/base/iddict.jl +++ b/base/iddict.jl @@ -4,11 +4,12 @@ IdDict([itr]) `IdDict{K,V}()` constructs a hash table using [`objectid`](@ref) as hash and -`===` as equality with keys of type `K` and values of type `V`. +`===` as equality with keys of type `K` and values of type `V`. See [`Dict`](@ref) +for further help and [`IdSet`](@ref) for the set version of this. -See [`Dict`](@ref) for further help. In the example below, The `Dict` -keys are all `isequal` and therefore get hashed the same, so they get overwritten. -The `IdDict` hashes by object-id, and thus preserves the 3 different keys. +In the example below, the `Dict` keys are all `isequal` and therefore get hashed +the same, so they get overwritten. The `IdDict` hashes by object-id, and thus +preserves the 3 different keys. # Examples ```julia-repl diff --git a/base/idset.jl b/base/idset.jl index 6e0b7a85a5b232..23f9ca009af0cc 100644 --- a/base/idset.jl +++ b/base/idset.jl @@ -1,5 +1,28 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license +""" + IdSet{T}([itr]) + IdSet() + +IdSet{T}() constructs a set (see [`Set`](@ref)) using +`===` as equality with values of type `V`. + +In the example below, the values are all `isequal` so they get overwritten. +The `IdSet` compares by `===` so preserves the 3 different keys. + +Examples +≡≡≡≡≡≡≡≡ + +julia> Set(Any[true, 1, 1.0]) +Set{Any} with 1 element: + 1.0 + +julia> IdSet{Any}(Any[true, 1, 1.0]) +IdSet{Any} with 3 elements: + 1.0 + 1 + true +""" mutable struct IdSet{K} <: AbstractSet{K} list::Memory{Any} idxs::Union{Memory{UInt8}, Memory{UInt16}, Memory{UInt32}} diff --git a/base/indices.jl b/base/indices.jl index 9f2115e6925646..0bd46f9787dabb 100644 --- a/base/indices.jl +++ b/base/indices.jl @@ -464,7 +464,7 @@ julia> extrema(b) Return a `LinearIndices` array with the specified shape or [`axes`](@ref). -# Example +# Examples The main purpose of this constructor is intuitive conversion from cartesian to linear indexing: diff --git a/base/libdl.jl b/base/libdl.jl index bd909bb7b90eb3..199d847572ca49 100644 --- a/base/libdl.jl +++ b/base/libdl.jl @@ -130,7 +130,7 @@ end Wrapper for usage with `do` blocks to automatically close the dynamic library once control flow leaves the `do` block scope. -# Example +# Examples ```julia vendor = dlopen("libblas") do lib if Libdl.dlsym(lib, :openblas_set_num_threads; throw_error=false) !== nothing @@ -234,7 +234,7 @@ end Get the full path of the library `libname`. -# Example +# Examples ```julia-repl julia> dlpath("libjulia") ``` diff --git a/base/loading.jl b/base/loading.jl index 1e6af4592b6a16..5f0ea1859bc0f6 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -2335,7 +2335,7 @@ and return the value of the last expression. The optional `args` argument can be used to set the input arguments of the script (i.e. the global `ARGS` variable). Note that definitions (e.g. methods, globals) are evaluated in the anonymous module and do not affect the current module. -# Example +# Examples ```jldoctest julia> write("testfile.jl", \"\"\" @@ -3558,7 +3558,7 @@ Macro to obtain the absolute path of the current directory as a string. If in a script, returns the directory of the script containing the `@__DIR__` macrocall. If run from a REPL or if evaluated by `julia -e `, returns the current working directory. -# Example +# Examples The example illustrates the difference in the behaviors of `@__DIR__` and `pwd()`, by creating a simple script in a different directory than the current working one and executing both commands: diff --git a/base/logging.jl b/base/logging.jl index 1853caa16148cc..436d00335acf3c 100644 --- a/base/logging.jl +++ b/base/logging.jl @@ -608,7 +608,7 @@ end Execute `function`, directing all log messages to `logger`. -# Example +# Examples ```julia function test(x) diff --git a/base/math.jl b/base/math.jl index b0870c60016f7b..0071d427fbbacc 100644 --- a/base/math.jl +++ b/base/math.jl @@ -177,7 +177,7 @@ a Goertzel-like [^DK62] algorithm if `x` is complex. !!! compat "Julia 1.4" This function requires Julia 1.4 or later. -# Example +# Examples ```jldoctest julia> evalpoly(2, (1, 2, 3)) 17 diff --git a/base/operators.jl b/base/operators.jl index 2138888c82d9f0..3d5ad705ed99a6 100644 --- a/base/operators.jl +++ b/base/operators.jl @@ -1242,7 +1242,7 @@ it into the original function. This is useful as an adaptor to pass a multi-argument function in a context that expects a single argument, but passes a tuple as that single argument. -# Example usage: +# Examples ```jldoctest julia> map(splat(+), zip(1:3,4:6)) 3-element Vector{Int64}: diff --git a/base/path.jl b/base/path.jl index 6d2fe933e4ec6e..3b8124f34f174a 100644 --- a/base/path.jl +++ b/base/path.jl @@ -435,11 +435,11 @@ normpath(a::AbstractString, b::AbstractString...) = normpath(joinpath(a,b...)) Convert a path to an absolute path by adding the current directory if necessary. Also normalizes the path as in [`normpath`](@ref). -# Example +# Examples If you are in a directory called `JuliaExample` and the data you are using is two levels up relative to the `JuliaExample` directory, you could write: -abspath("../../data") + abspath("../../data") Which gives a path like `"/home/JuliaUser/data/"`. diff --git a/base/process.jl b/base/process.jl index 24e676138bfae6..fbc4acfd83e805 100644 --- a/base/process.jl +++ b/base/process.jl @@ -114,6 +114,7 @@ end handle = Libc.malloc(_sizeof_uv_process) disassociate_julia_struct(handle) (; exec, flags, env, dir) = cmd + flags ⊻= UV_PROCESS_WINDOWS_DISABLE_EXACT_NAME # libuv inverts the default for this, so flip this bit now iolock_begin() err = ccall(:jl_spawn, Int32, (Cstring, Ptr{Cstring}, Ptr{Cvoid}, Ptr{Cvoid}, diff --git a/base/reflection.jl b/base/reflection.jl index f1a385068757c6..65a46242c389dd 100644 --- a/base/reflection.jl +++ b/base/reflection.jl @@ -880,6 +880,9 @@ issingletontype(@nospecialize(t)) = (@_total_meta; isa(t, DataType) && isdefined Compute a type that contains the intersection of `T` and `S`. Usually this will be the smallest such type or one close to it. + +A special case where exact behavior is guaranteed: when `T <: S`, +`typeintersect(S, T) == T == typeintersect(T, S)`. """ typeintersect(@nospecialize(a), @nospecialize(b)) = (@_total_meta; ccall(:jl_type_intersection, Any, (Any, Any), a::Type, b::Type)) @@ -1061,7 +1064,7 @@ fieldtypes(T::Type) = (@_foldable_meta; ntupleany(i -> fieldtype(T, i), fieldcou Return a collection of all instances of the given type, if applicable. Mostly used for enumerated types (see `@enum`). -# Example +# Examples ```jldoctest julia> @enum Color red blue green @@ -1332,6 +1335,15 @@ function method_instances(@nospecialize(f), @nospecialize(t), world::UInt) return results end +function method_instance(@nospecialize(f), @nospecialize(t); + world=Base.get_world_counter(), method_table=nothing) + tt = signature_type(f, t) + mi = ccall(:jl_method_lookup_by_tt, Any, + (Any, Csize_t, Any), + tt, world, method_table) + return mi::Union{Nothing, MethodInstance} +end + default_debug_info_kind() = unsafe_load(cglobal(:jl_default_debug_info_kind, Cint)) # this type mirrors jl_cgparams_t (documented in julia.h) @@ -1546,7 +1558,7 @@ internals. - `interp::Core.Compiler.AbstractInterpreter = Core.Compiler.NativeInterpreter(world)`: optional, controls the abstract interpreter to use, use the native interpreter if not specified. -# Example +# Examples One can put the argument types in a tuple to get the corresponding `code_typed`. @@ -1654,7 +1666,7 @@ internals. If it is an integer, it specifies the number of passes to run. If it is `nothing` (default), all passes are run. -# Example +# Examples One can put the argument types in a tuple to get the corresponding `code_ircode`. @@ -1752,7 +1764,7 @@ candidates for `f` and `types` (see also [`methods(f, types)`](@ref methods). methods matching with the given `f` and `types`. The list's order matches the order returned by `methods(f, types)`. -# Example +# Examples ```julia julia> Base.return_types(sum, Tuple{Vector{Int}}) @@ -1821,7 +1833,7 @@ Returns an inferred return type of the function call specified by `f` and `types It returns a single return type, taking into account all potential outcomes of any function call entailed by the given signature type. -# Example +# Examples ```julia julia> checksym(::Symbol) = :symbol; @@ -1892,7 +1904,7 @@ It works like [`Base.return_types`](@ref), but it infers the exception types ins methods matching with the given `f` and `types`. The list's order matches the order returned by `methods(f, types)`. -# Example +# Examples ```julia julia> throw_if_number(::Number) = error("number is given"); @@ -1975,7 +1987,7 @@ Returns the type of exception potentially thrown by the function call specified It returns a single exception type, taking into account all potential outcomes of any function call entailed by the given signature type. -# Example +# Examples ```julia julia> f1(x) = x * 2; @@ -2059,7 +2071,7 @@ Returns the possible computation effects of the function call specified by `f` a It returns a single effect, taking into account all potential outcomes of any function call entailed by the given signature type. -# Example +# Examples ```julia julia> f1(x) = x * 2; diff --git a/base/secretbuffer.jl b/base/secretbuffer.jl index 61eeffdb4f18df..bf37c3caa6c23b 100644 --- a/base/secretbuffer.jl +++ b/base/secretbuffer.jl @@ -200,7 +200,7 @@ resetting its pointer and size. This function is used to securely erase the sensitive data held in the buffer, reducing the potential for information leaks. -# Example +# Examples ```julia s = SecretBuffer() write(s, 's', 'e', 'c', 'r', 'e', 't') diff --git a/base/shell.jl b/base/shell.jl index dd4533c182534c..9f15550a1aa59f 100644 --- a/base/shell.jl +++ b/base/shell.jl @@ -416,7 +416,7 @@ rather than returned as a string. See also [`escape_microsoft_c_args`](@ref), [`shell_escape_posixly`](@ref). -# Example +# Examples ```jldoctest julia> Base.shell_escape_wincmd("a^\\"^o\\"^u\\"") "a^^\\"^o\\"^^u^\\"" diff --git a/base/show.jl b/base/show.jl index 8c59bb3bd9f6d4..a5bf5f73ba0ed0 100644 --- a/base/show.jl +++ b/base/show.jl @@ -3174,7 +3174,7 @@ representing argument `x` in terms of its type. (The double-colon is omitted if `toplevel=true`.) However, you can specialize this function for specific types to customize printing. -# Example +# Examples A SubArray created as `view(a, :, 3, 2:5)`, where `a` is a 3-dimensional Float64 array, has type diff --git a/base/slicearray.jl b/base/slicearray.jl index de4272550bdb07..215cf13f9651ea 100644 --- a/base/slicearray.jl +++ b/base/slicearray.jl @@ -96,7 +96,7 @@ See also [`eachrow`](@ref), [`eachcol`](@ref), [`mapslices`](@ref) and [`selectd !!! compat "Julia 1.9" Prior to Julia 1.9, this returned an iterator, and only a single dimension `dims` was supported. -# Example +# Examples ```jldoctest julia> m = [1 2 3; 4 5 6; 7 8 9] @@ -144,7 +144,7 @@ See also [`eachcol`](@ref), [`eachslice`](@ref) and [`mapslices`](@ref). !!! compat "Julia 1.9" Prior to Julia 1.9, this returned an iterator. -# Example +# Examples ```jldoctest julia> a = [1 2; 3 4] @@ -182,7 +182,7 @@ See also [`eachrow`](@ref), [`eachslice`](@ref) and [`mapslices`](@ref). !!! compat "Julia 1.9" Prior to Julia 1.9, this returned an iterator. -# Example +# Examples ```jldoctest julia> a = [1 2; 3 4] diff --git a/base/strings/annotated.jl b/base/strings/annotated.jl index 132801e49168a3..20a8f16db19626 100644 --- a/base/strings/annotated.jl +++ b/base/strings/annotated.jl @@ -45,7 +45,7 @@ AnnotatedString(s::S<:AbstractString, annotations::Vector{Tuple{UnitRange{Int}, A AnnotatedString can also be created with [`annotatedstring`](@ref), which acts much like [`string`](@ref) but preserves any annotations present in the arguments. -# Example +# Examples ```julia-repl julia> AnnotatedString("this is an example annotated string", diff --git a/base/threadingconstructs.jl b/base/threadingconstructs.jl index eef75916880daa..56d596958bc7e3 100644 --- a/base/threadingconstructs.jl +++ b/base/threadingconstructs.jl @@ -345,7 +345,7 @@ thread other than 1. In newly written library functions, `:static` scheduling is discouraged because the functions using this option cannot be called from arbitrary worker threads. -## Example +## Examples To illustrate of the different scheduling strategies, consider the following function `busywait` containing a non-yielding timed loop that runs for a given number of seconds. diff --git a/base/util.jl b/base/util.jl index 41eaf528d69252..a26a874c7a461c 100644 --- a/base/util.jl +++ b/base/util.jl @@ -375,7 +375,7 @@ then the user can enter just a newline character to select the `default`. See also `Base.winprompt` (for Windows) and `Base.getpass` for secure entry of passwords. -# Example +# Examples ```julia-repl julia> your_name = Base.prompt("Enter your name"); diff --git a/deps/checksums/libuv b/deps/checksums/libuv index 6ad61210bc0cce..7ac93952b8b34c 100644 --- a/deps/checksums/libuv +++ b/deps/checksums/libuv @@ -1,34 +1,34 @@ -LibUV.v2.0.1+14.aarch64-apple-darwin.tar.gz/md5/1a58ce9dc88984c3b5f7df97af6cbf83 -LibUV.v2.0.1+14.aarch64-apple-darwin.tar.gz/sha512/2bfd482ac759ac88d885371854affa8e358a10fea6c7756e0d1b366bc82ecbea56bdf24ca634525fb2a6fc2b3a5c77b07a4c6dec2923d8bffe2bc962bd3e7f84 -LibUV.v2.0.1+14.aarch64-linux-gnu.tar.gz/md5/7f270dd1e3046c8db432e350dd5cf114 -LibUV.v2.0.1+14.aarch64-linux-gnu.tar.gz/sha512/c0debcf17b54ba9f1588d4b267d610751f739d8ff96936c9d5fb6d8742039f8736c63fa70037322705569e221d73fb83c03b6ba9fb4454442fffd3a9f1a1a2da -LibUV.v2.0.1+14.aarch64-linux-musl.tar.gz/md5/07f56c32d5a2c12e6c351cf9f705631c -LibUV.v2.0.1+14.aarch64-linux-musl.tar.gz/sha512/8037d7aa0cb06850f055fd19cebdcfcf3146dde0d12768a9669bf05dcab91fdf3708798203258cb3f452158bdec7faae41e6afbb0e60b21403e683db3e23a1c9 -LibUV.v2.0.1+14.armv6l-linux-gnueabihf.tar.gz/md5/5558a7f68c7c375f40bc64da59fef0ad -LibUV.v2.0.1+14.armv6l-linux-gnueabihf.tar.gz/sha512/92ed6601cb5aa9a3ea2478a1485849543c9e847c8e85542e72f372a2d37c4c8b90f5ecb1bee1e462db31e1e8dba460f584b3cca9c833989c2b9ee404e355654e -LibUV.v2.0.1+14.armv6l-linux-musleabihf.tar.gz/md5/de6bfb7f0c0468b79e8895f166fb6340 -LibUV.v2.0.1+14.armv6l-linux-musleabihf.tar.gz/sha512/7948d007171bf57b827b489f3627ac74df447f4d696e8226e54e95ef0c8eed5a5ddbf758fbad841bc367f78cd61e6a5899eb478003dca3a79cb494b38cab830b -LibUV.v2.0.1+14.armv7l-linux-gnueabihf.tar.gz/md5/5be35de1d881f80981647c369b9b4ec8 -LibUV.v2.0.1+14.armv7l-linux-gnueabihf.tar.gz/sha512/458e5058ea4e794e0dc790da4c98569676056bac336df69762e8ccfec8f2955dcc55e8d090daa1b191c0ffa41392a04530c9bc28aa27cf411c1df2f1ba14bb97 -LibUV.v2.0.1+14.armv7l-linux-musleabihf.tar.gz/md5/8d034490da1ec2ef3dd3c69336177654 -LibUV.v2.0.1+14.armv7l-linux-musleabihf.tar.gz/sha512/7f595a8ab8b664d229cf6144e9ed1b5936ba8aaa70b92611ddb85bbe9046bb1b94d8417355a5abf058fb00023d4d56be0b2ddfd5dba896cd7b64e84e32dbfc5a -LibUV.v2.0.1+14.i686-linux-gnu.tar.gz/md5/ccb9aba78456c99b8473e8ddd328f90e -LibUV.v2.0.1+14.i686-linux-gnu.tar.gz/sha512/d382d90137db308933257a75e51d90988d6d07663b3b2915478547127d32f73ae6cdb4575d5ee20758f8850c7e85908fe4710c053cb361826621f22bc5b6502d -LibUV.v2.0.1+14.i686-linux-musl.tar.gz/md5/5ade48f16aa26bb68dc046d285c73043 -LibUV.v2.0.1+14.i686-linux-musl.tar.gz/sha512/f5728a5dc567268e59aa2697deb793ae427e11dcb6796c577e3da3ac24225ece5d4a6c4f903d4a7b184d3c3a3c8c1586c34b97e4a75de0a4e23ace720020fa8c -LibUV.v2.0.1+14.i686-w64-mingw32.tar.gz/md5/541210fef837c2ef7cffa508d282f9bb -LibUV.v2.0.1+14.i686-w64-mingw32.tar.gz/sha512/4541a02c59b66f97099b5264dce0cad90fcdf9a4d7ccd8e950cc1f3a530616a0fb2aa43db21b5b1f52819efef22cd0b68595d419e2e5b05924e344b0333f8bf8 -LibUV.v2.0.1+14.powerpc64le-linux-gnu.tar.gz/md5/26656d4eaae8739099c55054bad54f57 -LibUV.v2.0.1+14.powerpc64le-linux-gnu.tar.gz/sha512/f85f8cfd91e7b1b02b073931ef9a3bb05620641d18ada039744a92b8c40e5a3de8d7c5efa7189b88baf1eb11fbcf9e6d16031b86e40f99f1b7cfebb0f5c5adf1 -LibUV.v2.0.1+14.x86_64-apple-darwin.tar.gz/md5/c7da6b91394a20c43acdf6f680cb62e2 -LibUV.v2.0.1+14.x86_64-apple-darwin.tar.gz/sha512/238d22bd299ae3b0dfd24a5b38d6d0d07b751fb301487a2d1d2f5313ae3596f33492388ea9fbff549293787505fc527e174ebcd4068f1bda43b40bc19e016d89 -LibUV.v2.0.1+14.x86_64-linux-gnu.tar.gz/md5/8c8913068263257cce5042b725918e0e -LibUV.v2.0.1+14.x86_64-linux-gnu.tar.gz/sha512/a848381012d5a20a0c881f5835e479cfff811928ce508cc57041d69668782f2135c14c7e5388e7dbf693ae57aa1825d911f6f450b9e909cce45487b03a581a23 -LibUV.v2.0.1+14.x86_64-linux-musl.tar.gz/md5/16747c066b6d7fe56850c77f66ea7478 -LibUV.v2.0.1+14.x86_64-linux-musl.tar.gz/sha512/833a02f9191edf3b56f1e02f5671f22de6cb27ec3c9f770530ec95d8da7ba0b9c05bcdf6b094224ea8e43ba70918e1599f3237bd98900763daef80c327d3d2de -LibUV.v2.0.1+14.x86_64-unknown-freebsd.tar.gz/md5/e828eb79728e75766a72d7b304c9f989 -LibUV.v2.0.1+14.x86_64-unknown-freebsd.tar.gz/sha512/37df5b966f70b3d1e0eae603d4a6b00c84dffdfc3632ca581669a99a0cd894a81aff4361de3beed53ec032273f62cf397cf52085c6c387d0bbb2c57b59ae84fe -LibUV.v2.0.1+14.x86_64-w64-mingw32.tar.gz/md5/bded9d94435a70fd0dfff3f0fc605736 -LibUV.v2.0.1+14.x86_64-w64-mingw32.tar.gz/sha512/48793a386f6231d12f01b4718d87aaab409f0b807b03a3577e2401f7493caef36a5072fdc33f3cd3ce9733ba50ab344cb2e2fa6a21ba5adb56d6cca642afad0c -libuv-2723e256e952be0b015b3c0086f717c3d365d97e.tar.gz/md5/d2284d7f6fa75d6a35673d22e1be058b -libuv-2723e256e952be0b015b3c0086f717c3d365d97e.tar.gz/sha512/68d6ab740945b9ce3475118ce3d186fb67d7e8125784cc0c827df23d63f50c40c0261ef37365d8c11ab9462a8dd4e2e6b19e91e3c84b64d8fb84fd3894afc4ac +LibUV.v2.0.1+15.aarch64-apple-darwin.tar.gz/md5/f12ee08b8d5721bd88b651ac573c59ed +LibUV.v2.0.1+15.aarch64-apple-darwin.tar.gz/sha512/b3c53e04624d9c60e664db2eaaf3add696f95c52e55db0c577547f7bf7e045ce30cffa0e38c3451f483dcdb7ddcac1b7f43b694dfadb37282773ce416af1030a +LibUV.v2.0.1+15.aarch64-linux-gnu.tar.gz/md5/8cb9f4d6c6a4013fa9ed9ae120058275 +LibUV.v2.0.1+15.aarch64-linux-gnu.tar.gz/sha512/d4213ee47ebdcab4cc4719478608ffa461a5543a16656c2881587364c8ed1b39a2f418d5c3c6a04d7e6dd3df349f0afa72cd1df0e06db6146512356b37637024 +LibUV.v2.0.1+15.aarch64-linux-musl.tar.gz/md5/e23a0d7162fc3f09f0ea92d24cba3f4d +LibUV.v2.0.1+15.aarch64-linux-musl.tar.gz/sha512/f4a13eee72575092ab673777a53d43ce999a7a8bf847daa0a86b39bbfd3f6c1575f105a0bb629766268921ff94f10d354a0e53d32623f6ad35fca44e7bac25f8 +LibUV.v2.0.1+15.armv6l-linux-gnueabihf.tar.gz/md5/70ed0616cd3737a357b7571ab648d239 +LibUV.v2.0.1+15.armv6l-linux-gnueabihf.tar.gz/sha512/25a4b8a90b7bb62e31c1c2bb1d7e137050de26f311daa9f77be932ab3d9a2b92c82ce82ed37cc74a2b1cd5a60bd0dc412e92d31013d36ad35af2d4f376fbc0b0 +LibUV.v2.0.1+15.armv6l-linux-musleabihf.tar.gz/md5/e4320c51c8904a59c105f7b63d086c79 +LibUV.v2.0.1+15.armv6l-linux-musleabihf.tar.gz/sha512/bbc39d800277a66298c56849c1131a6f1958a2c8b2465b59527965a1bd3f36a4c87c1d7ad4be59ec0f4ca8f94ec1804a619eb963d956b77e645e0e00effc6613 +LibUV.v2.0.1+15.armv7l-linux-gnueabihf.tar.gz/md5/d5436552dc177fc3fd0cf4f575cc03b4 +LibUV.v2.0.1+15.armv7l-linux-gnueabihf.tar.gz/sha512/8d3722290151ecf65f4e3fe3440828492a7b115810b87c8711c5592f4dea69727e516228a5a1bdac430c74b288f12de390daf0a9408274aa27cdd69efc81cfee +LibUV.v2.0.1+15.armv7l-linux-musleabihf.tar.gz/md5/67e1ba03ddf2d2bdd79fef25a5976350 +LibUV.v2.0.1+15.armv7l-linux-musleabihf.tar.gz/sha512/535565657b5714da0db5c622b65b261a77f21f407b1166eee99f35ba3bb9c6fab4c7d1f3db70528767cef7c66c856c5101b01423be05efb9219ec4c76df0be6a +LibUV.v2.0.1+15.i686-linux-gnu.tar.gz/md5/ba1432ecd75e6a43ff197d51ba76446c +LibUV.v2.0.1+15.i686-linux-gnu.tar.gz/sha512/dc8940284d4ba05098037fcf4b3bada199878794ef34ad09d8992ef58e4c829b00a3fcca29c4f65b49edcab4274092232ff5d7619b3535333125043f89503cfc +LibUV.v2.0.1+15.i686-linux-musl.tar.gz/md5/237080cf5d1286a3d2f35d134a285d28 +LibUV.v2.0.1+15.i686-linux-musl.tar.gz/sha512/834f16a16cf6b765dfd094037c8a45ccdedc2eb9e45f527c6721eb0f60f4e56dc4f9b90a2a35e3ed10da4a937d8555e97034e0a29d733cac5352061ebe286799 +LibUV.v2.0.1+15.i686-w64-mingw32.tar.gz/md5/8a5261a6ce4200d272b5eda4fe9ecb31 +LibUV.v2.0.1+15.i686-w64-mingw32.tar.gz/sha512/b372b9368a9ac92775a8d6ee39b492905dc5f58f16d7edf792e0c2ffbd4507ede79139a24fe852dfa26068d0f076a4abf3c3b868a8a057b23fdbad80999d315f +LibUV.v2.0.1+15.powerpc64le-linux-gnu.tar.gz/md5/53db7b763af204477ce8f0bfae0ce15c +LibUV.v2.0.1+15.powerpc64le-linux-gnu.tar.gz/sha512/bbfe2518d4dc84fe73b7d3f3bcaf5aeef0db0d284c0e205e3e3670b8ce6f3ea593a0e52d125fd9a79cd098dba0d35f151cb46469fa25dfeef62ebcc966f94d4f +LibUV.v2.0.1+15.x86_64-apple-darwin.tar.gz/md5/b4699192c098564edc5589e90c47324e +LibUV.v2.0.1+15.x86_64-apple-darwin.tar.gz/sha512/2505e4060712143d3213747d4276c0b99dec78579d2ab0b71c5d7edf15ae80e0178138a11470c976d97de14e44b153dcb00c08c864523d7ee0ead8e48cf15d14 +LibUV.v2.0.1+15.x86_64-linux-gnu.tar.gz/md5/f5515c50106a0748b9a1986c912a00f3 +LibUV.v2.0.1+15.x86_64-linux-gnu.tar.gz/sha512/5822396039e14a5d919f2612559a8d62a925c4319e66eb05ed20faed754318762f5653851684701cd4ddb1edf10bfe25d252c3d9cd84228e498e825ba61146b1 +LibUV.v2.0.1+15.x86_64-linux-musl.tar.gz/md5/1962e6f21080e874d2ca0275c5b569b2 +LibUV.v2.0.1+15.x86_64-linux-musl.tar.gz/sha512/4702e13633d77a6c0aeb1e7cd252471a779177e20c68485130f420cc4878c8f7de7f0f51730008ba9dc0f275875a5947629d39aff200691e26f31d42e388d53d +LibUV.v2.0.1+15.x86_64-unknown-freebsd.tar.gz/md5/928a789c3cd3b4cefcc1cf13f5f179ac +LibUV.v2.0.1+15.x86_64-unknown-freebsd.tar.gz/sha512/ee58667b19fdf7ec0218b4645b3f5bed2e9fc01cc29eab8473ee02aaa044f94a48eb220c6427200aaf56eacf52d0f72156712d17017cfecbc25d3c1b71a4bd2f +LibUV.v2.0.1+15.x86_64-w64-mingw32.tar.gz/md5/d3b84729ee9d5a6e6a1e29357e25cced +LibUV.v2.0.1+15.x86_64-w64-mingw32.tar.gz/sha512/43ca5999d8e8ff820722b1a548bd4e277e95c739c3363ed6159d080dd06842316f5370e8e4f4a886bf76010f4aed2bbf01f6091845b0e84b75f709277c561649 +libuv-afa1c67fa496eb49ade1e520f76fd018a1409eaa.tar.gz/md5/3863ccd5a51f85cf76679070c99be6cd +libuv-afa1c67fa496eb49ade1e520f76fd018a1409eaa.tar.gz/sha512/bf4c705e05e730139b62de799331653eea2767898d654b8890ca2623db3adb9a1efcfcfab38af22e8ac44c67a9c5c018f1f7847a3703bee5f05657169a67d817 diff --git a/deps/libuv.version b/deps/libuv.version index 01bf4fecc6dc6f..9ae54aa7be91a7 100644 --- a/deps/libuv.version +++ b/deps/libuv.version @@ -3,5 +3,5 @@ LIBUV_JLL_NAME := LibUV ## source build LIBUV_VER := 2 -LIBUV_BRANCH=julia-uv2-1.44.2 -LIBUV_SHA1=2723e256e952be0b015b3c0086f717c3d365d97e +LIBUV_BRANCH=julia-uv2-1.48.0 +LIBUV_SHA1=afa1c67fa496eb49ade1e520f76fd018a1409eaa diff --git a/doc/src/base/collections.md b/doc/src/base/collections.md index 909f968b30bafc..9d68d55be3459c 100644 --- a/doc/src/base/collections.md +++ b/doc/src/base/collections.md @@ -225,14 +225,15 @@ Base.valtype Fully implemented by: - * [`IdDict`](@ref) * [`Dict`](@ref) + * [`IdDict`](@ref) * [`WeakKeyDict`](@ref) Partially implemented by: - * [`BitSet`](@ref) * [`Set`](@ref) + * [`BitSet`](@ref) + * [`IdSet`](@ref) * [`EnvDict`](@ref Base.EnvDict) * [`Array`](@ref) * [`BitArray`](@ref) @@ -246,6 +247,7 @@ Partially implemented by: Base.AbstractSet Base.Set Base.BitSet +Base.IdSet Base.union Base.union! Base.intersect @@ -264,8 +266,10 @@ Base.isdisjoint Fully implemented by: - * [`BitSet`](@ref) * [`Set`](@ref) + * [`BitSet`](@ref) + * [`IdSet`](@ref) + Partially implemented by: diff --git a/doc/src/devdocs/ast.md b/doc/src/devdocs/ast.md index f829b27663e624..c2cd0e92d58d20 100644 --- a/doc/src/devdocs/ast.md +++ b/doc/src/devdocs/ast.md @@ -627,6 +627,10 @@ for important details on how to modify these fields safely. The `MethodInstance` that this cache entry is derived from. + * `owner` + + A token that represents the owner of this `CodeInstance`. Will use `jl_egal` to match. + * `rettype`/`rettype_const` diff --git a/doc/src/devdocs/locks.md b/doc/src/devdocs/locks.md index f79f4f2b1e3e3a..50cdd738e3b344 100644 --- a/doc/src/devdocs/locks.md +++ b/doc/src/devdocs/locks.md @@ -155,6 +155,7 @@ MethodInstance/CodeInstance updates : Method->writelock, codegen lock > * specTypes > * sparam_vals > * def +> * owner > * These are set by `jl_type_infer` (while holding codegen lock): > * cache diff --git a/doc/src/manual/arrays.md b/doc/src/manual/arrays.md index 13b289becf6e07..6aa3a7a724e0e3 100644 --- a/doc/src/manual/arrays.md +++ b/doc/src/manual/arrays.md @@ -889,7 +889,7 @@ in their implementations, other arrays — like [`Diagonal`](@ref) — need the full set of cartesian indices to do their lookup (see [`IndexStyle`](@ref) to introspect which is which). -!!! warnings +!!! warning When iterating over all the indices for an array, it is better to iterate over [`eachindex(A)`](@ref) instead of `1:length(A)`. diff --git a/doc/src/manual/distributed-computing.md b/doc/src/manual/distributed-computing.md index e8a2146bdcf3e6..020181dd0a08c0 100644 --- a/doc/src/manual/distributed-computing.md +++ b/doc/src/manual/distributed-computing.md @@ -270,10 +270,11 @@ julia> addprocs(2) Module [`Distributed`](@ref man-distributed) must be explicitly loaded on the master process before invoking [`addprocs`](@ref). It is automatically made available on the worker processes. -Note that workers do not run a `~/.julia/config/startup.jl` startup script, nor do they synchronize -their global state (such as global variables, new method definitions, and loaded modules) with any -of the other running processes. You may use `addprocs(exeflags="--project")` to initialize a worker with -a particular environment, and then `@everywhere using ` or `@everywhere include("file.jl")`. +!!! note + Note that workers do not run a `~/.julia/config/startup.jl` startup script, nor do they synchronize + their global state (such as command-line switches, global variables, new method definitions, and loaded modules) with any + of the other running processes. You may use `addprocs(exeflags="--project")` to initialize a worker with + a particular environment, and then `@everywhere using ` or `@everywhere include("file.jl")`. Other types of clusters can be supported by writing your own custom `ClusterManager`, as described below in the [ClusterManagers](@ref) section. diff --git a/doc/src/manual/mathematical-operations.md b/doc/src/manual/mathematical-operations.md index 59af063ce8487c..c333aeb56c5d9e 100644 --- a/doc/src/manual/mathematical-operations.md +++ b/doc/src/manual/mathematical-operations.md @@ -394,7 +394,7 @@ Julia applies the following order and associativity of operations, from highest |:-------------- |:------------------------------------------------------------------------------------------------- |:-------------------------- | | Syntax | `.` followed by `::` | Left | | Exponentiation | `^` | Right | -| Unary | `+ - √` | Right[^1] | +| Unary | `+ - ! ~ ¬ √ ∛ ∜ ⋆ ± ∓ <: >:` | Right[^1] | | Bitshifts | `<< >> >>>` | Left | | Fractions | `//` | Left | | Multiplication | `* / % & \ ÷` | Left[^2] | diff --git a/src/builtins.c b/src/builtins.c index 412ccaf8bab04a..29aec53ae5a409 100644 --- a/src/builtins.c +++ b/src/builtins.c @@ -2378,6 +2378,7 @@ jl_fptr_args_t jl_get_builtin_fptr(jl_datatype_t *dt) jl_typemap_entry_t *entry = (jl_typemap_entry_t*)jl_atomic_load_relaxed(&dt->name->mt->defs); jl_method_instance_t *mi = jl_atomic_load_relaxed(&entry->func.method->unspecialized); jl_code_instance_t *ci = jl_atomic_load_relaxed(&mi->cache); + assert(ci->owner == jl_nothing); return jl_atomic_load_relaxed(&ci->specptr.fptr1); } diff --git a/src/gf.c b/src/gf.c index e8a5f7450b724a..00613cf9da486d 100644 --- a/src/gf.c +++ b/src/gf.c @@ -316,7 +316,7 @@ jl_datatype_t *jl_mk_builtin_func(jl_datatype_t *dt, const char *name, jl_fptr_a jl_atomic_store_relaxed(&m->unspecialized, mi); jl_gc_wb(m, mi); - jl_code_instance_t *codeinst = jl_new_codeinst(mi, + jl_code_instance_t *codeinst = jl_new_codeinst(mi, jl_nothing, (jl_value_t*)jl_any_type, (jl_value_t*)jl_any_type, jl_nothing, jl_nothing, 0, 1, ~(size_t)0, 0, 0, jl_nothing, 0); jl_mi_cache_insert(mi, codeinst); @@ -437,11 +437,13 @@ JL_DLLEXPORT jl_value_t *jl_call_in_typeinf_world(jl_value_t **args, int nargs) return ret; } -JL_DLLEXPORT jl_value_t *jl_rettype_inferred(jl_method_instance_t *mi, size_t min_world, size_t max_world) JL_NOTSAFEPOINT +STATIC_INLINE jl_value_t *_jl_rettype_inferred(jl_value_t *owner, jl_method_instance_t *mi, size_t min_world, size_t max_world) JL_NOTSAFEPOINT { jl_code_instance_t *codeinst = jl_atomic_load_relaxed(&mi->cache); while (codeinst) { - if (jl_atomic_load_relaxed(&codeinst->min_world) <= min_world && max_world <= jl_atomic_load_relaxed(&codeinst->max_world)) { + if (jl_atomic_load_relaxed(&codeinst->min_world) <= min_world && + max_world <= jl_atomic_load_relaxed(&codeinst->max_world) && + jl_egal(codeinst->owner, owner)) { jl_value_t *code = jl_atomic_load_relaxed(&codeinst->inferred); if (code && (code == jl_nothing || jl_ir_flag_inferred(code))) return (jl_value_t*)codeinst; @@ -450,24 +452,37 @@ JL_DLLEXPORT jl_value_t *jl_rettype_inferred(jl_method_instance_t *mi, size_t mi } return (jl_value_t*)jl_nothing; } -JL_DLLEXPORT jl_value_t *(*const jl_rettype_inferred_addr)(jl_method_instance_t *mi, size_t min_world, size_t max_world) JL_NOTSAFEPOINT = jl_rettype_inferred; + +JL_DLLEXPORT jl_value_t *jl_rettype_inferred(jl_value_t *owner, jl_method_instance_t *mi, size_t min_world, size_t max_world) JL_NOTSAFEPOINT +{ + return (jl_value_t*)_jl_rettype_inferred(owner, mi, min_world, max_world); +} + +JL_DLLEXPORT jl_value_t *jl_rettype_inferred_native(jl_method_instance_t *mi, size_t min_world, size_t max_world) JL_NOTSAFEPOINT +{ + return (jl_value_t*)_jl_rettype_inferred(jl_nothing, mi, min_world, max_world); +} + +JL_DLLEXPORT jl_value_t *(*const jl_rettype_inferred_addr)(jl_method_instance_t *mi, size_t min_world, size_t max_world) JL_NOTSAFEPOINT = jl_rettype_inferred_native; JL_DLLEXPORT jl_code_instance_t *jl_get_method_inferred( jl_method_instance_t *mi JL_PROPAGATES_ROOT, jl_value_t *rettype, size_t min_world, size_t max_world) { + jl_value_t *owner = jl_nothing; // TODO: owner should be arg jl_code_instance_t *codeinst = jl_atomic_load_relaxed(&mi->cache); while (codeinst) { if (jl_atomic_load_relaxed(&codeinst->min_world) == min_world && jl_atomic_load_relaxed(&codeinst->max_world) == max_world && + jl_egal(codeinst->owner, owner) && jl_egal(codeinst->rettype, rettype)) { return codeinst; } codeinst = jl_atomic_load_relaxed(&codeinst->next); } codeinst = jl_new_codeinst( - mi, rettype, (jl_value_t*)jl_any_type, NULL, NULL, + mi, owner, rettype, (jl_value_t*)jl_any_type, NULL, NULL, 0, min_world, max_world, 0, 0, jl_nothing, 0); jl_mi_cache_insert(mi, codeinst); return codeinst; @@ -484,7 +499,8 @@ JL_DLLEXPORT jl_code_instance_t *jl_get_codeinst_for_src( } JL_DLLEXPORT jl_code_instance_t *jl_new_codeinst( - jl_method_instance_t *mi, jl_value_t *rettype, jl_value_t *exctype, + jl_method_instance_t *mi, jl_value_t *owner, + jl_value_t *rettype, jl_value_t *exctype, jl_value_t *inferred_const, jl_value_t *inferred, int32_t const_flags, size_t min_world, size_t max_world, uint32_t ipo_effects, uint32_t effects, jl_value_t *analysis_results, @@ -496,6 +512,7 @@ JL_DLLEXPORT jl_code_instance_t *jl_new_codeinst( jl_code_instance_t *codeinst = (jl_code_instance_t*)jl_gc_alloc(ct->ptls, sizeof(jl_code_instance_t), jl_code_instance_type); codeinst->def = mi; + codeinst->owner = owner; jl_atomic_store_relaxed(&codeinst->min_world, min_world); jl_atomic_store_relaxed(&codeinst->max_world, max_world); codeinst->rettype = rettype; @@ -548,7 +565,7 @@ static int get_method_unspec_list(jl_typemap_entry_t *def, void *closure) if (!jl_is_svec(specializations)) { jl_method_instance_t *mi = (jl_method_instance_t*)specializations; assert(jl_is_method_instance(mi)); - if (jl_rettype_inferred(mi, world, world) == jl_nothing) + if (jl_rettype_inferred_native(mi, world, world) == jl_nothing) jl_array_ptr_1d_push((jl_array_t*)closure, (jl_value_t*)mi); return 1; } @@ -558,7 +575,7 @@ static int get_method_unspec_list(jl_typemap_entry_t *def, void *closure) jl_method_instance_t *mi = (jl_method_instance_t*)jl_svecref(specializations, i); if ((jl_value_t*)mi != jl_nothing) { assert(jl_is_method_instance(mi)); - if (jl_rettype_inferred(mi, world, world) == jl_nothing) + if (jl_rettype_inferred_native(mi, world, world) == jl_nothing) jl_array_ptr_1d_push((jl_array_t*)closure, (jl_value_t*)mi); } } @@ -678,7 +695,7 @@ JL_DLLEXPORT void jl_set_typeinf_func(jl_value_t *f) size_t i, l; for (i = 0, l = jl_array_nrows(unspec); i < l; i++) { jl_method_instance_t *mi = (jl_method_instance_t*)jl_array_ptr_ref(unspec, i); - if (jl_rettype_inferred(mi, world, world) == jl_nothing) + if (jl_rettype_inferred_native(mi, world, world) == jl_nothing) jl_type_infer(mi, world, 1); } JL_GC_POP(); @@ -1627,41 +1644,6 @@ JL_DLLEXPORT jl_value_t *jl_debug_method_invalidation(int state) return jl_nothing; } -// call external callbacks registered with this method_instance -static void invalidate_external(jl_method_instance_t *mi, size_t max_world) { - jl_array_t *callbacks = mi->callbacks; - if (callbacks) { - // AbstractInterpreter allows for MethodInstances to be present in non-local caches - // inform those caches about the invalidation. - JL_TRY { - size_t i, l = jl_array_nrows(callbacks); - jl_value_t **args; - JL_GC_PUSHARGS(args, 3); - // these arguments are constant per call - args[1] = (jl_value_t*)mi; - args[2] = jl_box_uint32(max_world); - - jl_task_t *ct = jl_current_task; - size_t last_age = ct->world_age; - ct->world_age = jl_get_world_counter(); - - jl_value_t **cbs = (jl_value_t**)jl_array_ptr_data(callbacks); - for (i = 0; i < l; i++) { - args[0] = cbs[i]; - jl_apply(args, 3); - } - ct->world_age = last_age; - JL_GC_POP(); - } - JL_CATCH { - jl_printf((JL_STREAM*)STDERR_FILENO, "error in invalidation callback: "); - jl_static_show((JL_STREAM*)STDERR_FILENO, jl_current_exception()); - jl_printf((JL_STREAM*)STDERR_FILENO, "\n"); - jlbacktrace(); // written to STDERR_FILENO - } - } -} - static void _invalidate_backedges(jl_method_instance_t *replaced_mi, size_t max_world, int depth); // recursively invalidate cached methods that had an edge to a replaced method @@ -1690,7 +1672,6 @@ static void invalidate_method_instance(jl_method_instance_t *replaced, size_t ma codeinst = jl_atomic_load_relaxed(&codeinst->next); } JL_GC_PUSH1(&replaced); - invalidate_external(replaced, max_world); // recurse to all backedges to update their valid range also _invalidate_backedges(replaced, max_world, depth + 1); JL_GC_POP(); @@ -1839,7 +1820,6 @@ static int invalidate_mt_cache(jl_typemap_entry_t *oldentry, void *closure0) } } if (intersects) { - // TODO call invalidate_external here? if (_jl_debug_method_invalidation) { jl_array_ptr_1d_push(_jl_debug_method_invalidation, (jl_value_t*)mi); jl_value_t *loctag = jl_cstr_to_string("invalidate_mt_cache"); @@ -1924,7 +1904,6 @@ static void jl_method_table_invalidate(jl_methtable_t *mt, jl_typemap_entry_t *m jl_method_instance_t *mi = (jl_method_instance_t*)jl_svecref(specializations, i); if ((jl_value_t*)mi != jl_nothing) { invalidated = 1; - invalidate_external(mi, max_world); invalidate_backedges(mi, max_world, "jl_method_table_disable"); } } @@ -2202,7 +2181,6 @@ void jl_method_table_activate(jl_methtable_t *mt, jl_typemap_entry_t *newentry) jl_array_del_end(backedges, nb - insb); } jl_array_ptr_1d_push(oldmi, (jl_value_t*)mi); - invalidate_external(mi, max_world); if (_jl_debug_method_invalidation && invalidated) { jl_array_ptr_1d_push(_jl_debug_method_invalidation, (jl_value_t*)mi); loctag = jl_cstr_to_string("jl_method_table_insert"); @@ -2302,7 +2280,7 @@ static jl_tupletype_t *lookup_arg_type_tuple(jl_value_t *arg1 JL_PROPAGATES_ROOT return jl_lookup_arg_tuple_type(arg1, args, nargs, 1); } -JL_DLLEXPORT jl_method_instance_t *jl_method_lookup_by_tt(jl_tupletype_t *tt, size_t world, jl_value_t *_mt) +JL_DLLEXPORT jl_value_t *jl_method_lookup_by_tt(jl_tupletype_t *tt, size_t world, jl_value_t *_mt) { jl_methtable_t *mt = NULL; if (_mt == jl_nothing) @@ -2311,7 +2289,10 @@ JL_DLLEXPORT jl_method_instance_t *jl_method_lookup_by_tt(jl_tupletype_t *tt, si assert(jl_isa(_mt, (jl_value_t*)jl_methtable_type)); mt = (jl_methtable_t*) _mt; } - return jl_mt_assoc_by_type(mt, tt, world); + jl_method_instance_t* mi = jl_mt_assoc_by_type(mt, tt, world); + if (!mi) + return jl_nothing; + return (jl_value_t*) mi; } JL_DLLEXPORT jl_method_instance_t *jl_method_lookup(jl_value_t **args, size_t nargs, size_t world) @@ -2503,7 +2484,7 @@ jl_code_instance_t *jl_compile_method_internal(jl_method_instance_t *mi, size_t jl_code_instance_t *unspec = jl_atomic_load_relaxed(&unspecmi->cache); jl_callptr_t unspec_invoke = NULL; if (unspec && (unspec_invoke = jl_atomic_load_acquire(&unspec->invoke))) { - jl_code_instance_t *codeinst = jl_new_codeinst(mi, + jl_code_instance_t *codeinst = jl_new_codeinst(mi, jl_nothing, (jl_value_t*)jl_any_type, (jl_value_t*)jl_any_type, NULL, NULL, 0, 1, ~(size_t)0, 0, 0, jl_nothing, 0); void *unspec_fptr = jl_atomic_load_relaxed(&unspec->specptr.fptr); @@ -2530,7 +2511,7 @@ jl_code_instance_t *jl_compile_method_internal(jl_method_instance_t *mi, size_t compile_option == JL_OPTIONS_COMPILE_MIN) { jl_code_info_t *src = jl_code_for_interpreter(mi, world); if (!jl_code_requires_compiler(src, 0)) { - jl_code_instance_t *codeinst = jl_new_codeinst(mi, + jl_code_instance_t *codeinst = jl_new_codeinst(mi, jl_nothing, (jl_value_t*)jl_any_type, (jl_value_t*)jl_any_type, NULL, NULL, 0, 1, ~(size_t)0, 0, 0, jl_nothing, 0); jl_atomic_store_release(&codeinst->invoke, jl_fptr_interpret_call); @@ -2565,7 +2546,8 @@ jl_code_instance_t *jl_compile_method_internal(jl_method_instance_t *mi, size_t // only these care about the exact specTypes, otherwise we can use it directly return ucache; } - codeinst = jl_new_codeinst(mi, (jl_value_t*)jl_any_type, (jl_value_t*)jl_any_type, NULL, NULL, + codeinst = jl_new_codeinst(mi, jl_nothing, + (jl_value_t*)jl_any_type, (jl_value_t*)jl_any_type, NULL, NULL, 0, 1, ~(size_t)0, 0, 0, jl_nothing, 0); void *unspec_fptr = jl_atomic_load_relaxed(&ucache->specptr.fptr); if (unspec_fptr) { @@ -2815,10 +2797,10 @@ static jl_method_instance_t *jl_get_compile_hint_specialization(jl_tupletype_t * static void _generate_from_hint(jl_method_instance_t *mi, size_t world) { - jl_value_t *codeinst = jl_rettype_inferred(mi, world, world); + jl_value_t *codeinst = jl_rettype_inferred_native(mi, world, world); if (codeinst == jl_nothing) { (void)jl_type_infer(mi, world, 1); - codeinst = jl_rettype_inferred(mi, world, world); + codeinst = jl_rettype_inferred_native(mi, world, world); } if (codeinst != jl_nothing) { if (jl_atomic_load_relaxed(&((jl_code_instance_t*)codeinst)->invoke) == jl_fptr_const_return) @@ -2857,10 +2839,10 @@ JL_DLLEXPORT void jl_compile_method_instance(jl_method_instance_t *mi, jl_tuplet jl_method_instance_t *mi2 = jl_specializations_get_linfo(mi->def.method, (jl_value_t*)types2, tpenv2); JL_GC_POP(); jl_atomic_store_relaxed(&mi2->precompiled, 1); - if (jl_rettype_inferred(mi2, world, world) == jl_nothing) + if (jl_rettype_inferred_native(mi2, world, world) == jl_nothing) (void)jl_type_infer(mi2, world, 1); if (jl_typeinf_func && jl_atomic_load_relaxed(&mi->def.method->primary_world) <= tworld) { - if (jl_rettype_inferred(mi2, tworld, tworld) == jl_nothing) + if (jl_rettype_inferred_native(mi2, tworld, tworld) == jl_nothing) (void)jl_type_infer(mi2, tworld, 1); } } diff --git a/src/jl_uv.c b/src/jl_uv.c index 582484f78e181f..e447faf8fa9c21 100644 --- a/src/jl_uv.c +++ b/src/jl_uv.c @@ -39,21 +39,24 @@ static void walk_print_cb(uv_handle_t *h, void *arg) const char *type = uv_handle_type_name(h->type); if (!type) type = ""; + size_t resource_id; // fits an int or pid_t on Unix, HANDLE or PID on Windows uv_os_fd_t fd; if (h->type == UV_PROCESS) - fd = uv_process_get_pid((uv_process_t*)h); - else if (uv_fileno(h, &fd)) - fd = (uv_os_fd_t)-1; + resource_id = (size_t)uv_process_get_pid((uv_process_t*)h); + else if (uv_fileno(h, &fd) == 0) + resource_id = (size_t)fd; + else + resource_id = -1; const char *pad = " "; // 16 spaces - int npad = fd == -1 ? 0 : snprintf(NULL, 0, "%zd", (size_t)fd); + int npad = resource_id == -1 ? 0 : snprintf(NULL, 0, "%zd", resource_id); if (npad < 0) npad = 0; npad += strlen(type); pad += npad < strlen(pad) ? npad : strlen(pad); - if (fd == -1) + if (resource_id == -1) jl_safe_printf(" %s %s%p->%p\n", type, pad, (void*)h, (void*)h->data); else - jl_safe_printf(" %s[%zd] %s%p->%p\n", type, (size_t)fd, pad, (void*)h, (void*)h->data); + jl_safe_printf(" %s[%zd] %s%p->%p\n", type, resource_id, pad, (void*)h, (void*)h->data); } static void wait_empty_func(uv_timer_t *t) @@ -1110,31 +1113,39 @@ static inline int ishexchar(char c) JL_DLLEXPORT int jl_ispty(uv_pipe_t *pipe) { - if (pipe->type != UV_NAMED_PIPE) return 0; + char namebuf[0]; size_t len = 0; - if (uv_pipe_getpeername(pipe, NULL, &len) != UV_ENOBUFS) return 0; + if (pipe->type != UV_NAMED_PIPE) + return 0; + if (uv_pipe_getpeername(pipe, namebuf, &len) != UV_ENOBUFS) + return 0; char *name = (char*)alloca(len + 1); - if (uv_pipe_getpeername(pipe, name, &len)) return 0; + if (uv_pipe_getpeername(pipe, name, &len)) + return 0; name[len] = '\0'; // return true if name matches regex: // ^\\\\?\\pipe\\(msys|cygwin)-[0-9a-z]{16}-[pt]ty[1-9][0-9]*- //jl_printf(JL_STDERR,"pipe_name: %s\n", name); int n = 0; - if (!strncmp(name,"\\\\?\\pipe\\msys-",14)) + if (!strncmp(name, "\\\\?\\pipe\\msys-", 14)) n = 14; - else if (!strncmp(name,"\\\\?\\pipe\\cygwin-",16)) + else if (!strncmp(name, "\\\\?\\pipe\\cygwin-", 16)) n = 16; else return 0; //jl_printf(JL_STDERR,"prefix pass\n"); name += n; for (int n = 0; n < 16; n++) - if (!ishexchar(*name++)) return 0; + if (!ishexchar(*name++)) + return 0; //jl_printf(JL_STDERR,"hex pass\n"); - if ((*name++)!='-') return 0; - if (*name != 'p' && *name != 't') return 0; + if ((*name++)!='-') + return 0; + if (*name != 'p' && *name != 't') + return 0; name++; - if (*name++ != 't' || *name++ != 'y') return 0; + if (*name++ != 't' || *name++ != 'y') + return 0; //jl_printf(JL_STDERR,"tty pass\n"); return 1; } diff --git a/src/jltypes.c b/src/jltypes.c index 84e90303affaa4..bf7561fc29e1b0 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -3265,25 +3265,23 @@ void jl_init_types(void) JL_GC_DISABLED jl_method_instance_type = jl_new_datatype(jl_symbol("MethodInstance"), core, jl_any_type, jl_emptysvec, - jl_perm_symsvec(10, + jl_perm_symsvec(9, "def", "specTypes", "sparam_vals", "uninferred", "backedges", - "callbacks", "cache", "inInference", "cache_with_orig", "precompiled"), - jl_svec(10, + jl_svec(9, jl_new_struct(jl_uniontype_type, jl_method_type, jl_module_type), jl_any_type, jl_simplevector_type, jl_any_type, jl_array_any_type, jl_any_type, - jl_any_type, jl_bool_type, jl_bool_type, jl_bool_type), @@ -3291,7 +3289,7 @@ void jl_init_types(void) JL_GC_DISABLED 0, 1, 3); // These fields should be constant, but Serialization wants to mutate them in initialization //const static uint32_t method_instance_constfields[1] = { 0x00000007 }; // (1<<0)|(1<<1)|(1<<2); - const static uint32_t method_instance_atomicfields[1] = { 0x00000248 }; // (1<<3)|(1<<6)|(1<<9); + const static uint32_t method_instance_atomicfields[1] = { 0x00000128 }; // (1<<3)|(1<<5)|(1<<8); //Fields 4 and 5 must be protected by method->write_lock, and thus all operations on jl_method_instance_t are threadsafe. TODO: except inInference //jl_method_instance_type->name->constfields = method_instance_constfields; jl_method_instance_type->name->atomicfields = method_instance_atomicfields; @@ -3299,8 +3297,9 @@ void jl_init_types(void) JL_GC_DISABLED jl_code_instance_type = jl_new_datatype(jl_symbol("CodeInstance"), core, jl_any_type, jl_emptysvec, - jl_perm_symsvec(16, + jl_perm_symsvec(17, "def", + "owner", "next", "min_world", "max_world", @@ -3312,11 +3311,12 @@ void jl_init_types(void) JL_GC_DISABLED //"absolute_max", "ipo_purity_bits", "purity_bits", "analysis_results", - "isspecsig", "precompile", "relocatability", + "specsigflags", "precompile", "relocatability", "invoke", "specptr"), // function object decls - jl_svec(16, + jl_svec(17, jl_method_instance_type, jl_any_type, + jl_any_type, jl_ulong_type, jl_ulong_type, jl_any_type, @@ -3333,11 +3333,11 @@ void jl_init_types(void) JL_GC_DISABLED jl_any_type, jl_any_type), // fptrs jl_emptysvec, 0, 1, 1); - jl_svecset(jl_code_instance_type->types, 1, jl_code_instance_type); - const static uint32_t code_instance_constfields[1] = { 0b0000010101110001 }; // Set fields 1, 5-7, 9, 11 as const - const static uint32_t code_instance_atomicfields[1] = { 0b1101001010001110 }; // Set fields 2-4, 8, 10, 13, 15-16 as atomic - //Fields 3-4 are only operated on by construction and deserialization, so are const at runtime - //Fields 11 and 15 must be protected by locks, and thus all operations on jl_code_instance_t are threadsafe + jl_svecset(jl_code_instance_type->types, 2, jl_code_instance_type); + const static uint32_t code_instance_constfields[1] = { 0b00000101011100011 }; // Set fields 1, 2, 6-8, 10, 12 as const + const static uint32_t code_instance_atomicfields[1] = { 0b11011010100011100 }; // Set fields 3-5, 9, 11, 13-14, 16-17 as atomic + //Fields 4-5 are only operated on by construction and deserialization, so are const at runtime + //Fields 12 and 16 must be protected by locks, and thus all operations on jl_code_instance_t are threadsafe jl_code_instance_type->name->constfields = code_instance_constfields; jl_code_instance_type->name->atomicfields = code_instance_atomicfields; @@ -3476,9 +3476,9 @@ void jl_init_types(void) JL_GC_DISABLED jl_svecset(jl_methtable_type->types, 9, jl_uint8_type); jl_svecset(jl_methtable_type->types, 10, jl_uint8_type); jl_svecset(jl_method_type->types, 12, jl_method_instance_type); - jl_svecset(jl_method_instance_type->types, 6, jl_code_instance_type); - jl_svecset(jl_code_instance_type->types, 14, jl_voidpointer_type); + jl_svecset(jl_method_instance_type->types, 5, jl_code_instance_type); jl_svecset(jl_code_instance_type->types, 15, jl_voidpointer_type); + jl_svecset(jl_code_instance_type->types, 16, jl_voidpointer_type); jl_svecset(jl_binding_type->types, 1, jl_globalref_type); jl_svecset(jl_binding_type->types, 2, jl_binding_type); diff --git a/src/julia.h b/src/julia.h index 1ad79675287860..852b671f744f68 100644 --- a/src/julia.h +++ b/src/julia.h @@ -391,7 +391,6 @@ struct _jl_method_instance_t { jl_svec_t *sparam_vals; // static parameter values, indexed by def.method->sig _Atomic(jl_value_t*) uninferred; // cached uncompressed code, for generated functions, top-level thunks, or the interpreter jl_array_t *backedges; // list of method-instances which call this method-instance; `invoke` records (invokesig, caller) pairs - jl_array_t *callbacks; // list of callback functions to inform external caches about invalidations _Atomic(struct _jl_code_instance_t*) cache; uint8_t inInference; // flags to tell if inference is running on this object uint8_t cache_with_orig; // !cache_with_specTypes @@ -412,6 +411,7 @@ typedef struct _jl_opaque_closure_t { typedef struct _jl_code_instance_t { JL_DATA_TYPE jl_method_instance_t *def; // method this is specialized from + jl_value_t *owner; // Compiler token this belongs to, `jl_nothing` is reserved for native _Atomic(struct _jl_code_instance_t*) next; // pointer to the next cache entry // world range for which this object is valid to use @@ -2545,7 +2545,7 @@ typedef struct { int gcstack_arg; // Pass the ptls value as an argument with swiftself int use_jlplt; // Whether to use the Julia PLT mechanism or emit symbols directly - // Cache access. Default: jl_rettype_inferred. + // Cache access. Default: jl_rettype_inferred_native. jl_codeinstance_lookup_t lookup; } jl_cgparams_t; extern JL_DLLEXPORT int jl_default_debug_info_kind; diff --git a/src/julia_internal.h b/src/julia_internal.h index e140dfa205d8ef..14b8b4f43ee929 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -669,7 +669,8 @@ jl_method_instance_t *jl_get_unspecialized_from_mi(jl_method_instance_t *method jl_method_instance_t *jl_get_unspecialized(jl_method_t *def JL_PROPAGATES_ROOT); JL_DLLEXPORT jl_code_instance_t* jl_new_codeinst( - jl_method_instance_t *mi, jl_value_t *rettype, jl_value_t *exctype, + jl_method_instance_t *mi, jl_value_t *owner, + jl_value_t *rettype, jl_value_t *exctype, jl_value_t *inferred_const, jl_value_t *inferred, int32_t const_flags, size_t min_world, size_t max_world, uint32_t ipo_effects, uint32_t effects, jl_value_t *analysis_results, @@ -809,7 +810,7 @@ JL_DLLEXPORT int jl_is_toplevel_only_expr(jl_value_t *e) JL_NOTSAFEPOINT; jl_value_t *jl_call_scm_on_ast_and_loc(const char *funcname, jl_value_t *expr, jl_module_t *inmodule, const char *file, int line); -JL_DLLEXPORT jl_method_instance_t *jl_method_lookup_by_tt(jl_tupletype_t *tt, size_t world, jl_value_t *_mt); +JL_DLLEXPORT jl_value_t *jl_method_lookup_by_tt(jl_tupletype_t *tt, size_t world, jl_value_t *_mt); JL_DLLEXPORT jl_method_instance_t *jl_method_lookup(jl_value_t **args, size_t nargs, size_t world); jl_value_t *jl_gf_invoke_by_method(jl_method_t *method, jl_value_t *gf, jl_value_t **args, size_t nargs); @@ -1021,7 +1022,7 @@ JL_DLLEXPORT jl_method_t *jl_new_method_uninit(jl_module_t*); JL_DLLEXPORT jl_methtable_t *jl_new_method_table(jl_sym_t *name, jl_module_t *module); JL_DLLEXPORT jl_method_instance_t *jl_get_specialization1(jl_tupletype_t *types, size_t world, size_t *min_valid, size_t *max_valid, int mt_cache); jl_method_instance_t *jl_get_specialized(jl_method_t *m, jl_value_t *types, jl_svec_t *sp); -JL_DLLEXPORT jl_value_t *jl_rettype_inferred(jl_method_instance_t *li JL_PROPAGATES_ROOT, size_t min_world, size_t max_world); +JL_DLLEXPORT jl_value_t *jl_rettype_inferred(jl_value_t *owner, jl_method_instance_t *li JL_PROPAGATES_ROOT, size_t min_world, size_t max_world); JL_DLLEXPORT jl_code_instance_t *jl_method_compiled(jl_method_instance_t *mi JL_PROPAGATES_ROOT, size_t world) JL_NOTSAFEPOINT; JL_DLLEXPORT jl_value_t *jl_methtable_lookup(jl_methtable_t *mt JL_PROPAGATES_ROOT, jl_value_t *type, size_t world); JL_DLLEXPORT jl_method_instance_t *jl_specializations_get_linfo( diff --git a/src/method.c b/src/method.c index 3d3cc4cb7ea4e3..88d43fb4b22ee3 100644 --- a/src/method.c +++ b/src/method.c @@ -488,7 +488,6 @@ JL_DLLEXPORT jl_method_instance_t *jl_new_method_instance_uninit(void) mi->sparam_vals = jl_emptysvec; jl_atomic_store_relaxed(&mi->uninferred, NULL); mi->backedges = NULL; - mi->callbacks = NULL; jl_atomic_store_relaxed(&mi->cache, NULL); mi->inInference = 0; mi->cache_with_orig = 0; diff --git a/src/opaque_closure.c b/src/opaque_closure.c index 0b0d1052bd4495..45b08fee668db5 100644 --- a/src/opaque_closure.c +++ b/src/opaque_closure.c @@ -153,7 +153,7 @@ JL_DLLEXPORT jl_opaque_closure_t *jl_new_opaque_closure_from_code_info(jl_tuplet sigtype = jl_argtype_with_function(env, (jl_value_t*)argt); jl_method_instance_t *mi = jl_specializations_get_linfo((jl_method_t*)root, sigtype, jl_emptysvec); - inst = jl_new_codeinst(mi, rt_ub, (jl_value_t*)jl_any_type, NULL, (jl_value_t*)ci, + inst = jl_new_codeinst(mi, jl_nothing, rt_ub, (jl_value_t*)jl_any_type, NULL, (jl_value_t*)ci, 0, world, world, 0, 0, jl_nothing, 0); jl_mi_cache_insert(mi, inst); diff --git a/src/staticdata.c b/src/staticdata.c index 8489fa116688e2..0d38dddb79aafb 100644 --- a/src/staticdata.c +++ b/src/staticdata.c @@ -803,7 +803,6 @@ static void jl_insert_into_serialization_queue(jl_serializer_state *s, jl_value_ // so must not be present here record_field_change((jl_value_t**)&mi->uninferred, NULL); record_field_change((jl_value_t**)&mi->backedges, NULL); - record_field_change((jl_value_t**)&mi->callbacks, NULL); record_field_change((jl_value_t**)&mi->cache, NULL); } else { @@ -835,6 +834,11 @@ static void jl_insert_into_serialization_queue(jl_serializer_state *s, jl_value_ if (s->incremental && jl_is_code_instance(v)) { jl_code_instance_t *ci = (jl_code_instance_t*)v; // make sure we don't serialize other reachable cache entries of foreign methods + // Should this now be: + // if (ci !in ci->defs->cache) + // record_field_change((jl_value_t**)&ci->next, NULL); + // Why are we checking that the method/module this originates from is in_image? + // and then disconnect this CI? if (jl_object_in_image((jl_value_t*)ci->def->def.value)) { // TODO: if (ci in ci->defs->cache) record_field_change((jl_value_t**)&ci->next, NULL); @@ -2392,7 +2396,6 @@ static void strip_specializations_(jl_method_instance_t *mi) if (jl_options.strip_ir) { record_field_change((jl_value_t**)&mi->uninferred, NULL); record_field_change((jl_value_t**)&mi->backedges, NULL); - record_field_change((jl_value_t**)&mi->callbacks, NULL); } } diff --git a/src/staticdata_utils.c b/src/staticdata_utils.c index aa39c53844a560..fc7a59d9d0bf9a 100644 --- a/src/staticdata_utils.c +++ b/src/staticdata_utils.c @@ -239,11 +239,7 @@ static jl_array_t *queue_external_cis(jl_array_t *list) assert(found == 0 || found == 1 || found == 2); assert(stack.len == 0); if (found == 1 && jl_atomic_load_relaxed(&ci->max_world) == ~(size_t)0) { - void **bp = ptrhash_bp(&visited, mi); - if (*bp != (void*)((char*)HT_NOTFOUND + 3)) { - *bp = (void*)((char*)HT_NOTFOUND + 3); - jl_array_ptr_1d_push(new_ext_cis, (jl_value_t*)ci); - } + jl_array_ptr_1d_push(new_ext_cis, (jl_value_t*)ci); } } } @@ -1188,13 +1184,23 @@ static void jl_insert_backedges(jl_array_t *edges, jl_array_t *ext_targets, jl_a jl_code_instance_t *ci = (jl_code_instance_t*)jl_array_ptr_ref(ext_ci_list, i); if (jl_atomic_load_relaxed(&ci->max_world) == WORLD_AGE_REVALIDATION_SENTINEL) { assert(jl_atomic_load_relaxed(&ci->min_world) == minworld); - ptrhash_put(&cis_pending_validation, (void*)ci->def, (void*)ci); + void **bp = ptrhash_bp(&cis_pending_validation, (void*)ci->def); + assert(!jl_atomic_load_relaxed(&ci->next)); + if (*bp == HT_NOTFOUND) + *bp = (void*)ci; + else { + // Do ci->owner bifurcates the cache, we temporarily + // form a linked list of all the CI that need to be connected later + jl_code_instance_t *prev_ci = (jl_code_instance_t *)*bp; + jl_atomic_store_relaxed(&ci->next, prev_ci); + *bp = (void*)ci; + } } else { assert(jl_atomic_load_relaxed(&ci->min_world) == 1); assert(jl_atomic_load_relaxed(&ci->max_world) == ~(size_t)0); jl_method_instance_t *caller = ci->def; - if (jl_atomic_load_relaxed(&ci->inferred) && jl_rettype_inferred(caller, minworld, ~(size_t)0) == jl_nothing) { + if (jl_atomic_load_relaxed(&ci->inferred) && jl_rettype_inferred(ci->owner, caller, minworld, ~(size_t)0) == jl_nothing) { jl_mi_cache_insert(caller, ci); } //jl_static_show((JL_STREAM*)ios_stderr, (jl_value_t*)caller); @@ -1237,18 +1243,26 @@ static void jl_insert_backedges(jl_array_t *edges, jl_array_t *ext_targets, jl_a // Update any external CIs and add them to the cache. assert(jl_is_code_instance(ci)); jl_code_instance_t *codeinst = (jl_code_instance_t*)ci; - assert(jl_atomic_load_relaxed(&codeinst->min_world) == minworld); - assert(jl_atomic_load_relaxed(&codeinst->max_world) == WORLD_AGE_REVALIDATION_SENTINEL); - assert(jl_atomic_load_relaxed(&codeinst->inferred)); - jl_atomic_store_relaxed(&codeinst->max_world, maxvalid); - - if (jl_rettype_inferred(caller, minworld, maxvalid) != jl_nothing) { - // We already got a code instance for this world age range from somewhere else - we don't need - // this one. - continue; + while (codeinst) { + jl_code_instance_t *next_ci = jl_atomic_load_relaxed(&codeinst->next); + jl_atomic_store_relaxed(&codeinst->next, NULL); + + jl_value_t *owner = codeinst->owner; + JL_GC_PROMISE_ROOTED(owner); + + assert(jl_atomic_load_relaxed(&codeinst->min_world) == minworld); + assert(jl_atomic_load_relaxed(&codeinst->max_world) == WORLD_AGE_REVALIDATION_SENTINEL); + assert(jl_atomic_load_relaxed(&codeinst->inferred)); + jl_atomic_store_relaxed(&codeinst->max_world, maxvalid); + + if (jl_rettype_inferred(owner, caller, minworld, maxvalid) != jl_nothing) { + // We already got a code instance for this world age range from somewhere else - we don't need + // this one. + } else { + jl_mi_cache_insert(caller, codeinst); + } + codeinst = next_ci; } - - jl_mi_cache_insert(caller, codeinst); } else { // Likely internal. Find the CI already in the cache hierarchy. diff --git a/stdlib/Dates/src/conversions.jl b/stdlib/Dates/src/conversions.jl index 30f1f2581d1fa8..0d413d2cf53a18 100644 --- a/stdlib/Dates/src/conversions.jl +++ b/stdlib/Dates/src/conversions.jl @@ -84,7 +84,7 @@ today() = Date(now()) Return a `DateTime` corresponding to the user's system time as UTC/GMT. For other time zones, see the TimeZones.jl package. -# Example +# Examples ```julia julia> now(UTC) 2023-01-04T10:52:24.864 diff --git a/stdlib/Dates/src/io.jl b/stdlib/Dates/src/io.jl index 257e86064c2fbb..3980ad3a7245f4 100644 --- a/stdlib/Dates/src/io.jl +++ b/stdlib/Dates/src/io.jl @@ -472,7 +472,7 @@ end Describes the ISO8601 formatting for a date and time. This is the default value for `Dates.format` of a `DateTime`. -# Example +# Examples ```jldoctest julia> Dates.format(DateTime(2018, 8, 8, 12, 0, 43, 1), ISODateTimeFormat) "2018-08-08T12:00:43.001" @@ -486,7 +486,7 @@ default_format(::Type{DateTime}) = ISODateTimeFormat Describes the ISO8601 formatting for a date. This is the default value for `Dates.format` of a `Date`. -# Example +# Examples ```jldoctest julia> Dates.format(Date(2018, 8, 8), ISODateFormat) "2018-08-08" @@ -500,7 +500,7 @@ default_format(::Type{Date}) = ISODateFormat Describes the ISO8601 formatting for a time. This is the default value for `Dates.format` of a `Time`. -# Example +# Examples ```jldoctest julia> Dates.format(Time(12, 0, 43, 1), ISOTimeFormat) "12:00:43.001" @@ -514,7 +514,7 @@ default_format(::Type{Time}) = ISOTimeFormat Describes the RFC1123 formatting for a date and time. -# Example +# Examples ```jldoctest julia> Dates.format(DateTime(2018, 8, 8, 12, 0, 43, 1), RFC1123Format) "Wed, 08 Aug 2018 12:00:43" @@ -538,7 +538,7 @@ pattern given in the `format` string (see [`DateFormat`](@ref) for syntax). that you create a [`DateFormat`](@ref) object instead and use that as the second argument to avoid performance loss when using the same format repeatedly. -# Example +# Examples ```jldoctest julia> DateTime("2020-01-01", "yyyy-mm-dd") 2020-01-01T00:00:00 @@ -578,7 +578,7 @@ in the `format` string (see [`DateFormat`](@ref) for syntax). that you create a [`DateFormat`](@ref) object instead and use that as the second argument to avoid performance loss when using the same format repeatedly. -# Example +# Examples ```jldoctest julia> Date("2020-01-01", "yyyy-mm-dd") 2020-01-01 @@ -618,7 +618,7 @@ in the `format` string (see [`DateFormat`](@ref) for syntax). that you create a [`DateFormat`](@ref) object instead and use that as the second argument to avoid performance loss when using the same format repeatedly. -# Example +# Examples ```jldoctest julia> Time("12:34pm", "HH:MMp") 12:34:00 diff --git a/stdlib/FileWatching/test/runtests.jl b/stdlib/FileWatching/test/runtests.jl index 9ba6456d20a981..b9ad8d9bc77776 100644 --- a/stdlib/FileWatching/test/runtests.jl +++ b/stdlib/FileWatching/test/runtests.jl @@ -161,7 +161,7 @@ test2_12992() ####################################################################### # This section tests file watchers. # ####################################################################### -F_GETPATH = Sys.islinux() || Sys.iswindows() || Sys.isapple() # platforms where F_GETPATH is available +F_GETPATH = Sys.islinux() || Sys.iswindows() || Sys.isapple() || Sys.isfreebsd() # platforms where F_GETPATH is available F_PATH = F_GETPATH ? "afile.txt" : "" dir = mktempdir() file = joinpath(dir, "afile.txt") diff --git a/stdlib/InteractiveUtils/src/editless.jl b/stdlib/InteractiveUtils/src/editless.jl index 74fc5c6becfbd9..5b87dc0c57d404 100644 --- a/stdlib/InteractiveUtils/src/editless.jl +++ b/stdlib/InteractiveUtils/src/editless.jl @@ -77,7 +77,7 @@ already work: - pycharm - bbedit -# Example: +# Examples The following defines the usage of terminal-based `emacs`: diff --git a/stdlib/LibUV_jll/Project.toml b/stdlib/LibUV_jll/Project.toml index 605c1115b3d34c..8089516c1df148 100644 --- a/stdlib/LibUV_jll/Project.toml +++ b/stdlib/LibUV_jll/Project.toml @@ -1,6 +1,6 @@ name = "LibUV_jll" uuid = "183b4373-6708-53ba-ad28-60e28bb38547" -version = "2.0.1+14" +version = "2.0.1+15" [deps] Libdl = "8f399da3-3557-5675-b5ff-fb832c97cbdb" diff --git a/stdlib/LinearAlgebra/src/eigen.jl b/stdlib/LinearAlgebra/src/eigen.jl index 4ba540d42b2614..d1d2a156b1ed46 100644 --- a/stdlib/LinearAlgebra/src/eigen.jl +++ b/stdlib/LinearAlgebra/src/eigen.jl @@ -346,7 +346,7 @@ eigvals(A::AbstractMatrix{T}; kws...) where T = """ For a scalar input, `eigvals` will return a scalar. -# Example +# Examples ```jldoctest julia> eigvals(-2) -2 diff --git a/stdlib/Logging/docs/src/index.md b/stdlib/Logging/docs/src/index.md index ed17c23efdba6b..6d0af3ac21321c 100644 --- a/stdlib/Logging/docs/src/index.md +++ b/stdlib/Logging/docs/src/index.md @@ -313,6 +313,8 @@ Logging.Debug Logging.Info Logging.Warn Logging.Error +Logging.BelowMinLevel +Logging.AboveMaxLevel Logging.@create_log_macro ``` diff --git a/stdlib/Logging/src/Logging.jl b/stdlib/Logging/src/Logging.jl index 1cb1bca774c27b..c05d3b7227c341 100644 --- a/stdlib/Logging/src/Logging.jl +++ b/stdlib/Logging/src/Logging.jl @@ -14,7 +14,7 @@ using StyledStrings # Doing it this way (rather than with import) makes these symbols accessible to # tab completion. for sym in [ - :LogLevel, :BelowMinLevel, :AboveMaxLevel, + :LogLevel, :AbstractLogger, :NullLogger, :handle_message, :shouldlog, :min_enabled_level, :catch_exceptions, @@ -90,6 +90,18 @@ const Warn = Base.CoreLogging.Warn Alias for [`LogLevel(2000)`](@ref LogLevel). """ const Error = Base.CoreLogging.Error +""" + BelowMinLevel + +Alias for [`LogLevel(-1_000_001)`](@ref LogLevel). +""" +const BelowMinLevel = Base.CoreLogging.BelowMinLevel +""" + AboveMaxLevel + +Alias for [`LogLevel(1_000_001)`](@ref LogLevel). +""" +const AboveMaxLevel = Base.CoreLogging.AboveMaxLevel using Base.CoreLogging: closed_stream diff --git a/stdlib/Logging/test/runtests.jl b/stdlib/Logging/test/runtests.jl index 15371ac5d442c8..1a86c884295b44 100644 --- a/stdlib/Logging/test/runtests.jl +++ b/stdlib/Logging/test/runtests.jl @@ -302,8 +302,7 @@ end @testset "Docstrings" begin undoc = Docs.undocumented_names(Logging) - @test_broken isempty(undoc) - @test undoc == [:AboveMaxLevel, :BelowMinLevel] + @test isempty(undoc) end end diff --git a/stdlib/Markdown/src/render/html.jl b/stdlib/Markdown/src/render/html.jl index 3831e6acc7bb93..e7d436f2ccbda5 100644 --- a/stdlib/Markdown/src/render/html.jl +++ b/stdlib/Markdown/src/render/html.jl @@ -191,7 +191,7 @@ writing to an (optional) `io` stream or returning a string. One can alternatively use `show(io, "text/html", md)` or `repr("text/html", md)`, which differ in that they wrap the output in a `
...
` element. -# Example +# Examples ```jldoctest julia> html(md"hello _world_") "

hello world

\\n" diff --git a/stdlib/Markdown/src/render/latex.jl b/stdlib/Markdown/src/render/latex.jl index 03bb78ba3efec1..df52b2849f2b01 100644 --- a/stdlib/Markdown/src/render/latex.jl +++ b/stdlib/Markdown/src/render/latex.jl @@ -175,7 +175,7 @@ writing to an (optional) `io` stream or returning a string. One can alternatively use `show(io, "text/latex", md)` or `repr("text/latex", md)`. -# Example +# Examples ```jldoctest julia> latex(md"hello _world_") "hello \\\\emph{world}\\n\\n" diff --git a/stdlib/REPL/src/REPLCompletions.jl b/stdlib/REPL/src/REPLCompletions.jl index cd779b8868a371..621cd6f9021fba 100644 --- a/stdlib/REPL/src/REPLCompletions.jl +++ b/stdlib/REPL/src/REPLCompletions.jl @@ -527,25 +527,7 @@ function find_start_brace(s::AbstractString; c_start='(', c_end=')') return (startind:lastindex(s), method_name_end) end -struct REPLInterpreterCache - dict::IdDict{MethodInstance,CodeInstance} -end -REPLInterpreterCache() = REPLInterpreterCache(IdDict{MethodInstance,CodeInstance}()) -const REPL_INTERPRETER_CACHE = REPLInterpreterCache() - -function get_code_cache() - # XXX Avoid storing analysis results into the cache that persists across precompilation, - # as [sys|pkg]image currently doesn't support serializing externally created `CodeInstance`. - # Otherwise, `CodeInstance`s created by `REPLInterpreter`, that are much less optimized - # that those produced by `NativeInterpreter`, will leak into the native code cache, - # potentially causing runtime slowdown. - # (see https://github.com/JuliaLang/julia/issues/48453). - if Base.generating_output() - return REPLInterpreterCache() - else - return REPL_INTERPRETER_CACHE - end -end +struct REPLCacheToken end struct REPLInterpreter <: CC.AbstractInterpreter limit_aggressive_inference::Bool @@ -553,32 +535,21 @@ struct REPLInterpreter <: CC.AbstractInterpreter inf_params::CC.InferenceParams opt_params::CC.OptimizationParams inf_cache::Vector{CC.InferenceResult} - code_cache::REPLInterpreterCache function REPLInterpreter(limit_aggressive_inference::Bool=false; world::UInt = Base.get_world_counter(), inf_params::CC.InferenceParams = CC.InferenceParams(; aggressive_constant_propagation=true, unoptimize_throw_blocks=false), opt_params::CC.OptimizationParams = CC.OptimizationParams(), - inf_cache::Vector{CC.InferenceResult} = CC.InferenceResult[], - code_cache::REPLInterpreterCache = get_code_cache()) - return new(limit_aggressive_inference, world, inf_params, opt_params, inf_cache, code_cache) + inf_cache::Vector{CC.InferenceResult} = CC.InferenceResult[]) + return new(limit_aggressive_inference, world, inf_params, opt_params, inf_cache) end end CC.InferenceParams(interp::REPLInterpreter) = interp.inf_params CC.OptimizationParams(interp::REPLInterpreter) = interp.opt_params CC.get_inference_world(interp::REPLInterpreter) = interp.world CC.get_inference_cache(interp::REPLInterpreter) = interp.inf_cache -CC.code_cache(interp::REPLInterpreter) = CC.WorldView(interp.code_cache, CC.WorldRange(interp.world)) -CC.get(wvc::CC.WorldView{REPLInterpreterCache}, mi::MethodInstance, default) = get(wvc.cache.dict, mi, default) -CC.getindex(wvc::CC.WorldView{REPLInterpreterCache}, mi::MethodInstance) = getindex(wvc.cache.dict, mi) -CC.haskey(wvc::CC.WorldView{REPLInterpreterCache}, mi::MethodInstance) = haskey(wvc.cache.dict, mi) -function CC.setindex!(wvc::CC.WorldView{REPLInterpreterCache}, ci::CodeInstance, mi::MethodInstance) - CC.add_invalidation_callback!(mi) do replaced::MethodInstance, max_world::UInt32 - delete!(wvc.cache.dict, replaced) - end - return setindex!(wvc.cache.dict, ci, mi) -end +CC.cache_owner(::REPLInterpreter) = REPLCacheToken() # REPLInterpreter is only used for type analysis, so it should disable optimization entirely CC.may_optimize(::REPLInterpreter) = false @@ -1165,7 +1136,7 @@ function complete_identifiers!(suggestions::Vector{Completion}, @nospecialize(ff if ex === nothing ex = arg else - ex = Expr(:., out, QuoteNode(arg)) + ex = Expr(:., ex, QuoteNode(arg)) end else # invalid expression ex = nothing diff --git a/stdlib/REPL/src/precompile.jl b/stdlib/REPL/src/precompile.jl index da96eb07e15c2f..798077d62c4d46 100644 --- a/stdlib/REPL/src/precompile.jl +++ b/stdlib/REPL/src/precompile.jl @@ -4,8 +4,14 @@ module Precompile # Can't use this during incremental: `@eval Module() begin`` import ..REPL +# Prepare this staging area with all the loaded packages available +for (_pkgid, _mod) in Base.loaded_modules + if !(_pkgid.name in ("Main", "Core", "Base", "REPL")) + eval(:(const $(Symbol(_mod)) = $_mod)) + end +end -# Ugly hack for our cache file to not have a dependency edge on FakePTYs. +# Ugly hack for our cache file to not have a dependency edge on the FakePTYs file. Base._track_dependencies[] = false try Base.include(@__MODULE__, joinpath(Sys.BINDIR, "..", "share", "julia", "test", "testhelpers", "FakePTYs.jl")) @@ -172,10 +178,10 @@ generate_precompile_statements() = try end close(precompile_copy) wait(buffer_reader) - close(statements_step) return :ok end !PARALLEL_PRECOMPILATION && wait(step) + bind(statements_step, step) # Make statements unique statements = Set{String}() @@ -205,7 +211,7 @@ generate_precompile_statements() = try end end - fetch(step) == :ok || throw("Collecting precompiles failed.") + fetch(step) == :ok || throw("Collecting precompiles failed: $(c.excp)") return nothing finally GC.gc(true); GC.gc(false); # reduce memory footprint diff --git a/stdlib/REPL/test/replcompletions.jl b/stdlib/REPL/test/replcompletions.jl index 7fd36e3d147e63..0a73a944ec8ead 100644 --- a/stdlib/REPL/test/replcompletions.jl +++ b/stdlib/REPL/test/replcompletions.jl @@ -2232,6 +2232,11 @@ let s = "using .Issue52922.Inn" @test res @test "Inner1" in c end +let s = "using .Issue52922.Inner1." + c, r, res = test_complete_context(s) + @test res + @test "Inner12" in c +end let s = "using .Inner1.Inn" c, r, res = test_complete_context(s, Issue52922) @test res diff --git a/stdlib/Sockets/src/addrinfo.jl b/stdlib/Sockets/src/addrinfo.jl index bf5819f6388c6a..4ee9e07a584308 100644 --- a/stdlib/Sockets/src/addrinfo.jl +++ b/stdlib/Sockets/src/addrinfo.jl @@ -55,7 +55,7 @@ end Gets all of the IP addresses of the `host`. Uses the operating system's underlying `getaddrinfo` implementation, which may do a DNS lookup. -# Example +# Examples ```julia-repl julia> getalladdrinfo("google.com") 2-element Array{IPAddr,1}: @@ -362,7 +362,7 @@ are not guaranteed to be unique beyond their network segment, therefore routers do not forward them. Link-local addresses are from the address blocks `169.254.0.0/16` or `fe80::/10`. -# Example +# Examples ```julia filter(!islinklocaladdr, getipaddrs()) ``` diff --git a/stdlib/TOML/src/TOML.jl b/stdlib/TOML/src/TOML.jl index 64d715ceef832e..858b75a2e0eff9 100644 --- a/stdlib/TOML/src/TOML.jl +++ b/stdlib/TOML/src/TOML.jl @@ -110,7 +110,7 @@ const ParserError = Internals.ParserError """ - print([to_toml::Function], io::IO [=stdout], data::AbstractDict; sorted=false, by=identity, inline_tables::Base.IdSet{<:AbstractDict}) + print([to_toml::Function], io::IO [=stdout], data::AbstractDict; sorted=false, by=identity, inline_tables::IdSet{<:AbstractDict}) Write `data` as TOML syntax to the stream `io`. If the keyword argument `sorted` is set to `true`, sort tables according to the function given by the keyword argument `by`. If the keyword argument diff --git a/stdlib/TOML/src/print.jl b/stdlib/TOML/src/print.jl index 06e4f08f35c460..91ea4fd392e4bb 100644 --- a/stdlib/TOML/src/print.jl +++ b/stdlib/TOML/src/print.jl @@ -146,7 +146,7 @@ function print_table(f::MbyFunc, io::IO, a::AbstractDict, indent::Int = 0, first_block::Bool = true, sorted::Bool = false, - inline_tables::Base.IdSet, + inline_tables::IdSet, by::Function = identity, ) @@ -223,7 +223,7 @@ end # API # ####### -print(f::MbyFunc, io::IO, a::AbstractDict; sorted::Bool=false, by=identity, inline_tables::Base.IdSet{<:AbstractDict}=Base.IdSet{Dict{String}}()) = print_table(f, io, a; sorted, by, inline_tables) -print(f::MbyFunc, a::AbstractDict; sorted::Bool=false, by=identity, inline_tables::Base.IdSet{<:AbstractDict}=Base.IdSet{Dict{String}}()) = print(f, stdout, a; sorted, by, inline_tables) -print(io::IO, a::AbstractDict; sorted::Bool=false, by=identity, inline_tables::Base.IdSet{<:AbstractDict}=Base.IdSet{Dict{String}}()) = print_table(nothing, io, a; sorted, by, inline_tables) -print( a::AbstractDict; sorted::Bool=false, by=identity, inline_tables::Base.IdSet{<:AbstractDict}=Base.IdSet{Dict{String}}()) = print(nothing, stdout, a; sorted, by, inline_tables) +print(f::MbyFunc, io::IO, a::AbstractDict; sorted::Bool=false, by=identity, inline_tables::IdSet{<:AbstractDict}=IdSet{Dict{String}}()) = print_table(f, io, a; sorted, by, inline_tables) +print(f::MbyFunc, a::AbstractDict; sorted::Bool=false, by=identity, inline_tables::IdSet{<:AbstractDict}=IdSet{Dict{String}}()) = print(f, stdout, a; sorted, by, inline_tables) +print(io::IO, a::AbstractDict; sorted::Bool=false, by=identity, inline_tables::IdSet{<:AbstractDict}=IdSet{Dict{String}}()) = print_table(nothing, io, a; sorted, by, inline_tables) +print( a::AbstractDict; sorted::Bool=false, by=identity, inline_tables::IdSet{<:AbstractDict}=IdSet{Dict{String}}()) = print(nothing, stdout, a; sorted, by, inline_tables) diff --git a/stdlib/TOML/test/print.jl b/stdlib/TOML/test/print.jl index 9698a2871ae270..79a87b9f0f13fd 100644 --- a/stdlib/TOML/test/print.jl +++ b/stdlib/TOML/test/print.jl @@ -148,7 +148,7 @@ d = Dict( "y" => inline_dict, "z" => [1,2,3], ) -inline_tables = Base.IdSet{Dict}() +inline_tables = IdSet{Dict}() push!(inline_tables, inline_dict) @test toml_str(d; sorted=true, inline_tables) == """ @@ -165,7 +165,7 @@ d = Dict("deps" => Dict( "LocalPkg" => Dict("path" => "LocalPkg"), "Example" => Dict("url" => "https://github.com/JuliaLang/Example.jl"))) -inline_tables = Base.IdSet{Dict}() +inline_tables = IdSet{Dict}() push!(inline_tables, d["sources"]["LocalPkg"]) push!(inline_tables, d["sources"]["Example"]) @@ -180,7 +180,7 @@ Example = {url = "https://github.com/JuliaLang/Example.jl"} LocalPkg = {path = "LocalPkg"} """ -inline_tables = Base.IdSet{Dict}() +inline_tables = IdSet{Dict}() push!(inline_tables, d["sources"]["LocalPkg"]) s = """ [deps] diff --git a/stdlib/Test/src/logging.jl b/stdlib/Test/src/logging.jl index 7b3838903ce10b..42d3eaf8eaa486 100644 --- a/stdlib/Test/src/logging.jl +++ b/stdlib/Test/src/logging.jl @@ -55,7 +55,7 @@ most `n` times. See also: [`LogRecord`](@ref). -## Example +## Examples ```jldoctest julia> using Test, Logging diff --git a/test/compiler/AbstractInterpreter.jl b/test/compiler/AbstractInterpreter.jl index 77636bfba9a177..c0b320009b8ec7 100644 --- a/test/compiler/AbstractInterpreter.jl +++ b/test/compiler/AbstractInterpreter.jl @@ -368,7 +368,7 @@ let NoinlineModule = Module() # it should work for cached results method = only(methods(inlined_usually, (Float64,Float64,Float64,))) mi = CC.specialize_method(method, Tuple{typeof(inlined_usually),Float64,Float64,Float64}, Core.svec()) - @test haskey(interp.code_cache.dict, mi) + @test CC.haskey(CC.code_cache(interp), mi) let src = code_typed1((Float64,Float64,Float64); interp) do x, y, z inlined_usually(x, y, z) end @@ -442,7 +442,8 @@ function custom_lookup(mi::MethodInstance, min_world::UInt, max_world::UInt) end end end - return CONST_INVOKE_INTERP.code_cache.dict[mi] + # XXX: This seems buggy, custom_lookup should probably construct the absint on demand. + return CC.getindex(CC.code_cache(CONST_INVOKE_INTERP), mi) end let # generate cache diff --git a/test/compiler/EscapeAnalysis/EAUtils.jl b/test/compiler/EscapeAnalysis/EAUtils.jl index 2a4f04f8f79ea8..87228aaf2858ab 100644 --- a/test/compiler/EscapeAnalysis/EAUtils.jl +++ b/test/compiler/EscapeAnalysis/EAUtils.jl @@ -62,7 +62,7 @@ __clear_cache!() = empty!(GLOBAL_EA_CODE_CACHE) # imports import .CC: AbstractInterpreter, NativeInterpreter, WorldView, WorldRange, - InferenceParams, OptimizationParams, get_world_counter, get_inference_cache, code_cache, + InferenceParams, OptimizationParams, get_world_counter, get_inference_cache, ipo_dataflow_analysis!, cache_result! # usings using Core: @@ -71,11 +71,7 @@ using .CC: InferenceResult, OptimizationState, IRCode using .EA: analyze_escapes, ArgEscapeCache, EscapeInfo, EscapeState -struct CodeCache - cache::IdDict{MethodInstance,CodeInstance} -end -CodeCache() = CodeCache(IdDict{MethodInstance,CodeInstance}()) -const GLOBAL_CODE_CACHE = CodeCache() +struct EAToken end # when working outside of Core.Compiler, # cache entire escape state for later inspection and debugging @@ -86,7 +82,7 @@ struct EscapeCacheInfo end struct EscapeCache - cache::IdDict{MethodInstance,EscapeCacheInfo} + cache::IdDict{MethodInstance,EscapeCacheInfo} # TODO(aviatesk) Should this be CodeInstance to EscapeCacheInfo? end EscapeCache() = EscapeCache(IdDict{MethodInstance,EscapeCacheInfo}()) const GLOBAL_ESCAPE_CACHE = EscapeCache() @@ -102,17 +98,15 @@ mutable struct EscapeAnalyzer <: AbstractInterpreter const inf_params::InferenceParams const opt_params::OptimizationParams const inf_cache::Vector{InferenceResult} - const code_cache::CodeCache const escape_cache::EscapeCache const entry_mi::MethodInstance result::EscapeResultForEntry function EscapeAnalyzer(world::UInt, entry_mi::MethodInstance, - code_cache::CodeCache=GLOBAL_CODE_CACHE, escape_cache::EscapeCache=GLOBAL_ESCAPE_CACHE) inf_params = InferenceParams() opt_params = OptimizationParams() inf_cache = InferenceResult[] - return new(world, inf_params, opt_params, inf_cache, code_cache, escape_cache, entry_mi) + return new(world, inf_params, opt_params, inf_cache, escape_cache, entry_mi) end end @@ -120,28 +114,7 @@ CC.InferenceParams(interp::EscapeAnalyzer) = interp.inf_params CC.OptimizationParams(interp::EscapeAnalyzer) = interp.opt_params CC.get_inference_world(interp::EscapeAnalyzer) = interp.world CC.get_inference_cache(interp::EscapeAnalyzer) = interp.inf_cache - -struct EscapeAnalyzerCacheView - code_cache::CodeCache - escape_cache::EscapeCache -end - -function CC.code_cache(interp::EscapeAnalyzer) - worlds = WorldRange(CC.get_inference_world(interp)) - return WorldView(EscapeAnalyzerCacheView(interp.code_cache, interp.escape_cache), worlds) -end -CC.haskey(wvc::WorldView{EscapeAnalyzerCacheView}, mi::MethodInstance) = haskey(wvc.cache.code_cache.cache, mi) -CC.get(wvc::WorldView{EscapeAnalyzerCacheView}, mi::MethodInstance, default) = get(wvc.cache.code_cache.cache, mi, default) -CC.getindex(wvc::WorldView{EscapeAnalyzerCacheView}, mi::MethodInstance) = getindex(wvc.cache.code_cache.cache, mi) -function CC.setindex!(wvc::WorldView{EscapeAnalyzerCacheView}, ci::CodeInstance, mi::MethodInstance) - wvc.cache.code_cache.cache[mi] = ci - # register the callback on invalidation - CC.add_invalidation_callback!(mi) do replaced::MethodInstance, max_world::UInt32 - delete!(wvc.cache.code_cache.cache, replaced) - delete!(wvc.cache.escape_cache.cache, replaced) - end - return wvc -end +CC.cache_owner(::EscapeAnalyzer) = EAToken() function CC.ipo_dataflow_analysis!(interp::EscapeAnalyzer, ir::IRCode, caller::InferenceResult) # run EA on all frames that have been optimized diff --git a/test/compiler/invalidation.jl b/test/compiler/invalidation.jl index e3263156499c85..d5e86ca533f05e 100644 --- a/test/compiler/invalidation.jl +++ b/test/compiler/invalidation.jl @@ -7,51 +7,28 @@ include("irutils.jl") using Test const CC = Core.Compiler -import Core: MethodInstance, CodeInstance -import .CC: WorldRange, WorldView -struct InvalidationTesterCache - dict::IdDict{MethodInstance,CodeInstance} -end -InvalidationTesterCache() = InvalidationTesterCache(IdDict{MethodInstance,CodeInstance}()) - -const INVALIDATION_TESTER_CACHE = InvalidationTesterCache() +struct InvalidationTesterToken end struct InvalidationTester <: CC.AbstractInterpreter world::UInt inf_params::CC.InferenceParams opt_params::CC.OptimizationParams inf_cache::Vector{CC.InferenceResult} - code_cache::InvalidationTesterCache function InvalidationTester(; world::UInt = Base.get_world_counter(), inf_params::CC.InferenceParams = CC.InferenceParams(), opt_params::CC.OptimizationParams = CC.OptimizationParams(), - inf_cache::Vector{CC.InferenceResult} = CC.InferenceResult[], - code_cache::InvalidationTesterCache = INVALIDATION_TESTER_CACHE) - return new(world, inf_params, opt_params, inf_cache, code_cache) + inf_cache::Vector{CC.InferenceResult} = CC.InferenceResult[]) + return new(world, inf_params, opt_params, inf_cache) end end -struct InvalidationTesterCacheView - dict::IdDict{MethodInstance,CodeInstance} -end - CC.InferenceParams(interp::InvalidationTester) = interp.inf_params CC.OptimizationParams(interp::InvalidationTester) = interp.opt_params CC.get_inference_world(interp::InvalidationTester) = interp.world CC.get_inference_cache(interp::InvalidationTester) = interp.inf_cache -CC.code_cache(interp::InvalidationTester) = WorldView(InvalidationTesterCacheView(interp.code_cache.dict), WorldRange(interp.world)) -CC.get(wvc::WorldView{InvalidationTesterCacheView}, mi::MethodInstance, default) = get(wvc.cache.dict, mi, default) -CC.getindex(wvc::WorldView{InvalidationTesterCacheView}, mi::MethodInstance) = getindex(wvc.cache.dict, mi) -CC.haskey(wvc::WorldView{InvalidationTesterCacheView}, mi::MethodInstance) = haskey(wvc.cache.dict, mi) -function CC.setindex!(wvc::WorldView{InvalidationTesterCacheView}, ci::CodeInstance, mi::MethodInstance) - CC.add_invalidation_callback!(mi) do replaced::MethodInstance, max_world::UInt32 - delete!(wvc.cache.dict, replaced) - # Core.println("[InvalidationTester] ", replaced) # debug - end - setindex!(wvc.cache.dict, ci, mi) -end +CC.cache_owner(::InvalidationTester) = InvalidationTesterToken() # basic functionality test # ------------------------ @@ -63,33 +40,55 @@ basic_caller(x) = basic_callee(x) @test Base.return_types((Float64,); interp=InvalidationTester()) do x basic_caller(x) end |> only === Float64 -@test any(INVALIDATION_TESTER_CACHE.dict) do (mi, ci) - mi.def.name === :basic_callee + +let mi = Base.method_instance(basic_callee, (Float64,)) + ci = mi.cache + @test !isdefined(ci, :next) + @test ci.owner === InvalidationTesterToken() + @test ci.max_world == typemax(UInt) end -@test any(INVALIDATION_TESTER_CACHE.dict) do (mi, ci) - mi.def.name === :basic_caller + +let mi = Base.method_instance(basic_caller, (Float64,)) + ci = mi.cache + @test !isdefined(ci, :next) + @test ci.owner === InvalidationTesterToken() + @test ci.max_world == typemax(UInt) end # this redefinition below should invalidate the cache +const BASIC_CALLER_WORLD = Base.get_world_counter() basic_callee(x) = x, x -@test !any(INVALIDATION_TESTER_CACHE.dict) do (mi, ci) - mi.def.name === :basic_callee -end -@test !any(INVALIDATION_TESTER_CACHE.dict) do (mi, ci) - mi.def.name === :basic_caller +@test !isdefined(Base.method_instance(basic_callee, (Float64,)), :cache) +let mi = Base.method_instance(basic_caller, (Float64,)) + ci = mi.cache + @test !isdefined(ci, :next) + @test ci.owner === InvalidationTesterToken() + @test ci.max_world == BASIC_CALLER_WORLD end # re-run inference and check the result is updated (and new cache exists) @test Base.return_types((Float64,); interp=InvalidationTester()) do x basic_caller(x) end |> only === Tuple{Float64,Float64} -@test any(INVALIDATION_TESTER_CACHE.dict) do (mi, ci) - mi.def.name === :basic_callee +let mi = Base.method_instance(basic_callee, (Float64,)) + ci = mi.cache + @test !isdefined(ci, :next) + @test ci.owner === InvalidationTesterToken() + @test ci.max_world == typemax(UInt) end -@test any(INVALIDATION_TESTER_CACHE.dict) do (mi, ci) - mi.def.name === :basic_caller + +let mi = Base.method_instance(basic_caller, (Float64,)) + ci = mi.cache + @test isdefined(ci, :next) + @test ci.owner === InvalidationTesterToken() + @test ci.max_world == typemax(UInt) + ci = ci.next + @test !isdefined(ci, :next) + @test ci.owner === InvalidationTesterToken() + @test ci.max_world != typemax(UInt) end + # backedge optimization # --------------------- @@ -115,24 +114,47 @@ begin take!(GLOBAL_BUFFER) @test rt === Any @test any(iscall((src, pr48932_callee)), src.code) end - @test any(INVALIDATION_TESTER_CACHE.dict) do (mi, ci) - mi.def.name === :pr48932_callee + + let mi = only(Base.specializations(Base.only(Base.methods(pr48932_callee)))) + # Base.method_instance(pr48932_callee, (Any,)) + ci = mi.cache + @test isdefined(ci, :next) + @test ci.owner === InvalidationTesterToken() + @test ci.max_world == typemax(UInt) + + # In cache due to Base.return_types(pr48932_callee, (Any,)) + ci = ci.next + @test !isdefined(ci, :next) + @test ci.owner === nothing + @test ci.max_world == typemax(UInt) end - @test any(INVALIDATION_TESTER_CACHE.dict) do (mi, ci) - mi.def.name === :pr48932_caller + let mi = Base.method_instance(pr48932_caller, (Int,)) + ci = mi.cache + @test !isdefined(ci, :next) + @test ci.owner === InvalidationTesterToken() + @test ci.max_world == typemax(UInt) end + @test 42 == pr48932_caller(42) @test "42" == String(take!(GLOBAL_BUFFER)) # test that we didn't add the backedge from `pr48932_callee` to `pr48932_caller`: # this redefinition below should invalidate the cache of `pr48932_callee` but not that of `pr48932_caller` pr48932_callee(x) = (print(GLOBAL_BUFFER, x); nothing) - @test !any(INVALIDATION_TESTER_CACHE.dict) do (mi, ci) - mi.def.name === :pr48932_callee - end - @test any(INVALIDATION_TESTER_CACHE.dict) do (mi, ci) - mi.def.name === :pr48932_caller + + @test isempty(Base.specializations(Base.only(Base.methods(pr48932_callee)))) + let mi = only(Base.specializations(Base.only(Base.methods(pr48932_caller)))) + # Base.method_instance(pr48932_callee, (Any,)) + ci = mi.cache + @test isdefined(ci, :next) + @test ci.owner === nothing + @test ci.max_world == typemax(UInt) + ci = ci.next + @test !isdefined(ci, :next) + @test ci.owner === InvalidationTesterToken() + @test ci.max_world == typemax(UInt) end + @test isnothing(pr48932_caller(42)) @test "42" == String(take!(GLOBAL_BUFFER)) end @@ -159,23 +181,41 @@ begin take!(GLOBAL_BUFFER) @test rt === Nothing @test any(iscall((src, pr48932_callee_inferable)), src.code) end - @test any(INVALIDATION_TESTER_CACHE.dict) do (mi, ci) - mi.def.name === :pr48932_callee_inferable + + let mi = only(Base.specializations(Base.only(Base.methods(pr48932_callee_inferable)))) + ci = mi.cache + @test isdefined(ci, :next) + @test ci.owner === InvalidationTesterToken() + @test ci.max_world == typemax(UInt) + ci = ci.next + @test !isdefined(ci, :next) + @test ci.owner === nothing + @test ci.max_world == typemax(UInt) end - @test any(INVALIDATION_TESTER_CACHE.dict) do (mi, ci) - mi.def.name === :pr48932_caller_unuse + let mi = Base.method_instance(pr48932_caller_unuse, (Int,)) + ci = mi.cache + @test !isdefined(ci, :next) + @test ci.owner === InvalidationTesterToken() + @test ci.max_world == typemax(UInt) end + @test isnothing(pr48932_caller_unuse(42)) @test "42" == String(take!(GLOBAL_BUFFER)) # test that we didn't add the backedge from `pr48932_callee_inferable` to `pr48932_caller_unuse`: # this redefinition below should invalidate the cache of `pr48932_callee_inferable` but not that of `pr48932_caller_unuse` pr48932_callee_inferable(x) = (print(GLOBAL_BUFFER, "foo"); x) - @test !any(INVALIDATION_TESTER_CACHE.dict) do (mi, ci) - mi.def.name === :pr48932_callee_inferable - end - @test any(INVALIDATION_TESTER_CACHE.dict) do (mi, ci) - mi.def.name === :pr48932_caller_unuse + + @test isempty(Base.specializations(Base.only(Base.methods(pr48932_callee_inferable)))) + let mi = Base.method_instance(pr48932_caller_unuse, (Int,)) + ci = mi.cache + @test isdefined(ci, :next) + @test ci.owner === nothing + @test ci.max_world == typemax(UInt) + ci = ci.next + @test !isdefined(ci, :next) + @test ci.owner === InvalidationTesterToken() + @test ci.max_world == typemax(UInt) end @test isnothing(pr48932_caller_unuse(42)) @test "foo" == String(take!(GLOBAL_BUFFER)) @@ -201,24 +241,43 @@ begin take!(GLOBAL_BUFFER) @test rt === Any @test any(isinvoke(:pr48932_callee_inlined), src.code) end - @test any(INVALIDATION_TESTER_CACHE.dict) do (mi, ci) - mi.def.name === :pr48932_callee_inlined + + let mi = Base.method_instance(pr48932_callee_inlined, (Int,)) + ci = mi.cache + @test isdefined(ci, :next) + @test ci.owner === InvalidationTesterToken() + @test ci.max_world == typemax(UInt) + ci = ci.next + @test !isdefined(ci, :next) + @test ci.owner === nothing + @test ci.max_world == typemax(UInt) end - @test any(INVALIDATION_TESTER_CACHE.dict) do (mi, ci) - mi.def.name === :pr48932_caller_inlined + let mi = Base.method_instance(pr48932_caller_inlined, (Int,)) + ci = mi.cache + @test !isdefined(ci, :next) + @test ci.owner === InvalidationTesterToken() + @test ci.max_world == typemax(UInt) end + @test 42 == pr48932_caller_inlined(42) @test "42" == String(take!(GLOBAL_BUFFER)) # test that we added the backedge from `pr48932_callee_inlined` to `pr48932_caller_inlined`: # this redefinition below should invalidate the cache of `pr48932_callee_inlined` but not that of `pr48932_caller_inlined` @noinline pr48932_callee_inlined(@nospecialize x) = (print(GLOBAL_BUFFER, x); nothing) - @test !any(INVALIDATION_TESTER_CACHE.dict) do (mi, ci) - mi.def.name === :pr48932_callee_inlined - end - @test !any(INVALIDATION_TESTER_CACHE.dict) do (mi, ci) - mi.def.name === :pr48932_caller_inlined + + @test isempty(Base.specializations(Base.only(Base.methods(pr48932_callee_inlined)))) + let mi = Base.method_instance(pr48932_caller_inlined, (Int,)) + ci = mi.cache + @test isdefined(ci, :next) + @test ci.owner === nothing + @test ci.max_world != typemax(UInt) + ci = ci.next + @test !isdefined(ci, :next) + @test ci.owner === InvalidationTesterToken() + @test ci.max_world != typemax(UInt) end + @test isnothing(pr48932_caller_inlined(42)) @test "42" == String(take!(GLOBAL_BUFFER)) end diff --git a/test/compiler/newinterp.jl b/test/compiler/newinterp.jl index 4b2cabcf33c3b5..1157a52ebbcbea 100644 --- a/test/compiler/newinterp.jl +++ b/test/compiler/newinterp.jl @@ -9,39 +9,29 @@ Defines new `NewInterpreter <: AbstractInterpreter` whose cache is separated from the native code cache, satisfying the minimum interface requirements. """ macro newinterp(InterpName) - InterpCacheName = esc(Symbol(string(InterpName, "Cache"))) + InterpCacheName = QuoteNode(Symbol(string(InterpName, "Cache"))) InterpName = esc(InterpName) C = Core CC = Core.Compiler quote - struct $InterpCacheName - dict::IdDict{$C.MethodInstance,$C.CodeInstance} - end - $InterpCacheName() = $InterpCacheName(IdDict{$C.MethodInstance,$C.CodeInstance}()) struct $InterpName <: $CC.AbstractInterpreter meta # additional information world::UInt inf_params::$CC.InferenceParams opt_params::$CC.OptimizationParams inf_cache::Vector{$CC.InferenceResult} - code_cache::$InterpCacheName function $InterpName(meta = nothing; world::UInt = Base.get_world_counter(), inf_params::$CC.InferenceParams = $CC.InferenceParams(), opt_params::$CC.OptimizationParams = $CC.OptimizationParams(), - inf_cache::Vector{$CC.InferenceResult} = $CC.InferenceResult[], - code_cache::$InterpCacheName = $InterpCacheName()) - return new(meta, world, inf_params, opt_params, inf_cache, code_cache) + inf_cache::Vector{$CC.InferenceResult} = $CC.InferenceResult[]) + return new(meta, world, inf_params, opt_params, inf_cache) end end $CC.InferenceParams(interp::$InterpName) = interp.inf_params $CC.OptimizationParams(interp::$InterpName) = interp.opt_params $CC.get_inference_world(interp::$InterpName) = interp.world $CC.get_inference_cache(interp::$InterpName) = interp.inf_cache - $CC.code_cache(interp::$InterpName) = $CC.WorldView(interp.code_cache, $CC.WorldRange(interp.world)) - $CC.get(wvc::$CC.WorldView{$InterpCacheName}, mi::$C.MethodInstance, default) = get(wvc.cache.dict, mi, default) - $CC.getindex(wvc::$CC.WorldView{$InterpCacheName}, mi::$C.MethodInstance) = getindex(wvc.cache.dict, mi) - $CC.haskey(wvc::$CC.WorldView{$InterpCacheName}, mi::$C.MethodInstance) = haskey(wvc.cache.dict, mi) - $CC.setindex!(wvc::$CC.WorldView{$InterpCacheName}, ci::$C.CodeInstance, mi::$C.MethodInstance) = setindex!(wvc.cache.dict, ci, mi) + $CC.cache_owner(::$InterpName) = $InterpCacheName end end diff --git a/test/core.jl b/test/core.jl index a2c3b3cff9e6bb..aa16380c8a866f 100644 --- a/test/core.jl +++ b/test/core.jl @@ -14,7 +14,7 @@ include("testenv.jl") # sanity tests that our built-in types are marked correctly for const fields for (T, c) in ( (Core.CodeInfo, []), - (Core.CodeInstance, [:def, :rettype, :exctype, :rettype_const, :ipo_purity_bits, :analysis_results]), + (Core.CodeInstance, [:def, :owner, :rettype, :exctype, :rettype_const, :ipo_purity_bits, :analysis_results]), (Core.Method, [#=:name, :module, :file, :line, :primary_world, :sig, :slot_syms, :external_mt, :nargs, :called, :nospecialize, :nkw, :isva, :is_for_opaque_closure, :constprop=#]), (Core.MethodInstance, [#=:def, :specTypes, :sparam_vals=#]), (Core.MethodTable, [:module]), @@ -32,7 +32,7 @@ end # sanity tests that our built-in types are marked correctly for atomic fields for (T, c) in ( (Core.CodeInfo, []), - (Core.CodeInstance, [:next, :min_world, :max_world, :inferred, :purity_bits, :invoke, :specptr, :precompile]), + (Core.CodeInstance, [:next, :min_world, :max_world, :inferred, :purity_bits, :invoke, :specptr, :specsigflags, :precompile]), (Core.Method, [:primary_world, :deleted_world]), (Core.MethodInstance, [:uninferred, :cache, :precompiled]), (Core.MethodTable, [:defs, :leafcache, :cache, :max_args]), diff --git a/test/precompile.jl b/test/precompile.jl index d1360d1a06357a..90086ff7b7385a 100644 --- a/test/precompile.jl +++ b/test/precompile.jl @@ -1694,13 +1694,14 @@ precompile_test_harness("Issue #46558") do load_path @test (@eval $Foo.foo(1)) == 2 end +# TODO: Decide if we need to keep supporting this. precompile_test_harness("issue #46296") do load_path write(joinpath(load_path, "CodeInstancePrecompile.jl"), """ module CodeInstancePrecompile mi = first(Base.specializations(first(methods(identity)))) - ci = Core.CodeInstance(mi, Any, Any, nothing, nothing, zero(Int32), typemin(UInt), + ci = Core.CodeInstance(mi, nothing, Any, Any, nothing, nothing, zero(Int32), typemin(UInt), typemax(UInt), zero(UInt32), zero(UInt32), nothing, 0x00) __init__() = @assert ci isa Core.CodeInstance @@ -1711,6 +1712,69 @@ precompile_test_harness("issue #46296") do load_path (@eval (using CodeInstancePrecompile)) end +precompile_test_harness("AbstractInterpreter caching") do load_path + write(joinpath(load_path, "SimpleModule.jl"), + """ + module SimpleModule + basic_callee(x) = x + basic_caller(x) = basic_callee(x) + end + """) + write(joinpath(load_path, "CustomAbstractInterpreterCaching.jl"), + """ + module CustomAbstractInterpreterCaching + import SimpleModule: basic_caller, basic_callee + module Custom + const CC = Core.Compiler + + struct InvalidationTesterToken end + + struct InvalidationTester <: CC.AbstractInterpreter + world::UInt + inf_params::CC.InferenceParams + opt_params::CC.OptimizationParams + inf_cache::Vector{CC.InferenceResult} + function InvalidationTester(; + world::UInt = Base.get_world_counter(), + inf_params::CC.InferenceParams = CC.InferenceParams(), + opt_params::CC.OptimizationParams = CC.OptimizationParams(), + inf_cache::Vector{CC.InferenceResult} = CC.InferenceResult[]) + return new(world, inf_params, opt_params, inf_cache) + end + end + + CC.InferenceParams(interp::InvalidationTester) = interp.inf_params + CC.OptimizationParams(interp::InvalidationTester) = interp.opt_params + CC.get_inference_world(interp::InvalidationTester) = interp.world + CC.get_inference_cache(interp::InvalidationTester) = interp.inf_cache + CC.cache_owner(::InvalidationTester) = InvalidationTesterToken() + end + + Base.return_types((Float64,)) do x + basic_caller(x) + end + Base.return_types((Float64,); interp=Custom.InvalidationTester()) do x + basic_caller(x) + end + end + """) + Base.compilecache(Base.PkgId("CustomAbstractInterpreterCaching")) + (@eval begin + using CustomAbstractInterpreterCaching + let m = only(methods(CustomAbstractInterpreterCaching.basic_callee)) + mi = only(Base.specializations(m)) + ci = mi.cache + @test isdefined(ci, :next) + @test ci.owner === nothing + @test ci.max_world == typemax(UInt) + ci = ci.next + @test !isdefined(ci, :next) + @test ci.owner === CustomAbstractInterpreterCaching.Custom.InvalidationTesterToken() + @test ci.max_world == typemax(UInt) + end + end) +end + precompile_test_harness("Recursive types") do load_path write(joinpath(load_path, "RecursiveTypeDef.jl"), """ diff --git a/test/ranges.jl b/test/ranges.jl index 82593b53ff5030..549078bab45fea 100644 --- a/test/ranges.jl +++ b/test/ranges.jl @@ -235,9 +235,23 @@ end @test cmp_sn2(Tw(xw/yw), astuple(x/y)..., slopbits) end end + @testset "high precision of varying types" begin + x = Float32(π) + y = Float64(Base.MathConstants.γ) + @test Base.mul12(x, y)[1] ≈ Base.mul12(Float64(π), y)[1] rtol=1e-6 + @test Base.mul12(x, y)[2] ≈ Base.mul12(Float64(π), y)[2] atol=1e-15 + @test Base.div12(x, y)[1] ≈ Base.div12(Float64(π), y)[1] rtol=1e-6 + @test Base.div12(x, y)[2] ≈ Base.div12(Float64(π), y)[2] atol=1e-15 + xtp = Base.TwicePrecision{Float32}(π) + ytp = Base.TwicePrecision{Float64}(Base.MathConstants.γ) + @test Float32(xtp + ytp) ≈ Float32(Base.TwicePrecision{Float64}(π) + ytp) + end x1 = Base.TwicePrecision{Float64}(1) x0 = Base.TwicePrecision{Float64}(0) + @test eltype(x1) == Float64 + @test eltype(typeof(x1)) == Float64 + @test zero(typeof(x1)) === x0 xinf = Base.TwicePrecision{Float64}(Inf) @test Float64(x1+x0) == 1 @test Float64(x1+0) == 1 diff --git a/test/reflection.jl b/test/reflection.jl index f81605622a806b..c4e941fa7bb1a2 100644 --- a/test/reflection.jl +++ b/test/reflection.jl @@ -1006,8 +1006,9 @@ end @testset "lookup mi" begin @test 1+1 == 2 - mi1 = @ccall jl_method_lookup_by_tt(Tuple{typeof(+), Int, Int}::Any, Base.get_world_counter()::Csize_t, nothing::Any)::Ref{Core.MethodInstance} + mi1 = Base.method_instance(+, (Int, Int)) @test mi1.def.name == :+ + # Note `jl_method_lookup` doesn't returns CNull if not found mi2 = @ccall jl_method_lookup(Any[+, 1, 1]::Ptr{Any}, 3::Csize_t, Base.get_world_counter()::Csize_t)::Ref{Core.MethodInstance} @test mi1 == mi2 end diff --git a/test/sets.jl b/test/sets.jl index 2e7e19c5c1cdfb..c490e66793cb44 100644 --- a/test/sets.jl +++ b/test/sets.jl @@ -899,8 +899,8 @@ end b = [2, 3, 1, 3] ua = unique(a) ub = unique(b) - for TA in (Tuple, identity, Set, BitSet, Base.IdSet{Int}), - TB in (Tuple, identity, Set, BitSet, Base.IdSet{Int}), + for TA in (Tuple, identity, Set, BitSet, IdSet{Int}), + TB in (Tuple, identity, Set, BitSet, IdSet{Int}), uA = false:true, uB = false:true A = TA(uA ? ua : a) @@ -921,7 +921,7 @@ end @test !issetequal(B, A) @test !issetequal(B)(A) @test !issetequal(A)(B) - for T = (Tuple, identity, Set, BitSet, Base.IdSet{Int}) + for T = (Tuple, identity, Set, BitSet, IdSet{Int}) @test issetequal(A, T(A)) @test issetequal(B, T(B)) end @@ -982,7 +982,7 @@ end c = [3] d = [4] e = [5] - A = Base.IdSet{Vector{Int}}([a, b, c, d]) + A = IdSet{Vector{Int}}([a, b, c, d]) @test !isempty(A) B = copy(A) @test A ⊆ B diff --git a/test/spawn.jl b/test/spawn.jl index 9d58b32976357a..831eac493d4aa7 100644 --- a/test/spawn.jl +++ b/test/spawn.jl @@ -23,7 +23,7 @@ havebb = false function _tryonce_download_from_cache(desired_url::AbstractString) cache_url = "https://cache.julialang.org/$(desired_url)" - cache_output_filename = joinpath(mktempdir(), "myfile") + cache_output_filename = joinpath(mktempdir(), "busybox") cache_response = Downloads.request( cache_url; output = cache_output_filename,