summaryrefslogtreecommitdiff
path: root/vm_insnhelper.c
AgeCommit message (Collapse)Author
4 daysDisambiguate private and public RSTRUCT_ helpersJean Boussier
RSTRUCT_LEN / RSTRUCT_GET / RSTRUCT_SET all existing in two versions, one public that does type and frozens checks and one private that doesn't. The problem is that this is error prone because the public version is always accessible, but the private one require to include `internal/struct.h`. So you may have some code that rely on the public version, and later on the private header is included and changes the behavior. This already led to introducing a bug in YJIT & ZJIT: https://github.com/ruby/ruby/pull/15835
2025-12-18Store ractor_id directly on ECJohn Hawthorn
This is easier to access as ec->ractor_id instead of pointer-chasing through ec->thread->ractor->ractor_id Co-authored-by: Luke Gruber <luke.gru@gmail.com>
2025-12-16Respect encoding of ID in exception messagesDaisuke Aritomo
2025-12-16Make tracepoints with set_trace_func or TracePoint.new ractor local (#15468)Luke Gruber
Before this change, GC'ing any Ractor object caused you to lose all enabled tracepoints across all ractors (even main). Now tracepoints are ractor-local and this doesn't happen. Internal events are still global. Fixes [Bug #19112]
2025-12-04Change bmethod defined_ractor to use id insteadJohn Hawthorn
When defining a bmethod, we recorded the current Ractor's object in the method. However that was never marked and so could be GC'd and reused by a future Ractor. Instead we can use the Ractor's id, which we expect to be unique forever. Co-authored-by: Luke Gruber <luke.gru@gmail.com>
2025-11-28Use ALWAYS_INLINE for vm_getinstancevariableJohn Hawthorn
Recently rb_vm_getinstancevariable was introduced exposing this method to ZJIT. On clang specifically this ended up causing the compiler not to inline into vm_exec_core and cause a significant performance regression in optcarrot for the interpreter. Co-authored-by: Luke Gruber <luke.gru@gmail.com>
2025-11-25vm_cc_new: don't assume `cme` is present.Jean Boussier
[Bug #21694] `vm_search_super_method` explictly calls `vm_cc_new` with `cme=NULL` when there is no super class.
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-19ZJIT: Fix assertion failure when profiling VM_BLOCK_HANDLER_NONEAlan Wu
As can be seen in vm_block_handler_verify(), VM_BLOCK_HANDLER_NONE is not a valid argument for vm_block_handler(). Store nil in the profiler when seen instead of crashing.
2025-11-19Win32: Drop support for older than MSVC 8.0/_MSC_VER 1400Nobuyoshi Nakada
Visual C++ 2005 (8.0): - _MSC_VER: 1400 - MSVCRT_VERSION: 80
2025-11-18Extract `KW_SPECIFIED_BITS_MAX` for JITs (GH-15039)Jacob
Rename to `VM_KW_SPECIFIED_BITS_MAX` now that it's in `vm_core.h`.
2025-11-06ZJIT: Untag block handler (#15085)Max Bernstein
Storing the tagged block handler in profiles is not GC-safe (nice catch, Kokubun). Store the untagged block handler instead. Fix bug in https://github.com/ruby/ruby/pull/15051
2025-11-05ZJIT: Profile specific objects for invokeblock (#15051)Max Bernstein
I made a special kind of `ProfiledType` that looks at specific objects, not just their classes/shapes (https://github.com/ruby/ruby/pull/15051). Then I profiled some of our benchmarks. For lobsters: ``` Top-6 invokeblock handler (100.0% of total 1,064,155): megamorphic: 494,931 (46.5%) monomorphic_iseq: 337,171 (31.7%) polymorphic: 113,381 (10.7%) monomorphic_ifunc: 52,260 ( 4.9%) monomorphic_other: 38,970 ( 3.7%) no_profiles: 27,442 ( 2.6%) ``` For railsbench: ``` Top-6 invokeblock handler (100.0% of total 2,529,104): monomorphic_iseq: 834,452 (33.0%) megamorphic: 818,347 (32.4%) polymorphic: 632,273 (25.0%) monomorphic_ifunc: 224,243 ( 8.9%) monomorphic_other: 19,595 ( 0.8%) no_profiles: 194 ( 0.0%) ``` For shipit: ``` Top-6 invokeblock handler (100.0% of total 2,104,148): megamorphic: 1,269,889 (60.4%) polymorphic: 411,475 (19.6%) no_profiles: 173,367 ( 8.2%) monomorphic_other: 118,619 ( 5.6%) monomorphic_iseq: 84,891 ( 4.0%) monomorphic_ifunc: 45,907 ( 2.2%) ``` Seems like a monomorphic case for a specific ISEQ actually isn't a bad way of going about this, at least to start...
2025-11-04[DOC] Mention on top of `vm_*.c` files the VM translation unit they're in ↵Alan Wu
(#15048) vm_method.c already mentions it.
2025-10-31Avoid duping cc table when cme == NULLJohn Hawthorn
2025-10-31Remove always true conditonals in vm_populate_ccJohn Hawthorn
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-08[Bug #21629] Initialize `struct RArray`Nobuyoshi Nakada
2025-10-03[Bug #21620] Fix strict aliasing in rb_managed_id_table_lookupPeter Zhu
We cannot pass &ccs into rb_managed_id_table_lookup because rb_managed_id_table_lookup takes in a VALUE*, so it violates strict aliasing in C. This causes segfaults when compiling with LTO enabled.
2025-09-29Update current namespace management by using control frames and lexical contextsSatoshi Tagomori
to fix inconsistent and wrong current namespace detections. This includes: * Moving load_path and related things from rb_vm_t to rb_namespace_t to simplify accessing those values via namespace (instead of accessing either vm or ns) * Initializing root_namespace earlier and consolidate builtin_namespace into root_namespace * Adding VM_FRAME_FLAG_NS_REQUIRE for checkpoints to detect a namespace to load/require files * Removing implicit refinements in the root namespace which was used to determine the namespace to be loaded (replaced by VM_FRAME_FLAG_NS_REQUIRE) * Removing namespaces from rb_proc_t because its namespace can be identified by lexical context * Starting to use ep[VM_ENV_DATA_INDEX_SPECVAL] to store the current namespace when the frame type is MAGIC_TOP or MAGIC_CLASS (block handlers don't exist in this case)
2025-09-25Always use assert-free APIs when profiling and crashingAlan Wu
rb_profile_frames() is used by profilers in a way such that it can run on any instruction in the binary, and it crashed previously in the following situation in `RUBY_DEBUG` builds: ``` * thread #1, queue = 'com.apple.main-thread', stop reason = step over frame #0: 0x00000001002827f0 miniruby`vm_make_env_each(ec=0x0000000101866b00, cfp=0x000000080c91bee8) at vm.c:992:74 989 } 990 991 vm_make_env_each(ec, prev_cfp); -> 992 VM_FORCE_WRITE_SPECIAL_CONST(&ep[VM_ENV_DATA_INDEX_SPECVAL], VM_GUARDED_PREV_EP(prev_cfp->ep)); 993 } 994 } 995 else { (lldb) call rb_profile_frames(0, 100, $2, $3) /Users/alan/ruby/vm_core.h:1448: Assertion Failed: VM_ENV_FLAGS:FIXNUM_P(flags) ruby 3.5.0dev (2025-09-23T20:20:04Z master 06b7a70837) +PRISM [arm64-darwin25] -- Crash Report log information -------------------------------------------- See Crash Report log file in one of the following locations: * ~/Library/Logs/DiagnosticReports * /Library/Logs/DiagnosticReports for more details. Don't forget to include the above Crash Report log file in bug reports. -- Control frame information ----------------------------------------------- c:0008 p:---- s:0029 e:000028 CFUNC :lambda /Users/alan/ruby/vm_core.h:1448: Assertion Failed: VM_ENV_FLAGS:FIXNUM_P(flags) ruby 3.5.0dev (2025-09-23T20:20:04Z master 06b7a70837) +PRISM [arm64-darwin25] -- Crash Report log information -------------------------------------------- <snip> ``` There is a small window where the control frame is invalid and fails the assert. The double crash also shows that in `RUBY_DEBUG` builds, the crash reporter was previously not resilient to corrupt frame state. In release builds, it prints more info. Add unchecked APIs for the crash reporter and profilers so they work as well in `RUBY_DEBUG` builds as non-debug builds.
2025-09-17ZJIT: Const-fold IsMethodCfuncMax Bernstein
2025-09-10YJIT: Stop sharing rb_vm_invokesuper among different instructions (#14492)Takashi Kokubun
2025-09-08ZJIT: Fix backtraces on opt_new (#14461)Takashi Kokubun
2025-08-29YJIT: Stop sharing rb_vm_send among different instructions (#14393)Takashi Kokubun
2025-08-28Populate ivar caches for types other than T_OBJECTJean Boussier
`vm_setinstancevariable` had a codepath to try to match the inline cache for types other than T_OBJECT, but the cache population path in `vm_setivar_slowpath` was exclusive to T_OBJECT, so `vm_setivar_default` would never match anything. This commit improves `vm_setivar_slowpath` so that it is capable of filling the cache for all types, and adds a `vm_setivar_class` codepath for `T_CLASS` and `T_MODULE`. `vm_setivar`, `vm_setivar_default` and `vm_setivar_class` could be unified, but based on the very explicit `NOINLINE` I assume they were split to minimize codesize. ``` compare-ruby: ruby 3.5.0dev (2025-08-27T14:58:58Z merge-vm-setivar-d.. 5b749d8e53) +PRISM [arm64-darwin24] built-ruby: ruby 3.5.0dev (2025-08-27T16:30:31Z setivar-cache-gene.. 4fe78ff296) +PRISM [arm64-darwin24] | |compare-ruby|built-ruby| |:------------------------|-----------:|---------:| |vm_ivar_set_on_instance | 161.809| 164.688| | | -| 1.02x| |vm_ivar_set_on_generic | 58.769| 115.638| | | -| 1.97x| |vm_ivar_set_on_class | 70.034| 141.042| | | -| 2.01x| ```
2025-08-27Fix bad NameError raised using sendforward instruction through vcallLuke Gruber
If you called a VCALL method and the method takes forwarding arguments and then you forward those arguments along using the sendforward instruction, the method_missing class was wrongly chosen as NameError instead of NoMethodError. This is because the VM looked at the CallInfo of the vcall and determined it needed to raise NameError. Now we detect that case and raise NoMethodError. Fixes [Bug #21535]
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-08-26vm_getivar: unify codepathsJean Boussier
2025-08-21Make `vm_search_method` return a cme instead of a cc (#14299)Stan Lo
Make vm_search_method return a cme instead of a cc Both of its callers ended up calling `vm_cc_cme` on the result and only used the cme, so it's probably better to return a cme directly. This will also make it easier for ZJIT to later inline the `rb_vm_objtostring` call.
2025-08-13ZJIT: Fix `ObjToString` rewrite (#14196)Stan Lo
ZJIT: Fix ObjToString rewrite Currently, the rewrite for `ObjToString` always replaces it with a `SendWithoutBlock(to_s)` instruction when the receiver is not a string literal. This is incorrect because it calls `to_s` on the receiver even if it's already a string. This change fixes it by: - Avoiding the `SendWithoutBlock(to_s)` rewrite - Implement codegen for `ObjToString`
2025-08-06variable.c: refactor accesses to the generic_fields_tblJean Boussier
All accesses to `generic_fields_tbl_` are now encapsulated inside: - `rb_obj_fields` - `rb_obj_set_fields` - `rb_obj_replace_fields`
2025-08-01Convert `rb_class_cc_entries.entries` in a flexible array memberJean Boussier
`rb_class_cc_entries` is little more than a `len` and `capa`. Hence embedding the entries doesn't cost much extra copying and saves a bit of memory and some pointer chasing. Co-Authored-By: Étienne Barrié <etienne.barrie@gmail.com>
2025-08-01Refactor `vm_lookup_cc` to allow lock-free lookups in `RClass.cc_tbl`Jean Boussier
In multi-ractor mode, the `cc_tbl` mutations use the RCU pattern, which allow lock-less reads. Based on the assumption that invalidations and misses should be increasingly rare as the process ages, locking on modification isn't a big concern.
2025-08-01Make `RClass.cc_table` a managed objectJean Boussier
For now this doesn't change anything, but now that the table is managed by GC, it opens the door to use RCU when in multi-ractor mode, hence allow unsynchornized reads.
2025-07-31Get rid of RSHAPE_PARENT in favor of RSHAPE_DIRECT_CHILD_PJean Boussier
`RSHAPE_PARENT` is error prone because it returns a raw untagged shape_id. To check if a shape is a direct parent of another, tags should be discarded. So providing a comparison function is better than exposing untagged ids.
2025-07-11Rename some set_* functions to set_table_*Jeremy Evans
These functions conflict with the planned C-API functions. Since they deal with the underlying set_table pointers and not Set instances, this seems like a more accurate name as well.
2025-06-29* adjust indents. [ci skip]Nobuyoshi Nakada
2025-06-24Fix missing write barrier in rb_vm_rewrite_crefJohn Hawthorn
Found by wbcheck
2025-06-24Refactor rewrite_crefJohn Hawthorn
2025-06-24Set up callable_method_entry for DUMMY frame on ArgumentErrorYusuke Endoh
Before the patch: ``` $ ./miniruby -e '[1, 2].inject(:tap)' -e:1:in '<main>': wrong number of arguments (given 1, expected 0) (ArgumentError) from -e:1:in 'Enumerable#inject' from -e:1:in '<main>' ``` After the patch: ``` $ ./miniruby -e '[1, 2].inject(:tap)' -e:1:in 'Kernel#tap': wrong number of arguments (given 1, expected 0) (ArgumentError) from -e:1:in 'Enumerable#inject' from -e:1:in '<main>' ``` Fixes https://bugs.ruby-lang.org/issues/20968#change-113811
2025-06-23Make the critical level an enumNobuyoshi Nakada
2025-06-17Refactor generic fields to use `T_IMEMO/fields` objects.Jean Boussier
Followup: https://github.com/ruby/ruby/pull/13589 This simplify a lot of things, as we no longer need to manually manage the memory, we can use the Read-Copy-Update pattern and avoid numerous race conditions. Co-Authored-By: Étienne Barrié <etienne.barrie@gmail.com> Notes: Merged: https://github.com/ruby/ruby/pull/13626
2025-06-17Rename `imemo_class_fields` -> `imemo_fields`Jean Boussier
Notes: Merged: https://github.com/ruby/ruby/pull/13626
2025-06-17Optimize `benchmark/vm_ivar_of_class`Jean Boussier
``` compare-ruby: ruby 3.5.0dev (2025-06-17T08:45:40Z master e9d35671d2) +PRISM [arm64-darwin24] last_commit=[ruby/json] Fix a typo built-ruby: ruby 3.5.0dev (2025-06-17T09:27:05Z opt-getivar-for-cl.. ed1d7cd778) +PRISM [arm64-darwin24] | |compare-ruby|built-ruby| |:---------------------|-----------:|---------:| |vm_ivar_of_class_set | 12.306M| 13.957M| | | -| 1.13x| |vm_ivar_of_class | 16.167M| 24.029M| | | -| 1.49x| ``` Notes: Merged: https://github.com/ruby/ruby/pull/13639
2025-06-16ZJIT: Add support for putspecialobject (#13565)Stan Lo
* ZJIT: Add support for putspecialobject * Address feedback * Update tests * Adjust the indentation of a Ruby test --------- Co-authored-by: Takashi Kokubun <takashikkbn@gmail.com> Notes: Merged-By: k0kubun <takashikkbn@gmail.com>
2025-06-13Use the `shape_id` rather than `FL_EXIVAR`Jean Boussier
We still keep setting `FL_EXIVAR` so that `rb_shape_verify_consistency` can detect discrepancies. Notes: Merged: https://github.com/ruby/ruby/pull/13612
2025-06-12Fix class instance variable inside namespacesJean Boussier
Now that classes fields are delegated to an object with its own shape_id, we no longer need to mark all classes as TOO_COMPLEX. Notes: Merged: https://github.com/ruby/ruby/pull/13595
2025-06-12Turn `rb_classext_t.fields` into a T_IMEMO/class_fieldsJean Boussier
This behave almost exactly as a T_OBJECT, the layout is entirely compatible. This aims to solve two problems. First, it solves the problem of namspaced classes having a single `shape_id`. Now each namespaced classext has an object that can hold the namespace specific shape. Second, it open the door to later make class instance variable writes atomics, hence be able to read class variables without locking the VM. In the future, in multi-ractor mode, we can do the write on a copy of the `fields_obj` and then atomically swap it. Considerations: - Right now the `RClass` shape_id is always synchronized, but with namespace we should likely mark classes that have multiple namespace with a specific shape flag. Notes: Merged: https://github.com/ruby/ruby/pull/13411