summaryrefslogtreecommitdiff
path: root/compile.c
AgeCommit message (Collapse)Author
8 daysRemove `in_masgn` field from `struct iseq_compile_data`yui-knk
`in_masgn` has not been used since fb6e3a80009a744a4e0b75660f1ce6da65e20e6c.
2025-12-10Add `NUM2PTR` and `PTR2NUM` macrosNobuyoshi Nakada
These macros have been defined here and there, so collect them.
2025-12-09Remove needless `ruby2_keywords` field from `struct rb_args_info`yui-knk
`ruby2_keywords` is set only to be `0` in parse.y. However `args->ruby2_keywords` is initialized with `0` by `MEMZERO` in `rb_node_args_new` function and `body->param.flags.ruby2_keywords` is initialized with `0` by `ZALLOC` in `rb_iseq_constant_body_alloc` function, so `args->ruby2_keywords` does nothing for `body->param.flags.ruby2_keywords`.
2025-11-15Remove dead IBF_OBJECT_INTERNALPeter Zhu
2025-10-23use `SET_SHAREABLE`Koichi Sasada
to adopt strict shareable rule. * (basically) shareable objects only refer shareable objects * (exception) shareable objects can refere unshareable objects but should not leak reference to unshareable objects to Ruby world
2025-10-20[Bug #21644] compile.c: fix `newrange` INSN peephole optimization for ↵viralpraxis
chilled string ref: https://bugs.ruby-lang.org/issues/21644 ```shell $ ruby -v -e '("a" || "b").."c"' ruby 3.4.7 (2025-10-08 revision 7a5688e2a2) +PRISM [x86_64-linux] -e:1: warning: possibly useless use of .. in void context -e:1: [BUG] Stack consistency error (sp: 7, bp: 6) ruby 3.4.7 (2025-10-08 revision 7a5688e2a2) +PRISM [x86_64-linux] -- Control frame information ----------------------------------------------- c:0002 p:0013 s:0007 e:000005 EVAL -e:1 [FINISH] c:0001 p:0000 s:0003 E:001920 DUMMY [FINISH] -- Ruby level backtrace information ---------------------------------------- -e:1:in '<main>' -- Threading information --------------------------------------------------- Total ractor count: 1 Ruby thread count for this ractor: 1 -- C level backtrace information ------------------------------------------- ruby/3.4.7/lib/libruby.so.3.4(rb_print_backtrace+0x8) [0x78aa9573c882] /tmp/ruby-build.20251010151551.31019.jR04SY/ruby-3.4.7/vm_dump.c:823 ruby/3.4.7/lib/libruby.so.3.4(rb_vm_bugreport) /tmp/ruby-build.20251010151551.31019.jR04SY/ruby-3.4.7/vm_dump.c:1155 ruby/3.4.7/lib/libruby.so.3.4(rb_bug_without_die_internal+0x6b) [0x78aa9544c62f] /tmp/ruby-build.20251010151551.31019.jR04SY/ruby-3.4.7/error.c:1097 ruby/3.4.7/lib/libruby.so.3.4(rb_bug) /tmp/ruby-build.20251010151551.31019.jR04SY/ruby-3.4.7/error.c:1115 ruby/3.4.7/lib/libruby.so.3.4(vm_stack_consistency_error+0x1f) [0x78aa9544f091] /tmp/ruby-build.20251010151551.31019.jR04SY/ruby-3.4.7/vm_insnhelper.c:6523 ruby/3.4.7/lib/libruby.so.3.4(vm_get_cref) /tmp/ruby-build.20251010151551.31019.jR04SY/ruby-3.4.7/insns.def:1134 ruby/3.4.7/lib/libruby.so.3.4(vm_setclassvariable) /tmp/ruby-build.20251010151551.31019.jR04SY/ruby-3.4.7/vm_insnhelper.c:1630 ruby/3.4.7/lib/libruby.so.3.4(vm_setclassvariable) /tmp/ruby-build.20251010151551.31019.jR04SY/ruby-3.4.7/vm_insnhelper.c:1627 ruby/3.4.7/lib/libruby.so.3.4(vm_exec_core) /tmp/ruby-build.20251010151551.31019.jR04SY/ruby-3.4.7/insns.def:253 ruby/3.4.7/lib/libruby.so.3.4(vm_exec_loop+0xa) [0x78aa95724959] /tmp/ruby-build.20251010151551.31019.jR04SY/ruby-3.4.7/vm.c:2622 ruby/3.4.7/lib/libruby.so.3.4(rb_vm_exec) /tmp/ruby-build.20251010151551.31019.jR04SY/ruby-3.4.7/vm.c:2598 ruby/3.4.7/lib/libruby.so.3.4(rb_ec_exec_node+0xa5) [0x78aa95525695] /tmp/ruby-build.20251010151551.31019.jR04SY/ruby-3.4.7/eval.c:281 ruby/3.4.7/lib/libruby.so.3.4(ruby_run_node+0x83) [0x78aa95529333] /tmp/ruby-build.20251010151551.31019.jR04SY/ruby-3.4.7/eval.c:319 ruby/3.4.7/bin/ruby(rb_main+0x21) [0x59d86f5e0186] ./main.c:43 ruby/3.4.7/bin/ruby(main) ./main.c:68 /lib/x86_64-linux-gnu/libc.so.6(__libc_start_call_main+0x7a) [0x78aa9502a1ca] ../sysdeps/nptl/libc_start_call_main.h:58 /lib/x86_64-linux-gnu/libc.so.6(call_init+0x0) [0x78aa9502a28b] ../csu/libc-start.c:360 /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main_impl) ../csu/libc-start.c:347 /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main) (null):0 [0x59d86f5e01d5] ``` The optimization in question: https://github.com/ruby/ruby/blob/957c832db137e67289e93dfd9fd9e915b1f2fc87/compile.c\#L3453-L3480 Before entering the `newrange` optimization, the iseq looks like this: ``` == disasm: #<ISeq:<compiled>@<compiled>:1 (1,0)-(1,17)> 0000 putchilledstring "a" ( 1)[Li] 0002 dup 0003 branchif 8 0005 pop 0006 putchilledstring "b" 0008 putchilledstring "c" 0010 newrange 0 0012 leave ``` So the optimization constructs a new range using the wrong operands (`"b"` and `"c"` instead of `"a"` and `"c"`). I tried to fix this by checking whether the two previous instructions are labeled.
2025-10-10Fix memory leak when load_from_binary raisesPeter Zhu
ibf_load_code will leak memory allocated for the code if an exception is raised. The following script reproduces the leak: bin = RubyVM::InstructionSequence.of(1.method(:abs)).to_binary 10.times do 100_000.times do RubyVM::InstructionSequence.load_from_binary(bin) rescue ArgumentError end puts `ps -o rss= -p #{$$}` end Before: 18004 23380 28756 34260 39892 45396 50772 55892 61012 66132 After: 12536 12920 13304 13688 14072 14456 14840 15352 15608 15864
2025-09-25IBF: Remove unnecessary and potentially UB pointer castAlan Wu
[Bug #21569]
2025-09-25IBF: Avoid unaligned load on 32 bit platformsAleksey Maximov
[Bug #21569]
2025-09-24fix lvar_state dump sizeKoichi Sasada
`ibf_dump_write()` should consider the size of the element.
2025-09-24Ractor.shareable_procKoichi Sasada
call-seq: Ractor.sharable_proc(self: nil){} -> sharable proc It returns shareable Proc object. The Proc object is shareable and the self in a block will be replaced with the value passed via `self:` keyword. In a shareable Proc, the outer variables should * (1) refer shareable objects * (2) be not be overwritten ```ruby a = 42 Ractor.shareable_proc{ p a } #=> OK b = 43 Ractor.shareable_proc{ p b; b = 44 } #=> Ractor::IsolationError because 'b' is reassigned in the block. c = 44 Ractor.shareable_proc{ p c } #=> Ractor::IsolationError because 'c' will be reassigned outside of the block. c = 45 d = 45 d = 46 if cond Ractor.shareable_proc{ p d } #=> Ractor::IsolationError because 'd' was reassigned outside of the block. ``` The last `d`'s case can be relaxed in a future version. The above check will be done in a static analysis at compile time, so the reflection feature such as `Binding#local_varaible_set` can not be detected. ```ruby e = 42 shpr = Ractor.shareable_proc{ p e } #=> OK binding.local_variable_set(:e, 43) shpr.call #=> 42 (returns captured timing value) ``` Ractor.sharaeble_lambda is also introduced. [Feature #21550] [Feature #21557]
2025-08-28Make `RubyVM::AST.of` return a parent node of NODE_SCOPEYusuke Endoh
This change makes `RubyVM::AST.of` and `.node_id_for_backtrace_location` return a parent node of NODE_SCOPE (such as NODE_DEFN) instead of the NODE_SCOPE node itself. (In future, we may remove NODE_SCOPE, which is a bit hacky AST node.) This is preparation for [Feature #21543].
2025-08-26Remove `opt_aref_with` and `opt_aset_with`Aaron Patterson
When these instructions were introduced it was common to read from a hash with mutable string literals. However, these days, I think these instructions are fairly rare. I tested this with the lobsters benchmark, and saw no difference in speed. In order to be sure, I tracked down every use of this instruction in the lobsters benchmark, and there were only 4 places where it was used. Additionally, this patch fixes a case where "chilled strings" should emit a warning but they don't. ```ruby class Foo def self.[](x)= x.gsub!(/hello/, "hi") end Foo["hello world"] ``` Removing these instructions shows this warning: ``` > ./miniruby -vw test.rb ruby 3.5.0dev (2025-08-25T21:36:50Z rm-opt_aref_with dca08e286c) +PRISM [arm64-darwin24] test.rb:2: warning: literal string will be frozen in the future (run with --debug-frozen-string-literal for more information) ``` [Feature #21553]
2025-07-28Avoid GC while operands in inconsistent stateJohn Hawthorn
compile_data_calloc2 may run GC (though because it allocates from an arena this is rare in practice). When this happened when resizing operands there was a risk of seeing the insn in an inconsistent state. To solve this we need to make any allocations before we start modifying the instrucitons. This refactors the code to use a new insn_replace_with_operands() function that allocates the new operands array before modifying the instruction object. Co-authored-by: Aaron Patterson <tenderlove@ruby-lang.org>
2025-06-29Add underflow checkNobuyoshi Nakada
2025-06-28Check dump size in ibf_dump_writeErik Berlin
2025-06-26Fix loop variable type in compile.cErik Berlin
2025-06-24Fix load catch table write barrierJohn Hawthorn
I tried fixing this in 521b2fcba4e96898bfd237c79f17f19530b7a030, but re-running wbcheck with the stricter WBCHECK_VERIFY_AFTER_WB, revealed that this write barrier was fired too early, before the object was actually written to the parent. This solves the issue by writing the table to the parent immediately (and using calloc so that we don't mark random garbage).
2025-06-24Reduce exposure of FL_FREEZEJean Boussier
The `FL_FREEZE` flag is redundant with `SHAPE_ID_FL_FROZEN`, so ideally it should be eliminated in favor of the later. Doing so would eliminate the risk of desync between the two, but also solve the problem of the frozen status being global in namespace context (See Bug #21330).
2025-06-22Avoid allocation for positional splat for literal array keyword argumentJeremy Evans
If all nodes in the array are safe, then it is safe to avoid allocation for the positional splat: ```ruby m(*a, kw: [:a]) # Safe m(*a, kw: [meth]) # Unsafe ``` This avoids an unnecessary allocation in a Rails method call. Details: https://github.com/rails/rails/pull/54949/files#r2052645431
2025-06-19`struct iseq_catch_table` is packedNobuyoshi Nakada
2025-06-18Add missing write barrier for hash on iseqJohn Hawthorn
Found by wbcheck Notes: Merged: https://github.com/ruby/ruby/pull/13646
2025-06-18Add write barrier to rb_cArray_empty_frozenJohn Hawthorn
Found by wbcheck Notes: Merged: https://github.com/ruby/ruby/pull/13646
2025-06-18Add write barrier to rb_cHash_empty_frozenJohn Hawthorn
Found by wbcheck Notes: Merged: https://github.com/ruby/ruby/pull/13646
2025-06-18Use write barriers when loading catch tableJohn Hawthorn
Found by wbcheck Notes: Merged: https://github.com/ruby/ruby/pull/13646
2025-06-18Add missing write barriers to ibf_loadJohn Hawthorn
Found by wbcheck Notes: Merged: https://github.com/ruby/ruby/pull/13646
2025-06-18Fix a missing write barrier to mandatory_only_iseqJohn Hawthorn
Found by wbcheck Notes: Merged: https://github.com/ruby/ruby/pull/13646
2025-06-17* adjust indentNobuyoshi Nakada
Notes: Merged: https://github.com/ruby/ruby/pull/13634
2025-06-04Suppress overflow warning at `ALLOC_N` in `iseq_set_local_table`Nobuyoshi Nakada
`xmalloc2` checks the overflow of arguments multiplication. Notes: Merged: https://github.com/ruby/ruby/pull/13509
2025-06-02compile.c: Handle anonymous variables in `outer_variable_cmp`Jean Boussier
[Bug #21370] Notes: Merged: https://github.com/ruby/ruby/pull/13436
2025-05-15Align styles [ci skip]Nobuyoshi Nakada
2025-04-27Use a `set_table` for `rb_vm_struct.unused_block_warning_table`Jean Boussier
Now that we have a hash-set implementation we can use that instead of a hash-table with a static value.
2025-04-25Add parse.y implementationAaron Patterson
2025-04-09Fix coverage measurement for negative line numbersYusuke Endoh
Fixes [Bug #21220] Co-Authored-By: Mike Bourgeous <mike@mikebourgeous.com> Co-Authored-By: Jean Boussier <jean.boussier@gmail.com> Notes: Merged: https://github.com/ruby/ruby/pull/13089
2025-04-03compile.c: avoid allocating 0 length call_dataJean Boussier
if `body->ci_size` is `0`, there's no point allocating 0B, it just wastes an entry in the allocator. Notes: Merged: https://github.com/ruby/ruby/pull/13059
2025-03-20Remove leading `nop` from block when we don't need itAaron Patterson
Blocks insert a leading `nop` instruction in order to execute a "block call" tracepoint. Block compilation unconditionally inserts a leading `nop` plus a label after the instruction: https://github.com/ruby/ruby/blob/641f15b1c6bd8921407a1f045573d3b0605f00d3/prism_compile.c#L6867-L6869 This `nop` instruction is used entirely for firing the block entry tracepoint. The label exists so that the block can contain a loop but the block entry tracepoint is executed only once. For example, the following code is an infinite loop, but should only execute the b_call tracepoint once: ```ruby -> { redo }.call ``` Previous to this commit, we would eliminate the `nop` instruction, but only if there were no other jump instructions inside the block. This means that the following code would still contain a leading `nop` even though the label following the `nop` is unused: ```ruby -> { nil if bar } ``` ``` == disasm: #<ISeq:block in <main>@test.rb:1 (1,2)-(1,17)> (catch: FALSE) 0000 nop ( 1)[Bc] 0001 putself [Li] 0002 opt_send_without_block <calldata!mid:bar, argc:0, FCALL|VCALL|ARGS_SIMPLE> 0004 branchunless 8 0006 putnil 0007 leave [Br] 0008 putnil 0009 leave [Br] ``` This commit checks to see if the label inserted after the `nop` is actually a jump target. If it's not a jump target, then we should be safe to eliminate the leading `nop`: ``` > build-master/miniruby --dump=insns test.rb == disasm: #<ISeq:<main>@test.rb:1 (1,0)-(1,17)> 0000 putspecialobject 1 ( 1)[Li] 0002 send <calldata!mid:lambda, argc:0, FCALL>, block in <main> 0005 leave == disasm: #<ISeq:block in <main>@test.rb:1 (1,2)-(1,17)> 0000 putself ( 1)[LiBc] 0001 opt_send_without_block <calldata!mid:bar, argc:0, FCALL|VCALL|ARGS_SIMPLE> 0003 branchunless 7 0005 putnil 0006 leave [Br] 0007 putnil 0008 leave [Br] ``` We have a test for b_call tracepoints that use `redo` here: https://github.com/ruby/ruby/blob/aebf96f371c8d874398e0041b798892e545fa206/test/ruby/test_settracefunc.rb#L1728-L1736 Notes: Merged: https://github.com/ruby/ruby/pull/12957
2025-03-17Avoid pinning `storage_head` in `iseq_mark_and_move` (#12880)Eileen M. Uchitelle
* Avoid pinning `storage_head` in `iseq_mark_and_move` This refactor changes the behavior of `iseq_mark_and_move` to avoid pinning the `storage_head`. Previously pinning was required because they could be gc'd during `iseq_set_sequence` it would be possible to end up with a half build array of instructions. However, in order to implement a moving immix algorithm we can't pin these objects so this rafactoring changes the code to mark and move. To accomplish this, it was required to add `iseq_size`, `iseq_encoded`, and the `mark_bits` union to the `iseq_compile_data` struct. In addition `iseq_compile_data` sets a bool for whether there is a single or list of mark bits. While this change is needed for moving immix, it should be better for Ruby's GC as well. * Don't allocate mark_offset_bits for one word If only one word is needed, we don't need to allocate mark_offset_bits and can instead directly write to it. --------- Co-authored-by: Peter Zhu <peter@peterzhu.ca> Notes: Merged-By: eileencodes <eileencodes@gmail.com>
2025-01-08Avoid opt_aset_with optimization inside multiple assignmentJeremy Evans
Previously, since the opt_aset_with optimization was introduced, use of the opt_aset_with optimization inside multiple assignment would result in a segfault or incorrect instructions. Fixes [Bug #21012] Co-authored-by: Nobuyoshi Nakada <nobu.nakada@gmail.com> Notes: Merged: https://github.com/ruby/ruby/pull/12528 Merged-By: jeremyevans <code@jeremyevans.net>
2025-01-08[Bug #21011] `nd_value` is NULL in massignNobuyoshi Nakada
Notes: Merged: https://github.com/ruby/ruby/pull/12530
2025-01-08Introduce macro for creating child iseqs with callbacksydah
Use macro like `NEW_ISEQ` and `NEW_CHILD_ISEQ`. Notes: Merged: https://github.com/ruby/ruby/pull/11804
2025-01-07Use `ISEQ_BODY(iseq)` instead of `iseq->body`ydah
trivial change that unifies the format for access. Notes: Merged: https://github.com/ruby/ruby/pull/11803
2025-01-04Remove unused `FIXNUM_OR` macro from compile.cydah
This PR remove unused FIXNUM_OR macro from compile.c before: ``` ❯ git grep 'FIXNUM_OR' compile.c:#define FIXNUM_OR(n, i) ((n)|INT2FIX(i)) ``` after: ``` ❯ git grep 'FIXNUM_OR' ```
2025-01-03[Bug #20504] Move dynamic regexp concatenation to iseq compilerNobuyoshi Nakada
Notes: Merged: https://github.com/ruby/ruby/pull/12483
2024-12-15[Bug #20927] Fix compile_shareable_literal_constant for hash with keyword splattompng
Compilation of NODE_HASH in compile_shareable_literal_constant does not support hash that contains keyword splat. If there is a keyword splat, fallback to default case. Notes: Merged: https://github.com/ruby/ruby/pull/12338
2024-12-06[Bug #20926] Fix a crashes with `shareable_constant_value: ↵ydah
experimental_everything` using parse.y's parser https://bugs.ruby-lang.org/issues/20926 Notes: Merged: https://github.com/ruby/ruby/pull/12275
2024-11-30Use `RSTRING_PTR` instead of `StringValuePtr`Yusuke Endoh
... since it is certain to be a String in this context. Also, I want to avoid the anxious use of `StringValuePtr(str)` and `RSTRING_LEN(str)` as arguments in the same function call. Notes: Merged: https://github.com/ruby/ruby/pull/12216
2024-11-28`INIT_ANCHOR` no longer needed usuallyNobuyoshi Nakada
Notes: Merged: https://github.com/ruby/ruby/pull/12198
2024-11-28Initialize `LINK_ANCHOR` totallyNobuyoshi Nakada
Notes: Merged: https://github.com/ruby/ruby/pull/12198
2024-11-28Assert that non-empty LINK_ANCHOR does not loopNobuyoshi Nakada
After any `LINK_ELEMENT` sequence is added, `LINK_ANCHOR` must not loop. Notes: Merged: https://github.com/ruby/ruby/pull/12195
2024-11-26Optimize instructions when creating an array just to call `include?` (#12123)Randy Stauner
* Add opt_duparray_send insn to skip the allocation on `#include?` If the method isn't going to modify the array we don't need to copy it. This avoids the allocation / array copy for things like `[:a, :b].include?(x)`. This adds a BOP for include? and tracks redefinition for it on Array. Co-authored-by: Andrew Novoselac <andrew.novoselac@shopify.com> * YJIT: Implement opt_duparray_send include_p Co-authored-by: Andrew Novoselac <andrew.novoselac@shopify.com> * Update opt_newarray_send to support simple forms of include?(arg) Similar to opt_duparray_send but for non-static arrays. * YJIT: Implement opt_newarray_send include_p --------- Co-authored-by: Andrew Novoselac <andrew.novoselac@shopify.com> Notes: Merged-By: maximecb <maximecb@ruby-lang.org>