aboutsummaryrefslogtreecommitdiffstats
path: root/vm.c
Commit message (Collapse)AuthorAgeFilesLines
* Remove RubyVM::JIT (#5275)Takashi Kokubun2021-12-151-3/+0
| | | [Feature #18349] reverts [Feature #17490]
* Don't invalidate BOPs when aliases redefinedJohn Hawthorn2021-12-141-3/+8
| | | | | | | | | | | | | Previously when redefining an alias of a BOP, we would unnecessarily invalidate the bop. For example: class String alias len length private :len end This commit avoids this by checking that the called_id on the method entry matches the original_id on the definition.
* YJIT: Avoid unnecessary BOP invalidationJohn Hawthorn2021-12-141-3/+5
| | | | | Previously we would invalidate BOPs in YJIT when the method registered as a BOP was redefined on a subclass.
* Prepare for removing RubyVM::JIT (#5262)Takashi Kokubun2021-12-131-12/+11
|
* `Ractor.make_shareable` checks proc's seflKoichi Sasada2021-12-091-0/+4
| | | | | | | `Ractor.make_shareable(proc_obj)` raises an `IsolationError` if the self of `proc_obj` is not a shareable object. [Bug #18243]
* Lazily create singletons on instance_{exec,eval} (#5146)John Hawthorn2021-12-021-12/+15
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * Lazily create singletons on instance_{exec,eval} Previously when instance_exec or instance_eval was called on an object, that object would be given a singleton class so that method definitions inside the block would be added to the object rather than its class. This commit aims to improve performance by delaying the creation of the singleton class unless/until one is needed for method definition. Most of the time instance_eval is used without any method definition. This was implemented by adding a flag to the cref indicating that it represents a singleton of the object rather than a class itself. In this case CREF_CLASS returns the object's existing class, but in cases that we are defining a method (either via definemethod or VM_SPECIAL_OBJECT_CBASE which is used for undef and alias). This also happens to fix what I believe is a bug. Previously instance_eval behaved differently with regards to constant access for true/false/nil than for all other objects. I don't think this was intentional. String::Foo = "foo" "".instance_eval("Foo") # => "foo" Integer::Foo = "foo" 123.instance_eval("Foo") # => "foo" TrueClass::Foo = "foo" true.instance_eval("Foo") # NameError: uninitialized constant Foo This also slightly changes the error message when trying to define a method through instance_eval on an object which can't have a singleton class. Before: $ ruby -e '123.instance_eval { def foo; end }' -e:1:in `block in <main>': no class/module to add method (TypeError) After: $ ./ruby -e '123.instance_eval { def foo; end }' -e:1:in `block in <main>': can't define singleton (TypeError) IMO this error is a small improvement on the original and better matches the (both old and new) message when definging a method using `def self.` $ ruby -e '123.instance_eval{ def self.foo; end }' -e:1:in `block in <main>': can't define singleton (TypeError) Co-authored-by: Matthew Draper <matthew@trebex.net> * Remove "under" argument from yield_under * Move CREF_SINGLETON_SET into vm_cref_new * Simplify vm_get_const_base * Fix leaf VM_SPECIAL_OBJECT_CONST_BASE Co-authored-by: Matthew Draper <matthew@trebex.net>
* Rework tracing for blocks running as methodsAlan Wu2021-12-011-41/+32
| | | | | | | | | | | | | | | | | | | | | | | | | | | | The main impetus for this change is to fix [Bug #13392]. Previously, we fired the "return" TracePoint event after popping the stack frame for the block running as method (BMETHOD). This gave undesirable source location outputs as the return event normally fires right before the frame going away. The iseq for each block can run both as a block and as a method. To accommodate that, this commit makes vm_trace() fire call/return events for instructions that have b_call/b_return events attached when the iseq is running as a BMETHOD. The logic for rewriting to "trace_*" instruction is tweaked so that when the user listens to call/return events, instructions with b_call/b_return become trace variants. To continue to provide the return value for non-local returns done using the "return" or "break" keyword inside BMETHODs, the stack unwinding code is tweaked. b_return events now provide the same return value as return events for these non-local cases. A pre-existing test deemed not providing a return value for these b_return events as a limitation. This commit removes the checks for call/return TracePoint events that happen when calling into BMETHODs when no TracePoints are active. Technically, migrating just the return event is enough to fix the bug, but migrating both call and return removes our reliance on `VM_FRAME_FLAG_FINISH` and re-entering the interpreter when the caller is already in the interpreter.
* Refactor hacky ID tables to struct rb_ast_id_table_tYusuke Endoh2021-11-211-5/+4
| | | | | | | | | The implementation of a local variable tables was represented as `ID*`, but it was very hacky: the first element is not an ID but the size of the table, and, the last element is (sometimes) a link to the next local table only when the id tables are a linked list. This change converts the hacky implementation to a normal struct.
* `rb_method_optimized_t` for further extensionKoichi Sasada2021-11-191-2/+2
| | | | | Now `rb_method_optimized_t optimized` field is added to represent optimized method type.
* `vm_empty_cc_for_super`Koichi Sasada2021-11-171-0/+16
| | | | | | Same as `vm_empty_cc`, introduce a global variable which has `.call_ = vm_call_super_method`. Use it if the `cme == NULL` on `vm_search_super_method`.
* Convert IDs to IntegersNobuyoshi Nakada2021-11-081-4/+31
| | | | | | As the ID serial is 32bit value and internal IDs created in the parser are assigned from its maximum value, Symbol converted from it will exceed 32bit and overflow on 32bit platforms.
* Refine the error message for hidden variablesNobuyoshi Nakada2021-11-071-3/+8
|
* Preserve the encoding of message from outer local variableNobuyoshi Nakada2021-10-291-1/+1
| | | | In the case of read-only but refering an unshareable object.
* Preserve the encoding of message from outer local variablesNobuyoshi Nakada2021-10-291-47/+27
|
* Make Coverage suspendable (#4856)Yusuke Endoh2021-10-251-0/+2
| | | | | | | * Make Coverage suspendable Add `Coverage.suspend`, `Coverage.resume` and some methods. [Feature #18176] [ruby-core:105321]
* suppress warnings for probable NULL dererefencesNobuyoshi Nakada2021-10-241-0/+1
|
* Suppress sign-compare warningNobuyoshi Nakada2021-10-241-2/+2
|
* Deprecate include/prepend in refinements and add Refinement#import_methods ↵Shugo Maeda2021-10-211-0/+19
| | | | | | | | | | instead Refinement#import_methods imports methods from modules. Unlike Module#include, it copies methods and adds them into the refinement, so the refinement is activated in the imported methods. [Bug #17429] [ruby-core:101639]
* `RubyVM.keep_script_lines`Koichi Sasada2021-10-211-0/+39
| | | | | | | | | | | | | | `RubyVM.keep_script_lines` enables to keep script lines for each ISeq and AST. This feature is for debugger/REPL support. ```ruby RubyVM.keep_script_lines = true RubyVM::keep_script_lines = true eval("def foo = nil\ndef bar = nil") pp RubyVM::InstructionSequence.of(method(:foo)).script_lines ```
* Expand tabsAlan Wu2021-10-201-2/+2
|
* Cleanup diff against upstream. Add commentsAlan Wu2021-10-201-1/+1
| | | | | I did a `git diff --stat` against upstream and looked at all the files that are outside of YJIT to come up with these minor changes.
* Fix changes from rebaseNoah Gibbs2021-10-201-4/+3
|
* Count interpreter instructions when -DYJIT_STATS=1Alan Wu2021-10-201-13/+1
| | | | | | | | | | The interpreter instruction count was enabled based on RUBY_DEBUG as opposed to YJIT_STATS. In builds with YJIT_STATS=1 but RUBY_DEBUG=0, the count was not available. Move YJIT_STATS in yjit.h where declarations are expoed to code outside of YJIT. Also reduce the changes made to the interpreter for calling into YJIT's instruction counting function.
* Yet Another Ruby JIT!Jose Narvaez2021-10-201-6/+6
| | | | Renaming uJIT to YJIT. AKA s/ujit/yjit/g.
* WIP JIT-to-JIT returnsMaxime Chevalier-Boisvert2021-10-201-1/+1
|
* add bop to redefinition callbackAaron Patterson2021-10-201-1/+1
|
* Add a callback in to microjit when a BOP is redefinedAaron Patterson2021-10-201-0/+2
| | | | | This commit adds a callback `rb_ujit_bop_redefined` when a basic operation is redefined.
* Implement --ujit-stats and instructoin countingAlan Wu2021-10-201-0/+13
| | | | | | VM and ujit instruction counting in debug builds. shopify/ruby#19
* Moved the common codeNobuyoshi Nakada2021-10-131-4/+5
|
* Collect symbols instead of strings and get rid of rb_str_internNobuyoshi Nakada2021-10-081-3/+3
|
* Fix Ractor.make_shareable changing locals for ProcsAlan Wu2021-10-061-1/+1
| | | | | | | | | | | | | env_copy() uses rb_ary_delete_at() with a loop counting up while iterating through the list of read only locals. rb_ary_delete_at() can shift elements in the array to an index lesser than the loop index, causing locals to be missed and set to Qfalse in the returned environment. Iterate through the locals in reverse instead, this way the shifting never happens for locals that are yet to be visited and we process all the locals in the array. [Bug #18023]
* Using NIL_P macro instead of `== Qnil`S.H2021-10-031-7/+7
|
* Do not load file with same realpath twice when requiringJeremy Evans2021-10-021-0/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This fixes issues with paths being loaded twice in certain cases when symlinks are used. It took me multiple attempts to get this working. My original attempt tried to convert paths to realpaths before adding them to $LOADED_FEATURES. Unfortunately, this doesn't work well with the loaded feature index, which is based off load paths and not realpaths. While I was able to get require working, I'm fairly sure the loaded feature index was not being used as expected, which would have significant performance implications. Additionally, I was never able to get that approach working with autoload when autoloading a non-realpath file. It also broke some specs. This takes a more conservative approach. Directly before loading the file, if the file with the same realpath has been required, the loading of the file is skipped. The realpaths are stored as fstrings in a hidden hash. When rebuilding the loaded feature index, the hash of realpaths is also rebuilt. I'm guessing this makes rebuilding process slower, but I don think that is a hot path. In general, modifying loaded features is only done when reloading, and that tends to be in non-production environments. Change test_require_with_loaded_features_pop test to use 30 threads and 300 iterations, instead of 4 threads and 1000 iterations. I saw only sporadic failures with 4/1000, but consistent failures 30/300 threads. These failures were due to the fact that the concurrent deletions from $LOADED_FEATURES in other threads can result in rb_ary_entry returning nil when rebuilding the loaded features index. To avoid concurrency issues when rebuilding the loaded features index, the building of the index itself is left alone, and afterwards, a separate loop is done on a copy of the loaded feature snapshot in order to rebuild the realpaths hash. Fixes [Bug #17885]
* Revert "Do not load file with same realpath twice when requiring"Jeremy Evans2021-09-181-2/+0
| | | | | | | This reverts commit ddb85c5d2bdf75a83eb163856508691a7436b446. This commit causes unexpected warnings in TestTranscode#test_loading_race occasionally in CI.
* Do not load file with same realpath twice when requiringJeremy Evans2021-09-181-0/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This fixes issues with paths being loaded twice in certain cases when symlinks are used. It took me multiple attempts to get this working. My original attempt tried to convert paths to realpaths before adding them to $LOADED_FEATURES. Unfortunately, this doesn't work well with the loaded feature index, which is based off load paths and not realpaths. While I was able to get require working, I'm fairly sure the loaded feature index was not being used as expected, which would have significant performance implications. Additionally, I was never able to get that approach working with autoload when autoloading a non-realpath file. It also broke some specs. This takes a more conservative approach. Directly before loading the file, if the file with the same realpath has been required, the loading of the file is skipped. The realpaths are stored as fstrings in a hidden hash. When rebuilding the loaded feature index, the hash of realpaths is also rebuilt. I'm guessing this makes rebuilding process slower, but I don think that is a hot path. In general, modifying loaded features is only done when reloading, and that tends to be in non-production environments. Change test_require_with_loaded_features_pop test to use 30 threads and 300 iterations, instead of 4 threads and 1000 iterations. I saw only sporadic failures with 4/1000, but consistent failures 30/300 threads. These failures were due to the fact that the concurrent deletions from $LOADED_FEATURES in other threads can result in rb_ary_entry returning nil when rebuilding the loaded features index. To avoid concurrency issues when rebuilding the loaded features index, the building of the index itself is left alone, and afterwards, a separate loop is done on a copy of the loaded feature snapshot in order to rebuild the realpaths hash. Fixes [Bug #17885]
* Refactor vm_yield functionS-H-GAMELINKS2021-09-141-3/+1
|
* Remove printf family from the mjit headerNobuyoshi Nakada2021-09-111-10/+10
| | | | | Linking printf family functions makes mjit objects to link unnecessary code.
* include/ruby/internal/intern/vm.h: add doxygen卜部昌平2021-09-101-2/+0
| | | | Must not be a bad idea to improve documents. [ci skip]
* Show verbose error messages when single pattern match failsKazuki Tsujimoto2021-08-151-0/+7
| | | | | | | [0] => [0, *, a] #=> [0] length mismatch (given 1, expected 2+) (NoMatchingPatternError) Ignore test failures of typeprof caused by this change for now.
* Fix potential hang when joining threads.Samuel Williams2021-08-031-7/+10
| | | | | | | | | | | If the thread termination invokes user code after `th->status` becomes `THREAD_KILLED`, and the user unblock function causes that `th->status` to become something else (e.g. `THREAD_RUNNING`), threads waiting in `thread_join_sleep` will hang forever. We move the unblock function call to before the thread status is updated, and allow threads to join as soon as `th->value` becomes defined. This reverts commit 6505c77501f1924571b2fe620c5c7b31ede0cd22.
* Using RBOOL macroS.H2021-08-021-13/+5
|
* use me->def instead of me for opt_tableKoichi Sasada2021-07-291-6/+5
| | | | | | | | | | | | `vm_opt_method_table` is me=>bop table to manage the optimized methods (by specialized instruction). However, `me` can be invalidated to invalidate the method cache entry. [Bug #17725] To solve the issue, use `me-def` instead of `me` which simply copied at invalidation timing. A test by @jeremyevans https://github.com/ruby/ruby/pull/4376
* Revert "Fix potential hang when joining threads."Yusuke Endoh2021-07-281-10/+7
| | | | | | | | | | | This reverts commit 13f8521c630a15c87398dee0763e95f59c032a94. http://rubyci.s3.amazonaws.com/solaris11-gcc/ruby-master/log/20210727T230009Z.fail.html.gz http://rubyci.s3.amazonaws.com/solaris11-sunc/ruby-master/log/20210728T000009Z.fail.html.gz This revert is to confirm whether the commit is the cause. If the failures consistently occur after this revert, I'll reintroduce the commit.
* Fix infinite loop in ensure after NoMemoryErrorJeremy Evans2021-07-271-1/+1
| | | | | | | | | | | | | | VM patch from wanabe. Test based on example from buzztaiki (Taiki Sugawara). Test fails when compiles with -DRUBY_DEBUG, as that can can use rb_bug instead of NoMemoryError, which doesn't allow testing this case. Test also fails on MingW, as RangeError is used instead of NoMemoryError. Skip the test in either case. Fixes [Bug #15779]
* Fix potential hang when joining threads.Samuel Williams2021-07-271-7/+10
| | | | | | | | | If the thread termination invokes user code after `th->status` becomes `THREAD_KILLED`, and the user unblock function causes that `th->status` to become something else (e.g. `THREAD_RUNNING`), threads waiting in `thread_join_sleep` will hang forever. We move the unblock function call to before the thread status is updated, and allow threads to join as soon as `th->value` becomes defined.
* Add debug assertion in `rb_funcall*` that the current thread has the gvl.Samuel Williams2021-07-161-0/+1
|
* Keep GC disabled until VM bootstrap has done [Bug #17583]Nobuyoshi Nakada2021-07-011-2/+2
|
* Add a cache for class variableseileencodes2021-06-181-1/+4
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Redo of 34a2acdac788602c14bf05fb616215187badd504 and 931138b00696419945dc03e10f033b1f53cd50f3 which were reverted. GitHub PR #4340. This change implements a cache for class variables. Previously there was no cache for cvars. Cvar access is slow due to needing to travel all the way up th ancestor tree before returning the cvar value. The deeper the ancestor tree the slower cvar access will be. The benefits of the cache are more visible with a higher number of included modules due to the way Ruby looks up class variables. The benchmark here includes 26 modules and shows with the cache, this branch is 6.5x faster when accessing class variables. ``` compare-ruby: ruby 3.1.0dev (2021-03-15T06:22:34Z master 9e5105c) [x86_64-darwin19] built-ruby: ruby 3.1.0dev (2021-03-15T12:12:44Z add-cache-for-clas.. c6be009) [x86_64-darwin19] | |compare-ruby|built-ruby| |:--------|-----------:|---------:| |vm_cvar | 5.681M| 36.980M| | | -| 6.51x| ``` Benchmark.ips calling `ActiveRecord::Base.logger` from within a Rails application. ActiveRecord::Base.logger has 71 ancestors. The more ancestors a tree has, the more clear the speed increase. IE if Base had only one ancestor we'd see no improvement. This benchmark is run on a vanilla Rails application. Benchmark code: ```ruby require "benchmark/ips" require_relative "config/environment" Benchmark.ips do |x| x.report "logger" do ActiveRecord::Base.logger end end ``` Ruby 3.0 master / Rails 6.1: ``` Warming up -------------------------------------- logger 155.251k i/100ms Calculating ------------------------------------- ``` Ruby 3.0 with cvar cache / Rails 6.1: ``` Warming up -------------------------------------- logger 1.546M i/100ms Calculating ------------------------------------- logger 14.857M (± 4.8%) i/s - 74.198M in 5.006202s ``` Lastly we ran a benchmark to demonstate the difference between master and our cache when the number of modules increases. This benchmark measures 1 ancestor, 30 ancestors, and 100 ancestors. Ruby 3.0 master: ``` Warming up -------------------------------------- 1 module 1.231M i/100ms 30 modules 432.020k i/100ms 100 modules 145.399k i/100ms Calculating ------------------------------------- 1 module 12.210M (± 2.1%) i/s - 61.553M in 5.043400s 30 modules 4.354M (± 2.7%) i/s - 22.033M in 5.063839s 100 modules 1.434M (± 2.9%) i/s - 7.270M in 5.072531s Comparison: 1 module: 12209958.3 i/s 30 modules: 4354217.8 i/s - 2.80x (± 0.00) slower 100 modules: 1434447.3 i/s - 8.51x (± 0.00) slower ``` Ruby 3.0 with cvar cache: ``` Warming up -------------------------------------- 1 module 1.641M i/100ms 30 modules 1.655M i/100ms 100 modules 1.620M i/100ms Calculating ------------------------------------- 1 module 16.279M (± 3.8%) i/s - 82.038M in 5.046923s 30 modules 15.891M (± 3.9%) i/s - 79.459M in 5.007958s 100 modules 16.087M (± 3.6%) i/s - 81.005M in 5.041931s Comparison: 1 module: 16279458.0 i/s 100 modules: 16087484.6 i/s - same-ish: difference falls within error 30 modules: 15891406.2 i/s - same-ish: difference falls within error ``` Co-authored-by: Aaron Patterson <tenderlove@ruby-lang.org>
* node.h: Reduce struct size to fit with Ruby object size (five VALUEs)Yusuke Endoh2021-06-181-1/+1
| | | | | | | | by merging `rb_ast_body_t#line_count` and `#script_lines`. Fortunately `line_count == RARRAY_LEN(script_lines)` was always satisfied. When script_lines is saved, it has an array of lines, and when not saved, it has a Fixnum that represents the old line_count.
* Adjust styles [ci skip]Nobuyoshi Nakada2021-06-171-1/+2
| | | | | | | | | * --braces-after-func-def-line * --dont-cuddle-else * --procnames-start-lines * --space-after-for * --space-after-if * --space-after-while