Skip to content

JuliaSyntax:force specialize on function in parse_brackets#60403

Merged
KristofferC merged 1 commit intomasterfrom
kc/syntax_force_spec
Dec 17, 2025
Merged

JuliaSyntax:force specialize on function in parse_brackets#60403
KristofferC merged 1 commit intomasterfrom
kc/syntax_force_spec

Conversation

@KristofferC
Copy link
Copy Markdown
Member

@KristofferC KristofferC commented Dec 17, 2025

Brings over JuliaLang/JuliaSyntax.jl#601 here now that the repo has moved. But we need this on 1.13 (and 1.12) as well.

Without this the REPL becomes very laggy after loading GLMakie:

#= 3586.0 ms =# precompile(Tuple{typeof(REPL.LineEdit.refresh_multi_line), Base.Terminals.TerminalBuffer, Base.Terminals.UnixTerminal, Union{REPL.LineEdit.PrefixSearchState, REPL.LineEdit.PromptState}}) # recompile

Even though the function is directly called in the function body, I think the fact that there is a default argument prevents specialization from happening. To elaborate:

g(f, x=1) = f(..., x)

is rewritten internally as:

g(f, x) = f(..., x)
g(f) = g(f, 1)

now, the second generated method does not call f directly so it will heuristically be despecialized.

@KristofferC KristofferC added backport 1.13 Change should be backported to release-1.13 backport 1.12 Change should be backported to release-1.12 labels Dec 17, 2025
@KristofferC
Copy link
Copy Markdown
Member Author

cc @JamesWrigley

@JamesWrigley
Copy link
Copy Markdown
Member

Did you check that this fixes the invalidations? When I built Julia from that JuliaSyntax branch it didn't actually work: JuliaLang/JuliaSyntax.jl#601 (comment)

I ended up type-asserting everything, which did fix it: JuliaLang/JuliaSyntax.jl#601 (comment)

@KristofferC
Copy link
Copy Markdown
Member Author

I tested and it worked for me at least.

@JamesWrigley
Copy link
Copy Markdown
Member

Ok, maybe I screwed up the JuliaSyntax commit or something when building. Glad that this simpler fix works :)

@KristofferC
Copy link
Copy Markdown
Member Author

KristofferC commented Dec 17, 2025

You could confirm if you want to (juliaup add pr60403), I am not sure I checked the same things as you.

@JamesWrigley
Copy link
Copy Markdown
Member

Yep, they don't show up anymore 🎉

julia> using SnoopCompileCore

julia> invs, trees = begin
           invs = @snoop_invalidations import InitialValues
           using SnoopCompile, AbstractTrees
           trees = invalidation_trees(invs)
           invs, trees
       end;

