optimizer: renumber the scope operand of frame-less EnterNodes - #19
Closed
adienes wants to merge 14 commits into
Closed
optimizer: renumber the scope operand of frame-less EnterNodes#19adienes wants to merge 14 commits into
adienes wants to merge 14 commits into
Conversation
This is effectively the same as marking them static, as it makes it private to the file. Should not be a functional change, just clarifying the usage scope.
Helps to clean up some dead code and be a bit more clear about where current
usage is located. Mark all functions as any of:
- in a header
- `extern` (rare)
- `static`
- `namespace { ... }` (anonymous)
- `JL_DLLEXPORT` (or equivalent)
Helps to ensure we're exporting functions to gdb if intended to do so
(recent strip changes may make it harder to rely on non-exported
debugging functions being available, even though we didn't want regular
API users calling these).
…ed necessary due to static/extern/dllexport) (JuliaLang#62214) Add a StaticOrDeclared clang-tidy check that enforces that every function with external linkage defined in a source file is either: (a) declared in some header (i.e. it has a non-defining redeclaration that comes from an #included file, so the function is part of an API that other translation units can call), or (b) declared `static` (internal linkage), so it is private to its translation unit, or (c) explicitly exported with `JL_DLLEXPORT` -- i.e. it carries an explicit `__declspec(dllexport)` (on Windows) and/or `__attribute__((visibility("default")))` (elsewhere). Such a function is deliberately part of the public ABI even without a prototype, so it is permitted. Which attribute is present depends on the platform the analysis runs on, so both are accepted, or (d) explicitly annotated with the `extern` keyword in this file. Functions are external by default, so spelling out `extern` is a deliberate statement that the external linkage is intended, which overrides the warning. (This is the storage class `extern`, not the `extern "C"` language-linkage specifier.) This is intended to help ensure we discourage local prototypes, which can drift out of sync with their global prototype. It also lets the compiler generate slightly better code optimizations (inlining decisions) and minimizes the list of exported symbols for the linker.
…Lang#62278) thought I'd donate some tokens cc @benlorenz --------------------------------------------- A keyword sorter is defined as `kwcall(::NamedTuple, callee, args...)`, where the callee's self-type is spelled by lowering with `Core.Typeof`. Since JuliaLang#62001, `Core.Typeof` of a type value yields the egality `Core.TypeEgal` kind, and `jl_method_def` only normalized that back to the equality `Type` kind for the method's own function argument (position 0). The keyword sorter carries the real callee at argument 2, so its self-type stayed at the egality kind while the matching primary method used `Type`, making an inner and an outer keyword constructor mutually ambiguous. Normalize the kwcall callee self-type the same way as the function argument, so the sorter and its primary method agree on the callee kind. This pull request was written with the assistance of generative AI (Claude Fable 5). Fixes JuliaLang#62277 Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…uliaLang#62282) [Cherry-Picked from JuliaLang#62257, since the same issue has shown up on master now] GCC 16.1 raises false-positive `-Warray-bounds=` warnings against the inline storage of llvm::unique_function (FunctionExtras.h, via PointerIntPair.h) as inlined into JLJITLinkMemoryManager::InFlightAlloc::finalize, and merely emitting those diagnostics can crash the compiler outright with internal compiler error: in action_after_output, at context.cc:1055 as observed (nondeterministically) on the mingw64 CI builders, e.g. https://buildkite.com/julialang/julia-pr/builds/45#019f2929-01a7-42bf-a992-f711e5cab0e7 The ICE fires in the diagnostics machinery while the warning is being printed (other builds emit the same warnings and survive), so suppressing the known-bogus diagnostic also sidesteps the crash. The warnings are attributed to the LLVM header lines, so the suppression must precede their inclusion. Co-authored-by: Keno Fischer <Keno@users.noreply.github.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…aLang#61886) This PR documents the known bug JuliaLang#9498. --------- Co-authored-by: Andy Dienes <51664769+adienes@users.noreply.github.com>
…1527) WIP We have enough of the JIT changes to get some cache hits now, so this can be a useful experiment. This branch puts the native code cache in `~/.julia/cache/v1.14/`, doesn't do eviction, and has some logging you can trigger by setting `JULIA_OBJCACHE_LOG` to a file. The overall design and `src/objcache.{cpp,h}` are now ready for review, but a few TODOs remain: - `optimizeDLSyms` if we can merge something like JuliaLang#61569. - `LowerPTLS` can still put incorrect code into the cache, since it will embed the TLS variable offset for the running process into the compile code on x86.
…2287) Since JuliaLang#62001, `Core.Typeof` of a type value yields the egality `Core.TypeEgal` kind, but method definitions are still made at the equality level, so `jl_method_def` had to normalize the self-type back to the `Type` kind — first for the method's own function argument (JuliaLang#62001), then again for the kwcall callee (JuliaLang#62278), which had been missed and made inner and outer keyword constructors mutually ambiguous. Fix this in lowering instead, as suggested in JuliaLang#62278: add `Core.TypeEqOf`, which yields the equality kind `Type{x}` for type values (the pre-JuliaLang#62001 `Core.Typeof` semantics), spell the implicit self-type of method definitions with it in both flisp lowering and JuliaLowering, and drop both normalization branches from `jl_method_def`. Co-authored-by: Keno Fischer <Keno@users.noreply.github.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…ments and simplify script (JuliaLang#62281)
An attempt at fixing interrupt handling, also some specific interrupt hardening from manual tests, and adds interrupt tests. Fixes JuliaLang#58689 Closes JuliaLang#58849 Developed with Claude Fable 5: ---- Since JuliaLang#57544, an idle thread parks in a per-thread internal scheduler task. A SIGINT is always delivered to thread 1, which is almost always parked when the signal arrives, so the resulting `InterruptException` landed in the scheduler task's `wait_forever`, where it was reported as a confusing `Internal Task ERROR: InterruptException` and then dropped. As a result Ctrl-C no longer reached user code: - scripts blocked in `sleep`/IO could not be interrupted at all, - the REPL printed internal task errors on every Ctrl-C, - `Distributed.interrupt` (which just sends SIGINT to the worker process) became a silent no-op, breaking remote interrupts in Distributed, Malt.jl/Pluto, and IJulia. 1.12 and 1.13 worked around this by reverting JuliaLang#57544 and its follow-ups; master still had the scheduler task and the broken behavior. ## What this does **`base/task.jl`** — Each thread now remembers the last user task that yielded into the scheduler while going idle (never recording a completed task, so this does not delay collection of done tasks — the problem JuliaLang#57544 fixed). When an `InterruptException` is delivered to the scheduler task, it is re-thrown into a task that can meaningfully observe it instead of being dropped: the REPL backend if it is evaluating user code; silently dropped at an idle REPL prompt; otherwise the last idle task, falling back to the root task. Expected failures of the redirect (the victim raced to be rescheduled, or a second interrupt arrived mid-switch) drop the interrupt; anything unexpected is still reported. Delivery remains best-effort, as it always has been; robust cancellation is left to JuliaLang#60281. **`src/gf.c`** — Interrupting a process that is compiling (e.g. Ctrl-C during `Pkg.test`) frequently threw the `InterruptException` into type inference via the safepoint, unwinding the compiler mid-flight ("`Internal error: during type inference of ...`", an abort in assertion builds, and a lost interrupt). The inference entry point is now signal-atomic, so the interrupt is deferred and rethrown once compiler state is consistent. Forced interrupts (repeated Ctrl-C) bypass the deferral as before. **`stdlib/REPL/src/REPL.jl`** — An interrupt forwarded to the REPL backend just as user code finished evaluating (the forwarder checks `in_eval`, but eval can complete before the throw lands) was raised at `take!(backend.repl_channel)` and tore down the whole REPL session. The backend loop now ignores a stray `InterruptException` there and keeps serving. ## Validation New regression tests in `test/misc.jl` (pty-driven REPL + subprocess scenarios, Unix-only) and `stdlib/REPL/test/repl.jl`, all derived from the issue reports: | Scenario | 1.11 | master before | master after | |---|---|---|---| | SIGINT at idle REPL prompt | ok | internal-error noise | ok | | SIGINT during REPL `sleep` loop | ok | noise + interrupt works | ok | | SIGINT to `julia -e 'sleep(600)'` | exits after 2nd SIGINT | never exits | exits cleanly on 1st | | `Distributed.interrupt` of a busy worker | `RemoteException` | silent no-op | `RemoteException` | | SIGINT during `Pkg.test`-style run (compiling) | — | inference internal error / abort | clean `InterruptException` | The fix is platform-independent (the Windows delivery path in `signals-win.c` lands in the same scheduler task), but the tests are Unix-only since sending a console Ctrl-C from the test harness on Windows requires `GenerateConsoleCtrlEvent`/`CREATE_NEW_PROCESS_GROUP`, which the spawn API doesn't expose. This also adds the Unix portion of the CI coverage requested in JuliaLang#58849, and likely fixes the crash class in JuliaLang#50045 (unverified, needs network). Fixes JuliaLang#58689 Fixes JuliaLang#29369 Fixes JuliaLang#43451 Closes JuliaLang#58849 Fixes JuliaLang#50045 --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
adienes
force-pushed
the
fix-enternode-scope-renumber
branch
from
July 8, 2026 17:13
1736ecf to
0513e55
Compare
adienes
force-pushed
the
fix-enternode-scope-renumber
branch
2 times, most recently
from
July 8, 2026 17:31
e8e0609 to
698d6e8
Compare
`renumber_ir_elements!` skipped its EnterNode handling entirely when
`catch_dest == 0`, leaving the SSA reference of the scope operand stale
whenever `convert_to_ircode` inserted statements (unreachable markers
after `Union{}` calls, or coverage statements) earlier in the function.
The dangling reference makes the entered scope an arbitrary value, which
`Core.current_scope()` then observes at runtime inside the scoped region:
using Base.ScopedValues
const sval = ScopedValue(1)
@noinline getscope() = Core.current_scope()
function f(c::Bool)
if c
error("x")
end
@with sval => 2 getscope()
end
f(false) # Pair{ScopedValue{Int64}, Int64}, should be a Scope
Frame-less scope enters are currently only produced by the try/catch
elision for provably-nothrow regions (JuliaLang#52527), so this requires the
`@with` body to be nothrow; it affects all Julia versions since 1.11.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
adienes
force-pushed
the
fix-enternode-scope-renumber
branch
from
July 8, 2026 17:41
698d6e8 to
60b3833
Compare
Owner
Author
|
Superseded by JuliaLang#62300, which targets upstream master. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
renumber_ir_elements!only renumbered anEnterNode's operands whencatch_dest != 0, but frame-less enters (catch_dest == 0) still carry ascopeSSA operand. Whenconvert_to_ircodeinserts statements earlier in the function that reference goes stale, soCore.current_scope()observes an arbitrary value:Frame-less enters only arise from the nothrow try/catch elision (JuliaLang#52527), so the
@withbody must be nothrow; present since 1.11.Fixes JuliaLang#62082.
Written with AI assistance (Claude).