Граф коммитов

2325 Коммитов

Автор SHA1 Сообщение Дата
HParker c74dc8b4af Use reference counting to avoid memory leak in kwargs
Tracks other callinfo that references the same kwargs and frees them when all references are cleared.

[bug #19906]

Co-authored-by: Peter Zhu <peter@peterzhu.ca>
2023-10-01 10:55:19 -04:00
Nobuyoshi Nakada ac244938e8 Dump backtraces to an arbitrary stream 2023-09-25 22:57:28 +09:00
Peter Zhu f43dac0df2 Add rb_hash_free for the GC to use 2023-09-24 09:07:52 -04:00
Adam Hess 8b236e0c66 [Bug #19896]
fix memory leak in vm_method

This introduces a unified reference_count to clarify who is referencing a method.
This also allows us to treat the refinement method as the def owner since it counts itself as a reference

Co-authored-by: Peter Zhu <peter@peterzhu.ca>
2023-09-22 09:44:58 -04:00
Matt Valentine-House ec37636ab3 Only sort the heap on platforms with compaction 2023-09-18 14:34:38 +01:00
Matt Valentine-House 8792e421ce Allow pages to be sorted by pinned slot count
By compacting into slots with pinned objects first, we improve the
efficiency of compaction. As it is less likely that there will exist
pages containing only pinned objects after compaction. This will
increase the number of free pages left after compaction and enable us to
free them.

This used to be the default compaction method before it was removed
(inadvertently?) during the introduction of auto_compaction.

This commit will sort the pages by the pinned slot count at the start of
a major GC that has been triggered by explicitly calling GC.compact (and
thus setting objspace->flags.during_compaction).

It works using the same method by which we sort the heap by empty slot
count during GC.verify_compaction_references.
2023-09-18 14:34:38 +01:00
Matt Valentine-House 404a1c032a Move heap sorting into the main GC loop
Previously it was only being sorted during the verify compaction
references stage - so would only happen during testing.

This commit allows us to sort the heap prior to each explicit GC.compact
run
2023-09-18 14:34:38 +01:00
Matt Valentine-House d3852f71e4 Enable different heap sort methods during compaction
pass the sorting function in as a function pointer so we don't always
sort by how empty a page is
2023-09-18 14:34:38 +01:00
Peter Zhu 4aac7b1a9a Another try to fix build in emscripten
malloc_trim is defined in emscripten/emmalloc.h on emscripten.
2023-09-16 13:24:41 -04:00
Peter Zhu 209d5f8482 Fix malloc_trim on emscripten
```
gc.c:9746:5: error: implicit declaration of function 'malloc_trim' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
    malloc_trim(0);
    ^
```

http://rubyci.s3.amazonaws.com/crossruby/crossruby-master-wasm32_emscripten/log/20230916T104311Z.fail.html.gz
2023-09-16 09:08:55 -04:00
Jean Boussier c3ef7a528b Fix malloc_trim() on wasm32
```
compiling gc.c
gc.c:9746:5: error: implicit declaration of function 'malloc_trim' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
    malloc_trim(0);
    ^
1 error generated.
```
2023-09-16 09:52:46 +02:00
Adam Hess 4d86d932fd Free all heap pages at shutdown
previously heap_allocated_pages was decremented from heap_page_free causing only half the heap pages to be freed at shutdown
2023-09-15 13:24:32 -04:00
Jean Boussier efe2822708 Process.warmup: invoke `malloc_trim` if available
Similar to releasing free GC pages, releasing free malloc pages
reduce the amount of page faults post fork.
2023-09-15 17:45:21 +02:00
Peter Zhu b90272b3b6 Fix typo in gc.c 2023-09-12 11:20:22 -04:00
John Hawthorn 094f336a27 GC: Only force alloc slowpath for NEWOBJ hook
Previously, configuring any GC event hook would cause all allocations to
go through the newobj slowpath. We should only need to do that when the
newobj specifically is subscribed to.

This renames flags.has_hook to flags.has_newobj_hook, to make this new
usage clear. newobj_of0 was the only place which previously checked this
flag.
2023-09-07 13:51:56 -07:00
Peter Zhu 12102d101a Fix crash in WeakMap during compaction
WeakMap can crash during compaction because the st_insert could allocate
memory.
2023-09-06 14:20:23 -04:00
Peter Zhu 6778d2c582 Support freeing the lowest memory address page
This should help fix the following flaky test:

```
  1) Failure:
TestProcess#test_warmup_frees_pages [test/ruby/test_process.rb:2751]:
<0> expected but was
<1>.
```
2023-09-06 08:43:14 -04:00
Peter Zhu 9a8398a18f Introduce rb_gc_remove_weak
If we're during incremental marking, then Ruby code can execute that
deallocates certain memory buffers that have been called with
rb_gc_mark_weak, which can cause use-after-free bugs.
2023-09-05 14:32:15 -04:00
Peter Zhu ab9d1910ef Rename shady to uncollectible_wb_unprotected
The term "shady object" was renamed to "uncollectible write barrier
unprotected object", so rename `has_uncollectible_shady_objects` to
`has_uncollectible_wb_unprotected_objects` for consistency.
2023-09-05 10:55:23 -04:00
Peter Zhu 7a930cf0e4 Pool more slots for large size pools
We always sweep at least 2048 slots per sweep step, but only pool one
page. For large size pools, 2048 slots is many pages but one page is
very few slots. This commit changes it so that at least 1024 slots are
placed in the pooled pages per sweep step.
2023-09-05 10:52:35 -04:00
Peter Zhu ef65183692 Add check for T_NONE in rb_gc_mark_weak
This commit adds a check for T_NONE in rb_gc_mark_weak, just like
gc_mark_ptr. This will help debugging.
2023-09-05 09:27:11 -04:00
Peter Zhu bead539650 Incrementally mark even if we have free pages
We move all pooled pages to free pages at the start of incremental
marking, so we shouldn't run incremental marking only when we have run
out of free pages. This causes incremental marking to always complete
in a single step.
2023-09-01 11:58:50 -04:00
Peter Zhu 771576f021 Skip weak references to old objects in minor GC
If we are in a minor GC and the object to mark is old, then the old
object should already be marked and cannot be reclaimed in this GC cycle
so we don't need to add it to the weak refences list.
2023-09-01 09:31:59 -04:00
Matt Valentine-House 945945dad4 Remove gc_mark_values
Now that gc_mark_values and rb_gc_mark_values are identical, we should
remove one.
2023-08-31 19:31:18 +01:00
Matt Valentine-House 322548180d Prevent rb_gc_mark_values from pinning objects
This is an internal only function not exposed to the C extension API.
It's only use so far is from rb_vm_mark, where it's used to mark the
values in the vm->trap_list.cmd array.

There shouldn't be any reason why these cannot move.

This commit allows them to move by updating their references during the
reference updating step of compaction.

To do this we've introduced another internal function
rb_gc_update_values as a partner to rb_gc_mark_values.

This allows us to refactor rb_gc_mark_values to not pin
2023-08-31 19:31:18 +01:00
Peter Zhu 4f0d58260a Correctly calculate initial pages
The old algorithm could calculate an undercount for the initial pages
due to two issues:

1. It did not take into account that some heap pages will have one less
   slot due to alignment. It assumed that every heap page would be able
   to be fully filled with slots. Pages that are unaligned with the slot
   size will lose one slot. The new algorithm assumes that every page
   will be unaligned.
2. It performed integer division, which truncates down. This means that
   the number of pages might not actually satisfy the number of slots.

This can cause the heap to grow in `gc_sweep_finish_size_pool` after
allocating all of the allocatable pages because the total number of
slots would be less than the initial configured number of slots.
2023-08-31 09:28:31 -04:00
Peter Zhu 0aa404b957 Change heap init environment variable names
This commit changes RUBY_GC_HEAP_INIT_SIZE_{40,80,160,320,640}_SLOTS to
RUBY_GC_HEAP_{0,1,2,3,4}_INIT_SLOTS. This is easier to use because the
user does not need to determine the slot sizes (which can vary between
32 and 64 bit systems). They now just use the heap names
(`GC.stat_heap.keys`).
2023-08-30 19:37:11 -04:00
Peter Zhu fd0df1f8c6 Fix growth in minor GC when we have initial slots
If initial slots is set, then during a minor GC, if we have allocatable
pages but the heap is mostly full, then we will set `grow_heap` to true
since `total_slots` does not count allocatable pages so it will be less
than `init_slots`. This can cause `allocatable_pages` to grow to much
higher than desired since it will appear that the heap is mostly full.
2023-08-28 18:01:29 -04:00
Peter Zhu 5485680244 Expose RVALUE_OLD_AGE in GC::INTERNAL_CONSTANTS 2023-08-28 18:01:29 -04:00
Peter Zhu b7237e3bbd Free all empty heap pages in Process.warmup
This commit adds `free_empty_pages` which frees all empty heap pages and
moves the number of pages freed to the allocatable pages counter. This
is used in Process.warmup to improve performance because page
invalidation from copy-on-write is slower than allocating a new page.
2023-08-27 09:39:29 -04:00
Peter Zhu 9ea9f99248 [Feature #19785] Deprecate RUBY_GC_HEAP_INIT_SLOTS
This environment variable is replaced by
`RUBY_GC_HEAP_INIT_SIZE_%d_SLOTS`, so it doesn't make sense to keep it.
2023-08-25 21:50:56 -04:00
Peter Zhu 2091bf9493 Expose stats about weak references
[Feature #19783]

This commit adds stats about weak references to `GC.latest_gc_info`.
It adds the following two keys:

- `weak_references_count`: number of weak references registered during
  the last GC.
- `retained_weak_references_count`: number of weak references that
  survived the last GC.
2023-08-25 09:01:21 -04:00
Peter Zhu bfb395c620 Implement weak references in the GC
[Feature #19783]

This commit adds support for weak references in the GC through the
function `rb_gc_mark_weak`. Unlike strong references, weak references
does not mark the object, but rather lets the GC know that an object
refers to another one. If the child object is freed, the pointer from
the parent object is overwritten with `Qundef`.

Co-Authored-By: Jean Boussier <byroot@ruby-lang.org>
2023-08-25 09:01:21 -04:00
eileencodes b92d599eec Fix typo in anonymous class string
If anonymous was shorted it should be `anon` not `annon`. Fixes typo in
APPEND_S for anonymous classes.
2023-08-23 13:09:18 +09:00
Peter Zhu 5db8b9b366 Move total_freed_objects to size pool
This commit moves the `total_freed_objects` statistic to the size pool
which allows for `total_freed_objects` key in `GC.stat_heap`.
2023-08-17 15:53:00 -04:00
Peter Zhu 52506cbf51 Move total_allocated_objects to size pool
This commit moves the `total_allocated_objects` statistic to the size
pool which allows for `total_allocated_objects` key in `GC.stat_heap`.
2023-08-17 15:53:00 -04:00
Takashi Kokubun e210b899dc
Move the PC regardless of the leaf flag (#8232)
Co-authored-by: Alan Wu <alansi.xingwu@shopify.com>
2023-08-16 20:28:33 -07:00
Peter Zhu 0f94e65359 Add stat force_incremental_marking_finish_count
This commit adds key force_incremental_marking_finish_count to
GC.stat_heap. This statistic returns the number of times the size pool
has forced incremental marking to finish due to running out of slots.
2023-08-15 15:18:05 -04:00
Peter Zhu 300bc14589 [DOC] Improve some GC docs 2023-08-15 08:54:27 -04:00
Peter Zhu 74b9c7d207 Remove wrapper functions of RVALUE_REMEMBERED
Functions rgengc_remembered, rgengc_remembered_sweep, and
rgengc_remembersetbits_get are just wrappers of RVALUE_REMEMBERED and
doesn't do much more. We can remove all those and use RVALUE_REMEMBERED
directly instead.
2023-08-08 09:44:13 -04:00
Nobuyoshi Nakada acd27e3ec3
Move `GC_CAN_COMPILE_COMPACTION` definition before used 2023-08-06 18:45:40 +09:00
Peter Zhu 4b45b2764b Don't check stack for moved after compaction
We don't need to check stack for moved objects after compaction because
the mutator cannot run between marking the stack and the end of
compaction. However, the stack may have moved objects leftover from
marking and sweeping phases. This means that their pages will be
invalidated and all objects moved back. We don't need to move these
objects back.

This also fixes the issue on Windows where some compaction tests
sometimes fail due to the page of the object being invalidated.
2023-08-04 09:13:57 -04:00
Peter Zhu c65856d44f Remove unneeded function prototype
Function prototype for gc_mode_transition is not needed as it's not
used before the implementation.
2023-08-03 11:12:07 -04:00
Peter Zhu c01b17f7fc Fix default value of global_init_slots
Not setting a value to global_init_slots causes get_envparam_size to
output a broken default value.
2023-07-31 15:12:20 -04:00
Peter Zhu b98838b65c Store initial slots per size pool
This commit stores the initial slots per size pool, configured with
the environment variables `RUBY_GC_HEAP_INIT_SIZE_%d_SLOTS`. This
ensures that the configured initial slots remains a low bound for the
number of slots in the heap, which can prevent heaps from thrashing in
size.
2023-07-31 11:46:53 -04:00
Koichi Sasada cfd7729ce7 use inline cache for refinements
From Ruby 3.0, refined method invocations are slow because
resolved methods are not cached by inline cache because of
conservertive strategy. However, `using` clears all caches
so that it seems safe to cache resolved method entries.

This patch caches resolved method entries in inline cache
and clear all of inline method caches when `using` is called.

fix [Bug #18572]

```ruby
 # without refinements

class C
  def foo = :C
end

N = 1_000_000

obj = C.new
require 'benchmark'
Benchmark.bm{|x|
  x.report{N.times{
    obj.foo; obj.foo; obj.foo; obj.foo; obj.foo;
    obj.foo; obj.foo; obj.foo; obj.foo; obj.foo;
    obj.foo; obj.foo; obj.foo; obj.foo; obj.foo;
    obj.foo; obj.foo; obj.foo; obj.foo; obj.foo;
  }}
}

_END__
              user     system      total        real
master    0.362859   0.002544   0.365403 (  0.365424)
modified  0.357251   0.000000   0.357251 (  0.357258)
```

```ruby
 # with refinment but without using

class C
  def foo = :C
end

module R
  refine C do
    def foo = :R
  end
end

N = 1_000_000

obj = C.new
require 'benchmark'
Benchmark.bm{|x|
  x.report{N.times{
    obj.foo; obj.foo; obj.foo; obj.foo; obj.foo;
    obj.foo; obj.foo; obj.foo; obj.foo; obj.foo;
    obj.foo; obj.foo; obj.foo; obj.foo; obj.foo;
    obj.foo; obj.foo; obj.foo; obj.foo; obj.foo;
  }}
}
__END__
               user     system      total        real
master     0.957182   0.000000   0.957182 (  0.957212)
modified   0.359228   0.000000   0.359228 (  0.359238)
```

```ruby
 # with using

class C
  def foo = :C
end

module R
  refine C do
    def foo = :R
  end
end

N = 1_000_000

using R

obj = C.new
require 'benchmark'
Benchmark.bm{|x|
  x.report{N.times{
    obj.foo; obj.foo; obj.foo; obj.foo; obj.foo;
    obj.foo; obj.foo; obj.foo; obj.foo; obj.foo;
    obj.foo; obj.foo; obj.foo; obj.foo; obj.foo;
    obj.foo; obj.foo; obj.foo; obj.foo; obj.foo;
  }}
}
2023-07-31 17:13:43 +09:00
Koichi Sasada 36023d5cb7 mark `cc->cme_` if it is for `super`
`vm_search_super_method()` makes orphan CCs (they are not connected
from ccs) and `cc->cme_` can be collected before without marking.
2023-07-31 14:04:31 +09:00
Koichi Sasada 087a2deccf check `cc->*` liveness strictly
to fix SEGV like
http://ci.rvm.jp/results/trunk-repeat20-asserts@ruby-sp2-docker/4664004
```
/tmp/ruby/build/trunk-repeat20-asserts/libruby.so.3.3(sigsegv+0x4f) [0x7fcb0343e7df] /tmp/ruby/src/trunk-repeat20-asserts/signal.c:920
/lib/x86_64-linux-gnu/libc.so.6(0x7fcb02e4d520) [0x7fcb02e4d520]
/tmp/ruby/build/trunk-repeat20-asserts/libruby.so.3.3(RB_SPECIAL_CONST_P+0x13) [0x7fcb03311ea3] /tmp/ruby/src/trunk-repeat20-asserts/include/ruby/internal/special_consts.h:329
/tmp/ruby/build/trunk-repeat20-asserts/libruby.so.3.3(RB_BUILTIN_TYPE) /tmp/ruby/src/trunk-repeat20-asserts/include/ruby/internal/value_type.h:183
/tmp/ruby/build/trunk-repeat20-asserts/libruby.so.3.3(gc_object_moved_p) /tmp/ruby/src/trunk-repeat20-asserts/gc.c:1624
/tmp/ruby/build/trunk-repeat20-asserts/libruby.so.3.3(gc_object_moved_p+0xe) [0x7fcb0331ed16] /tmp/ruby/src/trunk-repeat20-asserts/include/ruby/internal/special_consts.h:329
/tmp/ruby/build/trunk-repeat20-asserts/libruby.so.3.3(gc_ref_update_imemo) /tmp/ruby/src/trunk-repeat20-asserts/gc.c:10132
/tmp/ruby/build/trunk-repeat20-asserts/libruby.so.3.3(gc_update_object_references) /tmp/ruby/src/trunk-repeat20-asserts/gc.c:10411
/tmp/ruby/build/trunk-repeat20-asserts/libruby.so.3.3(gc_ref_update+0xab) [0x7fcb0331fcbb] /tmp/ruby/src/trunk-repeat20-asserts/gc.c:10570
/tmp/ruby/build/trunk-repeat20-asserts/libruby.so.3.3(gc_update_references) /tmp/ruby/src/trunk-repeat20-asserts/gc.c:10604
/tmp/ruby/build/trunk-repeat20-asserts/libruby.so.3.3(gc_compact_finish) /tmp/ruby/src/trunk-repeat20-asserts/gc.c:5425
/tmp/ruby/build/trunk-repeat20-asserts/libruby.so.3.3(gc_sweep_compact) /tmp/ruby/src/trunk-repeat20-asserts/gc.c:8476
/tmp/ruby/build/trunk-repeat20-asserts/libruby.so.3.3(gc_sweep) /tmp/ruby/src/trunk-repeat20-asserts/gc.c:6040
/tmp/ruby/build/trunk-repeat20-asserts/libruby.so.3.3(gc_start+0xe25) [0x7fcb03325795] /tmp/ruby/src/trunk-repeat20-asserts/gc.c:9323
/tmp/ruby/build/trunk-repeat20-asserts/libruby.so.3.3(rb_multi_ractor_p+0x0) [0x7fcb03326108] /tmp/ruby/src/trunk-repeat20-asserts/gc.c:9208
/tmp/ruby/build/trunk-repeat20-asserts/libruby.so.3.3(rb_vm_lock_leave) /tmp/ruby/src/trunk-repeat20-asserts/vm_sync.h:92
/tmp/ruby/build/trunk-repeat20-asserts/libruby.so.3.3(garbage_collect) /tmp/ruby/src/trunk-repeat20-asserts/gc.c:9210
/tmp/ruby/build/trunk-repeat20-asserts/libruby.so.3.3(rbimpl_atomic_exchange+0x0) [0x7fcb033262b9] /tmp/ruby/src/trunk-repeat20-asserts/gc.c:9646
/tmp/ruby/build/trunk-repeat20-asserts/libruby.so.3.3(gc_finalize_deferred) /tmp/ruby/src/trunk-repeat20-asserts/gc.c:4345
/tmp/ruby/build/trunk-repeat20-asserts/libruby.so.3.3(gc_start_internal) /tmp/ruby/src/trunk-repeat20-asserts/gc.c:9647
/tmp/ruby/build/trunk-repeat20-asserts/libruby.so.3.3(gc_compact) /tmp/ruby/src/trunk-repeat20-asserts/gc.c:10748
```
2023-07-30 08:11:53 +09:00
Koichi Sasada 7a7aba755d check liveness of cc->klass and cc->cme_
`cc->klass` and `cc->cme_` can be free'ed while last marking
so that it should be checked bofore updating the pointers.

Note that `T_MOVED` is living, but `is_live_object()` returns false.
2023-07-29 14:25:15 +09:00
ko1 6dc15cc889 do not clear cme but invalidate cc
To invalidate a cc, we need to clear cc->klass by `vm_cc_invalidate()`.
I hope this patch fix the CI failures.
2023-07-29 09:06:14 +09:00