julia> trees
8-element Vector{SnoopCompile.MethodInvalidations}:
 inserting +(x, ::Union{InitialValues.NonspecificInitialValue, InitialValues.SpecificInitialValue{typeof(+)}}) @ InitialValues ~/.julia/packages/InitialValues/OWP8V/src/InitialValues.jl:161 invalidated:
   mt_backedges: 1: signature Tuple{typeof(+), Ptr{UInt16}, Any} triggered MethodInstance for Base._copyfrompacked!(::Ptr, ::Ptr{UInt16}) (0 children)
                 2: signature Tuple{typeof(+), Ptr{Tuple{UInt8, UInt8}}, Any} triggered MethodInstance for Base._copyfrompacked!(::Ptr, ::Ptr{Tuple{UInt8, UInt8}}) (0 children)
                 3: signature Tuple{typeof(+), Ptr{Int32}, Any} triggered MethodInstance for Base._copytopacked!(::Ptr{Int32}, ::Ptr) (0 children)
                 4: signature Tuple{typeof(+), Ptr{Int32}, Any} triggered MethodInstance for Base._copytopacked!(::Ptr{Int32}, ::Ptr{T} where T<:Function) (0 children)
                 5: signature Tuple{typeof(+), Ptr{T} where T<:(NTuple{_A, UInt8} where _A), Any} triggered MethodInstance for Base._copytopacked!(::Ptr{T} where T<:(NTuple{_A, UInt8} where _A), ::Ptr) (0 children)
                 6: signature Tuple{typeof(+), Ptr{T} where T<:(NTuple{_A, UInt8} where _A), Any} triggered MethodInstance for Base._copytopacked!(::Ptr{T} where T<:(NTuple{_A, UInt8} where _A), ::Ptr{T} where T<:Function) (0 children)

 inserting |(::Union{InitialValues.NonspecificInitialValue, InitialValues.SpecificInitialValue{typeof(|)}}, x) @ InitialValues ~/.julia/packages/InitialValues/OWP8V/src/InitialValues.jl:154 invalidated:
   mt_backedges: 1: signature Tuple{typeof(|), Any, Bool} triggered MethodInstance for Base._base(::Int64, ::Integer, ::Int64, ::Bool) (0 children)

 inserting &(::Union{InitialValues.NonspecificInitialValue, InitialValues.SpecificInitialValue{typeof(&)}}, x) @ InitialValues ~/.julia/packages/InitialValues/OWP8V/src/InitialValues.jl:154 invalidated:
   mt_backedges: 1: signature Tuple{typeof(&), Any, Bool} triggered MethodInstance for ==(::AbstractUnitRange, ::UnitRange{Int64}) (7 children)

 inserting add_sum(x, ::Union{InitialValues.NonspecificInitialValue, InitialValues.SpecificInitialValue{typeof(Base.add_sum)}}) @ InitialValues ~/.julia/packages/InitialValues/OWP8V/src/InitialValues.jl:161 invalidated:
   backedges: 1: superseding add_sum(x, y) @ Base reduce.jl:16 with MethodInstance for Base.add_sum(::Int64, ::Any) (39 children)

 inserting &(x, ::Union{InitialValues.NonspecificInitialValue, InitialValues.SpecificInitialValue{typeof(&)}}) @ InitialValues ~/.julia/packages/InitialValues/OWP8V/src/InitialValues.jl:161 invalidated:
   mt_backedges: 1: signature Tuple{typeof(&), Bool, Any} triggered MethodInstance for Base.var"#string#391"(::Int64, ::Int64, ::typeof(string), ::Unsigned) (0 children)
                 2: signature Tuple{typeof(&), Bool, Any} triggered MethodInstance for div(::Unsigned, ::Int64, ::RoundingMode{:Up}) (1 children)
                 3: signature Tuple{typeof(&), Bool, Any} triggered MethodInstance for isempty(::StepRange{Tuple{LineNumberNode, Expr}}) (2 children)
                 4: signature Tuple{typeof(&), Bool, Any} triggered MethodInstance for LinearAlgebra._chkstride1(::Bool, ::Any, ::Vararg{Any}) (8 children)
                 5: signature Tuple{typeof(&), Bool, Any} triggered MethodInstance for div(::Unsigned, ::Int64, ::RoundingMode{:Down}) (48 children)

 inserting *(::Union{InitialValues.NonspecificInitialValue, InitialValues.SpecificInitialValue{typeof(*)}}, x) @ InitialValues ~/.julia/packages/InitialValues/OWP8V/src/InitialValues.jl:154 invalidated:
   mt_backedges:  1: signature Tuple{typeof(*), Any, Compiler.MethodMatchInfo} triggered MethodInstance for Base.lerpi(::Integer, ::Integer, ::Compiler.MethodMatchInfo, ::Compiler.MethodMatchInfo) (0 children)
                  2: signature Tuple{typeof(*), Any, Compiler.CallMeta} triggered MethodInstance for Base.lerpi(::Integer, ::Integer, ::Compiler.CallMeta, ::Compiler.CallMeta) (0 children)
                  3: signature Tuple{typeof(*), Any, Compiler.ApplyCallInfo} triggered MethodInstance for Base.lerpi(::Integer, ::Integer, ::Compiler.ApplyCallInfo, ::Compiler.ApplyCallInfo) (0 children)
                  4: signature Tuple{typeof(*), Any, Nothing} triggered MethodInstance for Base.lerpi(::Integer, ::Integer, ::Nothing, ::Nothing) (0 children)
                  5: signature Tuple{typeof(*), Any, Compiler.AbstractIterationInfo} triggered MethodInstance for Base.lerpi(::Integer, ::Integer, ::Compiler.AbstractIterationInfo, ::Compiler.AbstractIterationInfo) (0 children)
                  6: signature Tuple{typeof(*), Any, Compiler.NewPhiCNode2} triggered MethodInstance for Base.lerpi(::Integer, ::Integer, ::Compiler.NewPhiCNode2, ::Compiler.NewPhiCNode2) (0 children)
                  7: signature Tuple{typeof(*), Any, Compiler.AbstractIterationInfo} triggered MethodInstance for Base.lerpi(::Integer, ::Integer, ::Compiler.AbstractIterationInfo, ::Compiler.AbstractIterationInfo) (1 children)
                  8: signature Tuple{typeof(*), Any, Compiler.MethodMatchInfo} triggered MethodInstance for Base.lerpi(::Integer, ::Integer, ::Compiler.MethodMatchInfo, ::Compiler.MethodMatchInfo) (10 children)
                  9: signature Tuple{typeof(*), Any, Compiler.CallMeta} triggered MethodInstance for Base.lerpi(::Integer, ::Integer, ::Compiler.CallMeta, ::Compiler.CallMeta) (10 children)
                 10: signature Tuple{typeof(*), Any, Compiler.ApplyCallInfo} triggered MethodInstance for Base.lerpi(::Integer, ::Integer, ::Compiler.ApplyCallInfo, ::Compiler.ApplyCallInfo) (10 children)
                 11: signature Tuple{typeof(*), Any, Nothing} triggered MethodInstance for Base.lerpi(::Integer, ::Integer, ::Nothing, ::Nothing) (10 children)
                 12: signature Tuple{typeof(*), Any, Module} triggered MethodInstance for Base.lerpi(::Integer, ::Integer, ::Module, ::Module) (10 children)
                 13: signature Tuple{typeof(*), Any, Compiler.NewPhiCNode2} triggered MethodInstance for Base.lerpi(::Integer, ::Integer, ::Compiler.NewPhiCNode2, ::Compiler.NewPhiCNode2) (10 children)
                 14: signature Tuple{typeof(*), Any, Tuple{LineNumberNode, Expr}} triggered MethodInstance for Base.lerpi(::Integer, ::Integer, ::Tuple{LineNumberNode, Expr}, ::Tuple{LineNumberNode, Expr}) (11 children)

 inserting convert(::Type{T}, ::Union{InitialValues.SpecificInitialValue{typeof(*)}, InitialValues.SpecificInitialValue{typeof(Base.mul_prod)}}) where T<:Union{AbstractString, Number} @ InitialValues ~/.julia/packages/InitialValues/OWP8V/src/InitialValues.jl:258 invalidated:
   mt_backedges:  1: signature Tuple{typeof(convert), Type{String}, Any} triggered MethodInstance for Base.Terminals.TTYTerminal(::Any, ::Any, ::Any, ::Any) (0 children)
                  2: signature Tuple{typeof(convert), Type{String}, Any} triggered MethodInstance for Base.CoreLogging.var"#handle_message#6"(::Base.Pairs{Symbol, Union{}, Nothing, @NamedTuple{}}, ::typeof(Base.CoreLogging.handle_message), ::Base.CoreLogging.ConsoleLogger, ::Base.CoreLogging.LogLevel, ::Any, ::Any, ::Any, ::Any, ::Any, ::Any) (1 children)
                  3: signature Tuple{typeof(convert), Type{String}, Any} triggered MethodInstance for Base.CoreLogging.var"#handle_message#3"(::Base.Pairs{Symbol, Union{}, Nothing, @NamedTuple{}}, ::typeof(Base.CoreLogging.handle_message), ::Base.CoreLogging.SimpleLogger, ::Base.CoreLogging.LogLevel, ::Any, ::Any, ::Any, ::Any, ::Any, ::Any) (1 children)
                  4: signature Tuple{typeof(convert), Type{String}, Any} triggered MethodInstance for setindex!(::Vector{String}, ::Any, ::Int64) (2 children)
                  5: signature Tuple{typeof(convert), Type{String}, Any} triggered MethodInstance for Base.CoreLogging.var"#handle_message#6"(::Base.Pairs{Symbol, _A, Nothing, A} where {_A, A<:NamedTuple}, ::typeof(Base.CoreLogging.handle_message), ::Base.CoreLogging.ConsoleLogger, ::Base.CoreLogging.LogLevel, ::Any, ::Any, ::Any, ::Any, ::Any, ::Any) (7 children)
                  6: signature Tuple{typeof(convert), Type{String}, Any} triggered MethodInstance for Base.CoreLogging.var"#handle_message#3"(::Base.Pairs{Symbol, _A, Nothing, A} where {_A, A<:NamedTuple}, ::typeof(Base.CoreLogging.handle_message), ::Base.CoreLogging.SimpleLogger, ::Base.CoreLogging.LogLevel, ::Any, ::Any, ::Any, ::Any, ::Any, ::Any) (7 children)
                  7: signature Tuple{typeof(convert), Type{String}, Any} triggered MethodInstance for setindex!(::Memory{String}, ::Any, ::Int64) (14 children)
                  8: signature Tuple{typeof(convert), Type{SubString{String}}, Any} triggered MethodInstance for setindex!(::Memory{SubString{String}}, ::Any, ::Int64) (14 children)
                  9: signature Tuple{typeof(convert), Type{SubString{Base.AnnotatedString{String}}}, Any} triggered MethodInstance for setindex!(::Memory{SubString{Base.AnnotatedString{String}}}, ::Any, ::Int64) (15 children)
                 10: signature Tuple{typeof(convert), Type{Union{Bool, Int64, String}}, Any} triggered MethodInstance for convert(::Type{Union{Nothing, Bool, Int64, String}}, ::Any) (113 children)

 inserting |(x, ::Union{InitialValues.NonspecificInitialValue, InitialValues.SpecificInitialValue{typeof(|)}}) @ InitialValues ~/.julia/packages/InitialValues/OWP8V/src/InitialValues.jl:161 invalidated:
   mt_backedges: 1: signature Tuple{typeof(|), Bool, Any} triggered MethodInstance for <=(::Any, ::VersionNumber) (0 children)
                 2: signature Tuple{typeof(|), Missing, Any} triggered MethodInstance for <=(::Any, ::VersionNumber) (307 children)

