summaryrefslogtreecommitdiff
path: root/zjit/src/codegen.rs
AgeCommit message (Collapse)Author
2025-12-18JIT: Move EC offsets to jit_bindgen_constantsJohn Hawthorn
Co-authored-by: Alan Wu <alanwu@ruby-lang.org>
2025-12-16ZJIT: Use rb_zjit_writebarrier_check_immediate() instead of ↵Benoit Daloze
rb_gc_writebarrier() in gen_write_barrier() * To avoid calling rb_gc_writebarrier() with an immediate value in gen_write_barrier(), and avoid the LIR jump issue.
2025-12-16Revert "ZJIT: Do not call rb_gc_writebarrier() with an immediate value in ↵Benoit Daloze
gen_write_barrier()" * This reverts commit 623559faa3dd0927b4034a752226a30ae8821604. * There is an issue with the jump in LIR, see https://github.com/ruby/ruby/pull/15542.
2025-12-16ZJIT: Do not call rb_gc_writebarrier() with an immediate value in ↵Benoit Daloze
gen_write_barrier()
2025-12-16Revert "ZJIT: Allow ccalls above 7 arguments"Alan Wu
This reverts commit 2f151e76b5dc578026706b31f054d5caf5374b05. The SP decrement (push) before the call do not match up with the pops after the call, so registers were restored incorrectly. Code from: ./miniruby --zjit-call-threshold=1 --zjit-dump-disasm -e 'p Time.new(1992, 9, 23, 23, 0, 0, :std)' str x11, [sp, #-0x10]! str x12, [sp, #-0x10]! stur x7, [sp] # last argument mov x0, x20 mov x7, x6 mov x6, x5 mov x5, x4 mov x4, x3 mov x3, x2 mov x2, x1 ldur x1, [x29, #-0x20] mov x16, #0xccfc movk x16, #0x2e7, lsl #16 movk x16, #1, lsl #32 blr x16 ldr x12, [sp], #0x10 # supposed to match str x12, [sp, #-0x10]!, but got last argument ldr x11, [sp], #0x10
2025-12-13ZJIT: Nil-fill locals in direct send (#15536)Randy Stauner
Avoid garbage reads from locals in eval. Before the fix the test fails with <"[\"x\", \"x\", \"x\", \"x\"]"> expected but was <"[\"x\", \"x\", \"x\", \"x286326928\"]">.
2025-12-12ZJIT: Allow ccalls above 7 arguments (#15312)Aiden Fox Ivey
ZJIT: Add stack support for CCalls
2025-12-12ZJIT: Inline `Hash#[]=`Stan Lo
2025-12-12ZJIT: Add Shape type to HIR (#15528)Max Bernstein
It's just a nicety (they fit fine as CUInt32) but this makes printing look nicer in real execution and also in tests (helps with #15489). Co-authored-by: Randy Stauner <randy@r4s6.net>
2025-12-10ZJIT: Re-compile ISEQs invalidated by PatchPoint (#15459)Takashi Kokubun
2025-12-10ZJIT: Use inline format args (#15482)Alex Rocha
2025-12-09ZJIT: Put keyword bits in callee frame rather than c_argsRandy Stauner
2025-12-09ZJIT: Handle caller_kwarg in direct send when all keyword params are requiredRandy Stauner
2025-12-09ZJIT: Support opt_newarray_send with PACK_BUFFERMax Bernstein
2025-12-09ZJIT: Add codegen for FixnumDiv (#15452)Abrar Habib
Fixes https://github.com/Shopify/ruby/issues/902 This pull request adds code generation for dividing fixnums. Testing confirms the normal case, flooring, and side-exiting on division by zero.
2025-12-08ZJIT: Avoid redundant SP save in codegen (#15448)Stan Lo
2025-12-03ZJIT: Optimize setivar with shape transition (#15375)Max Bernstein
Since we do a decent job of pre-sizing objects, don't handle the case where we would need to re-size an object. Also don't handle too-complex shapes. lobsters stats before: ``` Top-20 calls to C functions from JIT code (79.4% of total 90,051,140): rb_vm_opt_send_without_block: 19,762,433 (21.9%) rb_vm_setinstancevariable: 7,698,314 ( 8.5%) rb_hash_aref: 6,767,461 ( 7.5%) rb_vm_env_write: 5,373,080 ( 6.0%) rb_vm_send: 5,049,229 ( 5.6%) rb_vm_getinstancevariable: 4,535,259 ( 5.0%) rb_obj_is_kind_of: 3,746,306 ( 4.2%) rb_ivar_get_at_no_ractor_check: 3,745,237 ( 4.2%) rb_vm_invokesuper: 3,037,467 ( 3.4%) rb_ary_entry: 2,351,983 ( 2.6%) rb_vm_opt_getconstant_path: 1,344,740 ( 1.5%) rb_vm_invokeblock: 1,184,474 ( 1.3%) Hash#[]=: 1,064,288 ( 1.2%) rb_gc_writebarrier: 1,006,972 ( 1.1%) rb_ec_ary_new_from_values: 902,687 ( 1.0%) fetch: 898,667 ( 1.0%) rb_str_buf_append: 833,787 ( 0.9%) rb_class_allocate_instance: 822,024 ( 0.9%) Hash#fetch: 699,580 ( 0.8%) _bi20: 682,068 ( 0.8%) Top-4 setivar fallback reasons (100.0% of total 7,732,326): shape_transition: 6,032,109 (78.0%) not_monomorphic: 1,469,300 (19.0%) not_t_object: 172,636 ( 2.2%) too_complex: 58,281 ( 0.8%) ``` lobsters stats after: ``` Top-20 calls to C functions from JIT code (79.0% of total 88,322,656): rb_vm_opt_send_without_block: 19,777,880 (22.4%) rb_hash_aref: 6,771,589 ( 7.7%) rb_vm_env_write: 5,372,789 ( 6.1%) rb_gc_writebarrier: 5,195,527 ( 5.9%) rb_vm_send: 5,049,145 ( 5.7%) rb_vm_getinstancevariable: 4,538,485 ( 5.1%) rb_obj_is_kind_of: 3,746,241 ( 4.2%) rb_ivar_get_at_no_ractor_check: 3,745,172 ( 4.2%) rb_vm_invokesuper: 3,037,157 ( 3.4%) rb_ary_entry: 2,351,968 ( 2.7%) rb_vm_setinstancevariable: 1,703,337 ( 1.9%) rb_vm_opt_getconstant_path: 1,344,730 ( 1.5%) rb_vm_invokeblock: 1,184,290 ( 1.3%) Hash#[]=: 1,061,868 ( 1.2%) rb_ec_ary_new_from_values: 902,666 ( 1.0%) fetch: 898,666 ( 1.0%) rb_str_buf_append: 833,784 ( 0.9%) rb_class_allocate_instance: 821,778 ( 0.9%) Hash#fetch: 755,913 ( 0.9%) Top-4 setivar fallback reasons (100.0% of total 1,703,337): not_monomorphic: 1,472,405 (86.4%) not_t_object: 172,629 (10.1%) too_complex: 58,281 ( 3.4%) new_shape_needs_extension: 22 ( 0.0%) ``` I also noticed that primitive printing in HIR was broken so I fixed that. Co-authored-by: Aaron Patterson <tenderlove@ruby-lang.org>
2025-12-03ZJIT: Optimize NewArray to use rb_ec_ary_new_from_values (#15391)Goshanraj Govindaraj
2025-12-02ZJIT: Optimize GetIvar for non-T_OBJECTBenoit Daloze
* All Invariant::SingleRactorMode PatchPoint are replaced by assume_single_ractor_mode() to fix https://github.com/Shopify/ruby/issues/875 for SingleRactorMode patchpoints.
2025-12-01ZJIT: Open-code String#getbyteMax Bernstein
Don't call a C function.
2025-12-01ZJIT: Specialize Integer#>>Max Bernstein
Same as Integer#>>. Also add more strict type checks for both Integer#>> and Integer#<<.
2025-12-01ZJIT: Specialize String#<< with FixnumMax Bernstein
Append a codepoint.
2025-12-01ZJIT: Standardize method dispatch insns' `recv` field (#15334)Stan Lo
ZJIT: Standardize C call related insn fields - Add `recv` field to `CCall` and `CCallWithFrame` so now all method dispatch related instructions have `recv` field, separate from `args` field. This ensures consistent pointer arithmetic when generating code for these instructions. - Standardize `recv` field's display position in send related instructions.
2025-12-01ZJIT: Optimize variadic cfunc `Send` calls into `CCallVariadic` (#14898)Stan Lo
ZJIT: Optimize variadic cfunc Send calls into CCallVariadic
2025-11-26ZJIT: Count fallback reasons for set/get/definedivar (#15324)Max Bernstein
lobsters: ``` Top-4 setivar fallback reasons (100.0% of total 7,789,008): shape_transition: 6,074,085 (78.0%) not_monomorphic: 1,484,013 (19.1%) not_t_object: 172,629 ( 2.2%) too_complex: 58,281 ( 0.7%) Top-3 getivar fallback reasons (100.0% of total 9,348,832): not_t_object: 4,658,833 (49.8%) not_monomorphic: 4,542,316 (48.6%) too_complex: 147,683 ( 1.6%) Top-3 definedivar fallback reasons (100.0% of total 366,383): not_monomorphic: 361,389 (98.6%) too_complex: 3,062 ( 0.8%) not_t_object: 1,932 ( 0.5%) ``` railsbench: ``` Top-3 setivar fallback reasons (100.0% of total 15,119,057): shape_transition: 13,760,763 (91.0%) not_monomorphic: 982,368 ( 6.5%) not_t_object: 375,926 ( 2.5%) Top-2 getivar fallback reasons (100.0% of total 14,438,747): not_t_object: 7,643,870 (52.9%) not_monomorphic: 6,794,877 (47.1%) Top-2 definedivar fallback reasons (100.0% of total 209,613): not_monomorphic: 209,526 (100.0%) not_t_object: 87 ( 0.0%) ``` shipit: ``` Top-3 setivar fallback reasons (100.0% of total 14,516,254): shape_transition: 8,613,512 (59.3%) not_monomorphic: 5,761,398 (39.7%) not_t_object: 141,344 ( 1.0%) Top-2 getivar fallback reasons (100.0% of total 21,016,444): not_monomorphic: 11,313,482 (53.8%) not_t_object: 9,702,962 (46.2%) Top-2 definedivar fallback reasons (100.0% of total 290,382): not_monomorphic: 287,755 (99.1%) not_t_object: 2,627 ( 0.9%) ```
2025-11-21ZJIT: Don't make GuardNotFrozen consider immediatesMax Bernstein
2025-11-21ZJIT: Inline GuardNotFrozen into LIRMax Bernstein
No sense calling a C function.
2025-11-21ZJIT: Specialize Module#=== and Kernel#is_a? into IsAMax Bernstein
2025-11-21ZJIT: Inline Integer#<< for constant rhs (#15258)Max Bernstein
This is good for protoboeuf and other binary parsing
2025-11-21ZJIT: Inline Thread.current (#15272)Max Bernstein
Add `LoadEC` then it's just two `LoadField`.
2025-11-21ZJIT: Inline ArrayLength into LIRMax Bernstein
2025-11-20ZJIT: Read `iseq->body->param` directly instead of through FFIAlan Wu
Going through a call to a C function just to read a bitfield was a little extreme. We did it to be super conservative since bitfields have historically been the trigger of many bugs and surprises. Let's try directly accessing them with code from rust-bindgen. If this ends up causing issues, we can use the FFI approach behind nicer wrappers. In any case, directly access regular struct fields such as `lead_num` and `opt_num` to remove boilerplate.
2025-11-20ZJIT: Compile the VM_OPT_NEWARRAY_SEND_HASH variant of opt_newarray_sendKevin Menard
2025-11-20ZJIT: Rename array length reference to make the code easier to followKevin Menard
2025-11-20ZJIT: Put optional interpreter cache on both GetIvar and SetIvarMax Bernstein
2025-11-20ZJIT: Fix pointer types for SetInstanceVariableMax Bernstein
2025-11-19ZJIT: Count all calls to C functions from generated code (#15240)Max Bernstein
lobsters: ``` Top-20 calls to C functions from JIT code (79.9% of total 97,004,883): rb_vm_opt_send_without_block: 19,874,212 (20.5%) rb_vm_setinstancevariable: 9,774,841 (10.1%) rb_ivar_get: 9,358,866 ( 9.6%) rb_hash_aref: 6,828,948 ( 7.0%) rb_vm_send: 6,441,551 ( 6.6%) rb_vm_env_write: 5,375,989 ( 5.5%) rb_vm_invokesuper: 3,037,836 ( 3.1%) Module#===: 2,562,446 ( 2.6%) rb_ary_entry: 2,354,546 ( 2.4%) Kernel#is_a?: 1,424,092 ( 1.5%) rb_vm_opt_getconstant_path: 1,344,923 ( 1.4%) Thread.current: 1,300,822 ( 1.3%) rb_zjit_defined_ivar: 1,222,613 ( 1.3%) rb_vm_invokeblock: 1,184,555 ( 1.2%) Hash#[]=: 1,061,969 ( 1.1%) rb_ary_push: 1,024,987 ( 1.1%) rb_ary_new_capa: 904,003 ( 0.9%) rb_str_buf_append: 833,782 ( 0.9%) rb_class_allocate_instance: 822,626 ( 0.8%) Hash#fetch: 755,913 ( 0.8%) ``` railsbench: ``` Top-20 calls to C functions from JIT code (74.8% of total 189,170,268): rb_vm_opt_send_without_block: 29,870,307 (15.8%) rb_vm_setinstancevariable: 17,631,199 ( 9.3%) rb_hash_aref: 16,928,890 ( 8.9%) rb_ivar_get: 14,441,240 ( 7.6%) rb_vm_env_write: 11,571,001 ( 6.1%) rb_vm_send: 11,153,457 ( 5.9%) rb_vm_invokesuper: 7,568,267 ( 4.0%) Module#===: 6,065,923 ( 3.2%) Hash#[]=: 2,842,990 ( 1.5%) rb_ary_entry: 2,766,125 ( 1.5%) rb_ary_push: 2,722,079 ( 1.4%) rb_vm_invokeblock: 2,594,398 ( 1.4%) Thread.current: 2,560,129 ( 1.4%) rb_str_getbyte: 1,965,627 ( 1.0%) Kernel#is_a?: 1,961,815 ( 1.0%) rb_vm_opt_getconstant_path: 1,863,678 ( 1.0%) rb_hash_new_with_size: 1,796,456 ( 0.9%) rb_class_allocate_instance: 1,785,043 ( 0.9%) String#empty?: 1,713,414 ( 0.9%) rb_ary_new_capa: 1,678,834 ( 0.9%) ``` shipit: ``` Top-20 calls to C functions from JIT code (83.4% of total 182,402,821): rb_vm_opt_send_without_block: 45,753,484 (25.1%) rb_ivar_get: 21,020,650 (11.5%) rb_vm_setinstancevariable: 17,528,603 ( 9.6%) rb_hash_aref: 11,892,856 ( 6.5%) rb_vm_send: 11,723,471 ( 6.4%) rb_vm_env_write: 10,434,452 ( 5.7%) Module#===: 4,225,048 ( 2.3%) rb_vm_invokesuper: 3,705,906 ( 2.0%) Thread.current: 3,337,603 ( 1.8%) rb_ary_entry: 3,114,378 ( 1.7%) Hash#[]=: 2,509,912 ( 1.4%) Array#empty?: 2,282,994 ( 1.3%) rb_vm_invokeblock: 2,210,511 ( 1.2%) Hash#fetch: 2,017,960 ( 1.1%) _bi20: 1,975,147 ( 1.1%) rb_zjit_defined_ivar: 1,897,127 ( 1.0%) rb_vm_opt_getconstant_path: 1,813,294 ( 1.0%) rb_ary_new_capa: 1,615,406 ( 0.9%) Kernel#is_a?: 1,567,854 ( 0.9%) rb_class_allocate_instance: 1,560,035 ( 0.9%) ``` Thanks to @eregon for the idea. Co-authored-by: Jacob Denbeaux <jacob.denbeaux@shopify.com> Co-authored-by: Alan Wu <XrXr@users.noreply.github.com>
2025-11-18ZJIT: Rename the operand of Insn::GuardNotFrozen from val to recvBenoit Daloze
* When writing to an object, the receiver should be checked if it's frozen, not the value, so this avoids an error-prone autocomplete.
2025-11-18ZJIT: Inline setting Struct fieldsBenoit Daloze
* Add Insn::StoreField and Insn::WriteBarrier
2025-11-14ZJIT: Support JIT-to-JIT calls to callees with optional parametersAlan Wu
* Correct JIT entry points for optionals so each optional start with nil before their initialization routine runs. Establish `jit_entry_points[filled_opts_num]` gives the appropriate entry point * Correct number of HIR block parameters for each JIT entry point * Entry points that share the same ISEQ PC get separate entries since they start with different state. No more deduplication. * Reject post parameters. Was hidden behind check for optionals. * Make sure to visit every BB in iseq_to_hir(). Some wasn't visited when the initialization routine for an optional terminates the block in a `SideExit`. Remove the now impossible `FailedOptionalArguments`.
2025-11-14ZJIT: Check argument count matches callee's parametersAlan Wu
2025-11-10ZJIT: Rename things so that they aren't named "not_optimized_optimized" (#15135)Randy Stauner
These refer to "OptimizedMethodType" which is a subcategory of "MethodType::Optimized" so name them after the latter to avoid "not_optimized_optimized".
2025-11-10ZJIT: Set cfp->sp on leaf calls with GC (#15137)Takashi Kokubun
Co-authored-by: Randy Stauner <randy@r4s6.net>
2025-11-10ZJIT: Split unhandled_hir_insn and unknown_newarray_send stats (#15127)Takashi Kokubun
2025-11-10ZJIT: Rename not_optimized_instruction to uncategorized_instruction (#15130)Randy Stauner
Make it more obvious that this hasn't been handled and could be broken down more.
2025-11-10ZJIT: Deduplicate side exits (#15105)Takashi Kokubun
2025-11-07ZJIT: Specialize String#setbyte for fixnum case (#14927)Aiden Fox Ivey
2025-11-07ZJIT: Add compilation for checkkeyword (#14764)Jacob
<details> <summary>Before</summary> <br> ``` **ZJIT: Printing ZJIT statistics on exit*** Top-20 not inlined C methods (64.0% of total 3,683,424): Kernel#is_a?: 427,127 (11.6%) Hash#[]=: 426,276 (11.6%) String#start_with?: 336,245 ( 9.1%) ObjectSpace::WeakKeyMap#[]: 139,406 ( 3.8%) Hash#fetch: 127,291 ( 3.5%) String#hash: 79,259 ( 2.2%) Process.clock_gettime: 74,658 ( 2.0%) Array#any?: 74,441 ( 2.0%) Integer#==: 71,067 ( 1.9%) Kernel#dup: 68,058 ( 1.8%) Hash#key?: 62,306 ( 1.7%) Regexp#match?: 62,247 ( 1.7%) SQLite3::Statement#step: 61,172 ( 1.7%) SQLite3::Statement#done?: 61,172 ( 1.7%) Kernel#Array: 55,015 ( 1.5%) Integer#<=>: 49,127 ( 1.3%) String.new: 48,363 ( 1.3%) IO#read: 47,753 ( 1.3%) Array#include?: 43,307 ( 1.2%) Struct#initialize: 42,650 ( 1.2%) Top-3 not optimized method types for send (100.0% of total 1,022,743): iseq: 736,483 (72.0%) cfunc: 286,174 (28.0%) null: 86 ( 0.0%) Top-6 not optimized method types for send_without_block (100.0% of total 189,556): optimized_call: 115,966 (61.2%) optimized_send: 36,767 (19.4%) optimized_struct_aset: 33,788 (17.8%) null: 2,521 ( 1.3%) optimized_block_call: 510 ( 0.3%) cfunc: 4 ( 0.0%) Top-13 not optimized instructions (100.0% of total 1,648,882): invokesuper: 697,471 (42.3%) invokeblock: 496,687 (30.1%) sendforward: 221,094 (13.4%) opt_eq: 147,620 ( 9.0%) opt_minus: 40,865 ( 2.5%) opt_plus: 22,912 ( 1.4%) opt_send_without_block: 18,932 ( 1.1%) opt_gt: 867 ( 0.1%) opt_mult: 768 ( 0.0%) opt_neq: 654 ( 0.0%) opt_or: 508 ( 0.0%) opt_lt: 359 ( 0.0%) opt_ge: 145 ( 0.0%) Top-13 send fallback reasons (100.0% of total 8,308,826): send_without_block_polymorphic: 3,174,975 (38.2%) not_optimized_instruction: 1,648,882 (19.8%) fancy_call_feature: 1,072,807 (12.9%) send_not_optimized_method_type: 1,022,743 (12.3%) send_no_profiles: 599,715 ( 7.2%) send_without_block_no_profiles: 486,108 ( 5.9%) send_without_block_not_optimized_optimized_method_type: 187,031 ( 2.3%) send_polymorphic: 101,834 ( 1.2%) obj_to_string_not_string: 7,610 ( 0.1%) send_without_block_not_optimized_method_type: 2,525 ( 0.0%) send_without_block_direct_too_many_args: 2,369 ( 0.0%) send_without_block_cfunc_array_variadic: 2,190 ( 0.0%) ccall_with_frame_too_many_args: 37 ( 0.0%) Top-8 popular unsupported argument-parameter features (100.0% of total 1,209,121): param_opt: 583,595 (48.3%) param_forwardable: 178,162 (14.7%) param_block: 162,689 (13.5%) param_kw: 150,575 (12.5%) param_rest: 90,091 ( 7.5%) param_kwrest: 33,791 ( 2.8%) caller_splat: 10,214 ( 0.8%) caller_kw_splat: 4 ( 0.0%) Top-7 unhandled YARV insns (100.0% of total 128,032): checkkeyword: 88,698 (69.3%) invokesuperforward: 22,296 (17.4%) getblockparam: 16,292 (12.7%) getconstant: 336 ( 0.3%) checkmatch: 290 ( 0.2%) setblockparam: 101 ( 0.1%) once: 19 ( 0.0%) Top-1 compile error reasons (100.0% of total 21,283): exception_handler: 21,283 (100.0%) Top-18 side exit reasons (100.0% of total 2,335,562): guard_type_failure: 677,930 (29.0%) guard_shape_failure: 410,183 (17.6%) unhandled_kwarg: 235,100 (10.1%) patchpoint_stable_constant_names: 206,172 ( 8.8%) block_param_proxy_not_iseq_or_ifunc: 199,931 ( 8.6%) patchpoint_no_singleton_class: 188,359 ( 8.1%) unhandled_yarv_insn: 128,032 ( 5.5%) unknown_newarray_send: 124,805 ( 5.3%) patchpoint_method_redefined: 73,062 ( 3.1%) unhandled_hir_insn: 56,688 ( 2.4%) compile_error: 21,283 ( 0.9%) block_param_proxy_modified: 11,647 ( 0.5%) fixnum_mult_overflow: 954 ( 0.0%) patchpoint_no_ep_escape: 813 ( 0.0%) guard_bit_equals_failure: 316 ( 0.0%) obj_to_string_fallback: 230 ( 0.0%) interrupt: 35 ( 0.0%) guard_type_not_failure: 22 ( 0.0%) send_count: 26,775,579 dynamic_send_count: 8,308,826 (31.0%) optimized_send_count: 18,466,753 (69.0%) iseq_optimized_send_count: 7,611,729 (28.4%) inline_cfunc_optimized_send_count: 5,935,290 (22.2%) inline_iseq_optimized_send_count: 657,555 ( 2.5%) non_variadic_cfunc_optimized_send_count: 3,169,054 (11.8%) variadic_cfunc_optimized_send_count: 1,093,125 ( 4.1%) dynamic_getivar_count: 2,793,635 dynamic_setivar_count: 3,040,844 compiled_iseq_count: 4,496 failed_iseq_count: 0 compile_time: 915ms profile_time: 6ms gc_time: 6ms invalidation_time: 20ms vm_write_pc_count: 26,857,114 vm_write_sp_count: 25,770,558 vm_write_locals_count: 25,770,558 vm_write_stack_count: 25,770,558 vm_write_to_parent_iseq_local_count: 106,036 vm_read_from_parent_iseq_local_count: 3,213,992 guard_type_count: 27,683,170 guard_type_exit_ratio: 2.4% code_region_bytes: 32,178,176 side_exit_count: 2,335,562 total_insn_count: 170,714,077 vm_insn_count: 28,999,194 zjit_insn_count: 141,714,883 ratio_in_zjit: 83.0% ``` </details> <details> <summary>After</summary> <br> ``` **ZJIT: Printing ZJIT statistics on exit*** Top-20 not inlined C methods (63.9% of total 3,686,703): Kernel#is_a?: 427,123 (11.6%) Hash#[]=: 426,276 (11.6%) String#start_with?: 336,245 ( 9.1%) ObjectSpace::WeakKeyMap#[]: 139,406 ( 3.8%) Hash#fetch: 127,291 ( 3.5%) String#hash: 79,259 ( 2.1%) Process.clock_gettime: 74,658 ( 2.0%) Array#any?: 74,441 ( 2.0%) Integer#==: 71,067 ( 1.9%) Kernel#dup: 68,058 ( 1.8%) Regexp#match?: 62,336 ( 1.7%) Hash#key?: 62,306 ( 1.7%) SQLite3::Statement#step: 61,172 ( 1.7%) SQLite3::Statement#done?: 61,172 ( 1.7%) Kernel#Array: 55,048 ( 1.5%) Integer#<=>: 49,127 ( 1.3%) String.new: 48,363 ( 1.3%) IO#read: 47,753 ( 1.3%) Array#include?: 43,309 ( 1.2%) Struct#initialize: 42,650 ( 1.2%) Top-3 not optimized method types for send (100.0% of total 1,026,413): iseq: 737,496 (71.9%) cfunc: 288,831 (28.1%) null: 86 ( 0.0%) Top-6 not optimized method types for send_without_block (100.0% of total 189,556): optimized_call: 115,966 (61.2%) optimized_send: 36,767 (19.4%) optimized_struct_aset: 33,788 (17.8%) null: 2,521 ( 1.3%) optimized_block_call: 510 ( 0.3%) cfunc: 4 ( 0.0%) Top-13 not optimized instructions (100.0% of total 1,648,949): invokesuper: 697,452 (42.3%) invokeblock: 496,687 (30.1%) sendforward: 221,094 (13.4%) opt_eq: 147,620 ( 9.0%) opt_minus: 40,863 ( 2.5%) opt_plus: 22,912 ( 1.4%) opt_send_without_block: 19,020 ( 1.2%) opt_gt: 867 ( 0.1%) opt_mult: 768 ( 0.0%) opt_neq: 654 ( 0.0%) opt_or: 508 ( 0.0%) opt_lt: 359 ( 0.0%) opt_ge: 145 ( 0.0%) Top-13 send fallback reasons (100.0% of total 8,318,975): send_without_block_polymorphic: 3,177,471 (38.2%) not_optimized_instruction: 1,648,949 (19.8%) fancy_call_feature: 1,075,143 (12.9%) send_not_optimized_method_type: 1,026,413 (12.3%) send_no_profiles: 599,748 ( 7.2%) send_without_block_no_profiles: 486,190 ( 5.8%) send_without_block_not_optimized_optimized_method_type: 187,031 ( 2.2%) send_polymorphic: 102,497 ( 1.2%) obj_to_string_not_string: 8,412 ( 0.1%) send_without_block_not_optimized_method_type: 2,525 ( 0.0%) send_without_block_direct_too_many_args: 2,369 ( 0.0%) send_without_block_cfunc_array_variadic: 2,190 ( 0.0%) ccall_with_frame_too_many_args: 37 ( 0.0%) Top-8 popular unsupported argument-parameter features (100.0% of total 1,211,457): param_opt: 584,073 (48.2%) param_forwardable: 178,907 (14.8%) param_block: 162,689 (13.4%) param_kw: 151,688 (12.5%) param_rest: 90,091 ( 7.4%) param_kwrest: 33,791 ( 2.8%) caller_splat: 10,214 ( 0.8%) caller_kw_splat: 4 ( 0.0%) Top-6 unhandled YARV insns (100.0% of total 39,334): invokesuperforward: 22,296 (56.7%) getblockparam: 16,292 (41.4%) getconstant: 336 ( 0.9%) checkmatch: 290 ( 0.7%) setblockparam: 101 ( 0.3%) once: 19 ( 0.0%) Top-1 compile error reasons (100.0% of total 21,283): exception_handler: 21,283 (100.0%) Top-18 side exit reasons (100.0% of total 2,253,541): guard_type_failure: 682,695 (30.3%) guard_shape_failure: 410,183 (18.2%) unhandled_kwarg: 236,780 (10.5%) patchpoint_stable_constant_names: 206,310 ( 9.2%) block_param_proxy_not_iseq_or_ifunc: 199,931 ( 8.9%) patchpoint_no_singleton_class: 188,438 ( 8.4%) unknown_newarray_send: 124,805 ( 5.5%) patchpoint_method_redefined: 73,056 ( 3.2%) unhandled_hir_insn: 56,686 ( 2.5%) unhandled_yarv_insn: 39,334 ( 1.7%) compile_error: 21,283 ( 0.9%) block_param_proxy_modified: 11,647 ( 0.5%) fixnum_mult_overflow: 954 ( 0.0%) patchpoint_no_ep_escape: 813 ( 0.0%) guard_bit_equals_failure: 316 ( 0.0%) obj_to_string_fallback: 230 ( 0.0%) interrupt: 58 ( 0.0%) guard_type_not_failure: 22 ( 0.0%) send_count: 27,032,751 dynamic_send_count: 8,318,975 (30.8%) optimized_send_count: 18,713,776 (69.2%) iseq_optimized_send_count: 7,809,698 (28.9%) inline_cfunc_optimized_send_count: 5,980,083 (22.1%) inline_iseq_optimized_send_count: 657,677 ( 2.4%) non_variadic_cfunc_optimized_send_count: 3,170,381 (11.7%) variadic_cfunc_optimized_send_count: 1,095,937 ( 4.1%) dynamic_getivar_count: 2,793,987 dynamic_setivar_count: 3,350,905 compiled_iseq_count: 4,498 failed_iseq_count: 0 compile_time: 884ms profile_time: 6ms gc_time: 6ms invalidation_time: 19ms vm_write_pc_count: 27,417,915 vm_write_sp_count: 26,327,928 vm_write_locals_count: 26,327,928 vm_write_stack_count: 26,327,928 vm_write_to_parent_iseq_local_count: 106,036 vm_read_from_parent_iseq_local_count: 3,213,992 guard_type_count: 27,937,831 guard_type_exit_ratio: 2.4% code_region_bytes: 32,571,392 side_exit_count: 2,253,541 total_insn_count: 170,630,429 vm_insn_count: 26,617,244 zjit_insn_count: 144,013,185 ratio_in_zjit: 84.4% ``` </details>
2025-11-07ZJIT: Carve out IseqPayload into a separate module (#15098)Takashi Kokubun
2025-11-06ZJIT: Fix an incomplete comment (#15088)Takashi Kokubun