summaryrefslogtreecommitdiff
path: root/gc.c
AgeCommit message (Collapse)Author
2020-06-29get_envparam_double: 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-29gc_marks_finish: 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-22Convert RMoved to a doubly linked listAaron Patterson
This commit converts RMoved slots to a doubly linked list. I want to convert this to a doubly linked list because the read barrier (currently in development) must remove nodes from the moved list sometimes. Removing nodes from the list is much easier if the list is doubly linked. In addition, we can reuse the list manipulation routines. Notes: Merged: https://github.com/ruby/ruby/pull/3249
2020-06-16Check argument to ObjectSpace._id2refNobuyoshi Nakada
Ensure that the argument is an Integer or implicitly convert to, before dereferencing as a Bignum. Addressed a regression in b99833baec2. Reported by u75615 at https://hackerone.com/reports/898614
2020-06-11Adjusted indents [ci skip]Nobuyoshi Nakada
2020-06-10Fix ASan crashPeter Zhu
Notes: Merged: https://github.com/ruby/ruby/pull/3205
2020-06-09Revert "Combine sweeping and moving"Aaron Patterson
This reverts commit 02b216e5a70235f42f537e895d6f1afd05d8916a. This reverts commit 9b8825b6f94696c9659f93f5da9bf02644625f67. I found that combining sweep and move is not safe. I don't think that we can do compaction concurrently with _anything_ unless there is a read barrier installed. Here is a simple example. A class object is freed, and during it's free step, it tries to remove itself from its parent's subclass list. However, during the sweep step, the parent class was moved and the "currently being freed" class didn't have references updated yet. So we get a segv like this: ``` (lldb) bt * thread #1, name = 'ruby', stop reason = signal SIGSEGV * frame #0: 0x0000560763e344cb ruby`rb_st_lookup at st.c:320:43 frame #1: 0x0000560763e344cb ruby`rb_st_lookup(tab=0x2f7469672f6e6f72, key=3809, value=0x0000560765bf2270) at st.c:1010 frame #2: 0x0000560763e8f16a ruby`rb_search_class_path at variable.c:99:9 frame #3: 0x0000560763e8f141 ruby`rb_search_class_path at variable.c:145 frame #4: 0x0000560763e8f141 ruby`rb_search_class_path(klass=94589785585880) at variable.c:191 frame #5: 0x0000560763ec744e ruby`rb_vm_bugreport at vm_dump.c:996:17 frame #6: 0x0000560763f5b958 ruby`rb_bug_for_fatal_signal at error.c:675:5 frame #7: 0x0000560763e27dad ruby`sigsegv(sig=<unavailable>, info=<unavailable>, ctx=<unavailable>) at signal.c:955:5 frame #8: 0x00007f8b891d33c0 libpthread.so.0`___lldb_unnamed_symbol1$$libpthread.so.0 + 1 frame #9: 0x0000560763efa8bb ruby`rb_class_remove_from_super_subclasses(klass=94589790314280) at class.c:93:56 frame #10: 0x0000560763d10cb7 ruby`gc_sweep_step at gc.c:2674:2 frame #11: 0x0000560763d1187b ruby`gc_sweep at gc.c:4540:2 frame #12: 0x0000560763d101f0 ruby`gc_start at gc.c:6797:6 frame #13: 0x0000560763d15153 ruby`rb_gc_compact at gc.c:7479:12 frame #14: 0x0000560763eb4eb8 ruby`vm_exec_core at vm_insnhelper.c:5183:13 frame #15: 0x0000560763ea9bae ruby`rb_vm_exec at vm.c:1953:22 frame #16: 0x0000560763eac08d ruby`rb_yield at vm.c:1132:9 frame #17: 0x0000560763edb4f2 ruby`rb_ary_collect at array.c:3186:9 frame #18: 0x0000560763e9ee15 ruby`vm_call_cfunc_with_frame at vm_insnhelper.c:2575:12 frame #19: 0x0000560763eb2e66 ruby`vm_exec_core at vm_insnhelper.c:4177:11 frame #20: 0x0000560763ea9bae ruby`rb_vm_exec at vm.c:1953:22 frame #21: 0x0000560763eac08d ruby`rb_yield at vm.c:1132:9 frame #22: 0x0000560763edb4f2 ruby`rb_ary_collect at array.c:3186:9 frame #23: 0x0000560763e9ee15 ruby`vm_call_cfunc_with_frame at vm_insnhelper.c:2575:12 frame #24: 0x0000560763eb2e66 ruby`vm_exec_core at vm_insnhelper.c:4177:11 frame #25: 0x0000560763ea9bae ruby`rb_vm_exec at vm.c:1953:22 frame #26: 0x0000560763ceee01 ruby`rb_ec_exec_node(ec=0x0000560765afa530, n=0x0000560765b088e0) at eval.c:296:2 frame #27: 0x0000560763cf3b7b ruby`ruby_run_node(n=0x0000560765b088e0) at eval.c:354:12 frame #28: 0x0000560763cee4a3 ruby`main(argc=<unavailable>, argv=<unavailable>) at main.c:50:9 frame #29: 0x00007f8b88e560b3 libc.so.6`__libc_start_main + 243 frame #30: 0x0000560763cee4ee ruby`_start + 46 (lldb) f 9 frame #9: 0x0000560763efa8bb ruby`rb_class_remove_from_super_subclasses(klass=94589790314280) at class.c:93:56 90 91 *RCLASS_EXT(klass)->parent_subclasses = entry->next; 92 if (entry->next) { -> 93 RCLASS_EXT(entry->next->klass)->parent_subclasses = RCLASS_EXT(klass)->parent_subclasses; 94 } 95 xfree(entry); 96 } (lldb) command script import -r misc/lldb_cruby.py lldb scripts for ruby has been installed. (lldb) rp entry->next->klass (struct RMoved) $1 = (flags = 30, destination = 94589792806680, next = 94589784369160) (lldb) ```
2020-06-09Freeing cc tables doesn't need access to IDAaron Patterson
We don't need to resolve symbols when freeing cc tables, so this commit just changes the id table iterator to look at values rather than keys and values.
2020-06-08fix debugging outputAaron Patterson
2020-05-29Combine sweeping and movingAaron Patterson
This commit combines the sweep step with moving objects. With this commit, we can do: ```ruby GC.start(compact: true) ``` This code will do the following 3 steps: 1. Fully mark the heap 2. Sweep + Move objects 3. Update references By default, this will compact in order that heap pages are allocated. In other words, objects will be packed towards older heap pages (as opposed to heap pages with more pinned objects like `GC.compact` does).
2020-05-28Extract "free moved list" functionAaron Patterson
Extract a function to free the moved list. We'll use this function later on to compact at the same time as sweep.
2020-05-22Fix origin iclass pointer for modulesJeremy Evans
If a module has an origin, and that module is included in another module or class, previously the iclass created for the module had an origin pointer to the module's origin instead of the iclass's origin. Setting the origin pointer correctly requires using a stack, since the origin iclass is not created until after the iclass itself. Use a hidden ruby array to implement that stack. Correctly assigning the origin pointers in the iclass caused a use-after-free in GC. If a module with an origin is included in a class, the iclass shares a method table with the module and the iclass origin shares a method table with module origin. Mark iclass origin with a flag that notes that even though the iclass is an origin, it shares a method table, so the method table should not be garbage collected. The shared method table will be garbage collected when the module origin is garbage collected. I've tested that this does not introduce a memory leak. This change caused a VM assertion failure, which was traced to callable method entries using the incorrect defined_class. Update rb_vm_check_redefinition_opt_method and find_defined_class_by_owner to treat iclass origins different than class origins to avoid this issue. This also includes a fix for Module#included_modules to skip iclasses with origins. Fixes [Bug #16736] Notes: Merged: https://github.com/ruby/ruby/pull/3136
2020-05-22Revert "Fix origin iclass pointer for modules"Jeremy Evans
This reverts commit c745a60634260ba2080d35af6fdeaaae86fe5193. This triggers a VM assertion. Reverting until the issue can be debugged.
2020-05-22Fix origin iclass pointer for modulesJeremy Evans
If a module has an origin, and that module is included in another module or class, previously the iclass created for the module had an origin pointer to the module's origin instead of the iclass's origin. Setting the origin pointer correctly requires using a stack, since the origin iclass is not created until after the iclass itself. Use a hidden ruby array to implement that stack. Correctly assigning the origin pointers in the iclass caused a use-after-free in GC. If a module with an origin is included in a class, the iclass shares a method table with the module and the iclass origin shares a method table with module origin. Mark iclass origin with a flag that notes that even though the iclass is an origin, it shares a method table, so the method table should not be garbage collected. The shared method table will be garbage collected when the module origin is garbage collected. I've tested that this does not introduce a memory leak. This also includes a fix for Module#included_modules to skip iclasses with origins. Fixes [Bug #16736] Notes: Merged: https://github.com/ruby/ruby/pull/2978
2020-05-20Only marked objects should be considered movableAaron Patterson
Ruby's GC is incremental, meaning that during the mark phase (and also the sweep phase) programs are allowed to run. This means that programs can allocate objects before the mark or sweep phase have actually completed. Those objects may not have had a chance to be marked, so we can't know if they are movable or not. Something that references the newly created object might have called the pinning function during the mark phase, but since the mark phase hasn't run we can't know if there is a "pinning" relationship. To be conservative, we must only allow objects that are not pinned but also marked to move.
2020-05-18Allow references stored in the VM stack to moveAaron Patterson
We can update these references too, so lets allow them to move.
2020-05-11more on NULL versus functions卜部昌平
Function pointers are not void*. See also 115fec062ccf7c6d72c8d5f64b7a5d84c9fb2dd8 ce4ea956d24eab5089a143bba38126f2b11b55b6 8427fca49bd85205f5a8766292dd893f003c0e48
2020-05-11sed -i 's|ruby/impl|ruby/internal|'卜部昌平
To fix build failures. Notes: Merged: https://github.com/ruby/ruby/pull/3079
2020-05-11sed -i s/ruby3/rbimpl/g卜部昌平
Notes: Merged: https://github.com/ruby/ruby/pull/3079
2020-05-11sed -i s/RUBY3/RBIMPL/g卜部昌平
Devs do not love "3". The only exception is RUBY3_KEYWORDS in parse.y, which seems unrelated to our interests. Notes: Merged: https://github.com/ruby/ruby/pull/3079
2020-05-11sed -i s|ruby/3|ruby/impl|g卜部昌平
This shall fix compile errors. Notes: Merged: https://github.com/ruby/ruby/pull/3079
2020-05-11Added more NORETURN declarationsNobuyoshi Nakada
2020-05-07Allow global variables to moveAaron Patterson
This patch allows global variables that have been assigned in Ruby to move. I added a new function for the GC to call that will update global references and introduced a new callback in the global variable struct for updating references. Only pure Ruby global variables are supported right now, other references will be pinned.
2020-05-07`T_MOVED` should never be pushed on the mark stackAaron Patterson
No objects should ever reference a `T_MOVED` slot. If they do, it's absolutely a bug. If we kill the process when `T_MOVED` is pushed on the mark stack it will make it easier to identify which object holds a reference that hasn't been updated.
2020-05-04Output compaction stats in one loop / eliminate 0 countsAaron Patterson
We only need to loop `T_MASK` times once. Also, not every value between 0 and `T_MASK` is an actual Ruby type. Before this change, some integers were being added to the result hash even though they aren't actual types. This patch omits considered / moved entries that total 0, cleaning up the result hash and eliminating these "fake types".
2020-05-02Rename arguments for ObjectSpace::WeakMap#[]= for clarityBenoit Daloze
2020-05-02Fix ObjectSpace::WeakMap#key? to work if the value is nilBenoit Daloze
* Fixes [Bug #16826]
2020-04-29Mark ruby_memerror as NORETURNNobuyoshi Nakada
2020-04-29Remove debugging code from gc.cYusuke Endoh
Partially revert adab82b9a71f60ad1c7f4f8c134a5ae9198ab32a and c63b5c6179d700ceacf5cae8d3ee86da1294c781. The issue that these commits attempt to address was maybe fixed with 1c7f5a57125001447dc6173847dc68aa50bd8e93.
2020-04-27Fix a typo [ci skip]Kazuhiro NISHIYAMA
2020-04-25Assert that typed data is distinguished from non-typedNobuyoshi Nakada
Notes: Merged: https://github.com/ruby/ruby/pull/3058
2020-04-21rb_memerror: abort immediately卜部昌平
Ditto for adab82b9a71f60ad1c7f4f8c134a5ae9198ab32a. TRY_WITH_GC was found innocent.
2020-04-21Fixed a typo [ci skip]Nobuyoshi Nakada
2020-04-21TRY_WITH_GC: abort immediately卜部昌平
NoMemoryError is observed on icc but I fail to reproduce so far. Let me see the backtrace on CI.
2020-04-16Moved noreturn call to end of noreturn functionNobuyoshi Nakada
2020-04-08Suppress -Wswitch warningsNobuyoshi Nakada
2020-04-08Merge pull request #2991 from shyouhei/ruby.h卜部昌平
Split ruby.h Notes: Merged-By: shyouhei <shyouhei@ruby-lang.org>
2020-04-03Bail out before pushing unexpected objectNobuyoshi Nakada
2020-03-11fix type castKoichi Sasada
2020-03-11show method entry with iseq detailsKoichi Sasada
2020-03-04fix compile error w/ -DCALC_EXACT_MALLOC_SIZE卜部昌平
2020-02-26kill USE_RGENGC=0卜部昌平
This compile-time option has been broken for years (at least since commit 49369ef17316cd5d5819b038f286e1d951972b52, according to git bisect). Let's delete codes that no longer works. Notes: Merged: https://github.com/ruby/ruby/pull/2925
2020-02-26avoid #if inside of rb_str_new_cstr卜部昌平
ISO/IEC 9899:1999 section 6.10.3 paragraph 11 explicitly states that "If there are sequences of preprocessing tokens within the list of arguments that would otherwise act as preprocessing directives, the behavior is undefined." rb_str_new_cstr is in fact a macro. We cannot do this. Notes: Merged: https://github.com/ruby/ruby/pull/2925
2020-02-22Introduce disposable call-cache.Koichi Sasada
This patch contains several ideas: (1) Disposable inline method cache (IMC) for race-free inline method cache * Making call-cache (CC) as a RVALUE (GC target object) and allocate new CC on cache miss. * This technique allows race-free access from parallel processing elements like RCU. (2) Introduce per-Class method cache (pCMC) * Instead of fixed-size global method cache (GMC), pCMC allows flexible cache size. * Caching CCs reduces CC allocation and allow sharing CC's fast-path between same call-info (CI) call-sites. (3) Invalidate an inline method cache by invalidating corresponding method entries (MEs) * Instead of using class serials, we set "invalidated" flag for method entry itself to represent cache invalidation. * Compare with using class serials, the impact of method modification (add/overwrite/delete) is small. * Updating class serials invalidate all method caches of the class and sub-classes. * Proposed approach only invalidate the method cache of only one ME. See [Feature #16614] for more details. Notes: Merged: https://github.com/ruby/ruby/pull/2888
2020-02-22VALUE size packed callinfo (ci).Koichi Sasada
Now, rb_call_info contains how to call the method with tuple of (mid, orig_argc, flags, kwarg). Most of cases, kwarg == NULL and mid+argc+flags only requires 64bits. So this patch packed rb_call_info to VALUE (1 word) on such cases. If we can not represent it in VALUE, then use imemo_callinfo which contains conventional callinfo (rb_callinfo, renamed from rb_call_info). iseq->body->ci_kw_size is removed because all of callinfo is VALUE size (packed ci or a pointer to imemo_callinfo). To access ci information, we need to use these functions: vm_ci_mid(ci), _flag(ci), _argc(ci), _kwarg(ci). struct rb_call_info_kw_arg is renamed to rb_callinfo_kwarg. rb_funcallv_with_cc() and rb_method_basic_definition_p_with_cc() is temporary removed because cd->ci should be marked. Notes: Merged: https://github.com/ruby/ruby/pull/2888
2020-02-20TestTime#test_memsize: skip when on GC_DEBUG卜部昌平
GC_DEBUG=1 makes this test fail because it changes the size of struct RVALUE. I don't think the test is useful then. Let's just skip.
2020-02-10Revert "gc.c: make the stack overflow detection earlier under s390x"Yusuke Endoh
This reverts commit a28c166f787710227c6aac54befd72778f041485. This change didn't help. According to odaira, the issue was fixed by increasing `ulimit -s`.
2020-02-09Disable GC until VM objects get initialized [Bug #16616]Nobuyoshi Nakada
2020-02-09Separate objspace argument for rb_gc_disable and rb_gc_enableNobuyoshi Nakada
2020-02-09gc.c: make the stack overflow detection earlier under s390xYusuke Endoh
On s390x, TestFiber#test_stack_size fails with SEGV. https://rubyci.org/logs/rubyci.s3.amazonaws.com/rhel_zlinux/ruby-master/log/20200205T223421Z.fail.html.gz ``` TestFiber#test_stack_size [/home/chkbuild/build/20200205T223421Z/ruby/test/ruby/test_fiber.rb:356]: pid 23844 killed by SIGABRT (signal 6) (core dumped) | -e:1:in `times': stack level too deep (SystemStackError) | from -e:1:in `rec' | from -e:1:in `block (3 levels) in rec' | from -e:1:in `times' | from -e:1:in `block (2 levels) in rec' | from -e:1:in `times' | from -e:1:in `block in rec' | from -e:1:in `times' | from -e:1:in `rec' | ... 172 levels... | from -e:1:in `block in rec' | from -e:1:in `times' | from -e:1:in `rec' | from -e:1:in `block in <main>' | -e: [BUG] Segmentation fault at 0x0000000000000000 ``` This change tries a similar fix with ef64ab917eec02491f6bf7233a4031a8c35385e3 and 3ddbba84b5b1f001cd575a48cec56d7ce8e5fbb2.