@KristofferC KristofferC merged commit b34261b into master Dec 17, 2025
12 of 14 checks passed
@KristofferC KristofferC deleted the kc/syntax_force_spec branch December 17, 2025 17:56
@KristofferC KristofferC mentioned this pull request Dec 18, 2025
21 tasks
mlechu pushed a commit to JuliaLang/JuliaSyntax.jl that referenced this pull request Dec 19, 2025
mlechu pushed a commit to JuliaLang/JuliaSyntax.jl that referenced this pull request Dec 19, 2025
This was referenced Jan 9, 2026
@DilumAluthge
Copy link
Copy Markdown
Member

I see the backport 1.12 label on this PR, but of course JuliaSyntax doesn't live in the JuliaLang/julia repo for 1.12.

@mlechu @topolarity Can I assume that y'all will go through the same backports process for this PR as described in #60246 (comment)? If so, we can remove the backport 1.12 label from this PR - otherwise, the Backporter script will keep trying to backport it.

@JamesWrigley
Copy link
Copy Markdown
Member

Yeah this has a confusing history 😅 It was already backported in JuliaLang/JuliaSyntax.jl#613, but there was no PR to update the JuliaSyntax version in 1.12 because I then discovered it didn't work on 1.12: JuliaLang/JuliaSyntax.jl#600 (comment)

So then we made #60476 instead, which was backported to JuliaSyntax: JuliaLang/JuliaSyntax.jl#616

TL;DR: #60641 contains both this PR and #60476.

@JamesWrigley
Copy link
Copy Markdown
Member

That reminds me I need to do the same for 1.13. This PR has already been backported to JuliaSyntax (JuliaLang/JuliaSyntax.jl#614) but not #60476.

fingolfin pushed a commit that referenced this pull request Jan 28, 2026
…ction may be required with optional arguments (#60404)

Ref #60403
@KristofferC KristofferC mentioned this pull request Feb 4, 2026
56 tasks
@KristofferC KristofferC removed the backport 1.12 Change should be backported to release-1.12 label Feb 25, 2026
@KristofferC KristofferC mentioned this pull request Mar 13, 2026
39 tasks
@KristofferC KristofferC removed the backport 1.13 Change should be backported to release-1.13 label Mar 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants