Skip to content

Commit e068372

Browse files
authored
Backports for 1.12.0-rc1 (#58655)
2 parents c7b5ffa + c1f27d2 commit e068372

File tree

180 files changed

+3922
-3195
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

180 files changed

+3922
-3195
lines changed

Compiler/LICENSE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
MIT License
22

3-
Copyright (c) 2009-2024: Jeff Bezanson, Stefan Karpinski, Viral B. Shah, and other contributors: https://github.com/JuliaLang/julia/contributors
3+
Copyright (c) 2009-2025: Jeff Bezanson, Stefan Karpinski, Viral B. Shah, and other contributors: https://github.com/JuliaLang/julia/contributors
44

55
Permission is hereby granted, free of charge, to any person obtaining
66
a copy of this software and associated documentation files (the

Compiler/Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name = "Compiler"
22
uuid = "807dbc54-b67e-4c79-8afb-eafe4df6f2e1"
3-
version = "0.0.3"
3+
version = "0.1.1"
44

55
[compat]
66
julia = "1.10"

Compiler/README.md

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# The `Compiler` module
2+
3+
This directory maintains the implementation of the Julia compiler.
4+
5+
Through a bootstrapping process, it is bundled into the Julia runtime as `Base.Compiler`.
6+
7+
You can also use this `Compiler` module as the `Compiler` standard library by following the steps below.
8+
9+
## How to use
10+
11+
To utilize this `Compiler.jl` standard library, you need to declare it as a dependency in
12+
your `Project.toml` as follows:
13+
> Project.toml
14+
```toml
15+
[deps]
16+
Compiler = "807dbc54-b67e-4c79-8afb-eafe4df6f2e1"
17+
18+
[compat]
19+
Compiler = "0.1"
20+
```
21+
22+
With the setup above, [the special placeholder version (v0.1)](https://github.com/JuliaLang/BaseCompiler.jl)
23+
will be installed by default.[^1]
24+
25+
[^1]: Currently, only version v0.1 is registered in the [General](https://github.com/JuliaRegistries/General) registry.
26+
27+
If needed, you can switch to a custom implementation of the `Compiler` module by running
28+
```julia-repl
29+
pkg> dev /path/to/Compiler.jl # to use a local implementation
30+
```
31+
or
32+
```julia-repl
33+
pkg> add https://url/of/Compiler/branch # to use a remote implementation
34+
```
35+
This feature is particularly useful for developing or experimenting with alternative compiler implementations.
36+
37+
> [!note]
38+
> The Compiler.jl standard library is available starting from Julia v1.10.
39+
> However, switching to a custom compiler implementation is supported only from
40+
> Julia v1.12 onwards.
41+
42+
> [!warning]
43+
> When using a custom, non-`Base` version of `Compiler` implementation, it may be necessary
44+
> to run `InteractiveUtils.@activate Compiler` to ensure proper functionality of certain
45+
> reflection utilities.

Compiler/src/Compiler.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ else
3838
using Core.Intrinsics, Core.IR
3939

4040
using Core: ABIOverride, Builtin, CodeInstance, IntrinsicFunction, MethodInstance, MethodMatch,
41-
MethodTable, PartialOpaque, SimpleVector, TypeofVararg,
41+
MethodTable, MethodCache, PartialOpaque, SimpleVector, TypeofVararg,
4242
_apply_iterate, apply_type, compilerbarrier, donotdelete, memoryref_isassigned,
4343
memoryrefget, memoryrefnew, memoryrefoffset, memoryrefset!, print, println, show, svec,
4444
typename, unsafe_write, write

Compiler/src/abstractinterpretation.jl

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -363,15 +363,13 @@ function find_union_split_method_matches(interp::AbstractInterpreter, argtypes::
363363
arg_n = split_argtypes[i]::Vector{Any}
364364
sig_n = argtypes_to_type(arg_n)
365365
sig_n === Bottom && continue
366-
mt = ccall(:jl_method_table_for, Any, (Any,), sig_n)
367-
mt === nothing && return FailedMethodMatch("Could not identify method table for call")
368-
mt = mt::MethodTable
369366
thismatches = findall(sig_n, method_table(interp); limit = max_methods)
370367
if thismatches === nothing
371368
return FailedMethodMatch("For one of the union split cases, too many methods matched")
372369
end
373370
valid_worlds = intersect(valid_worlds, thismatches.valid_worlds)
374371
thisfullmatch = any(match::MethodMatch->match.fully_covers, thismatches)
372+
mt = Core.GlobalMethods
375373
thisinfo = MethodMatchInfo(thismatches, mt, sig_n, thisfullmatch)
376374
push!(infos, thisinfo)
377375
for idx = 1:length(thismatches)
@@ -385,18 +383,14 @@ function find_union_split_method_matches(interp::AbstractInterpreter, argtypes::
385383
end
386384

387385
function find_simple_method_matches(interp::AbstractInterpreter, @nospecialize(atype), max_methods::Int)
388-
mt = ccall(:jl_method_table_for, Any, (Any,), atype)
389-
if mt === nothing
390-
return FailedMethodMatch("Could not identify method table for call")
391-
end
392-
mt = mt::MethodTable
393386
matches = findall(atype, method_table(interp); limit = max_methods)
394387
if matches === nothing
395388
# this means too many methods matched
396389
# (assume this will always be true, so we don't compute / update valid age in this case)
397390
return FailedMethodMatch("Too many methods matched")
398391
end
399392
fullmatch = any(match::MethodMatch->match.fully_covers, matches)
393+
mt = Core.GlobalMethods
400394
info = MethodMatchInfo(matches, mt, atype, fullmatch)
401395
applicable = MethodMatchTarget[MethodMatchTarget(matches[idx], info.edges, idx) for idx = 1:length(matches)]
402396
return MethodMatches(applicable, info, matches.valid_worlds)

Compiler/src/bootstrap.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ function activate_codegen!()
1010
Core.eval(Compiler, quote
1111
let typeinf_world_age = Base.tls_world_age()
1212
@eval Core.OptimizedGenerics.CompilerPlugins.typeinf(::Nothing, mi::MethodInstance, source_mode::UInt8) =
13-
Base.invoke_in_world($(Expr(:$, :typeinf_world_age)), typeinf_ext_toplevel, mi, Base.tls_world_age(), source_mode)
13+
Base.invoke_in_world($(Expr(:$, :typeinf_world_age)), typeinf_ext_toplevel, mi, Base.tls_world_age(), source_mode, Compiler.TRIM_NO)
1414
end
1515
end)
1616
end
@@ -67,7 +67,7 @@ function bootstrap!()
6767
end
6868
mi = specialize_method(m.method, Tuple{params...}, m.sparams)
6969
#isa_compileable_sig(mi) || println(stderr, "WARNING: inferring `", mi, "` which isn't expected to be called.")
70-
typeinf_ext_toplevel(mi, world, isa_compileable_sig(mi) ? SOURCE_MODE_ABI : SOURCE_MODE_NOT_REQUIRED)
70+
typeinf_ext_toplevel(mi, world, isa_compileable_sig(mi) ? SOURCE_MODE_ABI : SOURCE_MODE_NOT_REQUIRED, TRIM_NO)
7171
end
7272
end
7373
end

Compiler/src/ssair/inlining.jl

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -126,10 +126,11 @@ function cfg_inline_item!(ir::IRCode, idx::Int, todo::InliningTodo, state::CFGIn
126126
block = block_for_inst(ir, idx)
127127
inline_into_block!(state, block)
128128

129-
if !isempty(inlinee_cfg.blocks[1].preds)
129+
if length(inlinee_cfg.blocks[1].preds) > 1
130130
need_split_before = true
131+
else
132+
@assert inlinee_cfg.blocks[1].preds[1] == 0
131133
end
132-
133134
last_block_idx = last(state.cfg.blocks[block].stmts)
134135
if false # TODO: ((idx+1) == last_block_idx && isa(ir[SSAValue(last_block_idx)], GotoNode))
135136
need_split = false
@@ -166,12 +167,18 @@ function cfg_inline_item!(ir::IRCode, idx::Int, todo::InliningTodo, state::CFGIn
166167
end
167168
new_block_range = (length(state.new_cfg_blocks)-length(inlinee_cfg.blocks)+1):length(state.new_cfg_blocks)
168169

169-
# Fixup the edges of the newely added blocks
170+
# Fixup the edges of the newly added blocks
170171
for (old_block, new_block) in enumerate(bb_rename_range)
171172
if old_block != 1 || need_split_before
172173
p = state.new_cfg_blocks[new_block].preds
173174
let bb_rename_range = bb_rename_range
174175
map!(p, p) do old_pred_block
176+
# the meaning of predecessor 0 depends on the block we encounter it:
177+
# - in the first block, it represents the function entry and so needs to be re-mapped
178+
if old_block == 1 && old_pred_block == 0
179+
return first(bb_rename_range) - 1
180+
end
181+
# - elsewhere, it represents external control-flow from a caught exception which is un-affected by inlining
175182
return old_pred_block == 0 ? 0 : bb_rename_range[old_pred_block]
176183
end
177184
end
@@ -186,10 +193,6 @@ function cfg_inline_item!(ir::IRCode, idx::Int, todo::InliningTodo, state::CFGIn
186193
end
187194
end
188195

189-
if need_split_before
190-
push!(state.new_cfg_blocks[first(bb_rename_range)].preds, first(bb_rename_range)-1)
191-
end
192-
193196
any_edges = false
194197
for (old_block, new_block) in enumerate(bb_rename_range)
195198
if (length(state.new_cfg_blocks[new_block].succs) == 0)
@@ -399,7 +402,7 @@ function ir_inline_item!(compact::IncrementalCompact, idx::Int, argexprs::Vector
399402
else
400403
bb_offset, post_bb_id = popfirst!(todo_bbs)
401404
# This implements the need_split_before flag above
402-
need_split_before = !isempty(item.ir.cfg.blocks[1].preds)
405+
need_split_before = length(item.ir.cfg.blocks[1].preds) > 1
403406
if need_split_before
404407
finish_current_bb!(compact, 0)
405408
end

Compiler/src/ssair/ir.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,9 @@ function compute_basic_blocks(stmts::Vector{Any})
105105
end
106106
# Compute successors/predecessors
107107
for (num, b) in enumerate(blocks)
108+
if b.stmts.start == 1
109+
push!(b.preds, 0) # the entry block has a virtual predecessor
110+
end
108111
terminator = stmts[last(b.stmts)]
109112
if isa(terminator, ReturnNode)
110113
# return never has any successors

Compiler/src/stmtinfo.jl

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -47,21 +47,20 @@ end
4747
add_edges_impl(edges::Vector{Any}, info::MethodMatchInfo) = _add_edges_impl(edges, info)
4848
function _add_edges_impl(edges::Vector{Any}, info::MethodMatchInfo, mi_edge::Bool=false)
4949
if !fully_covering(info)
50-
# add legacy-style missing backedge info also
5150
exists = false
5251
for i in 2:length(edges)
53-
if edges[i] === info.mt && edges[i-1] == info.atype
52+
if edges[i] === Core.GlobalMethods && edges[i-1] == info.atype
5453
exists = true
5554
break
5655
end
5756
end
5857
if !exists
5958
push!(edges, info.atype)
60-
push!(edges, info.mt)
59+
push!(edges, Core.GlobalMethods)
6160
end
6261
end
6362
nmatches = length(info.results)
64-
if nmatches == length(info.edges) == 1
63+
if nmatches == length(info.edges) == 1 && fully_covering(info)
6564
# try the optimized format for the representation, if possible and applicable
6665
# if this doesn't succeed, the backedge will be less precise,
6766
# but the forward edge will maintain the precision
@@ -79,13 +78,15 @@ function _add_edges_impl(edges::Vector{Any}, info::MethodMatchInfo, mi_edge::Boo
7978
end
8079
end
8180
# add check for whether this lookup already existed in the edges list
81+
# encode nmatches as negative if fully_covers is false
82+
encoded_nmatches = fully_covering(info) ? nmatches : -nmatches
8283
for i in 1:length(edges)
83-
if edges[i] === nmatches && edges[i+1] == info.atype
84+
if edges[i] === encoded_nmatches && edges[i+1] == info.atype
8485
# TODO: must also verify the CodeInstance match too
8586
return nothing
8687
end
8788
end
88-
push!(edges, nmatches, info.atype)
89+
push!(edges, encoded_nmatches, info.atype)
8990
for i = 1:nmatches
9091
edge = info.edges[i]
9192
m = info.results[i]
@@ -102,7 +103,7 @@ function add_one_edge!(edges::Vector{Any}, edge::MethodInstance)
102103
i = 1
103104
while i <= length(edges)
104105
edgeᵢ = edges[i]
105-
edgeᵢ isa Int && (i += 2 + edgeᵢ; continue)
106+
edgeᵢ isa Int && (i += 2 + abs(edgeᵢ); continue)
106107
edgeᵢ isa CodeInstance && (edgeᵢ = get_ci_mi(edgeᵢ))
107108
edgeᵢ isa MethodInstance || (i += 1; continue)
108109
if edgeᵢ === edge && !(i > 1 && edges[i-1] isa Type)
@@ -117,7 +118,7 @@ function add_one_edge!(edges::Vector{Any}, edge::CodeInstance)
117118
i = 1
118119
while i <= length(edges)
119120
edgeᵢ_orig = edgeᵢ = edges[i]
120-
edgeᵢ isa Int && (i += 2 + edgeᵢ; continue)
121+
edgeᵢ isa Int && (i += 2 + abs(edgeᵢ); continue)
121122
edgeᵢ isa CodeInstance && (edgeᵢ = get_ci_mi(edgeᵢ))
122123
edgeᵢ isa MethodInstance || (i += 1; continue)
123124
if edgeᵢ === edge.def && !(i > 1 && edges[i-1] isa Type)

Compiler/src/tfuncs.jl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,9 @@ end
405405
return isdefined_tfunc(𝕃, arg1, sym)
406406
end
407407
@nospecs function isdefined_tfunc(𝕃::AbstractLattice, arg1, sym)
408+
if arg1 isa MustAlias
409+
arg1 = widenmustalias(arg1)
410+
end
408411
arg1t = arg1 isa Const ? typeof(arg1.val) : isconstType(arg1) ? typeof(arg1.parameters[1]) : widenconst(arg1)
409412
a1 = unwrap_unionall(arg1t)
410413
if isa(a1, DataType) && !isabstracttype(a1)
@@ -3156,15 +3159,12 @@ function _hasmethod_tfunc(interp::AbstractInterpreter, argtypes::Vector{Any}, sv
31563159
isdispatchelem(ft) || return CallMeta(Bool, Any, Effects(), NoCallInfo()) # check that we might not have a subtype of `ft` at runtime, before doing supertype lookup below
31573160
types = rewrap_unionall(Tuple{ft, unwrapped.parameters...}, types)::Type
31583161
end
3159-
mt = ccall(:jl_method_table_for, Any, (Any,), types)
3160-
if !isa(mt, MethodTable)
3161-
return CallMeta(Bool, Any, EFFECTS_THROWS, NoCallInfo())
3162-
end
31633162
match, valid_worlds = findsup(types, method_table(interp))
31643163
update_valid_age!(sv, valid_worlds)
31653164
if match === nothing
31663165
rt = Const(false)
31673166
vresults = MethodLookupResult(Any[], valid_worlds, true)
3167+
mt = Core.GlobalMethods
31683168
vinfo = MethodMatchInfo(vresults, mt, types, false) # XXX: this should actually be an info with invoke-type edge
31693169
else
31703170
rt = Const(true)

0 commit comments

Comments
 (0)