summaryrefslogtreecommitdiff
path: root/vm_insnhelper.c
AgeCommit message (Collapse)Author
2020-11-09Add debug counter for ivar inline cache misses that could hitAaron Patterson
This commit adds a debug counter for the case where the inline cache *missed* but the ivar index table has an entry for that ivar. This is a case where a polymorphic cache could help Notes: Merged: https://github.com/ruby/ruby/pull/3750
2020-11-09Avoid slow path ivar settingAaron Patterson
If the ivar index table exists, we can avoid the slowest path for setting ivars. Notes: Merged: https://github.com/ruby/ruby/pull/3750
2020-11-09Update vm_insnhelper.cAaron Patterson
Co-authored-by: Takashi Kokubun <takashikkbn@gmail.com> Notes: Merged: https://github.com/ruby/ruby/pull/3740
2020-11-09Remove iv table size checkAaron Patterson
iv tables cannot shrink. If the inline cache was ever set, then there must be an entry for the instance variable in the iv table. Just set the iv list on the object to be equal to the iv index table size, then set the iv. Notes: Merged: https://github.com/ruby/ruby/pull/3740
2020-11-09eagerly initialize ivar table when index is small enoughAaron Patterson
When the inline cache is written, the iv table will contain an entry for the instance variable. If we get an inline cache hit, then we know the iv table must contain a value for the index written to the inline cache. If the index in the inline cache is larger than the list on the object, but *smaller* than the iv index table on the class, then we can just eagerly allocate the iv list to be the same size as the iv index table. This avoids duplicate work of checking frozen as well as looking up the index for the particular instance variable name. Notes: Merged: https://github.com/ruby/ruby/pull/3740
2020-10-30Ractor.make_shareable(a_proc)Koichi Sasada
Ractor.make_shareable() supports Proc object if (1) a Proc only read outer local variables (no assignments) (2) read outer local variables are shareable. Read local variables are stored in a snapshot, so after making shareable Proc, any assignments are not affeect like that: ```ruby a = 1 pr = Ractor.make_shareable(Proc.new{p a}) pr.call #=> 1 a = 2 pr.call #=> 1 # `a = 2` doesn't affect ``` [Feature #17284] Notes: Merged: https://github.com/ruby/ruby/pull/3722
2020-10-25Fix bootstrap-test error in previous commitJeremy Evans
2020-10-17sync RClass::ext::iv_index_tblKoichi Sasada
iv_index_tbl manages instance variable indexes (ID -> index). This data structure should be synchronized with other ractors so introduce some VM locks. This patch also introduced atomic ivar cache used by set/getinlinecache instructions. To make updating ivar cache (IVC), we changed iv_index_tbl data structure to manage (ID -> entry) and an entry points serial and index. IVC points to this entry so that cache update becomes atomically. Notes: Merged: https://github.com/ruby/ruby/pull/3662
2020-10-16Abort on system stack overflow during GCAlan Wu
Buggy native extensions could have mark functions that cause stack overflow. When a stack overflow happens during GC, Ruby used to recover by raising an exception, which runs the interpreter. It's not safe to run the interpreter during GC since the GC is in an inconsistent state. This could cause object allocation during GC, for example. Instead of running the interpreter and potentially causing a crash down the line, fail fast and abort. Notes: Merged: https://github.com/ruby/ruby/pull/3661
2020-10-14sync generic_ivtblKoichi Sasada
generic_ivtbl is a process global table to maintain instance variables for non T_OBJECT/T_CLASS/... objects. So we need to protect them for multi-Ractor exection. Hint: we can make them Ractor local for unshareable objects, but now it is premature optimization. Notes: Merged: https://github.com/ruby/ruby/pull/3655
2020-10-01Make minor improvements to supereileencodes
The changes here include: * Using `FL_TEST_RAW` instead of `FL_TEST` in the first check in `vm_search_super_method`. While the profile showed us spending a fair amount of time here, the subsequent benchmarks didn't show much improvement when adding this. Regardless, we know this does less work than `FL_TEST` and we know that `FL_TEST_RAW` is safe due to the previous check so it's a small but accurate optimization. * Set `mid` only once. Both `vm_ci_new_runtime` and `vm_ci_mid` were getting the `original_id` for the method entry. We can do this once and pass the variable to the 2 callers that need it. This also doesn't have a huge performance improvement but cleans up the code a bit. Benchmark: ``` | |compare-ruby|built-ruby| |:----------------|-----------:|---------:| |vm_iclass_super | 3.540M| 3.940M| | | -| 1.11x| ``` Co-authored-by: Aaron Patterson <tenderlove@ruby-lang.org> Notes: Merged: https://github.com/ruby/ruby/pull/3614
2020-09-25prohibi method call by defined_method in other racotrsKoichi Sasada
We can not call a non-isolated Proc in multiple ractors. Notes: Merged: https://github.com/ruby/ruby/pull/3584
2020-09-23Improve the performance of supereileencodes
This PR improves the performance of `super` calls. While working on some Rails optimizations jhawthorn discovered that `super` calls were slower than expected. The changes here do the following: 1) Adds a check for whether the call frame is not equal to the method entry iseq. This avoids the `rb_obj_is_kind_of` check on the next line which is quite slow. If the current call frame is equal to the method entry we know we can't have an instance eval, etc. 2) Changes `FL_TEST` to `FL_TEST_RAW`. This is safe because we've already done the check for `T_ICLASS` above. 3) Adds a benchmark for `T_ICLASS` super calls. 4) Note: makes a chage for `method_entry_cref` to use `const`. On master the benchmarks showed that `super` is 1.76x slower. Our changes improved the performance so that it is now only 1.36x slower. Benchmark IPS: ``` Warming up -------------------------------------- super 244.918k i/100ms method call 383.007k i/100ms Calculating ------------------------------------- super 2.280M (± 6.7%) i/s - 11.511M in 5.071758s method call 3.834M (± 4.9%) i/s - 19.150M in 5.008444s Comparison: method call: 3833648.3 i/s super: 2279837.9 i/s - 1.68x (± 0.00) slower ``` With changes: ``` Warming up -------------------------------------- super 308.777k i/100ms method call 375.051k i/100ms Calculating ------------------------------------- super 2.951M (± 5.4%) i/s - 14.821M in 5.039592s method call 3.551M (± 4.9%) i/s - 18.002M in 5.081695s Comparison: method call: 3551372.7 i/s super: 2950557.9 i/s - 1.20x (± 0.00) slower ``` Ruby VM benchmarks also showed an improvement: Existing `vm_super` benchmark`. ``` $ make benchmark ITEM=vm_super | |compare-ruby|built-ruby| |:---------|-----------:|---------:| |vm_super | 21.555M| 37.819M| | | -| 1.75x| ``` New `vm_iclass_super` benchmark: ``` $ make benchmark ITEM=vm_iclass_super | |compare-ruby|built-ruby| |:----------------|-----------:|---------:| |vm_iclass_super | 1.669M| 3.683M| | | -| 2.21x| ``` This is the benchmark script used for the benchmark-ips benchmarks: ```ruby require "benchmark/ips" class Foo def zuper; end def top; end last_method = "top" ("A".."M").each do |module_name| eval <<-EOM module #{module_name} def zuper; super; end def #{module_name.downcase} #{last_method} end end prepend #{module_name} EOM last_method = module_name.downcase end end foo = Foo.new Benchmark.ips do |x| x.report "super" do foo.zuper end x.report "method call" do foo.m end x.compare! end ``` Co-authored-by: Aaron Patterson <tenderlove@ruby-lang.org> Co-authored-by: John Hawthorn <john@hawthorn.email> Notes: Merged: https://github.com/ruby/ruby/pull/3545
2020-09-22Revert "Prevent SystemStackError when calling super in module with activated ↵Jeremy Evans
refinement" This reverts commit eeef16e190cdabc2ba474622720f8e3df7bac43b. This also reverts the spec change. Preventing the SystemStackError would be nice, but there is valid code that the fix breaks, and it is probably more common than cases that cause the SystemStackError. Fixes [Bug #17182] Notes: Merged: https://github.com/ruby/ruby/pull/3564
2020-09-15Interpolated strings are no longer frozen with frozen-string-literal: trueBenoit Daloze
* Remove freezestring instruction since this was the only usage for it. * [Feature #17104] Notes: Merged: https://github.com/ruby/ruby/pull/3488
2020-09-03Introduce Ractor mechanism for parallel executionKoichi Sasada
This commit introduces Ractor mechanism to run Ruby program in parallel. See doc/ractor.md for more details about Ractor. See ticket [Feature #17100] to see the implementation details and discussions. [Feature #17100] This commit does not complete the implementation. You can find many bugs on using Ractor. Also the specification will be changed so that this feature is experimental. You will see a warning when you make the first Ractor with `Ractor.new`. I hope this feature can help programmers from thread-safety issues. Notes: Merged: https://github.com/ruby/ruby/pull/3365
2020-09-01Remove the pc argument of vm_trace()Alan Wu
This makes the binary 272 bytes smaller on -O3 GCC 10.2.0. Notes: Merged: https://github.com/ruby/ruby/pull/3494
2020-08-27Fix Method#super_method for aliased methodsJeremy Evans
Previously, Method#super_method looked at the called_id to determine the method id to use, but that isn't correct for aliased methods, because the super target depends on the original method id, not the called_id. Additionally, aliases can reference methods defined in other classes and modules, and super lookup needs to start in the super of the defined class in such cases. This adds tests for Method#super_method for both types of aliases, one that uses VM_METHOD_TYPE_ALIAS and another that does not. Both check that the results for calling super methods return the expected values. To find the defined class for alias methods, add an rb_ prefix to find_defined_class_by_owner in vm_insnhelper.c and make it non-static, so that it can be called from method_super_method in proc.c. This bug was original discovered while researching [Bug #11189]. Fixes [Bug #17130] Notes: Merged: https://github.com/ruby/ruby/pull/3458 Merged-By: jeremyevans <code@jeremyevans.net>
2020-07-27Prevent SystemStackError when calling super in module with activated refinementJeremy Evans
Without this, if a refinement defines a method that calls super and includes a module with a module that calls super and has a activated refinement at the point super is called, the module method super call will end up calling back into the refinement method, creating a loop. Fixes [Bug #17007] Notes: Merged: https://github.com/ruby/ruby/pull/3309
2020-07-10Fixed another typoNobuyoshi Nakada
2020-07-10Fixed typosNobuyoshi Nakada
2020-07-10vm_push_frame_debug_counter_inc: use branches卜部昌平
Ko1 doesn't like previous code. Notes: Merged: https://github.com/ruby/ruby/pull/3296
2020-07-10vm_push_frame: move assignments around卜部昌平
Struct assignment using a compound literal is more readable than before, to me at least. It seems compilers reorder assignments anyways. Neither speedup nor slowdown is observed on my machine. Notes: Merged: https://github.com/ruby/ruby/pull/3296
2020-07-10vm_push_frame: move assertions out of the function卜部昌平
These assertions are purely static. Ned not be checked on-the-fly. Notes: Merged: https://github.com/ruby/ruby/pull/3296
2020-07-10vm_push_frame: hoist out debug codes卜部昌平
Made it a bit readable. Notes: Merged: https://github.com/ruby/ruby/pull/3296
2020-07-10nobody uses the return value of vm_push_frame卜部昌平
Surprised to see such a waste of time in this super duper hot path. Notes: Merged: https://github.com/ruby/ruby/pull/3296
2020-07-03Use ID instead of GENTRY for gvars. (#3278)Koichi Sasada
Use ID instead of GENTRY for gvars. Global variables are compiled into GENTRY (a pointer to struct rb_global_entry). This patch replace this GENTRY to ID and make the code simple. We need to search GENTRY from ID every time (st_lookup), so additional overhead will be introduced. However, the performance of accessing global variables is not important now a day and this simplicity helps Ractor development. Notes: Merged-By: ko1 <ko1@atdot.net>
2020-06-30Extracted METHOD_ENTRY_CACHEABLE macroNobuyoshi Nakada
2020-06-29vm_getivar: do not goto into a branch卜部昌平
I'm not necessarily against every goto in general, but jumping into a branch is definitely a bad idea. Better refactor. Notes: Merged: https://github.com/ruby/ruby/pull/3247
2020-06-25Decide JIT-ed insn based on cached cfuncTakashi Kokubun
for opt_* insns. opt_eq handles rb_obj_equal inside opt_eq, and all other cfunc is handled by opt_send_without_block. Therefore we can't decide which insn should be generated by checking whether it's cfunc cc or not. ``` $ benchmark-driver -v --rbenv 'before --jit;after --jit' benchmark/mjit_opt_cc_insns.yml --repeat-count=4 before --jit: ruby 2.8.0dev (2020-06-26T05:21:43Z master 9dbc2294a6) +JIT [x86_64-linux] after --jit: ruby 2.8.0dev (2020-06-26T06:30:18Z master 75cece1b0b) +JIT [x86_64-linux] last_commit=Decide JIT-ed insn based on cached cfunc Calculating ------------------------------------- before --jit after --jit mjit_nil?(1) 73.878M 74.021M i/s - 40.000M times in 0.541432s 0.540391s mjit_not(1) 72.635M 74.601M i/s - 40.000M times in 0.550702s 0.536187s mjit_eq(1, nil) 7.331M 7.445M i/s - 8.000M times in 1.091211s 1.074596s mjit_eq(nil, 1) 49.450M 64.711M i/s - 8.000M times in 0.161781s 0.123627s Comparison: mjit_nil?(1) after --jit: 74020528.4 i/s before --jit: 73878185.9 i/s - 1.00x slower mjit_not(1) after --jit: 74600882.0 i/s before --jit: 72634507.6 i/s - 1.03x slower mjit_eq(1, nil) after --jit: 7444657.4 i/s before --jit: 7331304.3 i/s - 1.02x slower mjit_eq(nil, 1) after --jit: 64710790.6 i/s before --jit: 49449507.4 i/s - 1.31x slower ```
2020-06-21Verify builtin inline annotation with VM_CHECK_MODE (#3244)Takashi Kokubun
* Verify builtin inline annotation with VM_CHECK_MODE * Remove static to fix the link issue on MJIT Notes: Merged-By: k0kubun <takashikkbn@gmail.com>
2020-06-21Fix -Wmaybe-uninitialized at vm_invoke_blockTakashi Kokubun
2020-06-17Replaced accessors of `Struct` with `invokebuiltin`Nobuyoshi Nakada
2020-06-16Revert "Replaced accessors of `Struct` with `invokebuiltin`"Nobuyoshi Nakada
This reverts commit 19cabe8b09d92d033c244f32ff622b8e513375f1, which didn't support tool/lib/iseq_loader_checker.rb.
2020-06-16Replaced accessors of `Struct` with `invokebuiltin`Nobuyoshi Nakada
2020-06-10vm_call_method: avoid marking on-stack object卜部昌平
This callcache is on stack, must not be GCed. However its contents are copied from other materials, which can be an ordinal object. Should set a flag to make sure it is properly skipped by the GC.
2020-06-09rb_eql_opt,rb_equal_opt: purge stale cc卜部昌平
When on USE_EMBED_CI, cd is stored statically. Previous use could cache stale cd->cc, which could have already been GCed. Need flush them. Notes: Merged: https://github.com/ruby/ruby/pull/3179
2020-06-09vm_ccs_push: do not cache non-heap entries卜部昌平
Entires not GC-able must be considered to be volatile. Not eligible for later use. Notes: Merged: https://github.com/ruby/ruby/pull/3179
2020-06-09VM_CI_NEW_ID: USE_EMBED_CI could be false卜部昌平
It was a wrong idea to assume CIs are always embedded. Notes: Merged: https://github.com/ruby/ruby/pull/3179
2020-06-09eliminate C99 compound literals卜部昌平
Ko1 prefers variables be assgined, instead of bare literals in function arguments. Notes: Merged: https://github.com/ruby/ruby/pull/3179
2020-06-09vm_call_method: use struct assignment卜部昌平
This further reduces the generated binary of vm_call_method from 566 bytes to 545 bytes on my machine, according to nm(1). Notes: Merged: https://github.com/ruby/ruby/pull/3179
2020-06-09rb_vm_call0: on-stack call info卜部昌平
This changeset reduces the generated binary of rb_vm_call0 from 281 bytes to 211 bytes on my machine. Should reduce GC pressure as well. Notes: Merged: https://github.com/ruby/ruby/pull/3179
2020-06-09vm_yield_setup_args: refactor use macro卜部昌平
Notes: Merged: https://github.com/ruby/ruby/pull/3179
2020-06-09vm_call_method: no call vm_cc_fill卜部昌平
This changeset reduces the generated binary of vm_call_method from 600 bytes to 566 bytes on my machine, accroding to nm(1). Notes: Merged: https://github.com/ruby/ruby/pull/3179
2020-06-09vm_call_refined: no call vm_cc_fill卜部昌平
This changeset reduces the generated binary of vm_call_method_each_type from 2,442 bytes to 2,378 bytes on my machine, accroding to nm(1). Notes: Merged: https://github.com/ruby/ruby/pull/3179
2020-06-09vm_call_zsuper: no call vm_cc_fill卜部昌平
This changeset reduces the generated binary of vm_call_method_each_type from 2,522 bytes to 2,442 bytes on my machine, accroding to nm(1). Notes: Merged: https://github.com/ruby/ruby/pull/3179
2020-06-09vm_call_method_missing_body: on-stack call info卜部昌平
This changeset reduces the generated binary of vm_call_method_missing_body from 604 bytes to 532 bytes on my machine. Should reduce GC pressure as well. Notes: Merged: https://github.com/ruby/ruby/pull/3179
2020-06-09vm_call_symbol: on-stack call info卜部昌平
This changeset reduces the generated binary of vm_call_symbol from 808 bytes to 798 bytes on my machine. Should reduce GC pressure as well. Notes: Merged: https://github.com/ruby/ruby/pull/3179
2020-06-09vm_call_alias: no call vm_cc_fill卜部昌平
This changeset reduces the generated binary of vm_call_alias from 188 bytes to 149 bytes on my machine, accroding to nm(1). Notes: Merged: https://github.com/ruby/ruby/pull/3179
2020-06-09rb_eql_opt: fully static call data卜部昌平
This changeset reduces the generated binary of rb_eql_opt from 86 bytes to 20 bytes on my machine, according to nm(1). Notes: Merged: https://github.com/ruby/ruby/pull/3179