summaryrefslogtreecommitdiff
path: root/gc.c
AgeCommit message (Collapse)Author
2021-08-27Fix memory leak in Variable Width AllocationPeter Zhu
Force recycled objects could create a freelist for the page. At the start of sweeping we should append to the freelist to avoid permanently losing the slots on the freelist. Notes: Merged: https://github.com/ruby/ruby/pull/4786
2021-08-25[Feature #18045] Implement size classes for GCPeter Zhu
This commits implements size classes in the GC for the Variable Width Allocation feature. Unless `USE_RVARGC` compile flag is set, only a single size class is created, maintaining current behaviour. See the redmine ticket for more details. Co-authored-by: Aaron Patterson <tenderlove@ruby-lang.org> Notes: Merged: https://github.com/ruby/ruby/pull/4773
2021-08-25[Feature #18045] Remove T_PAYLOADPeter Zhu
This commit removes T_PAYLOAD since the new VWA implementation no longer requires T_PAYLOAD types. Co-authored-by: Aaron Patterson <tenderlove@ruby-lang.org> Notes: Merged: https://github.com/ruby/ruby/pull/4773
2021-08-23Replace intptr_t with uintptr_t in gc.cPeter Zhu
Pointers may be large to the point where intptr_t would be negative. This is problematic when doing comparisons of pointers. Notes: Merged: https://github.com/ruby/ruby/pull/4765
2021-08-23Revert "[Feature #18045] Implement size classes for GC"Peter Zhu
This reverts commits 48ff7a9f3e47bffb3e4d067a12ba9b936261caa0 and b2e2cf2dedd104acad8610721db5e4d341f135ef because it is causing crashes in SPARC solaris and i386 debian. Notes: Merged: https://github.com/ruby/ruby/pull/4764
2021-08-23[Feature #18045] Implement size classes for GCPeter Zhu
This commits implements size classes in the GC for the Variable Width Allocation feature. Unless `USE_RVARGC` compile flag is set, only a single size class is created, maintaining current behaviour. See the redmine ticket for more details. Co-authored-by: Aaron Patterson <tenderlove@ruby-lang.org> Notes: Merged: https://github.com/ruby/ruby/pull/4680
2021-08-23[Feature #18045] Remove T_PAYLOADPeter Zhu
This commit removes T_PAYLOAD since the new VWA implementation no longer requires T_PAYLOAD types. Co-authored-by: Aaron Patterson <tenderlove@ruby-lang.org> Notes: Merged: https://github.com/ruby/ruby/pull/4680
2021-08-20Turned the reminder comment to a compile-time messageNobuyoshi Nakada
2021-08-20Undefine the alloc function for T_DATA classesMike Dalessio
which have not undefined or redefined it. When a `T_DATA` object is created whose class has not undefined or redefined the alloc function, the alloc function now gets undefined by Data_Wrap_Struct et al. Optionally, a future release may also warn that this being done. This should help developers of C extensions to meet the requirements explained in "doc/extension.rdoc". Without a check like this, there is no easy way for an author of a C extension to see where they have made a mistake. Notes: Merged: https://github.com/ruby/ruby/pull/4604
2021-08-16`SIZE_MAX` is not `size_t` on emscriptenNobuyoshi Nakada
Notes: Merged: https://github.com/ruby/ruby/pull/4745
2021-08-11Make during_compacting flag in GC one bitPeter Zhu
Commit c32218de1ba094223420a4ea017707f48d0009c5 turned during_compacting flag to 2 bits to support the case when there is no write barrier. But commit 32b7dcfb56a417c1d1c354102351fc1825d653bf changed compaction to always enable the write barrier. This commit cleans up some of the leftover code. Notes: Merged: https://github.com/ruby/ruby/pull/4730
2021-08-08Make bit flags `reason` unsignedNobuyoshi Nakada
2021-08-08Suppress warnings when GC_ENABLE_INCREMENTAL_MARK == 0Nobuyoshi Nakada
2021-08-02Using RBOOL macroS.H
Notes: Merged: https://github.com/ruby/ruby/pull/4695 Merged-By: nobu <nobu@ruby-lang.org>
2021-07-29Do not check pending interrupts when running finalizersJeremy Evans
This fixes cases where exceptions raised using Thread#raise are swallowed by finalizers and not delivered to the running thread. This could cause issues with finalizers that rely on pending interrupts, but that case is expected to be rarer. Fixes [Bug #13876] Fixes [Bug #15507] Co-authored-by: Koichi Sasada <ko1@atdot.net> Notes: Merged: https://github.com/ruby/ruby/pull/4366
2021-07-23Suppress exception message in finalizer [Feature #17798]Nobuyoshi Nakada
Notes: Merged: https://github.com/ruby/ruby/pull/4670
2021-07-23Show exception in finalizer [Feature #17798]Nobuyoshi Nakada
Notes: Merged: https://github.com/ruby/ruby/pull/4670
2021-07-23Access rb_execution_context_t::errinfo directlyNobuyoshi Nakada
Notes: Merged: https://github.com/ruby/ruby/pull/4670
2021-07-23Use rb_equalNobuyoshi Nakada
It can be optimized and handles Qnil properly. Notes: Merged: https://github.com/ruby/ruby/pull/4669
2021-07-23Finalizers no longer store the safe levelNobuyoshi Nakada
Notes: Merged: https://github.com/ruby/ruby/pull/4669
2021-07-22Don't recompute the heap pagePeter Zhu
We already page the page of the zombie calculated. Don't recalculate the page. Notes: Merged: https://github.com/ruby/ruby/pull/4668
2021-07-22Don't set flags in finalize_listPeter Zhu
The call after it to `heap_page_add_freeobj` will set the flags. Notes: Merged: https://github.com/ruby/ruby/pull/4668
2021-07-21Change GC verification to walk all pagesPeter Zhu
`gc_verify_internal_consistency_` does not walk pages in the tomb heap so numbers were off. This commit changes it to walk all allocated pages. Notes: Merged: https://github.com/ruby/ruby/pull/4666
2021-07-15[Bug #18014] Add assertion to verify freelistPeter Zhu
This commit adds an assertion has been added after `gc_page_sweep` to verify that the freelist length is equal to the number of free slots in the page. Notes: Merged: https://github.com/ruby/ruby/pull/4613
2021-07-15[Bug #18014] Fix memory leak in GC when using RactorsPeter Zhu
When a Ractor is removed, the freelist in the Ractor cache is not returned to the GC, leaving the freelist permanently lost. This commit recycles the freelist when the Ractor is destroyed, preventing a memory leak from occurring. Notes: Merged: https://github.com/ruby/ruby/pull/4613
2021-07-15[Bug #18014] Fix rb_gc_force_recycle unmark before sweepPeter Zhu
If we force recycle an object before the page is swept, we should clear it in the mark bitmap. If we don't clear it in the bitmap, then during sweeping we won't account for this free slot so the `free_slots` count of the page will be incorrect. Notes: Merged: https://github.com/ruby/ruby/pull/4613
2021-07-10Get rid of conflict in ccan/listNobuyoshi Nakada
Undefine LIST_HEAD from BSD-origin sys/queue.h.
2021-07-07gc.c: use each_stack_location for emscriptenYusuke Endoh
follow up of e4e416380d4b1b36ca1cc2e1e1ed993c9be694bb
2021-06-30Use stride passed into os_obj_of_iPeter Zhu
Notes: Merged: https://github.com/ruby/ruby/pull/4614
2021-06-29Fix crash on RGENGC_CHECK_MODE=4Peter Zhu
When running btest there is a crash when compiled with RGENGC_CHECK_MODE=4. The crash happens because `during_gc` is not turned off before `gc_marks_check` is called, causing the marking to happen on the main mark stack instead of mark stack created in `objspace_allrefs`. Notes: Merged: https://github.com/ruby/ruby/pull/4610
2021-06-22Fix asan error when walking heap for T_PAYLOAD objectseileencodes
Related to https://bugs.ruby-lang.org/issues/18001 Co-authored-by: Aaron Patterson <tenderlove@ruby-lang.org> Notes: Merged: https://github.com/ruby/ruby/pull/4597
2021-06-18Add a cache for class variableseileencodes
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> Notes: Merged: https://github.com/ruby/ruby/pull/4544
2021-06-17Refactor heap_set_incrementPeter Zhu
heap_set_increment essentially only calls heap_allocatable_pages_set. They only differ in behaviour when `additional_pages == 0`. However, this is only possible because heap_extend_pages may return 0. This commit also changes heap_extend_pages to always return at least 1. Notes: Merged: https://github.com/ruby/ruby/pull/4580
2021-06-17Adjust styles [ci skip]Nobuyoshi Nakada
* --braces-after-func-def-line * --dont-cuddle-else * --procnames-start-lines * --space-after-for * --space-after-if * --space-after-while
2021-06-13Added parentheses to silence sizeof-array-div warningsNobuyoshi Nakada
As well as 2366c681166a1dab95de6b9ca8ffcaae18aadd39.
2021-06-13Removed duplicate includeNobuyoshi Nakada
2021-06-10Finish GC before calling gc_set_initial_pagesPeter Zhu
If we are during incremental sweeping when calling gc_set_initial_pages there is an assertion error. The following patch will artificially produce the bug: ``` diff --git a/gc.c b/gc.c index c3157dbe2c..d7282cf8f0 100644 --- a/gc.c +++ b/gc.c @@ -404,7 +404,7 @@ int ruby_rgengc_debug; * 5: show all references */ #ifndef RGENGC_CHECK_MODE -#define RGENGC_CHECK_MODE 0 +#define RGENGC_CHECK_MODE 1 #endif // Note: using RUBY_ASSERT_WHEN() extend a macro in expr (info by nobu). @@ -10821,6 +10821,10 @@ gc_set_initial_pages(void) void ruby_gc_set_params(void) { + for (int i = 0; i < 10000; i++) { + rb_ary_new(); + } + /* RUBY_GC_HEAP_FREE_SLOTS */ if (get_envparam_size("RUBY_GC_HEAP_FREE_SLOTS", &gc_params.heap_free_slots, 0)) { /* ok */ ``` The crash looks like: ``` Assertion Failed: ../gc.c:2038:heap_add_page:!(heap == heap_eden && heap->sweeping_page) ``` Notes: Merged: https://github.com/ruby/ruby/pull/4562
2021-06-09Refactor gc_marks_start_heap to only configure heapPeter Zhu
Move the non-heap related configurations to gc_marks_start. Notes: Merged: https://github.com/ruby/ruby/pull/4560
2021-06-08Add multi-heap support to gc_marks_wb_unprotected_objectsPeter Zhu
Notes: Merged: https://github.com/ruby/ruby/pull/4559
2021-06-03Support an arbitrary number of header bits (< BITS_BITLENGTH)Aaron Patterson
NUM_IN_PAGE(page->start) will sometimes return a 0 or a 1 depending on how the alignment of the 40 byte slots work out. This commit uses the NUM_IN_PAGE function to shift the bitmap down on the first bitmap plane. Iterating on the first bitmap plane is "special", but this commit allows us to align object addresses on something besides 40 bytes, and also eliminates the need to fill guard bits.
2021-06-02use a bool instead of intAaron Patterson
2021-06-02Allocate exact space for objspace_each_objectsPeter Zhu
We are only iterating over the eden heap so `heap_eden->total_pages` contains the exact number of pages we need to allocate for. `heap_allocated_pages` may contain pages in the tomb. Notes: Merged: https://github.com/ruby/ruby/pull/4547
2021-06-01Use the current object as the compaction indexAaron Patterson
Instead of keeping track of the current bit plane, keep track of the actual slot when compacting. This means we don't need to re-scan objects inside the same bit plane when we continue with movement
2021-05-26Fill out switch statement in push_mark_stackAaron Patterson
When objects are popped from the mark stack, we check that the object is the right type (otherwise an rb_bug happens). The problem is that when we pop a bad object from the stack, we have no idea what pushed the bad object on the stack. This change makes an error happen when a bad object is pushed on the mark stack, that way we can track down the source of the bug. Notes: Merged: https://github.com/ruby/ruby/pull/4531
2021-05-25Disable compaction on platforms that can't support itAaron Patterson
Manual compaction also requires a read barrier, so we need to disable even manual compaction on platforms that don't support mprotect. [Bug #17871] Notes: Merged: https://github.com/ruby/ruby/pull/4528
2021-05-18Revert any references that are on the machine stack after compactingAaron Patterson
Since compaction can be concurrent, the machine stack is allowed to change while compaction is happening. When compaction finishes, there may be references on the machine stack that need to be reverted so that we can remove the read barrier. Notes: Merged: https://github.com/ruby/ruby/pull/4510
2021-05-16PAGE_SIZE is never used on msys/mingwNobuyoshi Nakada
2021-05-14Refix PAGE_SIZENobuyoshi Nakada
* honor actually used headers * include sys/user.h only when `PAGE_SIZE` is not defined
2021-05-14Make USE_MMAP_ALIGNED_ALLOC static constNobuyoshi Nakada
2021-05-13skip rb_bug for inconsistent zombies countKoichi Sasada
It seems a bug but it takes more time to debug. To stop CI failures, skip this rb_bug on `RGENGC_CHECK_MODE=2` temporarily.