Repository navigation
Route zero- and one-argument instance sends through shared helpers - #93
Merged
Merged
Conversation
Every `@objc` send used to expand its argument conversion, autorelease pool, tracing hook and result wrapping inline. `@objcproperties` puts one such send in every branch of the generated `objc_getproperty` and `objc_setproperty!` methods, so these methods get large: for Metal.jl, 690 methods holding 5.6 MB of compressed source, which Julia decompresses at every load to scan for bindings. On Julia 1.12 and later, instance sends with at most one argument now call `@inline` helpers that implement the same steps in the same order, with the `objc_msgSend` call generated per signature from `@ccall` expansions made at precompile time. Steady-state performance is unchanged. Tracing mode, struct returns through `objc_msgSend_stret`, `Out` arguments, sends with more arguments, and older Julia versions keep the expanded code. Both code paths share the result-wrapping logic. For Metal.jl, this shrinks the property methods' source to 0.7 MB and the image by 5.5 MB, and loads it 50 to 75 ms faster on Julia 1.12 and 1.13. Inferring a property method that wasn't precompiled takes slightly longer, about 0.5 ms per property.
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.
Every
@objcsend expands its argument conversion, autorelease pool, tracing hook and result wrapping inline, and@objcpropertiesputs one such send in every branch of the generatedobjc_getpropertyandobjc_setproperty!methods. For Metal.jl that's 690 methods holding 5.6 MB of compressed source, which Julia decompresses at every load to scan for bindings: 53 ms on Julia 1.13, 170 ms on 1.12.On Julia 1.12 and later, instance sends with at most one argument now call
@inlinehelpers that do the same steps in the same order, with theobjc_msgSendcall itself generated per signature from@ccallexpansions made at precompile time (and stored as immutable templates, so the generator only substitutes types). Tracing mode, struct returns throughobjc_msgSend_stret,Outarguments, sends with more arguments and older Julia versions keep the expanded code; both paths share the result-wrapping logic. The generated code is the same as before (@code_llvmidentical for getters, setters, adopting and one-argument sends, apart from a slightly different block layout in cascades with nullable-object properties), and steady-state property access is unchanged.For Metal.jl, the property methods' source shrinks to 0.7 MB and the image by 5.5 MB, and it loads 40 to 75 ms faster on Julia 1.12 and 1.13. The cost: inferring a property method that wasn't precompiled takes about 0.5 ms more per property, and the first send with a new signature generates its
ccall(about 0.7 ms).The added tests cover properties of each return-type shape, setters, adoption of
init/mutableCopyresults with deallocation checked, nil returns, the order in which the receiver, availability and argument are handled, and that the autorelease pool stays balanced when a conversion throws.