diff --git a/.github/workflows/zjit-macos.yml b/.github/workflows/zjit-macos.yml index f82baa081ab6cc..82cef518c3ea51 100644 --- a/.github/workflows/zjit-macos.yml +++ b/.github/workflows/zjit-macos.yml @@ -98,7 +98,7 @@ jobs: rustup install ${{ matrix.rust_version }} --profile minimal rustup default ${{ matrix.rust_version }} - - uses: taiki-e/install-action@4684b8405694ae9dd42c9f39ba901a70ae83f4a3 # v2.82.9 + - uses: taiki-e/install-action@50414676f9f5d50a65992c6dd2ed02641263226c # v2.82.10 with: tool: nextest@0.9 if: ${{ matrix.test_task == 'zjit-check' }} diff --git a/.github/workflows/zjit-ubuntu.yml b/.github/workflows/zjit-ubuntu.yml index 396397052e0758..81aa9dd4beaca7 100644 --- a/.github/workflows/zjit-ubuntu.yml +++ b/.github/workflows/zjit-ubuntu.yml @@ -141,7 +141,7 @@ jobs: ruby-version: '3.1' bundler: none - - uses: taiki-e/install-action@4684b8405694ae9dd42c9f39ba901a70ae83f4a3 # v2.82.9 + - uses: taiki-e/install-action@50414676f9f5d50a65992c6dd2ed02641263226c # v2.82.10 with: tool: nextest@0.9 if: ${{ matrix.test_task == 'zjit-check' }} diff --git a/array.c b/array.c index 6514015de21628..26ff60fb79738c 100644 --- a/array.c +++ b/array.c @@ -902,7 +902,7 @@ init_fake_ary_flags(void) struct RArray fake_ary = {0}; fake_ary.basic.flags = T_ARRAY; VALUE ary = (VALUE)&fake_ary; - RBASIC_SET_SHAPE_ID(ary, ROOT_SHAPE_ID | SHAPE_ID_LAYOUT_OTHER); + RBASIC_SET_FULL_SHAPE_ID(ary, ROOT_SHAPE_ID | SHAPE_ID_LAYOUT_OTHER); rb_ary_freeze(ary); return fake_ary.basic.flags; } diff --git a/common.mk b/common.mk index 07ece19ee98373..e7908cc0e54567 100644 --- a/common.mk +++ b/common.mk @@ -698,7 +698,7 @@ clean-local:: clean-runnable -$(Q)$(RMALL) dump_ast$(BUILD_EXEEXT)* -$(Q)$(RMALL) target -$(Q) $(RMDIR) enc/jis enc/trans enc $(COROUTINE_H:/Context.h=) coroutine target \ - $(PRISM_BUILD_DIR)/*/ $(PRISM_BUILD_DIR) tmp \ + $(PRISM_BUILD_DIR)/*/ $(PRISM_BUILD_DIR) gc/default gc tmp \ 2> $(NULL) || $(NULLCMD) bin/clean-runnable:: PHONY diff --git a/depend b/depend index 66264ed2dfaa28..b375948348d28a 100644 --- a/depend +++ b/depend @@ -3002,7 +3002,6 @@ debug_counter.$(OBJEXT): {$(VPATH)}internal/variable.h debug_counter.$(OBJEXT): {$(VPATH)}internal/warning_push.h debug_counter.$(OBJEXT): {$(VPATH)}internal/xmalloc.h debug_counter.$(OBJEXT): {$(VPATH)}missing.h -debug_counter.$(OBJEXT): {$(VPATH)}onigmo.h debug_counter.$(OBJEXT): {$(VPATH)}st.h debug_counter.$(OBJEXT): {$(VPATH)}subst.h debug_counter.$(OBJEXT): {$(VPATH)}thread_native.h @@ -3386,7 +3385,6 @@ dln.$(OBJEXT): {$(VPATH)}internal/variable.h dln.$(OBJEXT): {$(VPATH)}internal/warning_push.h dln.$(OBJEXT): {$(VPATH)}internal/xmalloc.h dln.$(OBJEXT): {$(VPATH)}missing.h -dln.$(OBJEXT): {$(VPATH)}onigmo.h dln.$(OBJEXT): {$(VPATH)}st.h dln.$(OBJEXT): {$(VPATH)}subst.h dln_find.$(OBJEXT): $(hdrdir)/ruby/ruby.h @@ -3546,7 +3544,6 @@ dln_find.$(OBJEXT): {$(VPATH)}internal/variable.h dln_find.$(OBJEXT): {$(VPATH)}internal/warning_push.h dln_find.$(OBJEXT): {$(VPATH)}internal/xmalloc.h dln_find.$(OBJEXT): {$(VPATH)}missing.h -dln_find.$(OBJEXT): {$(VPATH)}onigmo.h dln_find.$(OBJEXT): {$(VPATH)}st.h dln_find.$(OBJEXT): {$(VPATH)}subst.h dmydln.$(OBJEXT): $(hdrdir)/ruby/ruby.h @@ -3705,7 +3702,6 @@ dmydln.$(OBJEXT): {$(VPATH)}internal/variable.h dmydln.$(OBJEXT): {$(VPATH)}internal/warning_push.h dmydln.$(OBJEXT): {$(VPATH)}internal/xmalloc.h dmydln.$(OBJEXT): {$(VPATH)}missing.h -dmydln.$(OBJEXT): {$(VPATH)}onigmo.h dmydln.$(OBJEXT): {$(VPATH)}st.h dmydln.$(OBJEXT): {$(VPATH)}subst.h dmyenc.$(OBJEXT): {$(VPATH)}dmyenc.c @@ -5936,6 +5932,7 @@ gc.$(OBJEXT): $(hdrdir)/ruby.h gc.$(OBJEXT): $(hdrdir)/ruby/ruby.h gc.$(OBJEXT): $(hdrdir)/ruby/version.h gc.$(OBJEXT): $(top_srcdir)/gc/default/default.c +gc.$(OBJEXT): $(top_srcdir)/gc/default/zjit_fastpath.h gc.$(OBJEXT): $(top_srcdir)/gc/gc.h gc.$(OBJEXT): $(top_srcdir)/gc/gc_impl.h gc.$(OBJEXT): $(top_srcdir)/internal/array.h @@ -7107,7 +7104,6 @@ inits.$(OBJEXT): {$(VPATH)}internal/variable.h inits.$(OBJEXT): {$(VPATH)}internal/warning_push.h inits.$(OBJEXT): {$(VPATH)}internal/xmalloc.h inits.$(OBJEXT): {$(VPATH)}missing.h -inits.$(OBJEXT): {$(VPATH)}onigmo.h inits.$(OBJEXT): {$(VPATH)}prelude.rbinc inits.$(OBJEXT): {$(VPATH)}st.h inits.$(OBJEXT): {$(VPATH)}subst.h @@ -8524,7 +8520,6 @@ loadpath.$(OBJEXT): {$(VPATH)}internal/warning_push.h loadpath.$(OBJEXT): {$(VPATH)}internal/xmalloc.h loadpath.$(OBJEXT): {$(VPATH)}loadpath.c loadpath.$(OBJEXT): {$(VPATH)}missing.h -loadpath.$(OBJEXT): {$(VPATH)}onigmo.h loadpath.$(OBJEXT): {$(VPATH)}st.h loadpath.$(OBJEXT): {$(VPATH)}subst.h loadpath.$(OBJEXT): {$(VPATH)}verconf.h @@ -8862,7 +8857,6 @@ main.$(OBJEXT): {$(VPATH)}internal/warning_push.h main.$(OBJEXT): {$(VPATH)}internal/xmalloc.h main.$(OBJEXT): {$(VPATH)}main.c main.$(OBJEXT): {$(VPATH)}missing.h -main.$(OBJEXT): {$(VPATH)}onigmo.h main.$(OBJEXT): {$(VPATH)}st.h main.$(OBJEXT): {$(VPATH)}subst.h main.$(OBJEXT): {$(VPATH)}vm_debug.h @@ -9269,7 +9263,6 @@ math.$(OBJEXT): {$(VPATH)}internal/warning_push.h math.$(OBJEXT): {$(VPATH)}internal/xmalloc.h math.$(OBJEXT): {$(VPATH)}math.c math.$(OBJEXT): {$(VPATH)}missing.h -math.$(OBJEXT): {$(VPATH)}onigmo.h math.$(OBJEXT): {$(VPATH)}shape.h math.$(OBJEXT): {$(VPATH)}st.h math.$(OBJEXT): {$(VPATH)}subst.h @@ -16660,7 +16653,6 @@ setproctitle.$(OBJEXT): {$(VPATH)}internal/variable.h setproctitle.$(OBJEXT): {$(VPATH)}internal/warning_push.h setproctitle.$(OBJEXT): {$(VPATH)}internal/xmalloc.h setproctitle.$(OBJEXT): {$(VPATH)}missing.h -setproctitle.$(OBJEXT): {$(VPATH)}onigmo.h setproctitle.$(OBJEXT): {$(VPATH)}setproctitle.c setproctitle.$(OBJEXT): {$(VPATH)}st.h setproctitle.$(OBJEXT): {$(VPATH)}subst.h @@ -18650,6 +18642,8 @@ thread.$(OBJEXT): {$(VPATH)}onigmo.h thread.$(OBJEXT): {$(VPATH)}oniguruma.h thread.$(OBJEXT): {$(VPATH)}prism_compile.h thread.$(OBJEXT): {$(VPATH)}prism_xallocator.h +thread.$(OBJEXT): {$(VPATH)}probes.dmyh +thread.$(OBJEXT): {$(VPATH)}probes.h thread.$(OBJEXT): {$(VPATH)}ractor.h thread.$(OBJEXT): {$(VPATH)}ractor_core.h thread.$(OBJEXT): {$(VPATH)}ruby_assert.h @@ -19272,7 +19266,6 @@ util.$(OBJEXT): {$(VPATH)}internal/variable.h util.$(OBJEXT): {$(VPATH)}internal/warning_push.h util.$(OBJEXT): {$(VPATH)}internal/xmalloc.h util.$(OBJEXT): {$(VPATH)}missing.h -util.$(OBJEXT): {$(VPATH)}onigmo.h util.$(OBJEXT): {$(VPATH)}ruby_atomic.h util.$(OBJEXT): {$(VPATH)}st.h util.$(OBJEXT): {$(VPATH)}subst.h @@ -20719,6 +20712,8 @@ vm_sync.$(OBJEXT): {$(VPATH)}missing.h vm_sync.$(OBJEXT): {$(VPATH)}node.h vm_sync.$(OBJEXT): {$(VPATH)}onigmo.h vm_sync.$(OBJEXT): {$(VPATH)}oniguruma.h +vm_sync.$(OBJEXT): {$(VPATH)}probes.dmyh +vm_sync.$(OBJEXT): {$(VPATH)}probes.h vm_sync.$(OBJEXT): {$(VPATH)}ractor.h vm_sync.$(OBJEXT): {$(VPATH)}ractor_core.h vm_sync.$(OBJEXT): {$(VPATH)}ruby_assert.h @@ -21717,6 +21712,8 @@ zjit.$(OBJEXT): {$(VPATH)}prism_xallocator.h zjit.$(OBJEXT): {$(VPATH)}probes.dmyh zjit.$(OBJEXT): {$(VPATH)}probes.h zjit.$(OBJEXT): {$(VPATH)}probes_helper.h +zjit.$(OBJEXT): {$(VPATH)}ractor.h +zjit.$(OBJEXT): {$(VPATH)}ractor_core.h zjit.$(OBJEXT): {$(VPATH)}ruby_assert.h zjit.$(OBJEXT): {$(VPATH)}ruby_atomic.h zjit.$(OBJEXT): {$(VPATH)}rubyparser.h diff --git a/enc/depend b/enc/depend index c1a73bc4a2f843..4bf97dc880f195 100644 --- a/enc/depend +++ b/enc/depend @@ -5243,7 +5243,6 @@ enc/trans/big5.$(OBJEXT): internal/variable.h enc/trans/big5.$(OBJEXT): internal/warning_push.h enc/trans/big5.$(OBJEXT): internal/xmalloc.h enc/trans/big5.$(OBJEXT): missing.h -enc/trans/big5.$(OBJEXT): onigmo.h enc/trans/big5.$(OBJEXT): st.h enc/trans/big5.$(OBJEXT): subst.h enc/trans/cesu_8.$(OBJEXT): $(hdrdir)/ruby/ruby.h @@ -5404,7 +5403,6 @@ enc/trans/cesu_8.$(OBJEXT): internal/variable.h enc/trans/cesu_8.$(OBJEXT): internal/warning_push.h enc/trans/cesu_8.$(OBJEXT): internal/xmalloc.h enc/trans/cesu_8.$(OBJEXT): missing.h -enc/trans/cesu_8.$(OBJEXT): onigmo.h enc/trans/cesu_8.$(OBJEXT): st.h enc/trans/cesu_8.$(OBJEXT): subst.h enc/trans/chinese.$(OBJEXT): $(hdrdir)/ruby/ruby.h @@ -5565,7 +5563,6 @@ enc/trans/chinese.$(OBJEXT): internal/variable.h enc/trans/chinese.$(OBJEXT): internal/warning_push.h enc/trans/chinese.$(OBJEXT): internal/xmalloc.h enc/trans/chinese.$(OBJEXT): missing.h -enc/trans/chinese.$(OBJEXT): onigmo.h enc/trans/chinese.$(OBJEXT): st.h enc/trans/chinese.$(OBJEXT): subst.h enc/trans/ebcdic.$(OBJEXT): $(hdrdir)/ruby/ruby.h @@ -5726,7 +5723,6 @@ enc/trans/ebcdic.$(OBJEXT): internal/variable.h enc/trans/ebcdic.$(OBJEXT): internal/warning_push.h enc/trans/ebcdic.$(OBJEXT): internal/xmalloc.h enc/trans/ebcdic.$(OBJEXT): missing.h -enc/trans/ebcdic.$(OBJEXT): onigmo.h enc/trans/ebcdic.$(OBJEXT): st.h enc/trans/ebcdic.$(OBJEXT): subst.h enc/trans/emoji.$(OBJEXT): $(hdrdir)/ruby/ruby.h @@ -5887,7 +5883,6 @@ enc/trans/emoji.$(OBJEXT): internal/variable.h enc/trans/emoji.$(OBJEXT): internal/warning_push.h enc/trans/emoji.$(OBJEXT): internal/xmalloc.h enc/trans/emoji.$(OBJEXT): missing.h -enc/trans/emoji.$(OBJEXT): onigmo.h enc/trans/emoji.$(OBJEXT): st.h enc/trans/emoji.$(OBJEXT): subst.h enc/trans/emoji_iso2022_kddi.$(OBJEXT): $(hdrdir)/ruby/ruby.h @@ -6048,7 +6043,6 @@ enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/variable.h enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/warning_push.h enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/xmalloc.h enc/trans/emoji_iso2022_kddi.$(OBJEXT): missing.h -enc/trans/emoji_iso2022_kddi.$(OBJEXT): onigmo.h enc/trans/emoji_iso2022_kddi.$(OBJEXT): st.h enc/trans/emoji_iso2022_kddi.$(OBJEXT): subst.h enc/trans/emoji_sjis_docomo.$(OBJEXT): $(hdrdir)/ruby/ruby.h @@ -6209,7 +6203,6 @@ enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/variable.h enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/warning_push.h enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/xmalloc.h enc/trans/emoji_sjis_docomo.$(OBJEXT): missing.h -enc/trans/emoji_sjis_docomo.$(OBJEXT): onigmo.h enc/trans/emoji_sjis_docomo.$(OBJEXT): st.h enc/trans/emoji_sjis_docomo.$(OBJEXT): subst.h enc/trans/emoji_sjis_kddi.$(OBJEXT): $(hdrdir)/ruby/ruby.h @@ -6370,7 +6363,6 @@ enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/variable.h enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/warning_push.h enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/xmalloc.h enc/trans/emoji_sjis_kddi.$(OBJEXT): missing.h -enc/trans/emoji_sjis_kddi.$(OBJEXT): onigmo.h enc/trans/emoji_sjis_kddi.$(OBJEXT): st.h enc/trans/emoji_sjis_kddi.$(OBJEXT): subst.h enc/trans/emoji_sjis_softbank.$(OBJEXT): $(hdrdir)/ruby/ruby.h @@ -6531,7 +6523,6 @@ enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/variable.h enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/warning_push.h enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/xmalloc.h enc/trans/emoji_sjis_softbank.$(OBJEXT): missing.h -enc/trans/emoji_sjis_softbank.$(OBJEXT): onigmo.h enc/trans/emoji_sjis_softbank.$(OBJEXT): st.h enc/trans/emoji_sjis_softbank.$(OBJEXT): subst.h enc/trans/escape.$(OBJEXT): $(hdrdir)/ruby/ruby.h @@ -6692,7 +6683,6 @@ enc/trans/escape.$(OBJEXT): internal/variable.h enc/trans/escape.$(OBJEXT): internal/warning_push.h enc/trans/escape.$(OBJEXT): internal/xmalloc.h enc/trans/escape.$(OBJEXT): missing.h -enc/trans/escape.$(OBJEXT): onigmo.h enc/trans/escape.$(OBJEXT): st.h enc/trans/escape.$(OBJEXT): subst.h enc/trans/gb18030.$(OBJEXT): $(hdrdir)/ruby/ruby.h @@ -6853,7 +6843,6 @@ enc/trans/gb18030.$(OBJEXT): internal/variable.h enc/trans/gb18030.$(OBJEXT): internal/warning_push.h enc/trans/gb18030.$(OBJEXT): internal/xmalloc.h enc/trans/gb18030.$(OBJEXT): missing.h -enc/trans/gb18030.$(OBJEXT): onigmo.h enc/trans/gb18030.$(OBJEXT): st.h enc/trans/gb18030.$(OBJEXT): subst.h enc/trans/gbk.$(OBJEXT): $(hdrdir)/ruby/ruby.h @@ -7014,7 +7003,6 @@ enc/trans/gbk.$(OBJEXT): internal/variable.h enc/trans/gbk.$(OBJEXT): internal/warning_push.h enc/trans/gbk.$(OBJEXT): internal/xmalloc.h enc/trans/gbk.$(OBJEXT): missing.h -enc/trans/gbk.$(OBJEXT): onigmo.h enc/trans/gbk.$(OBJEXT): st.h enc/trans/gbk.$(OBJEXT): subst.h enc/trans/iso2022.$(OBJEXT): $(hdrdir)/ruby/ruby.h @@ -7176,7 +7164,6 @@ enc/trans/iso2022.$(OBJEXT): internal/variable.h enc/trans/iso2022.$(OBJEXT): internal/warning_push.h enc/trans/iso2022.$(OBJEXT): internal/xmalloc.h enc/trans/iso2022.$(OBJEXT): missing.h -enc/trans/iso2022.$(OBJEXT): onigmo.h enc/trans/iso2022.$(OBJEXT): st.h enc/trans/iso2022.$(OBJEXT): subst.h enc/trans/japanese.$(OBJEXT): $(hdrdir)/ruby/ruby.h @@ -7337,7 +7324,6 @@ enc/trans/japanese.$(OBJEXT): internal/variable.h enc/trans/japanese.$(OBJEXT): internal/warning_push.h enc/trans/japanese.$(OBJEXT): internal/xmalloc.h enc/trans/japanese.$(OBJEXT): missing.h -enc/trans/japanese.$(OBJEXT): onigmo.h enc/trans/japanese.$(OBJEXT): st.h enc/trans/japanese.$(OBJEXT): subst.h enc/trans/japanese_euc.$(OBJEXT): $(hdrdir)/ruby/ruby.h @@ -7498,7 +7484,6 @@ enc/trans/japanese_euc.$(OBJEXT): internal/variable.h enc/trans/japanese_euc.$(OBJEXT): internal/warning_push.h enc/trans/japanese_euc.$(OBJEXT): internal/xmalloc.h enc/trans/japanese_euc.$(OBJEXT): missing.h -enc/trans/japanese_euc.$(OBJEXT): onigmo.h enc/trans/japanese_euc.$(OBJEXT): st.h enc/trans/japanese_euc.$(OBJEXT): subst.h enc/trans/japanese_sjis.$(OBJEXT): $(hdrdir)/ruby/ruby.h @@ -7659,7 +7644,6 @@ enc/trans/japanese_sjis.$(OBJEXT): internal/variable.h enc/trans/japanese_sjis.$(OBJEXT): internal/warning_push.h enc/trans/japanese_sjis.$(OBJEXT): internal/xmalloc.h enc/trans/japanese_sjis.$(OBJEXT): missing.h -enc/trans/japanese_sjis.$(OBJEXT): onigmo.h enc/trans/japanese_sjis.$(OBJEXT): st.h enc/trans/japanese_sjis.$(OBJEXT): subst.h enc/trans/korean.$(OBJEXT): $(hdrdir)/ruby/ruby.h @@ -7820,7 +7804,6 @@ enc/trans/korean.$(OBJEXT): internal/variable.h enc/trans/korean.$(OBJEXT): internal/warning_push.h enc/trans/korean.$(OBJEXT): internal/xmalloc.h enc/trans/korean.$(OBJEXT): missing.h -enc/trans/korean.$(OBJEXT): onigmo.h enc/trans/korean.$(OBJEXT): st.h enc/trans/korean.$(OBJEXT): subst.h enc/trans/newline.$(OBJEXT): $(hdrdir)/ruby/ruby.h @@ -7980,7 +7963,6 @@ enc/trans/newline.$(OBJEXT): internal/variable.h enc/trans/newline.$(OBJEXT): internal/warning_push.h enc/trans/newline.$(OBJEXT): internal/xmalloc.h enc/trans/newline.$(OBJEXT): missing.h -enc/trans/newline.$(OBJEXT): onigmo.h enc/trans/newline.$(OBJEXT): st.h enc/trans/newline.$(OBJEXT): subst.h enc/trans/single_byte.$(OBJEXT): $(hdrdir)/ruby/ruby.h @@ -8141,7 +8123,6 @@ enc/trans/single_byte.$(OBJEXT): internal/variable.h enc/trans/single_byte.$(OBJEXT): internal/warning_push.h enc/trans/single_byte.$(OBJEXT): internal/xmalloc.h enc/trans/single_byte.$(OBJEXT): missing.h -enc/trans/single_byte.$(OBJEXT): onigmo.h enc/trans/single_byte.$(OBJEXT): st.h enc/trans/single_byte.$(OBJEXT): subst.h enc/trans/transdb.$(OBJEXT): $(hdrdir)/ruby.h @@ -8302,7 +8283,6 @@ enc/trans/transdb.$(OBJEXT): internal/variable.h enc/trans/transdb.$(OBJEXT): internal/warning_push.h enc/trans/transdb.$(OBJEXT): internal/xmalloc.h enc/trans/transdb.$(OBJEXT): missing.h -enc/trans/transdb.$(OBJEXT): onigmo.h enc/trans/transdb.$(OBJEXT): st.h enc/trans/transdb.$(OBJEXT): subst.h enc/trans/transdb.$(OBJEXT): transdb.h @@ -8464,7 +8444,6 @@ enc/trans/utf8_mac.$(OBJEXT): internal/variable.h enc/trans/utf8_mac.$(OBJEXT): internal/warning_push.h enc/trans/utf8_mac.$(OBJEXT): internal/xmalloc.h enc/trans/utf8_mac.$(OBJEXT): missing.h -enc/trans/utf8_mac.$(OBJEXT): onigmo.h enc/trans/utf8_mac.$(OBJEXT): st.h enc/trans/utf8_mac.$(OBJEXT): subst.h enc/trans/utf_16_32.$(OBJEXT): $(hdrdir)/ruby/ruby.h @@ -8625,7 +8604,6 @@ enc/trans/utf_16_32.$(OBJEXT): internal/variable.h enc/trans/utf_16_32.$(OBJEXT): internal/warning_push.h enc/trans/utf_16_32.$(OBJEXT): internal/xmalloc.h enc/trans/utf_16_32.$(OBJEXT): missing.h -enc/trans/utf_16_32.$(OBJEXT): onigmo.h enc/trans/utf_16_32.$(OBJEXT): st.h enc/trans/utf_16_32.$(OBJEXT): subst.h enc/unicode.$(OBJEXT): $(UNICODE_HDR_DIR)/casefold.h diff --git a/ext/-test-/RUBY_ALIGNOF/depend b/ext/-test-/RUBY_ALIGNOF/depend index 4fc0e775dcad74..103d20b33c8de5 100644 --- a/ext/-test-/RUBY_ALIGNOF/depend +++ b/ext/-test-/RUBY_ALIGNOF/depend @@ -156,7 +156,6 @@ c.o: $(hdrdir)/ruby/internal/variable.h c.o: $(hdrdir)/ruby/internal/warning_push.h c.o: $(hdrdir)/ruby/internal/xmalloc.h c.o: $(hdrdir)/ruby/missing.h -c.o: $(hdrdir)/ruby/onigmo.h c.o: $(hdrdir)/ruby/ruby.h c.o: $(hdrdir)/ruby/st.h c.o: $(hdrdir)/ruby/subst.h diff --git a/ext/-test-/arith_seq/beg_len_step/depend b/ext/-test-/arith_seq/beg_len_step/depend index e84aada9e065c3..098c8ff1f0f0fb 100644 --- a/ext/-test-/arith_seq/beg_len_step/depend +++ b/ext/-test-/arith_seq/beg_len_step/depend @@ -155,7 +155,6 @@ beg_len_step.o: $(hdrdir)/ruby/internal/variable.h beg_len_step.o: $(hdrdir)/ruby/internal/warning_push.h beg_len_step.o: $(hdrdir)/ruby/internal/xmalloc.h beg_len_step.o: $(hdrdir)/ruby/missing.h -beg_len_step.o: $(hdrdir)/ruby/onigmo.h beg_len_step.o: $(hdrdir)/ruby/ruby.h beg_len_step.o: $(hdrdir)/ruby/st.h beg_len_step.o: $(hdrdir)/ruby/subst.h diff --git a/ext/-test-/arith_seq/extract/depend b/ext/-test-/arith_seq/extract/depend index 69d2fa9ddd7c9f..5c07cea4b4b1dd 100644 --- a/ext/-test-/arith_seq/extract/depend +++ b/ext/-test-/arith_seq/extract/depend @@ -155,7 +155,6 @@ extract.o: $(hdrdir)/ruby/internal/variable.h extract.o: $(hdrdir)/ruby/internal/warning_push.h extract.o: $(hdrdir)/ruby/internal/xmalloc.h extract.o: $(hdrdir)/ruby/missing.h -extract.o: $(hdrdir)/ruby/onigmo.h extract.o: $(hdrdir)/ruby/ruby.h extract.o: $(hdrdir)/ruby/st.h extract.o: $(hdrdir)/ruby/subst.h diff --git a/ext/-test-/array/concat/depend b/ext/-test-/array/concat/depend index 7fa8248d4dd93d..8edf45465f707d 100644 --- a/ext/-test-/array/concat/depend +++ b/ext/-test-/array/concat/depend @@ -156,7 +156,6 @@ to_ary_concat.o: $(hdrdir)/ruby/internal/variable.h to_ary_concat.o: $(hdrdir)/ruby/internal/warning_push.h to_ary_concat.o: $(hdrdir)/ruby/internal/xmalloc.h to_ary_concat.o: $(hdrdir)/ruby/missing.h -to_ary_concat.o: $(hdrdir)/ruby/onigmo.h to_ary_concat.o: $(hdrdir)/ruby/ruby.h to_ary_concat.o: $(hdrdir)/ruby/st.h to_ary_concat.o: $(hdrdir)/ruby/subst.h diff --git a/ext/-test-/array/resize/depend b/ext/-test-/array/resize/depend index d2ef9bcee43f11..e6a228b43d779c 100644 --- a/ext/-test-/array/resize/depend +++ b/ext/-test-/array/resize/depend @@ -155,7 +155,6 @@ resize.o: $(hdrdir)/ruby/internal/variable.h resize.o: $(hdrdir)/ruby/internal/warning_push.h resize.o: $(hdrdir)/ruby/internal/xmalloc.h resize.o: $(hdrdir)/ruby/missing.h -resize.o: $(hdrdir)/ruby/onigmo.h resize.o: $(hdrdir)/ruby/ruby.h resize.o: $(hdrdir)/ruby/st.h resize.o: $(hdrdir)/ruby/subst.h diff --git a/ext/-test-/bignum/depend b/ext/-test-/bignum/depend index 81c80d73a8c6af..82972f10327311 100644 --- a/ext/-test-/bignum/depend +++ b/ext/-test-/bignum/depend @@ -156,7 +156,6 @@ big2str.o: $(hdrdir)/ruby/internal/variable.h big2str.o: $(hdrdir)/ruby/internal/warning_push.h big2str.o: $(hdrdir)/ruby/internal/xmalloc.h big2str.o: $(hdrdir)/ruby/missing.h -big2str.o: $(hdrdir)/ruby/onigmo.h big2str.o: $(hdrdir)/ruby/ruby.h big2str.o: $(hdrdir)/ruby/st.h big2str.o: $(hdrdir)/ruby/subst.h @@ -320,7 +319,6 @@ bigzero.o: $(hdrdir)/ruby/internal/variable.h bigzero.o: $(hdrdir)/ruby/internal/warning_push.h bigzero.o: $(hdrdir)/ruby/internal/xmalloc.h bigzero.o: $(hdrdir)/ruby/missing.h -bigzero.o: $(hdrdir)/ruby/onigmo.h bigzero.o: $(hdrdir)/ruby/ruby.h bigzero.o: $(hdrdir)/ruby/st.h bigzero.o: $(hdrdir)/ruby/subst.h @@ -484,7 +482,6 @@ div.o: $(hdrdir)/ruby/internal/variable.h div.o: $(hdrdir)/ruby/internal/warning_push.h div.o: $(hdrdir)/ruby/internal/xmalloc.h div.o: $(hdrdir)/ruby/missing.h -div.o: $(hdrdir)/ruby/onigmo.h div.o: $(hdrdir)/ruby/ruby.h div.o: $(hdrdir)/ruby/st.h div.o: $(hdrdir)/ruby/subst.h @@ -648,7 +645,6 @@ init.o: $(hdrdir)/ruby/internal/variable.h init.o: $(hdrdir)/ruby/internal/warning_push.h init.o: $(hdrdir)/ruby/internal/xmalloc.h init.o: $(hdrdir)/ruby/missing.h -init.o: $(hdrdir)/ruby/onigmo.h init.o: $(hdrdir)/ruby/ruby.h init.o: $(hdrdir)/ruby/st.h init.o: $(hdrdir)/ruby/subst.h @@ -810,7 +806,6 @@ intpack.o: $(hdrdir)/ruby/internal/variable.h intpack.o: $(hdrdir)/ruby/internal/warning_push.h intpack.o: $(hdrdir)/ruby/internal/xmalloc.h intpack.o: $(hdrdir)/ruby/missing.h -intpack.o: $(hdrdir)/ruby/onigmo.h intpack.o: $(hdrdir)/ruby/ruby.h intpack.o: $(hdrdir)/ruby/st.h intpack.o: $(hdrdir)/ruby/subst.h @@ -974,7 +969,6 @@ mul.o: $(hdrdir)/ruby/internal/variable.h mul.o: $(hdrdir)/ruby/internal/warning_push.h mul.o: $(hdrdir)/ruby/internal/xmalloc.h mul.o: $(hdrdir)/ruby/missing.h -mul.o: $(hdrdir)/ruby/onigmo.h mul.o: $(hdrdir)/ruby/ruby.h mul.o: $(hdrdir)/ruby/st.h mul.o: $(hdrdir)/ruby/subst.h @@ -1138,7 +1132,6 @@ str2big.o: $(hdrdir)/ruby/internal/variable.h str2big.o: $(hdrdir)/ruby/internal/warning_push.h str2big.o: $(hdrdir)/ruby/internal/xmalloc.h str2big.o: $(hdrdir)/ruby/missing.h -str2big.o: $(hdrdir)/ruby/onigmo.h str2big.o: $(hdrdir)/ruby/ruby.h str2big.o: $(hdrdir)/ruby/st.h str2big.o: $(hdrdir)/ruby/subst.h diff --git a/ext/-test-/bug-14834/depend b/ext/-test-/bug-14834/depend index 660de6d5cf5369..f83939d559f63c 100644 --- a/ext/-test-/bug-14834/depend +++ b/ext/-test-/bug-14834/depend @@ -156,7 +156,6 @@ bug-14834.o: $(hdrdir)/ruby/internal/variable.h bug-14834.o: $(hdrdir)/ruby/internal/warning_push.h bug-14834.o: $(hdrdir)/ruby/internal/xmalloc.h bug-14834.o: $(hdrdir)/ruby/missing.h -bug-14834.o: $(hdrdir)/ruby/onigmo.h bug-14834.o: $(hdrdir)/ruby/ruby.h bug-14834.o: $(hdrdir)/ruby/st.h bug-14834.o: $(hdrdir)/ruby/subst.h diff --git a/ext/-test-/bug-3571/depend b/ext/-test-/bug-3571/depend index b1452bdf5ec8dd..69c970b6f25703 100644 --- a/ext/-test-/bug-3571/depend +++ b/ext/-test-/bug-3571/depend @@ -156,7 +156,6 @@ bug.o: $(hdrdir)/ruby/internal/variable.h bug.o: $(hdrdir)/ruby/internal/warning_push.h bug.o: $(hdrdir)/ruby/internal/xmalloc.h bug.o: $(hdrdir)/ruby/missing.h -bug.o: $(hdrdir)/ruby/onigmo.h bug.o: $(hdrdir)/ruby/ruby.h bug.o: $(hdrdir)/ruby/st.h bug.o: $(hdrdir)/ruby/subst.h diff --git a/ext/-test-/bug-5832/depend b/ext/-test-/bug-5832/depend index b1452bdf5ec8dd..69c970b6f25703 100644 --- a/ext/-test-/bug-5832/depend +++ b/ext/-test-/bug-5832/depend @@ -156,7 +156,6 @@ bug.o: $(hdrdir)/ruby/internal/variable.h bug.o: $(hdrdir)/ruby/internal/warning_push.h bug.o: $(hdrdir)/ruby/internal/xmalloc.h bug.o: $(hdrdir)/ruby/missing.h -bug.o: $(hdrdir)/ruby/onigmo.h bug.o: $(hdrdir)/ruby/ruby.h bug.o: $(hdrdir)/ruby/st.h bug.o: $(hdrdir)/ruby/subst.h diff --git a/ext/-test-/bug_reporter/depend b/ext/-test-/bug_reporter/depend index 14275ab9820c07..e9993c3295505e 100644 --- a/ext/-test-/bug_reporter/depend +++ b/ext/-test-/bug_reporter/depend @@ -156,7 +156,6 @@ bug_reporter.o: $(hdrdir)/ruby/internal/variable.h bug_reporter.o: $(hdrdir)/ruby/internal/warning_push.h bug_reporter.o: $(hdrdir)/ruby/internal/xmalloc.h bug_reporter.o: $(hdrdir)/ruby/missing.h -bug_reporter.o: $(hdrdir)/ruby/onigmo.h bug_reporter.o: $(hdrdir)/ruby/ruby.h bug_reporter.o: $(hdrdir)/ruby/st.h bug_reporter.o: $(hdrdir)/ruby/subst.h diff --git a/ext/-test-/class/depend b/ext/-test-/class/depend index 91204b36b89fd0..557206cefb41f4 100644 --- a/ext/-test-/class/depend +++ b/ext/-test-/class/depend @@ -155,7 +155,6 @@ class2name.o: $(hdrdir)/ruby/internal/variable.h class2name.o: $(hdrdir)/ruby/internal/warning_push.h class2name.o: $(hdrdir)/ruby/internal/xmalloc.h class2name.o: $(hdrdir)/ruby/missing.h -class2name.o: $(hdrdir)/ruby/onigmo.h class2name.o: $(hdrdir)/ruby/ruby.h class2name.o: $(hdrdir)/ruby/st.h class2name.o: $(hdrdir)/ruby/subst.h @@ -317,7 +316,6 @@ init.o: $(hdrdir)/ruby/internal/variable.h init.o: $(hdrdir)/ruby/internal/warning_push.h init.o: $(hdrdir)/ruby/internal/xmalloc.h init.o: $(hdrdir)/ruby/missing.h -init.o: $(hdrdir)/ruby/onigmo.h init.o: $(hdrdir)/ruby/ruby.h init.o: $(hdrdir)/ruby/st.h init.o: $(hdrdir)/ruby/subst.h diff --git a/ext/-test-/debug/depend b/ext/-test-/debug/depend index f9d50e25140357..4ae0378ef2072d 100644 --- a/ext/-test-/debug/depend +++ b/ext/-test-/debug/depend @@ -156,7 +156,6 @@ init.o: $(hdrdir)/ruby/internal/variable.h init.o: $(hdrdir)/ruby/internal/warning_push.h init.o: $(hdrdir)/ruby/internal/xmalloc.h init.o: $(hdrdir)/ruby/missing.h -init.o: $(hdrdir)/ruby/onigmo.h init.o: $(hdrdir)/ruby/ruby.h init.o: $(hdrdir)/ruby/st.h init.o: $(hdrdir)/ruby/subst.h @@ -318,7 +317,6 @@ inspector.o: $(hdrdir)/ruby/internal/variable.h inspector.o: $(hdrdir)/ruby/internal/warning_push.h inspector.o: $(hdrdir)/ruby/internal/xmalloc.h inspector.o: $(hdrdir)/ruby/missing.h -inspector.o: $(hdrdir)/ruby/onigmo.h inspector.o: $(hdrdir)/ruby/ruby.h inspector.o: $(hdrdir)/ruby/st.h inspector.o: $(hdrdir)/ruby/subst.h @@ -480,7 +478,6 @@ profile_frames.o: $(hdrdir)/ruby/internal/variable.h profile_frames.o: $(hdrdir)/ruby/internal/warning_push.h profile_frames.o: $(hdrdir)/ruby/internal/xmalloc.h profile_frames.o: $(hdrdir)/ruby/missing.h -profile_frames.o: $(hdrdir)/ruby/onigmo.h profile_frames.o: $(hdrdir)/ruby/ruby.h profile_frames.o: $(hdrdir)/ruby/st.h profile_frames.o: $(hdrdir)/ruby/subst.h diff --git a/ext/-test-/dln/empty/depend b/ext/-test-/dln/empty/depend index 2e20de2d4ce906..58f15085983101 100644 --- a/ext/-test-/dln/empty/depend +++ b/ext/-test-/dln/empty/depend @@ -156,7 +156,6 @@ empty.o: $(hdrdir)/ruby/internal/variable.h empty.o: $(hdrdir)/ruby/internal/warning_push.h empty.o: $(hdrdir)/ruby/internal/xmalloc.h empty.o: $(hdrdir)/ruby/missing.h -empty.o: $(hdrdir)/ruby/onigmo.h empty.o: $(hdrdir)/ruby/ruby.h empty.o: $(hdrdir)/ruby/st.h empty.o: $(hdrdir)/ruby/subst.h diff --git a/ext/-test-/econv/depend b/ext/-test-/econv/depend index 02d7ee451f85a0..3a5bc9c6590a1b 100644 --- a/ext/-test-/econv/depend +++ b/ext/-test-/econv/depend @@ -329,7 +329,6 @@ init.o: $(hdrdir)/ruby/internal/variable.h init.o: $(hdrdir)/ruby/internal/warning_push.h init.o: $(hdrdir)/ruby/internal/xmalloc.h init.o: $(hdrdir)/ruby/missing.h -init.o: $(hdrdir)/ruby/onigmo.h init.o: $(hdrdir)/ruby/ruby.h init.o: $(hdrdir)/ruby/st.h init.o: $(hdrdir)/ruby/subst.h diff --git a/ext/-test-/ensure_and_callcc/depend b/ext/-test-/ensure_and_callcc/depend index ddf2e0e300e384..54431847a687bf 100644 --- a/ext/-test-/ensure_and_callcc/depend +++ b/ext/-test-/ensure_and_callcc/depend @@ -156,7 +156,6 @@ ensure_and_callcc.o: $(hdrdir)/ruby/internal/variable.h ensure_and_callcc.o: $(hdrdir)/ruby/internal/warning_push.h ensure_and_callcc.o: $(hdrdir)/ruby/internal/xmalloc.h ensure_and_callcc.o: $(hdrdir)/ruby/missing.h -ensure_and_callcc.o: $(hdrdir)/ruby/onigmo.h ensure_and_callcc.o: $(hdrdir)/ruby/ruby.h ensure_and_callcc.o: $(hdrdir)/ruby/st.h ensure_and_callcc.o: $(hdrdir)/ruby/subst.h diff --git a/ext/-test-/enumerator_kw/depend b/ext/-test-/enumerator_kw/depend index e70dbb47792381..b6d2f0a9989788 100644 --- a/ext/-test-/enumerator_kw/depend +++ b/ext/-test-/enumerator_kw/depend @@ -156,7 +156,6 @@ enumerator_kw.o: $(hdrdir)/ruby/internal/variable.h enumerator_kw.o: $(hdrdir)/ruby/internal/warning_push.h enumerator_kw.o: $(hdrdir)/ruby/internal/xmalloc.h enumerator_kw.o: $(hdrdir)/ruby/missing.h -enumerator_kw.o: $(hdrdir)/ruby/onigmo.h enumerator_kw.o: $(hdrdir)/ruby/ruby.h enumerator_kw.o: $(hdrdir)/ruby/st.h enumerator_kw.o: $(hdrdir)/ruby/subst.h diff --git a/ext/-test-/eval/depend b/ext/-test-/eval/depend index 672ce96f2e8e03..03a1c7d7ef9bee 100644 --- a/ext/-test-/eval/depend +++ b/ext/-test-/eval/depend @@ -155,7 +155,6 @@ eval.o: $(hdrdir)/ruby/internal/variable.h eval.o: $(hdrdir)/ruby/internal/warning_push.h eval.o: $(hdrdir)/ruby/internal/xmalloc.h eval.o: $(hdrdir)/ruby/missing.h -eval.o: $(hdrdir)/ruby/onigmo.h eval.o: $(hdrdir)/ruby/ruby.h eval.o: $(hdrdir)/ruby/st.h eval.o: $(hdrdir)/ruby/subst.h diff --git a/ext/-test-/exception/depend b/ext/-test-/exception/depend index 9a7fc1b73bd5d9..690e5ad3776231 100644 --- a/ext/-test-/exception/depend +++ b/ext/-test-/exception/depend @@ -155,7 +155,6 @@ dataerror.o: $(hdrdir)/ruby/internal/variable.h dataerror.o: $(hdrdir)/ruby/internal/warning_push.h dataerror.o: $(hdrdir)/ruby/internal/xmalloc.h dataerror.o: $(hdrdir)/ruby/missing.h -dataerror.o: $(hdrdir)/ruby/onigmo.h dataerror.o: $(hdrdir)/ruby/ruby.h dataerror.o: $(hdrdir)/ruby/st.h dataerror.o: $(hdrdir)/ruby/subst.h @@ -490,7 +489,6 @@ ensured.o: $(hdrdir)/ruby/internal/variable.h ensured.o: $(hdrdir)/ruby/internal/warning_push.h ensured.o: $(hdrdir)/ruby/internal/xmalloc.h ensured.o: $(hdrdir)/ruby/missing.h -ensured.o: $(hdrdir)/ruby/onigmo.h ensured.o: $(hdrdir)/ruby/ruby.h ensured.o: $(hdrdir)/ruby/st.h ensured.o: $(hdrdir)/ruby/subst.h @@ -652,7 +650,6 @@ init.o: $(hdrdir)/ruby/internal/variable.h init.o: $(hdrdir)/ruby/internal/warning_push.h init.o: $(hdrdir)/ruby/internal/xmalloc.h init.o: $(hdrdir)/ruby/missing.h -init.o: $(hdrdir)/ruby/onigmo.h init.o: $(hdrdir)/ruby/ruby.h init.o: $(hdrdir)/ruby/st.h init.o: $(hdrdir)/ruby/subst.h diff --git a/ext/-test-/fatal/depend b/ext/-test-/fatal/depend index 1b1d32c776f320..306bc9099c2dbd 100644 --- a/ext/-test-/fatal/depend +++ b/ext/-test-/fatal/depend @@ -157,7 +157,6 @@ init.o: $(hdrdir)/ruby/internal/variable.h init.o: $(hdrdir)/ruby/internal/warning_push.h init.o: $(hdrdir)/ruby/internal/xmalloc.h init.o: $(hdrdir)/ruby/missing.h -init.o: $(hdrdir)/ruby/onigmo.h init.o: $(hdrdir)/ruby/ruby.h init.o: $(hdrdir)/ruby/st.h init.o: $(hdrdir)/ruby/subst.h @@ -319,7 +318,6 @@ invalid.o: $(hdrdir)/ruby/internal/variable.h invalid.o: $(hdrdir)/ruby/internal/warning_push.h invalid.o: $(hdrdir)/ruby/internal/xmalloc.h invalid.o: $(hdrdir)/ruby/missing.h -invalid.o: $(hdrdir)/ruby/onigmo.h invalid.o: $(hdrdir)/ruby/ruby.h invalid.o: $(hdrdir)/ruby/st.h invalid.o: $(hdrdir)/ruby/subst.h @@ -481,7 +479,6 @@ rb_fatal.o: $(hdrdir)/ruby/internal/variable.h rb_fatal.o: $(hdrdir)/ruby/internal/warning_push.h rb_fatal.o: $(hdrdir)/ruby/internal/xmalloc.h rb_fatal.o: $(hdrdir)/ruby/missing.h -rb_fatal.o: $(hdrdir)/ruby/onigmo.h rb_fatal.o: $(hdrdir)/ruby/ruby.h rb_fatal.o: $(hdrdir)/ruby/st.h rb_fatal.o: $(hdrdir)/ruby/subst.h diff --git a/ext/-test-/file/depend b/ext/-test-/file/depend index f28f52b2d58248..fe320f3d44a98f 100644 --- a/ext/-test-/file/depend +++ b/ext/-test-/file/depend @@ -329,7 +329,6 @@ init.o: $(hdrdir)/ruby/internal/variable.h init.o: $(hdrdir)/ruby/internal/warning_push.h init.o: $(hdrdir)/ruby/internal/xmalloc.h init.o: $(hdrdir)/ruby/missing.h -init.o: $(hdrdir)/ruby/onigmo.h init.o: $(hdrdir)/ruby/ruby.h init.o: $(hdrdir)/ruby/st.h init.o: $(hdrdir)/ruby/subst.h diff --git a/ext/-test-/float/depend b/ext/-test-/float/depend index ba9b88c9cfcf34..334ed33c3b2299 100644 --- a/ext/-test-/float/depend +++ b/ext/-test-/float/depend @@ -159,7 +159,6 @@ init.o: $(hdrdir)/ruby/internal/variable.h init.o: $(hdrdir)/ruby/internal/warning_push.h init.o: $(hdrdir)/ruby/internal/xmalloc.h init.o: $(hdrdir)/ruby/missing.h -init.o: $(hdrdir)/ruby/onigmo.h init.o: $(hdrdir)/ruby/ruby.h init.o: $(hdrdir)/ruby/st.h init.o: $(hdrdir)/ruby/subst.h @@ -321,7 +320,6 @@ nextafter.o: $(hdrdir)/ruby/internal/variable.h nextafter.o: $(hdrdir)/ruby/internal/warning_push.h nextafter.o: $(hdrdir)/ruby/internal/xmalloc.h nextafter.o: $(hdrdir)/ruby/missing.h -nextafter.o: $(hdrdir)/ruby/onigmo.h nextafter.o: $(hdrdir)/ruby/ruby.h nextafter.o: $(hdrdir)/ruby/st.h nextafter.o: $(hdrdir)/ruby/subst.h diff --git a/ext/-test-/funcall/depend b/ext/-test-/funcall/depend index 1cc94db86d1131..e54370306f47ca 100644 --- a/ext/-test-/funcall/depend +++ b/ext/-test-/funcall/depend @@ -156,7 +156,6 @@ funcall.o: $(hdrdir)/ruby/internal/variable.h funcall.o: $(hdrdir)/ruby/internal/warning_push.h funcall.o: $(hdrdir)/ruby/internal/xmalloc.h funcall.o: $(hdrdir)/ruby/missing.h -funcall.o: $(hdrdir)/ruby/onigmo.h funcall.o: $(hdrdir)/ruby/ruby.h funcall.o: $(hdrdir)/ruby/st.h funcall.o: $(hdrdir)/ruby/subst.h diff --git a/ext/-test-/gvl/call_without_gvl/depend b/ext/-test-/gvl/call_without_gvl/depend index 1f5a9da0bce843..236d1e1d3b6148 100644 --- a/ext/-test-/gvl/call_without_gvl/depend +++ b/ext/-test-/gvl/call_without_gvl/depend @@ -155,7 +155,6 @@ call_without_gvl.o: $(hdrdir)/ruby/internal/variable.h call_without_gvl.o: $(hdrdir)/ruby/internal/warning_push.h call_without_gvl.o: $(hdrdir)/ruby/internal/xmalloc.h call_without_gvl.o: $(hdrdir)/ruby/missing.h -call_without_gvl.o: $(hdrdir)/ruby/onigmo.h call_without_gvl.o: $(hdrdir)/ruby/ruby.h call_without_gvl.o: $(hdrdir)/ruby/st.h call_without_gvl.o: $(hdrdir)/ruby/subst.h diff --git a/ext/-test-/hash/depend b/ext/-test-/hash/depend index 8628dd37eacdd6..416b93f9de37b1 100644 --- a/ext/-test-/hash/depend +++ b/ext/-test-/hash/depend @@ -156,7 +156,6 @@ delete.o: $(hdrdir)/ruby/internal/variable.h delete.o: $(hdrdir)/ruby/internal/warning_push.h delete.o: $(hdrdir)/ruby/internal/xmalloc.h delete.o: $(hdrdir)/ruby/missing.h -delete.o: $(hdrdir)/ruby/onigmo.h delete.o: $(hdrdir)/ruby/ruby.h delete.o: $(hdrdir)/ruby/st.h delete.o: $(hdrdir)/ruby/subst.h @@ -318,7 +317,6 @@ init.o: $(hdrdir)/ruby/internal/variable.h init.o: $(hdrdir)/ruby/internal/warning_push.h init.o: $(hdrdir)/ruby/internal/xmalloc.h init.o: $(hdrdir)/ruby/missing.h -init.o: $(hdrdir)/ruby/onigmo.h init.o: $(hdrdir)/ruby/ruby.h init.o: $(hdrdir)/ruby/st.h init.o: $(hdrdir)/ruby/subst.h diff --git a/ext/-test-/integer/depend b/ext/-test-/integer/depend index 648dc31358144d..d0589b5e5dd8a8 100644 --- a/ext/-test-/integer/depend +++ b/ext/-test-/integer/depend @@ -156,7 +156,6 @@ core_ext.o: $(hdrdir)/ruby/internal/variable.h core_ext.o: $(hdrdir)/ruby/internal/warning_push.h core_ext.o: $(hdrdir)/ruby/internal/xmalloc.h core_ext.o: $(hdrdir)/ruby/missing.h -core_ext.o: $(hdrdir)/ruby/onigmo.h core_ext.o: $(hdrdir)/ruby/ruby.h core_ext.o: $(hdrdir)/ruby/st.h core_ext.o: $(hdrdir)/ruby/subst.h @@ -329,7 +328,6 @@ init.o: $(hdrdir)/ruby/internal/variable.h init.o: $(hdrdir)/ruby/internal/warning_push.h init.o: $(hdrdir)/ruby/internal/xmalloc.h init.o: $(hdrdir)/ruby/missing.h -init.o: $(hdrdir)/ruby/onigmo.h init.o: $(hdrdir)/ruby/ruby.h init.o: $(hdrdir)/ruby/st.h init.o: $(hdrdir)/ruby/subst.h @@ -491,7 +489,6 @@ my_integer.o: $(hdrdir)/ruby/internal/variable.h my_integer.o: $(hdrdir)/ruby/internal/warning_push.h my_integer.o: $(hdrdir)/ruby/internal/xmalloc.h my_integer.o: $(hdrdir)/ruby/missing.h -my_integer.o: $(hdrdir)/ruby/onigmo.h my_integer.o: $(hdrdir)/ruby/ruby.h my_integer.o: $(hdrdir)/ruby/st.h my_integer.o: $(hdrdir)/ruby/subst.h diff --git a/ext/-test-/iseq_load/depend b/ext/-test-/iseq_load/depend index df3711943edc5e..9361ddb93844ce 100644 --- a/ext/-test-/iseq_load/depend +++ b/ext/-test-/iseq_load/depend @@ -156,7 +156,6 @@ iseq_load.o: $(hdrdir)/ruby/internal/variable.h iseq_load.o: $(hdrdir)/ruby/internal/warning_push.h iseq_load.o: $(hdrdir)/ruby/internal/xmalloc.h iseq_load.o: $(hdrdir)/ruby/missing.h -iseq_load.o: $(hdrdir)/ruby/onigmo.h iseq_load.o: $(hdrdir)/ruby/ruby.h iseq_load.o: $(hdrdir)/ruby/st.h iseq_load.o: $(hdrdir)/ruby/subst.h diff --git a/ext/-test-/iter/depend b/ext/-test-/iter/depend index 5b49c7b315494c..161947382cd91b 100644 --- a/ext/-test-/iter/depend +++ b/ext/-test-/iter/depend @@ -156,7 +156,6 @@ break.o: $(hdrdir)/ruby/internal/variable.h break.o: $(hdrdir)/ruby/internal/warning_push.h break.o: $(hdrdir)/ruby/internal/xmalloc.h break.o: $(hdrdir)/ruby/missing.h -break.o: $(hdrdir)/ruby/onigmo.h break.o: $(hdrdir)/ruby/ruby.h break.o: $(hdrdir)/ruby/st.h break.o: $(hdrdir)/ruby/subst.h @@ -318,7 +317,6 @@ init.o: $(hdrdir)/ruby/internal/variable.h init.o: $(hdrdir)/ruby/internal/warning_push.h init.o: $(hdrdir)/ruby/internal/xmalloc.h init.o: $(hdrdir)/ruby/missing.h -init.o: $(hdrdir)/ruby/onigmo.h init.o: $(hdrdir)/ruby/ruby.h init.o: $(hdrdir)/ruby/st.h init.o: $(hdrdir)/ruby/subst.h @@ -480,7 +478,6 @@ yield.o: $(hdrdir)/ruby/internal/variable.h yield.o: $(hdrdir)/ruby/internal/warning_push.h yield.o: $(hdrdir)/ruby/internal/xmalloc.h yield.o: $(hdrdir)/ruby/missing.h -yield.o: $(hdrdir)/ruby/onigmo.h yield.o: $(hdrdir)/ruby/ruby.h yield.o: $(hdrdir)/ruby/st.h yield.o: $(hdrdir)/ruby/subst.h diff --git a/ext/-test-/load/dot.dot/depend b/ext/-test-/load/dot.dot/depend index cf4680c63ee20f..339837d1832ad7 100644 --- a/ext/-test-/load/dot.dot/depend +++ b/ext/-test-/load/dot.dot/depend @@ -156,7 +156,6 @@ dot.dot.o: $(hdrdir)/ruby/internal/variable.h dot.dot.o: $(hdrdir)/ruby/internal/warning_push.h dot.dot.o: $(hdrdir)/ruby/internal/xmalloc.h dot.dot.o: $(hdrdir)/ruby/missing.h -dot.dot.o: $(hdrdir)/ruby/onigmo.h dot.dot.o: $(hdrdir)/ruby/ruby.h dot.dot.o: $(hdrdir)/ruby/st.h dot.dot.o: $(hdrdir)/ruby/subst.h diff --git a/ext/-test-/load/protect/depend b/ext/-test-/load/protect/depend index 780ba382baf52e..c76c6f88ed9591 100644 --- a/ext/-test-/load/protect/depend +++ b/ext/-test-/load/protect/depend @@ -156,7 +156,6 @@ protect.o: $(hdrdir)/ruby/internal/variable.h protect.o: $(hdrdir)/ruby/internal/warning_push.h protect.o: $(hdrdir)/ruby/internal/xmalloc.h protect.o: $(hdrdir)/ruby/missing.h -protect.o: $(hdrdir)/ruby/onigmo.h protect.o: $(hdrdir)/ruby/ruby.h protect.o: $(hdrdir)/ruby/st.h protect.o: $(hdrdir)/ruby/subst.h diff --git a/ext/-test-/load/resolve_symbol_resolver/depend b/ext/-test-/load/resolve_symbol_resolver/depend index d6107a6cf05568..f422898b691af7 100644 --- a/ext/-test-/load/resolve_symbol_resolver/depend +++ b/ext/-test-/load/resolve_symbol_resolver/depend @@ -156,7 +156,6 @@ resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/variable.h resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/warning_push.h resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/xmalloc.h resolve_symbol_resolver.o: $(hdrdir)/ruby/missing.h -resolve_symbol_resolver.o: $(hdrdir)/ruby/onigmo.h resolve_symbol_resolver.o: $(hdrdir)/ruby/ruby.h resolve_symbol_resolver.o: $(hdrdir)/ruby/st.h resolve_symbol_resolver.o: $(hdrdir)/ruby/subst.h diff --git a/ext/-test-/load/resolve_symbol_target/depend b/ext/-test-/load/resolve_symbol_target/depend index 52f922db422ec0..aa0b5327bee023 100644 --- a/ext/-test-/load/resolve_symbol_target/depend +++ b/ext/-test-/load/resolve_symbol_target/depend @@ -156,7 +156,6 @@ resolve_symbol_target.o: $(hdrdir)/ruby/internal/variable.h resolve_symbol_target.o: $(hdrdir)/ruby/internal/warning_push.h resolve_symbol_target.o: $(hdrdir)/ruby/internal/xmalloc.h resolve_symbol_target.o: $(hdrdir)/ruby/missing.h -resolve_symbol_target.o: $(hdrdir)/ruby/onigmo.h resolve_symbol_target.o: $(hdrdir)/ruby/ruby.h resolve_symbol_target.o: $(hdrdir)/ruby/st.h resolve_symbol_target.o: $(hdrdir)/ruby/subst.h diff --git a/ext/-test-/load/stringify_symbols/depend b/ext/-test-/load/stringify_symbols/depend index f6621b0127ed34..2d4d79a7b7a21a 100644 --- a/ext/-test-/load/stringify_symbols/depend +++ b/ext/-test-/load/stringify_symbols/depend @@ -156,7 +156,6 @@ stringify_symbols.o: $(hdrdir)/ruby/internal/variable.h stringify_symbols.o: $(hdrdir)/ruby/internal/warning_push.h stringify_symbols.o: $(hdrdir)/ruby/internal/xmalloc.h stringify_symbols.o: $(hdrdir)/ruby/missing.h -stringify_symbols.o: $(hdrdir)/ruby/onigmo.h stringify_symbols.o: $(hdrdir)/ruby/ruby.h stringify_symbols.o: $(hdrdir)/ruby/st.h stringify_symbols.o: $(hdrdir)/ruby/subst.h diff --git a/ext/-test-/load/stringify_target/depend b/ext/-test-/load/stringify_target/depend index d453d873229786..c66575d4e4fbc5 100644 --- a/ext/-test-/load/stringify_target/depend +++ b/ext/-test-/load/stringify_target/depend @@ -156,7 +156,6 @@ stringify_target.o: $(hdrdir)/ruby/internal/variable.h stringify_target.o: $(hdrdir)/ruby/internal/warning_push.h stringify_target.o: $(hdrdir)/ruby/internal/xmalloc.h stringify_target.o: $(hdrdir)/ruby/missing.h -stringify_target.o: $(hdrdir)/ruby/onigmo.h stringify_target.o: $(hdrdir)/ruby/ruby.h stringify_target.o: $(hdrdir)/ruby/st.h stringify_target.o: $(hdrdir)/ruby/subst.h diff --git a/ext/-test-/marshal/compat/depend b/ext/-test-/marshal/compat/depend index 0b2d1ce777f75b..36b9235c230de1 100644 --- a/ext/-test-/marshal/compat/depend +++ b/ext/-test-/marshal/compat/depend @@ -156,7 +156,6 @@ usrcompat.o: $(hdrdir)/ruby/internal/variable.h usrcompat.o: $(hdrdir)/ruby/internal/warning_push.h usrcompat.o: $(hdrdir)/ruby/internal/xmalloc.h usrcompat.o: $(hdrdir)/ruby/missing.h -usrcompat.o: $(hdrdir)/ruby/onigmo.h usrcompat.o: $(hdrdir)/ruby/ruby.h usrcompat.o: $(hdrdir)/ruby/st.h usrcompat.o: $(hdrdir)/ruby/subst.h diff --git a/ext/-test-/marshal/internal_ivar/depend b/ext/-test-/marshal/internal_ivar/depend index 198637c52f29a1..a2e093d809b941 100644 --- a/ext/-test-/marshal/internal_ivar/depend +++ b/ext/-test-/marshal/internal_ivar/depend @@ -156,7 +156,6 @@ internal_ivar.o: $(hdrdir)/ruby/internal/variable.h internal_ivar.o: $(hdrdir)/ruby/internal/warning_push.h internal_ivar.o: $(hdrdir)/ruby/internal/xmalloc.h internal_ivar.o: $(hdrdir)/ruby/missing.h -internal_ivar.o: $(hdrdir)/ruby/onigmo.h internal_ivar.o: $(hdrdir)/ruby/ruby.h internal_ivar.o: $(hdrdir)/ruby/st.h internal_ivar.o: $(hdrdir)/ruby/subst.h diff --git a/ext/-test-/marshal/usr/depend b/ext/-test-/marshal/usr/depend index 99cc51180de996..5ffb8c58de24be 100644 --- a/ext/-test-/marshal/usr/depend +++ b/ext/-test-/marshal/usr/depend @@ -156,7 +156,6 @@ usrmarshal.o: $(hdrdir)/ruby/internal/variable.h usrmarshal.o: $(hdrdir)/ruby/internal/warning_push.h usrmarshal.o: $(hdrdir)/ruby/internal/xmalloc.h usrmarshal.o: $(hdrdir)/ruby/missing.h -usrmarshal.o: $(hdrdir)/ruby/onigmo.h usrmarshal.o: $(hdrdir)/ruby/ruby.h usrmarshal.o: $(hdrdir)/ruby/st.h usrmarshal.o: $(hdrdir)/ruby/subst.h diff --git a/ext/-test-/memory_view/depend b/ext/-test-/memory_view/depend index f1a8b2404851af..a6ffd76f459669 100644 --- a/ext/-test-/memory_view/depend +++ b/ext/-test-/memory_view/depend @@ -157,7 +157,6 @@ memory_view.o: $(hdrdir)/ruby/internal/warning_push.h memory_view.o: $(hdrdir)/ruby/internal/xmalloc.h memory_view.o: $(hdrdir)/ruby/memory_view.h memory_view.o: $(hdrdir)/ruby/missing.h -memory_view.o: $(hdrdir)/ruby/onigmo.h memory_view.o: $(hdrdir)/ruby/ruby.h memory_view.o: $(hdrdir)/ruby/st.h memory_view.o: $(hdrdir)/ruby/subst.h diff --git a/ext/-test-/method/depend b/ext/-test-/method/depend index eab03eb4bff625..95745b3daea8eb 100644 --- a/ext/-test-/method/depend +++ b/ext/-test-/method/depend @@ -156,7 +156,6 @@ arity.o: $(hdrdir)/ruby/internal/variable.h arity.o: $(hdrdir)/ruby/internal/warning_push.h arity.o: $(hdrdir)/ruby/internal/xmalloc.h arity.o: $(hdrdir)/ruby/missing.h -arity.o: $(hdrdir)/ruby/onigmo.h arity.o: $(hdrdir)/ruby/ruby.h arity.o: $(hdrdir)/ruby/st.h arity.o: $(hdrdir)/ruby/subst.h @@ -318,7 +317,6 @@ init.o: $(hdrdir)/ruby/internal/variable.h init.o: $(hdrdir)/ruby/internal/warning_push.h init.o: $(hdrdir)/ruby/internal/xmalloc.h init.o: $(hdrdir)/ruby/missing.h -init.o: $(hdrdir)/ruby/onigmo.h init.o: $(hdrdir)/ruby/ruby.h init.o: $(hdrdir)/ruby/st.h init.o: $(hdrdir)/ruby/subst.h diff --git a/ext/-test-/notimplement/depend b/ext/-test-/notimplement/depend index b1452bdf5ec8dd..69c970b6f25703 100644 --- a/ext/-test-/notimplement/depend +++ b/ext/-test-/notimplement/depend @@ -156,7 +156,6 @@ bug.o: $(hdrdir)/ruby/internal/variable.h bug.o: $(hdrdir)/ruby/internal/warning_push.h bug.o: $(hdrdir)/ruby/internal/xmalloc.h bug.o: $(hdrdir)/ruby/missing.h -bug.o: $(hdrdir)/ruby/onigmo.h bug.o: $(hdrdir)/ruby/ruby.h bug.o: $(hdrdir)/ruby/st.h bug.o: $(hdrdir)/ruby/subst.h diff --git a/ext/-test-/num2int/depend b/ext/-test-/num2int/depend index ccd33727bf2055..75536363ac650d 100644 --- a/ext/-test-/num2int/depend +++ b/ext/-test-/num2int/depend @@ -156,7 +156,6 @@ num2int.o: $(hdrdir)/ruby/internal/variable.h num2int.o: $(hdrdir)/ruby/internal/warning_push.h num2int.o: $(hdrdir)/ruby/internal/xmalloc.h num2int.o: $(hdrdir)/ruby/missing.h -num2int.o: $(hdrdir)/ruby/onigmo.h num2int.o: $(hdrdir)/ruby/ruby.h num2int.o: $(hdrdir)/ruby/st.h num2int.o: $(hdrdir)/ruby/subst.h diff --git a/ext/-test-/path_to_class/depend b/ext/-test-/path_to_class/depend index 47c93be2fc7534..e535058e092935 100644 --- a/ext/-test-/path_to_class/depend +++ b/ext/-test-/path_to_class/depend @@ -156,7 +156,6 @@ path_to_class.o: $(hdrdir)/ruby/internal/variable.h path_to_class.o: $(hdrdir)/ruby/internal/warning_push.h path_to_class.o: $(hdrdir)/ruby/internal/xmalloc.h path_to_class.o: $(hdrdir)/ruby/missing.h -path_to_class.o: $(hdrdir)/ruby/onigmo.h path_to_class.o: $(hdrdir)/ruby/ruby.h path_to_class.o: $(hdrdir)/ruby/st.h path_to_class.o: $(hdrdir)/ruby/subst.h diff --git a/ext/-test-/popen_deadlock/depend b/ext/-test-/popen_deadlock/depend index faa103fec4d28f..0b8932e8b8a191 100644 --- a/ext/-test-/popen_deadlock/depend +++ b/ext/-test-/popen_deadlock/depend @@ -156,7 +156,6 @@ infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/variable.h infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/warning_push.h infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/xmalloc.h infinite_loop_dlsym.o: $(hdrdir)/ruby/missing.h -infinite_loop_dlsym.o: $(hdrdir)/ruby/onigmo.h infinite_loop_dlsym.o: $(hdrdir)/ruby/ruby.h infinite_loop_dlsym.o: $(hdrdir)/ruby/st.h infinite_loop_dlsym.o: $(hdrdir)/ruby/subst.h diff --git a/ext/-test-/postponed_job/depend b/ext/-test-/postponed_job/depend index d8898c732a0fe1..ff567e39215ce5 100644 --- a/ext/-test-/postponed_job/depend +++ b/ext/-test-/postponed_job/depend @@ -157,7 +157,6 @@ postponed_job.o: $(hdrdir)/ruby/internal/variable.h postponed_job.o: $(hdrdir)/ruby/internal/warning_push.h postponed_job.o: $(hdrdir)/ruby/internal/xmalloc.h postponed_job.o: $(hdrdir)/ruby/missing.h -postponed_job.o: $(hdrdir)/ruby/onigmo.h postponed_job.o: $(hdrdir)/ruby/ruby.h postponed_job.o: $(hdrdir)/ruby/st.h postponed_job.o: $(hdrdir)/ruby/subst.h diff --git a/ext/-test-/proc/depend b/ext/-test-/proc/depend index 4dd1aa7fb4307b..97834db0a2d422 100644 --- a/ext/-test-/proc/depend +++ b/ext/-test-/proc/depend @@ -156,7 +156,6 @@ init.o: $(hdrdir)/ruby/internal/variable.h init.o: $(hdrdir)/ruby/internal/warning_push.h init.o: $(hdrdir)/ruby/internal/xmalloc.h init.o: $(hdrdir)/ruby/missing.h -init.o: $(hdrdir)/ruby/onigmo.h init.o: $(hdrdir)/ruby/ruby.h init.o: $(hdrdir)/ruby/st.h init.o: $(hdrdir)/ruby/subst.h @@ -318,7 +317,6 @@ receiver.o: $(hdrdir)/ruby/internal/variable.h receiver.o: $(hdrdir)/ruby/internal/warning_push.h receiver.o: $(hdrdir)/ruby/internal/xmalloc.h receiver.o: $(hdrdir)/ruby/missing.h -receiver.o: $(hdrdir)/ruby/onigmo.h receiver.o: $(hdrdir)/ruby/ruby.h receiver.o: $(hdrdir)/ruby/st.h receiver.o: $(hdrdir)/ruby/subst.h @@ -480,7 +478,6 @@ super.o: $(hdrdir)/ruby/internal/variable.h super.o: $(hdrdir)/ruby/internal/warning_push.h super.o: $(hdrdir)/ruby/internal/xmalloc.h super.o: $(hdrdir)/ruby/missing.h -super.o: $(hdrdir)/ruby/onigmo.h super.o: $(hdrdir)/ruby/ruby.h super.o: $(hdrdir)/ruby/st.h super.o: $(hdrdir)/ruby/subst.h diff --git a/ext/-test-/random/depend b/ext/-test-/random/depend index 1d738ff50f3c53..380c30fbe4a355 100644 --- a/ext/-test-/random/depend +++ b/ext/-test-/random/depend @@ -155,7 +155,6 @@ bad_version.o: $(hdrdir)/ruby/internal/variable.h bad_version.o: $(hdrdir)/ruby/internal/warning_push.h bad_version.o: $(hdrdir)/ruby/internal/xmalloc.h bad_version.o: $(hdrdir)/ruby/missing.h -bad_version.o: $(hdrdir)/ruby/onigmo.h bad_version.o: $(hdrdir)/ruby/random.h bad_version.o: $(hdrdir)/ruby/ruby.h bad_version.o: $(hdrdir)/ruby/st.h @@ -318,7 +317,6 @@ init.o: $(hdrdir)/ruby/internal/variable.h init.o: $(hdrdir)/ruby/internal/warning_push.h init.o: $(hdrdir)/ruby/internal/xmalloc.h init.o: $(hdrdir)/ruby/missing.h -init.o: $(hdrdir)/ruby/onigmo.h init.o: $(hdrdir)/ruby/ruby.h init.o: $(hdrdir)/ruby/st.h init.o: $(hdrdir)/ruby/subst.h @@ -479,7 +477,6 @@ loop.o: $(hdrdir)/ruby/internal/variable.h loop.o: $(hdrdir)/ruby/internal/warning_push.h loop.o: $(hdrdir)/ruby/internal/xmalloc.h loop.o: $(hdrdir)/ruby/missing.h -loop.o: $(hdrdir)/ruby/onigmo.h loop.o: $(hdrdir)/ruby/random.h loop.o: $(hdrdir)/ruby/ruby.h loop.o: $(hdrdir)/ruby/st.h diff --git a/ext/-test-/rational/depend b/ext/-test-/rational/depend index fd8df5e4f57273..d949fca66bcc88 100644 --- a/ext/-test-/rational/depend +++ b/ext/-test-/rational/depend @@ -160,7 +160,6 @@ rat.o: $(hdrdir)/ruby/internal/variable.h rat.o: $(hdrdir)/ruby/internal/warning_push.h rat.o: $(hdrdir)/ruby/internal/xmalloc.h rat.o: $(hdrdir)/ruby/missing.h -rat.o: $(hdrdir)/ruby/onigmo.h rat.o: $(hdrdir)/ruby/ruby.h rat.o: $(hdrdir)/ruby/st.h rat.o: $(hdrdir)/ruby/subst.h diff --git a/ext/-test-/rb_call_super_kw/depend b/ext/-test-/rb_call_super_kw/depend index 1ffafebd98ff4a..bf34323ca7ddc8 100644 --- a/ext/-test-/rb_call_super_kw/depend +++ b/ext/-test-/rb_call_super_kw/depend @@ -156,7 +156,6 @@ rb_call_super_kw.o: $(hdrdir)/ruby/internal/variable.h rb_call_super_kw.o: $(hdrdir)/ruby/internal/warning_push.h rb_call_super_kw.o: $(hdrdir)/ruby/internal/xmalloc.h rb_call_super_kw.o: $(hdrdir)/ruby/missing.h -rb_call_super_kw.o: $(hdrdir)/ruby/onigmo.h rb_call_super_kw.o: $(hdrdir)/ruby/ruby.h rb_call_super_kw.o: $(hdrdir)/ruby/st.h rb_call_super_kw.o: $(hdrdir)/ruby/subst.h diff --git a/ext/-test-/recursion/depend b/ext/-test-/recursion/depend index e4fc781dfe4fad..b6487eb4dfa624 100644 --- a/ext/-test-/recursion/depend +++ b/ext/-test-/recursion/depend @@ -156,7 +156,6 @@ recursion.o: $(hdrdir)/ruby/internal/variable.h recursion.o: $(hdrdir)/ruby/internal/warning_push.h recursion.o: $(hdrdir)/ruby/internal/xmalloc.h recursion.o: $(hdrdir)/ruby/missing.h -recursion.o: $(hdrdir)/ruby/onigmo.h recursion.o: $(hdrdir)/ruby/ruby.h recursion.o: $(hdrdir)/ruby/st.h recursion.o: $(hdrdir)/ruby/subst.h diff --git a/ext/-test-/regexp/depend b/ext/-test-/regexp/depend index e656d00c57cd5c..6e2b24ac27ec1c 100644 --- a/ext/-test-/regexp/depend +++ b/ext/-test-/regexp/depend @@ -156,7 +156,6 @@ init.o: $(hdrdir)/ruby/internal/variable.h init.o: $(hdrdir)/ruby/internal/warning_push.h init.o: $(hdrdir)/ruby/internal/xmalloc.h init.o: $(hdrdir)/ruby/missing.h -init.o: $(hdrdir)/ruby/onigmo.h init.o: $(hdrdir)/ruby/ruby.h init.o: $(hdrdir)/ruby/st.h init.o: $(hdrdir)/ruby/subst.h @@ -318,7 +317,6 @@ new.o: $(hdrdir)/ruby/internal/variable.h new.o: $(hdrdir)/ruby/internal/warning_push.h new.o: $(hdrdir)/ruby/internal/xmalloc.h new.o: $(hdrdir)/ruby/missing.h -new.o: $(hdrdir)/ruby/onigmo.h new.o: $(hdrdir)/ruby/ruby.h new.o: $(hdrdir)/ruby/st.h new.o: $(hdrdir)/ruby/subst.h diff --git a/ext/-test-/sanitizers/depend b/ext/-test-/sanitizers/depend index 69d302381db754..0e6e632803307e 100644 --- a/ext/-test-/sanitizers/depend +++ b/ext/-test-/sanitizers/depend @@ -155,7 +155,6 @@ sanitizers.o: $(hdrdir)/ruby/internal/variable.h sanitizers.o: $(hdrdir)/ruby/internal/warning_push.h sanitizers.o: $(hdrdir)/ruby/internal/xmalloc.h sanitizers.o: $(hdrdir)/ruby/missing.h -sanitizers.o: $(hdrdir)/ruby/onigmo.h sanitizers.o: $(hdrdir)/ruby/ruby.h sanitizers.o: $(hdrdir)/ruby/st.h sanitizers.o: $(hdrdir)/ruby/subst.h diff --git a/ext/-test-/scan_args/depend b/ext/-test-/scan_args/depend index 2a28e043c4da0c..ca0fc1923860b0 100644 --- a/ext/-test-/scan_args/depend +++ b/ext/-test-/scan_args/depend @@ -156,7 +156,6 @@ scan_args.o: $(hdrdir)/ruby/internal/variable.h scan_args.o: $(hdrdir)/ruby/internal/warning_push.h scan_args.o: $(hdrdir)/ruby/internal/xmalloc.h scan_args.o: $(hdrdir)/ruby/missing.h -scan_args.o: $(hdrdir)/ruby/onigmo.h scan_args.o: $(hdrdir)/ruby/ruby.h scan_args.o: $(hdrdir)/ruby/st.h scan_args.o: $(hdrdir)/ruby/subst.h diff --git a/ext/-test-/st/foreach/depend b/ext/-test-/st/foreach/depend index a95ecda94f9bd9..29aab2bb29511f 100644 --- a/ext/-test-/st/foreach/depend +++ b/ext/-test-/st/foreach/depend @@ -156,7 +156,6 @@ foreach.o: $(hdrdir)/ruby/internal/variable.h foreach.o: $(hdrdir)/ruby/internal/warning_push.h foreach.o: $(hdrdir)/ruby/internal/xmalloc.h foreach.o: $(hdrdir)/ruby/missing.h -foreach.o: $(hdrdir)/ruby/onigmo.h foreach.o: $(hdrdir)/ruby/ruby.h foreach.o: $(hdrdir)/ruby/st.h foreach.o: $(hdrdir)/ruby/subst.h diff --git a/ext/-test-/st/numhash/depend b/ext/-test-/st/numhash/depend index c9e87bcd0ac5f9..18320d55f56805 100644 --- a/ext/-test-/st/numhash/depend +++ b/ext/-test-/st/numhash/depend @@ -156,7 +156,6 @@ numhash.o: $(hdrdir)/ruby/internal/variable.h numhash.o: $(hdrdir)/ruby/internal/warning_push.h numhash.o: $(hdrdir)/ruby/internal/xmalloc.h numhash.o: $(hdrdir)/ruby/missing.h -numhash.o: $(hdrdir)/ruby/onigmo.h numhash.o: $(hdrdir)/ruby/ruby.h numhash.o: $(hdrdir)/ruby/st.h numhash.o: $(hdrdir)/ruby/subst.h diff --git a/ext/-test-/st/update/depend b/ext/-test-/st/update/depend index d275a3526a7f88..247f0efd6b39b6 100644 --- a/ext/-test-/st/update/depend +++ b/ext/-test-/st/update/depend @@ -156,7 +156,6 @@ update.o: $(hdrdir)/ruby/internal/variable.h update.o: $(hdrdir)/ruby/internal/warning_push.h update.o: $(hdrdir)/ruby/internal/xmalloc.h update.o: $(hdrdir)/ruby/missing.h -update.o: $(hdrdir)/ruby/onigmo.h update.o: $(hdrdir)/ruby/ruby.h update.o: $(hdrdir)/ruby/st.h update.o: $(hdrdir)/ruby/subst.h diff --git a/ext/-test-/string/depend b/ext/-test-/string/depend index 74519141c08f9b..478ae3b82b7500 100644 --- a/ext/-test-/string/depend +++ b/ext/-test-/string/depend @@ -842,7 +842,6 @@ ellipsize.o: $(hdrdir)/ruby/internal/variable.h ellipsize.o: $(hdrdir)/ruby/internal/warning_push.h ellipsize.o: $(hdrdir)/ruby/internal/xmalloc.h ellipsize.o: $(hdrdir)/ruby/missing.h -ellipsize.o: $(hdrdir)/ruby/onigmo.h ellipsize.o: $(hdrdir)/ruby/ruby.h ellipsize.o: $(hdrdir)/ruby/st.h ellipsize.o: $(hdrdir)/ruby/subst.h @@ -1699,7 +1698,6 @@ init.o: $(hdrdir)/ruby/internal/variable.h init.o: $(hdrdir)/ruby/internal/warning_push.h init.o: $(hdrdir)/ruby/internal/xmalloc.h init.o: $(hdrdir)/ruby/missing.h -init.o: $(hdrdir)/ruby/onigmo.h init.o: $(hdrdir)/ruby/ruby.h init.o: $(hdrdir)/ruby/st.h init.o: $(hdrdir)/ruby/subst.h @@ -1861,7 +1859,6 @@ modify.o: $(hdrdir)/ruby/internal/variable.h modify.o: $(hdrdir)/ruby/internal/warning_push.h modify.o: $(hdrdir)/ruby/internal/xmalloc.h modify.o: $(hdrdir)/ruby/missing.h -modify.o: $(hdrdir)/ruby/onigmo.h modify.o: $(hdrdir)/ruby/ruby.h modify.o: $(hdrdir)/ruby/st.h modify.o: $(hdrdir)/ruby/subst.h @@ -2196,7 +2193,6 @@ nofree.o: $(hdrdir)/ruby/internal/variable.h nofree.o: $(hdrdir)/ruby/internal/warning_push.h nofree.o: $(hdrdir)/ruby/internal/xmalloc.h nofree.o: $(hdrdir)/ruby/missing.h -nofree.o: $(hdrdir)/ruby/onigmo.h nofree.o: $(hdrdir)/ruby/ruby.h nofree.o: $(hdrdir)/ruby/st.h nofree.o: $(hdrdir)/ruby/subst.h @@ -2705,7 +2701,6 @@ rb_interned_str.o: $(hdrdir)/ruby/internal/variable.h rb_interned_str.o: $(hdrdir)/ruby/internal/warning_push.h rb_interned_str.o: $(hdrdir)/ruby/internal/xmalloc.h rb_interned_str.o: $(hdrdir)/ruby/missing.h -rb_interned_str.o: $(hdrdir)/ruby/onigmo.h rb_interned_str.o: $(hdrdir)/ruby/ruby.h rb_interned_str.o: $(hdrdir)/ruby/st.h rb_interned_str.o: $(hdrdir)/ruby/subst.h @@ -2867,7 +2862,6 @@ rb_str_dup.o: $(hdrdir)/ruby/internal/variable.h rb_str_dup.o: $(hdrdir)/ruby/internal/warning_push.h rb_str_dup.o: $(hdrdir)/ruby/internal/xmalloc.h rb_str_dup.o: $(hdrdir)/ruby/missing.h -rb_str_dup.o: $(hdrdir)/ruby/onigmo.h rb_str_dup.o: $(hdrdir)/ruby/ruby.h rb_str_dup.o: $(hdrdir)/ruby/st.h rb_str_dup.o: $(hdrdir)/ruby/subst.h @@ -3029,7 +3023,6 @@ set_len.o: $(hdrdir)/ruby/internal/variable.h set_len.o: $(hdrdir)/ruby/internal/warning_push.h set_len.o: $(hdrdir)/ruby/internal/xmalloc.h set_len.o: $(hdrdir)/ruby/missing.h -set_len.o: $(hdrdir)/ruby/onigmo.h set_len.o: $(hdrdir)/ruby/ruby.h set_len.o: $(hdrdir)/ruby/st.h set_len.o: $(hdrdir)/ruby/subst.h diff --git a/ext/-test-/struct/depend b/ext/-test-/struct/depend index 8f8cf15788dc32..e2638e4cdf5115 100644 --- a/ext/-test-/struct/depend +++ b/ext/-test-/struct/depend @@ -156,7 +156,6 @@ data.o: $(hdrdir)/ruby/internal/variable.h data.o: $(hdrdir)/ruby/internal/warning_push.h data.o: $(hdrdir)/ruby/internal/xmalloc.h data.o: $(hdrdir)/ruby/missing.h -data.o: $(hdrdir)/ruby/onigmo.h data.o: $(hdrdir)/ruby/ruby.h data.o: $(hdrdir)/ruby/st.h data.o: $(hdrdir)/ruby/subst.h @@ -318,7 +317,6 @@ duplicate.o: $(hdrdir)/ruby/internal/variable.h duplicate.o: $(hdrdir)/ruby/internal/warning_push.h duplicate.o: $(hdrdir)/ruby/internal/xmalloc.h duplicate.o: $(hdrdir)/ruby/missing.h -duplicate.o: $(hdrdir)/ruby/onigmo.h duplicate.o: $(hdrdir)/ruby/ruby.h duplicate.o: $(hdrdir)/ruby/st.h duplicate.o: $(hdrdir)/ruby/subst.h @@ -480,7 +478,6 @@ init.o: $(hdrdir)/ruby/internal/variable.h init.o: $(hdrdir)/ruby/internal/warning_push.h init.o: $(hdrdir)/ruby/internal/xmalloc.h init.o: $(hdrdir)/ruby/missing.h -init.o: $(hdrdir)/ruby/onigmo.h init.o: $(hdrdir)/ruby/ruby.h init.o: $(hdrdir)/ruby/st.h init.o: $(hdrdir)/ruby/subst.h @@ -642,7 +639,6 @@ len.o: $(hdrdir)/ruby/internal/variable.h len.o: $(hdrdir)/ruby/internal/warning_push.h len.o: $(hdrdir)/ruby/internal/xmalloc.h len.o: $(hdrdir)/ruby/missing.h -len.o: $(hdrdir)/ruby/onigmo.h len.o: $(hdrdir)/ruby/ruby.h len.o: $(hdrdir)/ruby/st.h len.o: $(hdrdir)/ruby/subst.h @@ -804,7 +800,6 @@ member.o: $(hdrdir)/ruby/internal/variable.h member.o: $(hdrdir)/ruby/internal/warning_push.h member.o: $(hdrdir)/ruby/internal/xmalloc.h member.o: $(hdrdir)/ruby/missing.h -member.o: $(hdrdir)/ruby/onigmo.h member.o: $(hdrdir)/ruby/ruby.h member.o: $(hdrdir)/ruby/st.h member.o: $(hdrdir)/ruby/subst.h diff --git a/ext/-test-/symbol/depend b/ext/-test-/symbol/depend index a07567a5e38427..b1d8e1aab6fd3c 100644 --- a/ext/-test-/symbol/depend +++ b/ext/-test-/symbol/depend @@ -156,7 +156,6 @@ init.o: $(hdrdir)/ruby/internal/variable.h init.o: $(hdrdir)/ruby/internal/warning_push.h init.o: $(hdrdir)/ruby/internal/xmalloc.h init.o: $(hdrdir)/ruby/missing.h -init.o: $(hdrdir)/ruby/onigmo.h init.o: $(hdrdir)/ruby/ruby.h init.o: $(hdrdir)/ruby/st.h init.o: $(hdrdir)/ruby/subst.h @@ -318,7 +317,6 @@ type.o: $(hdrdir)/ruby/internal/variable.h type.o: $(hdrdir)/ruby/internal/warning_push.h type.o: $(hdrdir)/ruby/internal/xmalloc.h type.o: $(hdrdir)/ruby/missing.h -type.o: $(hdrdir)/ruby/onigmo.h type.o: $(hdrdir)/ruby/ruby.h type.o: $(hdrdir)/ruby/st.h type.o: $(hdrdir)/ruby/subst.h diff --git a/ext/-test-/thread/id/depend b/ext/-test-/thread/id/depend index 6f4a912aa8e6ae..6b76b31ddcc3b7 100644 --- a/ext/-test-/thread/id/depend +++ b/ext/-test-/thread/id/depend @@ -156,7 +156,6 @@ id.o: $(hdrdir)/ruby/internal/variable.h id.o: $(hdrdir)/ruby/internal/warning_push.h id.o: $(hdrdir)/ruby/internal/xmalloc.h id.o: $(hdrdir)/ruby/missing.h -id.o: $(hdrdir)/ruby/onigmo.h id.o: $(hdrdir)/ruby/ruby.h id.o: $(hdrdir)/ruby/st.h id.o: $(hdrdir)/ruby/subst.h diff --git a/ext/-test-/thread/instrumentation/depend b/ext/-test-/thread/instrumentation/depend index 176d637786d728..63e1c7e44fb63f 100644 --- a/ext/-test-/thread/instrumentation/depend +++ b/ext/-test-/thread/instrumentation/depend @@ -156,7 +156,6 @@ instrumentation.o: $(hdrdir)/ruby/internal/variable.h instrumentation.o: $(hdrdir)/ruby/internal/warning_push.h instrumentation.o: $(hdrdir)/ruby/internal/xmalloc.h instrumentation.o: $(hdrdir)/ruby/missing.h -instrumentation.o: $(hdrdir)/ruby/onigmo.h instrumentation.o: $(hdrdir)/ruby/ruby.h instrumentation.o: $(hdrdir)/ruby/st.h instrumentation.o: $(hdrdir)/ruby/subst.h diff --git a/ext/-test-/thread/lock_native_thread/depend b/ext/-test-/thread/lock_native_thread/depend index 067dacb5fc7bf7..a32843e531494a 100644 --- a/ext/-test-/thread/lock_native_thread/depend +++ b/ext/-test-/thread/lock_native_thread/depend @@ -155,7 +155,6 @@ lock_native_thread.o: $(hdrdir)/ruby/internal/variable.h lock_native_thread.o: $(hdrdir)/ruby/internal/warning_push.h lock_native_thread.o: $(hdrdir)/ruby/internal/xmalloc.h lock_native_thread.o: $(hdrdir)/ruby/missing.h -lock_native_thread.o: $(hdrdir)/ruby/onigmo.h lock_native_thread.o: $(hdrdir)/ruby/ruby.h lock_native_thread.o: $(hdrdir)/ruby/st.h lock_native_thread.o: $(hdrdir)/ruby/subst.h diff --git a/ext/-test-/time/depend b/ext/-test-/time/depend index 2ac5a85445ab87..e5b05f311358e8 100644 --- a/ext/-test-/time/depend +++ b/ext/-test-/time/depend @@ -156,7 +156,6 @@ init.o: $(hdrdir)/ruby/internal/variable.h init.o: $(hdrdir)/ruby/internal/warning_push.h init.o: $(hdrdir)/ruby/internal/xmalloc.h init.o: $(hdrdir)/ruby/missing.h -init.o: $(hdrdir)/ruby/onigmo.h init.o: $(hdrdir)/ruby/ruby.h init.o: $(hdrdir)/ruby/st.h init.o: $(hdrdir)/ruby/subst.h @@ -484,7 +483,6 @@ new.o: $(hdrdir)/ruby/internal/variable.h new.o: $(hdrdir)/ruby/internal/warning_push.h new.o: $(hdrdir)/ruby/internal/xmalloc.h new.o: $(hdrdir)/ruby/missing.h -new.o: $(hdrdir)/ruby/onigmo.h new.o: $(hdrdir)/ruby/ruby.h new.o: $(hdrdir)/ruby/st.h new.o: $(hdrdir)/ruby/subst.h diff --git a/ext/-test-/tracepoint/depend b/ext/-test-/tracepoint/depend index b1256d31b7aa73..014ba83b16af6a 100644 --- a/ext/-test-/tracepoint/depend +++ b/ext/-test-/tracepoint/depend @@ -156,7 +156,6 @@ gc_hook.o: $(hdrdir)/ruby/internal/variable.h gc_hook.o: $(hdrdir)/ruby/internal/warning_push.h gc_hook.o: $(hdrdir)/ruby/internal/xmalloc.h gc_hook.o: $(hdrdir)/ruby/missing.h -gc_hook.o: $(hdrdir)/ruby/onigmo.h gc_hook.o: $(hdrdir)/ruby/ruby.h gc_hook.o: $(hdrdir)/ruby/st.h gc_hook.o: $(hdrdir)/ruby/subst.h @@ -318,7 +317,6 @@ tracepoint.o: $(hdrdir)/ruby/internal/variable.h tracepoint.o: $(hdrdir)/ruby/internal/warning_push.h tracepoint.o: $(hdrdir)/ruby/internal/xmalloc.h tracepoint.o: $(hdrdir)/ruby/missing.h -tracepoint.o: $(hdrdir)/ruby/onigmo.h tracepoint.o: $(hdrdir)/ruby/ruby.h tracepoint.o: $(hdrdir)/ruby/st.h tracepoint.o: $(hdrdir)/ruby/subst.h diff --git a/ext/-test-/typeddata/depend b/ext/-test-/typeddata/depend index 3bcce0e2870fb2..b9b4915eeed590 100644 --- a/ext/-test-/typeddata/depend +++ b/ext/-test-/typeddata/depend @@ -156,7 +156,6 @@ typeddata.o: $(hdrdir)/ruby/internal/variable.h typeddata.o: $(hdrdir)/ruby/internal/warning_push.h typeddata.o: $(hdrdir)/ruby/internal/xmalloc.h typeddata.o: $(hdrdir)/ruby/missing.h -typeddata.o: $(hdrdir)/ruby/onigmo.h typeddata.o: $(hdrdir)/ruby/ruby.h typeddata.o: $(hdrdir)/ruby/st.h typeddata.o: $(hdrdir)/ruby/subst.h diff --git a/ext/-test-/vm/depend b/ext/-test-/vm/depend index e6d60f5864820a..9313f2ee36fa19 100644 --- a/ext/-test-/vm/depend +++ b/ext/-test-/vm/depend @@ -155,7 +155,6 @@ at_exit.o: $(hdrdir)/ruby/internal/variable.h at_exit.o: $(hdrdir)/ruby/internal/warning_push.h at_exit.o: $(hdrdir)/ruby/internal/xmalloc.h at_exit.o: $(hdrdir)/ruby/missing.h -at_exit.o: $(hdrdir)/ruby/onigmo.h at_exit.o: $(hdrdir)/ruby/ruby.h at_exit.o: $(hdrdir)/ruby/st.h at_exit.o: $(hdrdir)/ruby/subst.h diff --git a/ext/continuation/depend b/ext/continuation/depend index 4724fad81c9af5..b395d3d4d7a1bb 100644 --- a/ext/continuation/depend +++ b/ext/continuation/depend @@ -155,7 +155,6 @@ continuation.o: $(hdrdir)/ruby/internal/variable.h continuation.o: $(hdrdir)/ruby/internal/warning_push.h continuation.o: $(hdrdir)/ruby/internal/xmalloc.h continuation.o: $(hdrdir)/ruby/missing.h -continuation.o: $(hdrdir)/ruby/onigmo.h continuation.o: $(hdrdir)/ruby/ruby.h continuation.o: $(hdrdir)/ruby/st.h continuation.o: $(hdrdir)/ruby/subst.h diff --git a/ext/date/depend b/ext/date/depend index da8bd9207f1629..4fb78149a16509 100644 --- a/ext/date/depend +++ b/ext/date/depend @@ -508,7 +508,6 @@ date_strftime.o: $(hdrdir)/ruby/internal/variable.h date_strftime.o: $(hdrdir)/ruby/internal/warning_push.h date_strftime.o: $(hdrdir)/ruby/internal/xmalloc.h date_strftime.o: $(hdrdir)/ruby/missing.h -date_strftime.o: $(hdrdir)/ruby/onigmo.h date_strftime.o: $(hdrdir)/ruby/ruby.h date_strftime.o: $(hdrdir)/ruby/st.h date_strftime.o: $(hdrdir)/ruby/subst.h diff --git a/ext/digest/bubblebabble/depend b/ext/digest/bubblebabble/depend index c6e887024d5194..02d88e960c112a 100644 --- a/ext/digest/bubblebabble/depend +++ b/ext/digest/bubblebabble/depend @@ -156,7 +156,6 @@ bubblebabble.o: $(hdrdir)/ruby/internal/variable.h bubblebabble.o: $(hdrdir)/ruby/internal/warning_push.h bubblebabble.o: $(hdrdir)/ruby/internal/xmalloc.h bubblebabble.o: $(hdrdir)/ruby/missing.h -bubblebabble.o: $(hdrdir)/ruby/onigmo.h bubblebabble.o: $(hdrdir)/ruby/ruby.h bubblebabble.o: $(hdrdir)/ruby/st.h bubblebabble.o: $(hdrdir)/ruby/subst.h diff --git a/ext/digest/depend b/ext/digest/depend index 345d8ca2d45215..3eabb1d1d6a570 100644 --- a/ext/digest/depend +++ b/ext/digest/depend @@ -156,7 +156,6 @@ digest.o: $(hdrdir)/ruby/internal/variable.h digest.o: $(hdrdir)/ruby/internal/warning_push.h digest.o: $(hdrdir)/ruby/internal/xmalloc.h digest.o: $(hdrdir)/ruby/missing.h -digest.o: $(hdrdir)/ruby/onigmo.h digest.o: $(hdrdir)/ruby/ruby.h digest.o: $(hdrdir)/ruby/st.h digest.o: $(hdrdir)/ruby/subst.h diff --git a/ext/digest/md5/depend b/ext/digest/md5/depend index f40e4eebed75f0..d1c25c28c89aa7 100644 --- a/ext/digest/md5/depend +++ b/ext/digest/md5/depend @@ -159,7 +159,6 @@ md5.o: $(hdrdir)/ruby/internal/variable.h md5.o: $(hdrdir)/ruby/internal/warning_push.h md5.o: $(hdrdir)/ruby/internal/xmalloc.h md5.o: $(hdrdir)/ruby/missing.h -md5.o: $(hdrdir)/ruby/onigmo.h md5.o: $(hdrdir)/ruby/ruby.h md5.o: $(hdrdir)/ruby/st.h md5.o: $(hdrdir)/ruby/subst.h @@ -323,7 +322,6 @@ md5init.o: $(hdrdir)/ruby/internal/variable.h md5init.o: $(hdrdir)/ruby/internal/warning_push.h md5init.o: $(hdrdir)/ruby/internal/xmalloc.h md5init.o: $(hdrdir)/ruby/missing.h -md5init.o: $(hdrdir)/ruby/onigmo.h md5init.o: $(hdrdir)/ruby/ruby.h md5init.o: $(hdrdir)/ruby/st.h md5init.o: $(hdrdir)/ruby/subst.h diff --git a/ext/digest/rmd160/depend b/ext/digest/rmd160/depend index 0f7f026bea4760..aec484f7b3ee38 100644 --- a/ext/digest/rmd160/depend +++ b/ext/digest/rmd160/depend @@ -159,7 +159,6 @@ rmd160.o: $(hdrdir)/ruby/internal/variable.h rmd160.o: $(hdrdir)/ruby/internal/warning_push.h rmd160.o: $(hdrdir)/ruby/internal/xmalloc.h rmd160.o: $(hdrdir)/ruby/missing.h -rmd160.o: $(hdrdir)/ruby/onigmo.h rmd160.o: $(hdrdir)/ruby/ruby.h rmd160.o: $(hdrdir)/ruby/st.h rmd160.o: $(hdrdir)/ruby/subst.h @@ -323,7 +322,6 @@ rmd160init.o: $(hdrdir)/ruby/internal/variable.h rmd160init.o: $(hdrdir)/ruby/internal/warning_push.h rmd160init.o: $(hdrdir)/ruby/internal/xmalloc.h rmd160init.o: $(hdrdir)/ruby/missing.h -rmd160init.o: $(hdrdir)/ruby/onigmo.h rmd160init.o: $(hdrdir)/ruby/ruby.h rmd160init.o: $(hdrdir)/ruby/st.h rmd160init.o: $(hdrdir)/ruby/subst.h diff --git a/ext/digest/sha1/depend b/ext/digest/sha1/depend index c5ea09758a4928..e6bd9d8f731cd9 100644 --- a/ext/digest/sha1/depend +++ b/ext/digest/sha1/depend @@ -159,7 +159,6 @@ sha1.o: $(hdrdir)/ruby/internal/variable.h sha1.o: $(hdrdir)/ruby/internal/warning_push.h sha1.o: $(hdrdir)/ruby/internal/xmalloc.h sha1.o: $(hdrdir)/ruby/missing.h -sha1.o: $(hdrdir)/ruby/onigmo.h sha1.o: $(hdrdir)/ruby/ruby.h sha1.o: $(hdrdir)/ruby/st.h sha1.o: $(hdrdir)/ruby/subst.h @@ -323,7 +322,6 @@ sha1init.o: $(hdrdir)/ruby/internal/variable.h sha1init.o: $(hdrdir)/ruby/internal/warning_push.h sha1init.o: $(hdrdir)/ruby/internal/xmalloc.h sha1init.o: $(hdrdir)/ruby/missing.h -sha1init.o: $(hdrdir)/ruby/onigmo.h sha1init.o: $(hdrdir)/ruby/ruby.h sha1init.o: $(hdrdir)/ruby/st.h sha1init.o: $(hdrdir)/ruby/subst.h diff --git a/ext/digest/sha2/depend b/ext/digest/sha2/depend index 6621a5fee378b5..2b74776b3e097c 100644 --- a/ext/digest/sha2/depend +++ b/ext/digest/sha2/depend @@ -159,7 +159,6 @@ sha2.o: $(hdrdir)/ruby/internal/variable.h sha2.o: $(hdrdir)/ruby/internal/warning_push.h sha2.o: $(hdrdir)/ruby/internal/xmalloc.h sha2.o: $(hdrdir)/ruby/missing.h -sha2.o: $(hdrdir)/ruby/onigmo.h sha2.o: $(hdrdir)/ruby/ruby.h sha2.o: $(hdrdir)/ruby/st.h sha2.o: $(hdrdir)/ruby/subst.h @@ -323,7 +322,6 @@ sha2init.o: $(hdrdir)/ruby/internal/variable.h sha2init.o: $(hdrdir)/ruby/internal/warning_push.h sha2init.o: $(hdrdir)/ruby/internal/xmalloc.h sha2init.o: $(hdrdir)/ruby/missing.h -sha2init.o: $(hdrdir)/ruby/onigmo.h sha2init.o: $(hdrdir)/ruby/ruby.h sha2init.o: $(hdrdir)/ruby/st.h sha2init.o: $(hdrdir)/ruby/subst.h diff --git a/ext/fcntl/depend b/ext/fcntl/depend index 0f02a81f9d330c..57ea0f21068068 100644 --- a/ext/fcntl/depend +++ b/ext/fcntl/depend @@ -156,7 +156,6 @@ fcntl.o: $(hdrdir)/ruby/internal/variable.h fcntl.o: $(hdrdir)/ruby/internal/warning_push.h fcntl.o: $(hdrdir)/ruby/internal/xmalloc.h fcntl.o: $(hdrdir)/ruby/missing.h -fcntl.o: $(hdrdir)/ruby/onigmo.h fcntl.o: $(hdrdir)/ruby/ruby.h fcntl.o: $(hdrdir)/ruby/st.h fcntl.o: $(hdrdir)/ruby/subst.h diff --git a/ext/rbconfig/sizeof/depend b/ext/rbconfig/sizeof/depend index c9a9d59cae789e..7e6c950769f759 100644 --- a/ext/rbconfig/sizeof/depend +++ b/ext/rbconfig/sizeof/depend @@ -170,7 +170,6 @@ limits.o: $(hdrdir)/ruby/internal/variable.h limits.o: $(hdrdir)/ruby/internal/warning_push.h limits.o: $(hdrdir)/ruby/internal/xmalloc.h limits.o: $(hdrdir)/ruby/missing.h -limits.o: $(hdrdir)/ruby/onigmo.h limits.o: $(hdrdir)/ruby/ruby.h limits.o: $(hdrdir)/ruby/st.h limits.o: $(hdrdir)/ruby/subst.h @@ -331,7 +330,6 @@ sizes.o: $(hdrdir)/ruby/internal/variable.h sizes.o: $(hdrdir)/ruby/internal/warning_push.h sizes.o: $(hdrdir)/ruby/internal/xmalloc.h sizes.o: $(hdrdir)/ruby/missing.h -sizes.o: $(hdrdir)/ruby/onigmo.h sizes.o: $(hdrdir)/ruby/ruby.h sizes.o: $(hdrdir)/ruby/st.h sizes.o: $(hdrdir)/ruby/subst.h diff --git a/ext/ripper/depend b/ext/ripper/depend index 6bac9d2135be88..db83378a1d53db 100644 --- a/ext/ripper/depend +++ b/ext/ripper/depend @@ -209,7 +209,6 @@ eventids1.o: $(hdrdir)/ruby/internal/variable.h eventids1.o: $(hdrdir)/ruby/internal/warning_push.h eventids1.o: $(hdrdir)/ruby/internal/xmalloc.h eventids1.o: $(hdrdir)/ruby/missing.h -eventids1.o: $(hdrdir)/ruby/onigmo.h eventids1.o: $(hdrdir)/ruby/ruby.h eventids1.o: $(hdrdir)/ruby/st.h eventids1.o: $(hdrdir)/ruby/subst.h diff --git a/gc.c b/gc.c index fe4ecc8d37a484..aec4aba173a9f8 100644 --- a/gc.c +++ b/gc.c @@ -194,7 +194,6 @@ rb_gc_get_ractor_newobj_cache(void) void rb_gc_initialize_vm_context(struct rb_gc_vm_context *context) { - rb_native_mutex_initialize(&context->lock); context->ec = GET_EC(); } @@ -379,7 +378,7 @@ rb_gc_obj_changed_slot_size(VALUE obj, size_t slot_size) { RUBY_ASSERT(RB_TYPE_P(obj, T_OBJECT)); - RBASIC_SET_SHAPE_ID_WITH_CAPACITY(obj, rb_obj_shape_transition_capacity(obj, rb_shape_capacity_for_slot_size(slot_size))); + RBASIC_SET_FULL_SHAPE_ID(obj, rb_obj_shape_transition_slot_size(obj, slot_size)); } void rb_vm_update_references(void *ptr); @@ -622,9 +621,11 @@ typedef struct gc_function_map { struct rb_gc_vm_context *(*get_vm_context)(void *objspace_ptr); // Object allocation VALUE (*new_obj)(void *objspace_ptr, void *cache_ptr, VALUE klass, VALUE flags, bool wb_protected, size_t alloc_size, size_t *actual_alloc_size); + bool (*zjit_new_obj_fastpath)(void *objspace_ptr, size_t alloc_size, VALUE flags, VALUE klass, struct rb_gc_zjit_fastpath *fastpath); size_t (*obj_slot_size)(VALUE obj); size_t (*size_slot_size)(void *objspace_ptr, size_t size); bool (*size_allocatable_p)(size_t size); + size_t (*max_allocation_size)(void); // Malloc void *(*malloc)(void *objspace_ptr, size_t size, bool gc_allowed); void *(*calloc)(void *objspace_ptr, size_t size, bool gc_allowed); @@ -800,9 +801,11 @@ ruby_modular_gc_init(void) load_modular_gc_func(get_vm_context); // Object allocation load_modular_gc_func(new_obj); + load_modular_gc_func(zjit_new_obj_fastpath); load_modular_gc_func(obj_slot_size); load_modular_gc_func(size_slot_size); load_modular_gc_func(size_allocatable_p); + load_modular_gc_func(max_allocation_size); // Malloc load_modular_gc_func(malloc); load_modular_gc_func(calloc); @@ -887,9 +890,11 @@ ruby_modular_gc_init(void) # define rb_gc_impl_get_vm_context rb_gc_functions.get_vm_context // Object allocation # define rb_gc_impl_new_obj rb_gc_functions.new_obj +# define rb_gc_impl_zjit_new_obj_fastpath rb_gc_functions.zjit_new_obj_fastpath # define rb_gc_impl_obj_slot_size rb_gc_functions.obj_slot_size # define rb_gc_impl_size_slot_size rb_gc_functions.size_slot_size # define rb_gc_impl_size_allocatable_p rb_gc_functions.size_allocatable_p +# define rb_gc_impl_max_allocation_size rb_gc_functions.max_allocation_size // Malloc # define rb_gc_impl_malloc rb_gc_functions.malloc # define rb_gc_impl_calloc rb_gc_functions.calloc @@ -1034,14 +1039,14 @@ rb_newobj(rb_execution_context_t *ec, VALUE klass, VALUE flags, shape_id_t shape VALUE obj = rb_gc_impl_new_obj(rb_gc_get_objspace(), cr->newobj_cache, klass, flags, wb_protected, size, &actual_alloc_size); GC_ASSERT(actual_alloc_size >= size); - shape_id = (shape_id & ~SHAPE_ID_CAPACITY_MASK) | rb_shape_id_with_capacity(rb_shape_capacity_for_slot_size(actual_alloc_size)); + shape_id = rb_shape_transition_slot_size(shape_id, actual_alloc_size); #if RACTOR_CHECK_MODE void rb_ractor_setup_belonging(VALUE obj); rb_ractor_setup_belonging(obj); #endif - RBASIC_SET_SHAPE_ID_NO_CHECKS(obj, shape_id); + RBASIC_SET_FULL_SHAPE_ID_NO_CHECKS(obj, shape_id); gc_validate_pc(obj); @@ -1049,6 +1054,10 @@ rb_newobj(rb_execution_context_t *ec, VALUE klass, VALUE flags, shape_id_t shape gc_newobj_hook(obj); } + if (RUBY_DTRACE_GC_OBJ_NEW_ENABLED()) { + RUBY_DTRACE_GC_OBJ_NEW((void*)obj, flags); + } + #if RGENGC_CHECK_MODE # ifndef GC_DEBUG_SLOT_FILL_SPECIAL_VALUE # define GC_DEBUG_SLOT_FILL_SPECIAL_VALUE 255 @@ -1093,7 +1102,7 @@ rb_newobj_of(VALUE klass, VALUE flags, size_t size) static VALUE class_allocate_complex_instance(VALUE klass, uint32_t capacity) { - shape_id_t initial_shape_id = rb_shape_id_with_robject_layout(0); + shape_id_t initial_shape_id = rb_shape_transition_robject(0); VALUE obj = rb_newobj_of_with_shape(klass, T_OBJECT, initial_shape_id, sizeof(struct RObject)); rb_obj_init_complex(obj, rb_st_init_numtable_with_size(capacity)); return obj; @@ -1106,8 +1115,8 @@ rb_class_allocate_instance(VALUE klass) VALUE obj; // Directly start as COMPLEX if we know we're over the limit. - RUBY_ASSERT(SHAPE_MAX_CAPACITY > 0); - if (RB_UNLIKELY(index_tbl_num_entries > SHAPE_MAX_CAPACITY)) { + RUBY_ASSERT(rb_shape_max_capacity() > 0); + if (RB_UNLIKELY(index_tbl_num_entries > rb_shape_max_capacity())) { obj = class_allocate_complex_instance(klass, index_tbl_num_entries); } else { @@ -1118,7 +1127,7 @@ rb_class_allocate_instance(VALUE klass) // There might be a NEWOBJ tracepoint callback, and it may set fields. // So the shape must be passed to `NEWOBJ_OF`. - obj = rb_newobj_of_with_shape(klass, T_OBJECT, rb_shape_id_with_robject_layout(0), size); + obj = rb_newobj_of_with_shape(klass, T_OBJECT, rb_shape_transition_robject(0), size); #if RUBY_DEBUG VALUE *ptr = ROBJECT_FIELDS(obj); @@ -1534,7 +1543,13 @@ rb_gc_obj_free(void *objspace, VALUE obj) RB_DEBUG_COUNTER_INC(obj_free); - switch (BUILTIN_TYPE(obj)) { + enum ruby_value_type builtin_type = BUILTIN_TYPE(obj); + + if (RUBY_DTRACE_GC_OBJ_FREE_ENABLED()) { + RUBY_DTRACE_GC_OBJ_FREE((void*)obj, RBASIC(obj)->flags); + } + + switch (builtin_type) { case T_NIL: case T_FIXNUM: case T_TRUE: @@ -1545,7 +1560,7 @@ rb_gc_obj_free(void *objspace, VALUE obj) break; } - switch (BUILTIN_TYPE(obj)) { + switch (builtin_type) { case T_OBJECT: if (FL_TEST_RAW(obj, ROBJECT_HEAP)) { if (rb_obj_shape_complex_p(obj)) { @@ -3711,6 +3726,17 @@ rb_gc_ractor_cache_free(void *cache) rb_gc_impl_ractor_cache_free(rb_gc_get_objspace(), cache); } +bool +rb_gc_zjit_new_obj_fastpath(size_t alloc_size, VALUE flags, VALUE klass, struct rb_gc_zjit_fastpath *fastpath) +{ +#if RACTOR_CHECK_MODE || defined(RUBY_ASAN_ENABLED) + (void)rb_gc_impl_zjit_new_obj_fastpath; + return false; +#else + return rb_gc_impl_zjit_new_obj_fastpath(rb_gc_get_objspace(), alloc_size, flags, klass, fastpath); +#endif +} + void rb_gc_register_mark_object(VALUE obj) { @@ -4009,6 +4035,12 @@ rb_gc_size_allocatable_p(size_t size) return rb_gc_impl_size_allocatable_p(size); } +size_t +rb_gc_max_allocation_size(void) +{ + return rb_gc_impl_max_allocation_size(); +} + static enum rb_id_table_iterator_result update_id_table(VALUE *value, void *data, int existing) { @@ -4224,7 +4256,7 @@ vm_weak_table_gen_fields_foreach(st_data_t key, st_data_t value, st_data_t data) // set the shape on it so that the GC finalizer won't try to remove // it again. A "root shape" indicates to the GC that this object // has no fields on it, hence it won't be in the gen fields table. - RBASIC_SET_SHAPE_ID((VALUE)key, ROOT_SHAPE_ID | SHAPE_ID_LAYOUT_OTHER); + RBASIC_SET_SHAPE_ID((VALUE)key, ROOT_SHAPE_ID); return ST_DELETE; case ST_REPLACE: { @@ -5413,6 +5445,10 @@ static void *ruby_xmalloc_body(size_t size); void * ruby_xmalloc(size_t size) { + if (RUBY_DTRACE_GC_XMALLOC_ENABLED()) { + RUBY_DTRACE_GC_XMALLOC(1, size); + } + return handle_malloc_failure(ruby_xmalloc_body(size)); } @@ -5455,6 +5491,10 @@ static void *ruby_xmalloc2_body(size_t n, size_t size); void * ruby_xmalloc2(size_t n, size_t size) { + if (RUBY_DTRACE_GC_XMALLOC_ENABLED()) { + RUBY_DTRACE_GC_XMALLOC(n, size); + } + return handle_malloc_failure(ruby_xmalloc2_body(n, size)); } @@ -5469,6 +5509,10 @@ static void *ruby_xcalloc_body(size_t n, size_t size); void * ruby_xcalloc(size_t n, size_t size) { + if (RUBY_DTRACE_GC_XCALLOC_ENABLED()) { + RUBY_DTRACE_GC_XCALLOC(n, size); + } + return handle_malloc_failure(ruby_xcalloc_body(n, size)); } @@ -5532,9 +5576,20 @@ ruby_xrealloc2(void *ptr, size_t n, size_t size) #ifdef ruby_xfree_sized #undef ruby_xfree_sized #endif + +static bool g_nofree = false; + void ruby_xfree_sized(void *x, size_t size) { + if (g_nofree) { + return; + } + + if (RUBY_DTRACE_GC_XFREE_ENABLED()) { + RUBY_DTRACE_GC_XFREE(x, size); + } + if (LIKELY(x)) { /* It's possible for a C extension's pthread destructor function set by pthread_key_create * to be called after ruby_vm_destruct and attempt to free memory. Fall back to mimfree in @@ -5798,6 +5853,12 @@ rb_gc_checking_shareable(void) void Init_GC(void) { + const char* nofree_str = getenv("RUBY_NO_FREE"); + if (nofree_str && strcmp(nofree_str, "yes") == 0) { + fprintf(stderr, "WARNING: Enabling no-free mode! xfree() will never free anything!\n"); + g_nofree = true; + } + #undef rb_intern rb_gc_register_address(&id2ref_value); diff --git a/gc/default/default.c b/gc/default/default.c index b39a1bd85592fd..5cc14e22ddfae2 100644 --- a/gc/default/default.c +++ b/gc/default/default.c @@ -1,6 +1,7 @@ #include "ruby/internal/config.h" #include +#include #ifndef _WIN32 # include @@ -73,6 +74,13 @@ rb_hrtime_sub(rb_hrtime_t a, rb_hrtime_t b) #include "probes.h" +#define RUBY_DTRACE_GC_HOOK(name, ...) \ + do {if (RUBY_DTRACE_GC_##name##_ENABLED()) RUBY_DTRACE_GC_##name(__VA_ARGS__);} while (0) + +#if USE_ZJIT +# include "gc/default/zjit_fastpath.h" +#endif + #ifdef BUILDING_MODULAR_GC # define RB_DEBUG_COUNTER_INC(_name) ((void)0) # define RB_DEBUG_COUNTER_INC_IF(_name, cond) (!!(cond)) @@ -233,16 +241,15 @@ static RB_THREAD_LOCAL_SPECIFIER int malloc_increase_local; #endif typedef struct ractor_newobj_heap_cache { - uintptr_t cursor; - uintptr_t cursor_end; struct free_region *next_region; struct heap_page *using_page; - size_t allocated_objects_count; + uintptr_t region_end; } rb_ractor_newobj_heap_cache_t; typedef struct ractor_newobj_cache { size_t incremental_mark_step_allocated_slots; rb_ractor_newobj_heap_cache_t heap_caches[HEAP_COUNT]; + struct gc_bump_pointer_heap bump_heaps[]; } rb_ractor_newobj_cache_t; typedef struct { @@ -1757,11 +1764,31 @@ calloc1(size_t n) return calloc(1, n); } +static void +gc_ractor_jit_cursor_sync(void *c, void *data) +{ + rb_ractor_newobj_cache_t *gc_cache = c; + bool tracing = (bool)(uintptr_t)data; + + for (size_t heap_idx = 0; heap_idx < HEAP_COUNT; heap_idx++) { + struct gc_bump_pointer_heap *bump = &gc_cache->bump_heaps[heap_idx]; + bump->jit_cursor_end = tracing ? bump->cursor : bump->cursor_end; + } +} + void rb_gc_impl_set_event_hook(void *objspace_ptr, const rb_event_flag_t event) { rb_objspace_t *objspace = objspace_ptr; + rb_event_flag_t old_events = objspace->hook_events; objspace->hook_events = event & RUBY_INTERNAL_EVENT_OBJSPACE_MASK; + + bool was_tracing = old_events & RUBY_INTERNAL_EVENT_NEWOBJ; + bool now_tracing = objspace->hook_events & RUBY_INTERNAL_EVENT_NEWOBJ; + if (was_tracing != now_tracing) { + rb_gc_ractor_newobj_cache_foreach(gc_ractor_jit_cursor_sync, + (void *)(uintptr_t)now_tracing); + } } unsigned long long @@ -2458,28 +2485,60 @@ heap_slot_size(unsigned char pool_id) return pool_slot_sizes[pool_id] - RVALUE_OVERHEAD; } +size_t +rb_gc_impl_max_allocation_size(void) +{ + return heap_slot_size(HEAP_COUNT - 1); +} + bool rb_gc_impl_size_allocatable_p(size_t size) { - return size + RVALUE_OVERHEAD <= pool_slot_sizes[HEAP_COUNT - 1]; + return size <= rb_gc_impl_max_allocation_size(); +} + +static inline void +gc_bump_flush_alloc_count(struct gc_bump_pointer_heap *bump, rb_heap_t *heap) +{ + if (bump->slot_size == 0) return; + + size_t n = (bump->cursor - bump->region_start) / bump->slot_size; + if (n > 0) { + RUBY_ATOMIC_SIZE_ADD(heap->total_allocated_objects, n); + bump->region_start = bump->cursor; + } } -static const size_t ALLOCATED_COUNT_STEP = 1024; static void -ractor_cache_flush_count(rb_objspace_t *objspace, rb_ractor_newobj_cache_t *cache) +ractor_cache_flush_count(rb_objspace_t *objspace, rb_ractor_newobj_cache_t *gc_cache) { for (int heap_idx = 0; heap_idx < HEAP_COUNT; heap_idx++) { - rb_ractor_newobj_heap_cache_t *heap_cache = &cache->heap_caches[heap_idx]; + gc_bump_flush_alloc_count(&gc_cache->bump_heaps[heap_idx], &heaps[heap_idx]); + } +} - rb_heap_t *heap = &heaps[heap_idx]; - RUBY_ATOMIC_SIZE_ADD(heap->total_allocated_objects, heap_cache->allocated_objects_count); - heap_cache->allocated_objects_count = 0; +static inline void +ractor_cache_open_window(rb_objspace_t *objspace, struct gc_bump_pointer_heap *bump, + rb_ractor_newobj_heap_cache_t *heap_cache) +{ + uintptr_t end = heap_cache->region_end; + + if (RB_UNLIKELY(is_incremental_marking(objspace))) { + uintptr_t window_end = bump->cursor + INCREMENTAL_MARK_STEP_ALLOCATIONS * bump->slot_size; + if (window_end < end) end = window_end; } + + bump->cursor_end = end; + bump->jit_cursor_end = + RB_UNLIKELY(objspace->hook_events & RUBY_INTERNAL_EVENT_NEWOBJ) ? bump->cursor : end; } static inline bool -ractor_cache_advance_region(rb_ractor_newobj_heap_cache_t *heap_cache) +ractor_cache_advance_region(rb_objspace_t *objspace, struct gc_bump_pointer_heap *bump, + rb_ractor_newobj_heap_cache_t *heap_cache, rb_heap_t *heap) { + gc_bump_flush_alloc_count(bump, heap); + struct free_region *region = heap_cache->next_region; if (region == NULL) { return false; @@ -2487,51 +2546,42 @@ ractor_cache_advance_region(rb_ractor_newobj_heap_cache_t *heap_cache) rb_asan_unpoison_object((VALUE)region, false); GC_ASSERT(RB_TYPE_P((VALUE)region, T_NONE)); - heap_cache->cursor = (uintptr_t)region; - heap_cache->cursor_end = region->end; + bump->cursor = (uintptr_t)region; + bump->region_start = (uintptr_t)region; + heap_cache->region_end = region->end; heap_cache->next_region = region->next; rb_asan_poison_object((VALUE)region); + ractor_cache_open_window(objspace, bump, heap_cache); + return true; } static inline VALUE -ractor_cache_allocate_slot(rb_objspace_t *objspace, rb_ractor_newobj_cache_t *cache, +ractor_cache_allocate_slot(rb_objspace_t *objspace, rb_ractor_newobj_cache_t *gc_cache, size_t heap_idx) { - rb_ractor_newobj_heap_cache_t *heap_cache = &cache->heap_caches[heap_idx]; + struct gc_bump_pointer_heap *bump = &gc_cache->bump_heaps[heap_idx]; - uintptr_t cursor = heap_cache->cursor; - if (RB_UNLIKELY(cursor >= heap_cache->cursor_end)) { - if (!ractor_cache_advance_region(heap_cache)) { + uintptr_t cursor = bump->cursor; + if (RB_UNLIKELY(cursor + bump->slot_size > bump->cursor_end)) { + if (RB_UNLIKELY(is_incremental_marking(objspace))) { return Qfalse; } - cursor = heap_cache->cursor; - } - if (RB_UNLIKELY(is_incremental_marking(objspace))) { - // Not allowed to allocate without running an incremental marking step - if (cache->incremental_mark_step_allocated_slots >= INCREMENTAL_MARK_STEP_ALLOCATIONS) { + rb_ractor_newobj_heap_cache_t *heap_cache = &gc_cache->heap_caches[heap_idx]; + if (!ractor_cache_advance_region(objspace, bump, heap_cache, &heaps[heap_idx])) { return Qfalse; } - - cache->incremental_mark_step_allocated_slots++; + cursor = bump->cursor; } VALUE obj = (VALUE)cursor; rb_asan_unpoison_object(obj, true); - heap_cache->cursor = cursor + pool_slot_sizes[heap_idx]; - - heap_cache->allocated_objects_count++; - rb_heap_t *heap = &heaps[heap_idx]; - if (heap_cache->allocated_objects_count >= ALLOCATED_COUNT_STEP) { - RUBY_ATOMIC_SIZE_ADD(heap->total_allocated_objects, heap_cache->allocated_objects_count); - heap_cache->allocated_objects_count = 0; - } + bump->cursor = cursor + bump->slot_size; #if RGENGC_CHECK_MODE GC_ASSERT(rb_gc_impl_obj_slot_size(obj) == heap_slot_size(heap_idx)); - // zero clear MEMZERO((char *)obj, char, heap_slot_size(heap_idx)); #endif return obj; @@ -2557,14 +2607,15 @@ heap_next_free_page(rb_objspace_t *objspace, rb_heap_t *heap) } static inline void -ractor_cache_set_page(rb_objspace_t *objspace, rb_ractor_newobj_cache_t *cache, size_t heap_idx, +ractor_cache_set_page(rb_objspace_t *objspace, rb_ractor_newobj_cache_t *gc_cache, size_t heap_idx, struct heap_page *page) { gc_report(3, objspace, "ractor_set_cache: Using page %p\n", (void *)page->body); - rb_ractor_newobj_heap_cache_t *heap_cache = &cache->heap_caches[heap_idx]; + struct gc_bump_pointer_heap *bump = &gc_cache->bump_heaps[heap_idx]; + rb_ractor_newobj_heap_cache_t *heap_cache = &gc_cache->heap_caches[heap_idx]; - GC_ASSERT(heap_cache->cursor >= heap_cache->cursor_end); + GC_ASSERT(bump->cursor + bump->slot_size > bump->cursor_end); GC_ASSERT(heap_cache->next_region == NULL); GC_ASSERT(page->free_slots != 0); GC_ASSERT(page->free_region != NULL); @@ -2574,11 +2625,14 @@ ractor_cache_set_page(rb_objspace_t *objspace, rb_ractor_newobj_cache_t *cache, struct free_region *region = page->free_region; rb_asan_unpoison_object((VALUE)region, false); GC_ASSERT(RB_TYPE_P((VALUE)region, T_NONE)); - heap_cache->cursor = (uintptr_t)region; - heap_cache->cursor_end = region->end; + bump->cursor = (uintptr_t)region; + bump->region_start = (uintptr_t)region; + heap_cache->region_end = region->end; heap_cache->next_region = region->next; rb_asan_poison_object((VALUE)region); + ractor_cache_open_window(objspace, bump, heap_cache); + page->free_slots = 0; page->free_region = NULL; } @@ -2615,11 +2669,50 @@ rb_gc_impl_size_slot_size(void *objspace_ptr, size_t size) return heap_slot_size((unsigned char)heap_idx_for_size(size)); } -NOINLINE(static VALUE newobj_cache_miss(rb_objspace_t *objspace, rb_ractor_newobj_cache_t *cache, size_t heap_idx, bool vm_locked)); +bool +rb_gc_impl_zjit_new_obj_fastpath(void *objspace_ptr, size_t alloc_size, VALUE flags, VALUE klass, + struct rb_gc_zjit_fastpath *fastpath) +{ +#if USE_ZJIT + size_t heap_idx = 0; + size_t slot_size = 0; + for (; pool_slot_sizes[heap_idx] != 0; heap_idx++) { + if (alloc_size <= pool_slot_sizes[heap_idx]) { + slot_size = pool_slot_sizes[heap_idx]; + break; + } + } + if (slot_size == 0) return false; + + size_t bump_base = offsetof(rb_ractor_newobj_cache_t, bump_heaps) + + heap_idx * sizeof(struct gc_bump_pointer_heap); + + struct rb_gc_zjit_default_new_obj_fastpath default_fastpath = { + bump_base + offsetof(struct gc_bump_pointer_heap, cursor), + bump_base + offsetof(struct gc_bump_pointer_heap, jit_cursor_end), + slot_size, + flags, + klass + }; + + memset(fastpath, 0, sizeof(*fastpath)); + fastpath->kind = RB_GC_ZJIT_FASTPATH_DEFAULT; + memcpy(fastpath->data.words, &default_fastpath, sizeof(default_fastpath)); + + return true; +#else + return false; +#endif +} + +NOINLINE(static VALUE newobj_bump_pointer_miss(rb_objspace_t *objspace, rb_ractor_newobj_cache_t *gc_cache, size_t heap_idx, bool vm_locked)); static VALUE -newobj_cache_miss(rb_objspace_t *objspace, rb_ractor_newobj_cache_t *cache, size_t heap_idx, bool vm_locked) +newobj_bump_pointer_miss(rb_objspace_t *objspace, rb_ractor_newobj_cache_t *gc_cache, size_t heap_idx, bool vm_locked) { + struct gc_bump_pointer_heap *bump = &gc_cache->bump_heaps[heap_idx]; + rb_ractor_newobj_cache_t *cache = gc_cache; + rb_ractor_newobj_heap_cache_t *heap_cache = &cache->heap_caches[heap_idx]; rb_heap_t *heap = &heaps[heap_idx]; VALUE obj = Qfalse; @@ -2632,21 +2725,57 @@ newobj_cache_miss(rb_objspace_t *objspace, rb_ractor_newobj_cache_t *cache, size } { + if (RB_UNLIKELY(during_gc || ruby_gc_stressful)) { + if (during_gc) { + dont_gc_on(); + during_gc = 0; + if (rb_memerror_reentered()) { + rb_memerror(); + } + rb_bug("object allocation during garbage collection phase"); + } + + if (ruby_gc_stressful) { + if (!garbage_collect(objspace, GPR_FLAG_NEWOBJ)) { + rb_memerror(); + } + } + } + if (is_incremental_marking(objspace)) { - gc_continue(objspace, heap); - cache->incremental_mark_step_allocated_slots = 0; + if (bump->slot_size > 0) { + cache->incremental_mark_step_allocated_slots += + (bump->cursor - bump->region_start) / bump->slot_size; + } + gc_bump_flush_alloc_count(bump, heap); + + if (cache->incremental_mark_step_allocated_slots >= INCREMENTAL_MARK_STEP_ALLOCATIONS) { + gc_continue(objspace, heap); + cache->incremental_mark_step_allocated_slots = 0; + } + + if (bump->cursor + bump->slot_size <= heap_cache->region_end) { + ractor_cache_open_window(objspace, bump, heap_cache); + obj = ractor_cache_allocate_slot(objspace, gc_cache, heap_idx); + } + } - // Retry allocation after resetting incremental_mark_step_allocated_slots - obj = ractor_cache_allocate_slot(objspace, cache, heap_idx); + if (obj == Qfalse) { + if (ractor_cache_advance_region(objspace, bump, heap_cache, heap)) { + obj = ractor_cache_allocate_slot(objspace, gc_cache, heap_idx); + } } if (obj == Qfalse) { - // Get next free page (possibly running GC) struct heap_page *page = heap_next_free_page(objspace, heap); - ractor_cache_set_page(objspace, cache, heap_idx, page); + ractor_cache_set_page(objspace, gc_cache, heap_idx, page); + + obj = ractor_cache_allocate_slot(objspace, gc_cache, heap_idx); + } - // Retry allocation after moving to new page - obj = ractor_cache_allocate_slot(objspace, cache, heap_idx); + if (RB_UNLIKELY(ruby_gc_stressful)) { + bump->cursor_end = bump->cursor; + bump->jit_cursor_end = bump->cursor; } } @@ -2661,45 +2790,28 @@ newobj_cache_miss(rb_objspace_t *objspace, rb_ractor_newobj_cache_t *cache, size } static VALUE -newobj_alloc(rb_objspace_t *objspace, rb_ractor_newobj_cache_t *cache, size_t heap_idx, bool vm_locked) +newobj_alloc(rb_objspace_t *objspace, rb_ractor_newobj_cache_t *gc_cache, size_t heap_idx, bool vm_locked) { - VALUE obj = ractor_cache_allocate_slot(objspace, cache, heap_idx); + VALUE obj = ractor_cache_allocate_slot(objspace, gc_cache, heap_idx); if (RB_UNLIKELY(obj == Qfalse)) { - obj = newobj_cache_miss(objspace, cache, heap_idx, vm_locked); + obj = newobj_bump_pointer_miss(objspace, gc_cache, heap_idx, vm_locked); } return obj; } -ALWAYS_INLINE(static VALUE newobj_slowpath(VALUE klass, VALUE flags, rb_objspace_t *objspace, rb_ractor_newobj_cache_t *cache, int wb_protected, size_t heap_idx)); +ALWAYS_INLINE(static VALUE newobj_slowpath(VALUE klass, VALUE flags, rb_objspace_t *objspace, rb_ractor_newobj_cache_t *gc_cache, int wb_protected, size_t heap_idx)); static inline VALUE -newobj_slowpath(VALUE klass, VALUE flags, rb_objspace_t *objspace, rb_ractor_newobj_cache_t *cache, int wb_protected, size_t heap_idx) +newobj_slowpath(VALUE klass, VALUE flags, rb_objspace_t *objspace, rb_ractor_newobj_cache_t *gc_cache, int wb_protected, size_t heap_idx) { VALUE obj; unsigned int lev; lev = RB_GC_CR_LOCK(); { - if (RB_UNLIKELY(during_gc || ruby_gc_stressful)) { - if (during_gc) { - dont_gc_on(); - during_gc = 0; - if (rb_memerror_reentered()) { - rb_memerror(); - } - rb_bug("object allocation during garbage collection phase"); - } - - if (ruby_gc_stressful) { - if (!garbage_collect(objspace, GPR_FLAG_NEWOBJ)) { - rb_memerror(); - } - } - } - - obj = newobj_alloc(objspace, cache, heap_idx, true); + obj = newobj_alloc(objspace, gc_cache, heap_idx, true); newobj_init(klass, flags, wb_protected, objspace, obj); } RB_GC_CR_UNLOCK(lev); @@ -2708,20 +2820,20 @@ newobj_slowpath(VALUE klass, VALUE flags, rb_objspace_t *objspace, rb_ractor_new } NOINLINE(static VALUE newobj_slowpath_wb_protected(VALUE klass, VALUE flags, - rb_objspace_t *objspace, rb_ractor_newobj_cache_t *cache, size_t heap_idx)); + rb_objspace_t *objspace, rb_ractor_newobj_cache_t *gc_cache, size_t heap_idx)); NOINLINE(static VALUE newobj_slowpath_wb_unprotected(VALUE klass, VALUE flags, - rb_objspace_t *objspace, rb_ractor_newobj_cache_t *cache, size_t heap_idx)); + rb_objspace_t *objspace, rb_ractor_newobj_cache_t *gc_cache, size_t heap_idx)); static VALUE -newobj_slowpath_wb_protected(VALUE klass, VALUE flags, rb_objspace_t *objspace, rb_ractor_newobj_cache_t *cache, size_t heap_idx) +newobj_slowpath_wb_protected(VALUE klass, VALUE flags, rb_objspace_t *objspace, rb_ractor_newobj_cache_t *gc_cache, size_t heap_idx) { - return newobj_slowpath(klass, flags, objspace, cache, TRUE, heap_idx); + return newobj_slowpath(klass, flags, objspace, gc_cache, TRUE, heap_idx); } static VALUE -newobj_slowpath_wb_unprotected(VALUE klass, VALUE flags, rb_objspace_t *objspace, rb_ractor_newobj_cache_t *cache, size_t heap_idx) +newobj_slowpath_wb_unprotected(VALUE klass, VALUE flags, rb_objspace_t *objspace, rb_ractor_newobj_cache_t *gc_cache, size_t heap_idx) { - return newobj_slowpath(klass, flags, objspace, cache, FALSE, heap_idx); + return newobj_slowpath(klass, flags, objspace, gc_cache, FALSE, heap_idx); } VALUE @@ -2742,19 +2854,19 @@ rb_gc_impl_new_obj(void *objspace_ptr, void *cache_ptr, VALUE klass, VALUE flags size_t heap_idx = heap_idx_for_size(alloc_size); *actual_alloc_size = heap_slot_size((unsigned char)heap_idx); - rb_ractor_newobj_cache_t *cache = (rb_ractor_newobj_cache_t *)cache_ptr; + rb_ractor_newobj_cache_t *gc_cache = (rb_ractor_newobj_cache_t *)cache_ptr; if (!RB_UNLIKELY(during_gc || ruby_gc_stressful) && wb_protected) { - obj = newobj_alloc(objspace, cache, heap_idx, false); + obj = newobj_alloc(objspace, gc_cache, heap_idx, false); newobj_init(klass, flags, wb_protected, objspace, obj); } else { RB_DEBUG_COUNTER_INC(obj_newobj_slowpath); obj = wb_protected ? - newobj_slowpath_wb_protected(klass, flags, objspace, cache, heap_idx) : - newobj_slowpath_wb_unprotected(klass, flags, objspace, cache, heap_idx); + newobj_slowpath_wb_protected(klass, flags, objspace, gc_cache, heap_idx) : + newobj_slowpath_wb_unprotected(klass, flags, objspace, gc_cache, heap_idx); } return obj; @@ -3475,7 +3587,6 @@ heap_page_alloc_slot_from_region(struct heap_page *free_page) asan_unlock_freelist(free_page); if (new_start < region_end) { - /* Shrink the region: rewrite its header one slot forward. */ VALUE next_start = (VALUE)new_start; rb_asan_unpoison_object(next_start, false); struct free_region *new_region = (struct free_region *)new_start; @@ -3486,7 +3597,6 @@ heap_page_alloc_slot_from_region(struct heap_page *free_page) free_page->free_region = new_region; } else { - /* The region held a single slot. */ free_page->free_region = next; } asan_lock_freelist(free_page); @@ -3511,7 +3621,6 @@ try_move(rb_objspace_t *objspace, rb_heap_t *heap, struct heap_page *free_page, uintptr_t dest_slot = heap_page_alloc_slot_from_region(free_page); if (dest_slot == 0) { - /* if we can't get a slot then the page must be full */ return false; } VALUE dest = (VALUE)dest_slot; @@ -4003,16 +4112,17 @@ gc_mode_transition(rb_objspace_t *objspace, enum gc_mode mode) } static void -heap_page_flush_cache_regions(struct heap_page *page, rb_ractor_newobj_heap_cache_t *heap_cache) +heap_page_flush_cache_regions(struct heap_page *page, struct gc_bump_pointer_heap *bump, + rb_ractor_newobj_heap_cache_t *heap_cache) { struct free_region *chain = heap_cache->next_region; - if (heap_cache->cursor < heap_cache->cursor_end) { - VALUE start = (VALUE)heap_cache->cursor; + if (bump->cursor < heap_cache->region_end) { + VALUE start = (VALUE)bump->cursor; rb_asan_unpoison_object(start, false); struct free_region *remnant = (struct free_region *)start; remnant->flags = 0; - remnant->end = heap_cache->cursor_end; + remnant->end = heap_cache->region_end; remnant->next = chain; rb_asan_poison_object(start); chain = remnant; @@ -4069,30 +4179,45 @@ static int compare_pinned_slots(const void *left, const void *right, void *d); static void gc_ractor_newobj_cache_clear(void *c, void *data) { - rb_objspace_t *objspace = rb_gc_get_objspace(); - rb_ractor_newobj_cache_t *newobj_cache = c; + rb_objspace_t *objspace = data; + rb_ractor_newobj_cache_t *gc_cache = c; + rb_ractor_newobj_cache_t *newobj_cache = gc_cache; newobj_cache->incremental_mark_step_allocated_slots = 0; for (size_t heap_idx = 0; heap_idx < HEAP_COUNT; heap_idx++) { - + struct gc_bump_pointer_heap *bump = &gc_cache->bump_heaps[heap_idx]; rb_ractor_newobj_heap_cache_t *cache = &newobj_cache->heap_caches[heap_idx]; rb_heap_t *heap = &heaps[heap_idx]; - RUBY_ATOMIC_SIZE_ADD(heap->total_allocated_objects, cache->allocated_objects_count); - cache->allocated_objects_count = 0; + gc_bump_flush_alloc_count(bump, heap); struct heap_page *page = cache->using_page; - RUBY_DEBUG_LOG("ractor using_page:%p cursor:%p", (void *)page, (void *)cache->cursor); + RUBY_DEBUG_LOG("ractor using_page:%p cursor:%p", (void *)page, (void *)bump->cursor); if (page) { - heap_page_flush_cache_regions(page, cache); + heap_page_flush_cache_regions(page, bump, cache); } cache->using_page = NULL; - cache->cursor = 0; - cache->cursor_end = 0; cache->next_region = NULL; + cache->region_end = 0; + bump->cursor = 0; + bump->cursor_end = 0; + bump->jit_cursor_end = 0; + bump->region_start = 0; + } +} + +static void +gc_ractor_newobj_cache_exhaust(void *c, void *data) +{ + rb_ractor_newobj_cache_t *gc_cache = c; + + for (size_t heap_idx = 0; heap_idx < HEAP_COUNT; heap_idx++) { + struct gc_bump_pointer_heap *bump = &gc_cache->bump_heaps[heap_idx]; + bump->cursor_end = bump->cursor; + bump->jit_cursor_end = bump->cursor; } } @@ -4183,7 +4308,7 @@ gc_sweep_start(rb_objspace_t *objspace) } } - rb_gc_ractor_newobj_cache_foreach(gc_ractor_newobj_cache_clear, NULL); + rb_gc_ractor_newobj_cache_foreach(gc_ractor_newobj_cache_clear, objspace); } static void @@ -4292,6 +4417,8 @@ gc_sweep_step(rb_objspace_t *objspace, rb_heap_t *heap) gc_sweep_page(objspace, heap, &ctx); int free_slots = ctx.freed_slots + ctx.empty_slots; + RUBY_DTRACE_GC_HOOK(SWEEP_PAGE, ctx.page->slot_size, ctx.final_slots, ctx.freed_slots, ctx.empty_slots); + heap->sweeping_page = ccan_list_next(&heap->pages, sweep_page, page_node); if (free_slots == sweep_page->total_slots) { @@ -5053,12 +5180,13 @@ gc_mark_stacked_objects(rb_objspace_t *objspace, int incremental, size_t count) } gc_mark_children(objspace, obj); + popped_count++; + if (incremental) { if (RGENGC_CHECK_MODE && !RVALUE_MARKING(objspace, obj)) { rb_bug("gc_mark_stacked_objects: incremental, but marking bit is 0"); } CLEAR_IN_BITMAP(GET_HEAP_MARKING_BITS(obj), obj); - popped_count++; if (popped_count + (objspace->marked_slots - marked_slots_at_the_beginning) > count) { break; @@ -5069,6 +5197,8 @@ gc_mark_stacked_objects(rb_objspace_t *objspace, int incremental, size_t count) } } + RUBY_DTRACE_GC_HOOK(MARK_STACKED_OBJECTS, popped_count); + if (RGENGC_CHECK_MODE >= 3) gc_verify_internal_consistency(objspace); if (is_mark_stack_empty(mstack)) { @@ -6235,6 +6365,10 @@ gc_marks_start(rb_objspace_t *objspace, int full_mark) mark_roots(objspace, NULL); + if (is_incremental_marking(objspace)) { + rb_gc_ractor_newobj_cache_foreach(gc_ractor_newobj_cache_exhaust, NULL); + } + gc_report(1, objspace, "gc_marks_start: (%s) end, stack in %"PRIdSIZE"\n", full_mark ? "full" : "minor", mark_stack_size(&objspace->mark_stack)); } @@ -6692,17 +6826,25 @@ rb_gc_impl_ractor_cache_alloc(void *objspace_ptr, void *ractor) objspace->live_ractor_cache_count++; - return calloc1(sizeof(rb_ractor_newobj_cache_t)); + rb_ractor_newobj_cache_t *gc_cache = + calloc1(sizeof(rb_ractor_newobj_cache_t) + + sizeof(struct gc_bump_pointer_heap) * (HEAP_COUNT + 1)); + + for (size_t i = 0; i < HEAP_COUNT; i++) { + gc_cache->bump_heaps[i].slot_size = pool_slot_sizes[i]; + } + return gc_cache; } void -rb_gc_impl_ractor_cache_free(void *objspace_ptr, void *cache) +rb_gc_impl_ractor_cache_free(void *objspace_ptr, void *cache_ptr) { rb_objspace_t *objspace = objspace_ptr; + rb_ractor_newobj_cache_t *gc_cache = cache_ptr; objspace->live_ractor_cache_count--; - gc_ractor_newobj_cache_clear(cache, NULL); - free(cache); + gc_ractor_newobj_cache_clear(gc_cache, objspace); + free(gc_cache); } static void @@ -7113,6 +7255,8 @@ gc_enter(rb_objspace_t *objspace, enum gc_enter_event event, unsigned int *lock_ { *lock_lev = RB_GC_VM_LOCK(); + RUBY_DTRACE_GC_HOOK(ENTER, event); + if (objspace->profile.run) { switch (event) { case gc_enter_event_start: @@ -7160,6 +7304,8 @@ gc_exit(rb_objspace_t *objspace, enum gc_enter_event event, unsigned int *lock_l { GC_ASSERT(during_gc != 0); + RUBY_DTRACE_GC_HOOK(EXIT, event); + rb_gc_event_hook(0, RUBY_INTERNAL_EVENT_GC_EXIT); if (objspace->profile.gc_pause_start_time) { @@ -7239,6 +7385,8 @@ gc_sweeping_enter(rb_objspace_t *objspace) if (MEASURE_GC) { gc_clock_start(&objspace->profile.sweeping_start_time); } + + rb_gc_initialize_vm_context(&objspace->vm_context); } static void @@ -8328,6 +8476,10 @@ rb_gc_impl_stress_set(void *objspace_ptr, VALUE flag) objspace->flags.gc_stressful = RTEST(flag); objspace->gc_stress_mode = flag; + + if (objspace->flags.gc_stressful) { + rb_gc_ractor_newobj_cache_foreach(gc_ractor_newobj_cache_exhaust, NULL); + } } static int @@ -9160,9 +9312,6 @@ gc_prof_timer_stop(rb_objspace_t *objspace) } } -#define RUBY_DTRACE_GC_HOOK(name) \ - do {if (RUBY_DTRACE_GC_##name##_ENABLED()) RUBY_DTRACE_GC_##name();} while (0) - static inline void gc_prof_mark_timer_start(rb_objspace_t *objspace) { @@ -10198,7 +10347,7 @@ rb_gc_impl_after_fork(void *objspace_ptr, rb_pid_t pid) objspace->fork_vm_lock_lev = 0; if (pid == 0) { /* child process */ - rb_gc_ractor_newobj_cache_foreach(gc_ractor_newobj_cache_clear, NULL); + rb_gc_ractor_newobj_cache_foreach(gc_ractor_newobj_cache_clear, objspace); } } @@ -10332,7 +10481,7 @@ rb_gc_impl_init(void) rb_hash_aset(gc_constants, ID2SYM(rb_intern("HEAP_PAGE_BITMAP_SIZE")), SIZET2NUM(HEAP_PAGE_BITMAP_SIZE)); rb_hash_aset(gc_constants, ID2SYM(rb_intern("HEAP_PAGE_SIZE")), SIZET2NUM(HEAP_PAGE_SIZE)); rb_hash_aset(gc_constants, ID2SYM(rb_intern("HEAP_COUNT")), LONG2FIX(HEAP_COUNT)); - rb_hash_aset(gc_constants, ID2SYM(rb_intern("RVARGC_MAX_ALLOCATE_SIZE")), LONG2FIX(heap_slot_size(HEAP_COUNT - 1))); + rb_hash_aset(gc_constants, ID2SYM(rb_intern("RVARGC_MAX_ALLOCATE_SIZE")), SIZET2NUM(rb_gc_impl_max_allocation_size())); rb_hash_aset(gc_constants, ID2SYM(rb_intern("RVALUE_OLD_AGE")), LONG2FIX(RVALUE_OLD_AGE)); if (RB_BUG_INSTEAD_OF_RB_MEMERROR+0) { rb_hash_aset(gc_constants, ID2SYM(rb_intern("RB_BUG_INSTEAD_OF_RB_MEMERROR")), Qtrue); diff --git a/gc/default/zjit_fastpath.h b/gc/default/zjit_fastpath.h new file mode 100644 index 00000000000000..08dd00928f50f3 --- /dev/null +++ b/gc/default/zjit_fastpath.h @@ -0,0 +1,21 @@ +#ifndef RUBY_GC_DEFAULT_ZJIT_FASTPATH_H +#define RUBY_GC_DEFAULT_ZJIT_FASTPATH_H + +#include + +#include "gc/gc_impl.h" +#include "ruby/internal/static_assert.h" +#include "ruby/ruby.h" + +struct rb_gc_zjit_default_new_obj_fastpath { + size_t cursor_offset; + size_t jit_cursor_end_offset; + size_t slot_size; + VALUE flags; + VALUE klass; +}; + +RBIMPL_STATIC_ASSERT(zjit_default_fastpath_fits, + sizeof(struct rb_gc_zjit_default_new_obj_fastpath) <= sizeof(union rb_gc_zjit_fastpath_data)); + +#endif /* RUBY_GC_DEFAULT_ZJIT_FASTPATH_H */ diff --git a/gc/gc.h b/gc/gc.h index 2a20d65c56cf1d..d8c351c7e92754 100644 --- a/gc/gc.h +++ b/gc/gc.h @@ -38,8 +38,6 @@ struct rb_gc_obj_suffix { #endif struct rb_gc_vm_context { - rb_nativethread_lock_t lock; - struct rb_execution_context_struct *ec; }; diff --git a/gc/gc_impl.h b/gc/gc_impl.h index 892831c8c175a8..5aa8fee1503a79 100644 --- a/gc/gc_impl.h +++ b/gc/gc_impl.h @@ -10,6 +10,33 @@ */ #include "ruby/ruby.h" +#include +#include + +struct gc_bump_pointer_heap { + uintptr_t cursor; + uintptr_t cursor_end; + uintptr_t jit_cursor_end; + uintptr_t region_start; + size_t slot_size; +}; + +enum rb_gc_zjit_fastpath_kind { + RB_GC_ZJIT_FASTPATH_DEFAULT = 1, + RB_GC_ZJIT_FASTPATH_MMTK = 2, +}; + +#define RB_GC_ZJIT_FASTPATH_DATA_WORDS 19 + +union rb_gc_zjit_fastpath_data { + uintptr_t words[RB_GC_ZJIT_FASTPATH_DATA_WORDS]; +}; + +struct rb_gc_zjit_fastpath { + enum rb_gc_zjit_fastpath_kind kind; + union rb_gc_zjit_fastpath_data data; +}; + #ifndef RB_GC_OBJECT_METADATA_ENTRY_DEFINED # define RB_GC_OBJECT_METADATA_ENTRY_DEFINED struct rb_gc_object_metadata_entry { @@ -56,9 +83,20 @@ GC_IMPL_FN void rb_gc_impl_config_set(void *objspace_ptr, VALUE hash); GC_IMPL_FN struct rb_gc_vm_context *rb_gc_impl_get_vm_context(void *objspace_ptr); // Object allocation GC_IMPL_FN VALUE rb_gc_impl_new_obj(void *objspace_ptr, void *cache_ptr, VALUE klass, VALUE flags, bool wb_protected, size_t alloc_size, size_t *actual_alloc_size); +/* This is an (optional) function that allows the GC implementation to return + * metadata for ZJIT's fast path object allocator. Returns `true` if ZJIT can + * use the fast path allocator, `false` otherwise. + * + * The GC is provided `alloc_size`, `flags`, and `class` which describe the + * object to be allocated. The GC can use this information to perform + * precomputation and fill `fastpath` with GC-specific metadata. ZJIT owns the + * generated instruction sequence; see zjit/src/gc_fastpath.rs. + */ +GC_IMPL_FN bool rb_gc_impl_zjit_new_obj_fastpath(void *objspace_ptr, size_t alloc_size, VALUE flags, VALUE klass, struct rb_gc_zjit_fastpath *fastpath); GC_IMPL_FN size_t rb_gc_impl_obj_slot_size(VALUE obj); GC_IMPL_FN size_t rb_gc_impl_size_slot_size(void *objspace_ptr, size_t size); GC_IMPL_FN bool rb_gc_impl_size_allocatable_p(size_t size); +GC_IMPL_FN size_t rb_gc_impl_max_allocation_size(void); // Malloc /* * BEWARE: These functions may or may not run under GVL. diff --git a/gc/mmtk/mmtk.c b/gc/mmtk/mmtk.c index 3600a3d2e36ce8..6c43c89b5952f0 100644 --- a/gc/mmtk/mmtk.c +++ b/gc/mmtk/mmtk.c @@ -1,5 +1,6 @@ #include #include +#include #include "ruby/assert.h" #include "ruby/atomic.h" @@ -9,6 +10,10 @@ #include "gc/gc_impl.h" #include "gc/mmtk/mmtk.h" +#if USE_ZJIT +# include "gc/mmtk/zjit_fastpath.h" +#endif + #include "ccan/list/list.h" #include "darray.h" @@ -104,6 +109,8 @@ RB_THREAD_LOCAL_SPECIFIER VALUE marking_parent_object; #include +#define MMTK_ALLOCATION_SEMANTICS_DEFAULT 0 + static inline VALUE rb_mmtk_call_object_closure(VALUE obj, bool pin); static void @@ -643,6 +650,20 @@ rb_gc_impl_ractor_cache_free(void *objspace_ptr, void *cache_ptr) objspace->live_ractor_cache_count--; mmtk_destroy_mutator(cache->mutator); + + free(cache); +} + +static bool +zjit_mmtk_gc_stress_p(void *objspace_ptr) +{ + return ((struct objspace *)objspace_ptr)->gc_stress; +} + +static bool +zjit_mmtk_newobj_tracing_p(void) +{ + return rb_gc_event_hook_required_p(RUBY_INTERNAL_EVENT_NEWOBJ); } void rb_gc_impl_set_params(void *objspace_ptr) { } @@ -663,6 +684,59 @@ static size_t heap_sizes[MMTK_HEAP_COUNT + 1] = { }; #endif +bool +rb_gc_impl_zjit_new_obj_fastpath(void *objspace_ptr, size_t alloc_size, VALUE flags, VALUE klass, + struct rb_gc_zjit_fastpath *fastpath) +{ +#if USE_ZJIT && RB_GC_OBJ_SUFFIX_SIZE == 0 + struct objspace *objspace = objspace_ptr; + + size_t payload_size = alloc_size; + for (int i = 0; i < MMTK_HEAP_COUNT; i++) { + if (payload_size == heap_sizes[i]) break; + if (payload_size < heap_sizes[i]) { + payload_size = heap_sizes[i]; + break; + } + } + + if (payload_size > MMTK_MAX_OBJ_SIZE) return false; + + size_t total_size = payload_size + sizeof(VALUE) + RB_GC_OBJ_SUFFIX_SIZE; + size_t value_size_shift = sizeof(VALUE) == 8 ? 3 : 2; + + struct rb_gc_zjit_mmtk_new_obj_fastpath mmtk_fastpath = { + objspace, + offsetof(struct objspace, total_allocated_objects), + offsetof(struct MMTk_ractor_cache, mutator), + offsetof(struct MMTk_ractor_cache, bump_pointer), + offsetof(struct MMTk_ractor_cache, obj_free_parallel_buf), + offsetof(struct MMTk_ractor_cache, obj_free_parallel_count), + offsetof(MMTk_BumpPointer, cursor), + offsetof(MMTk_BumpPointer, limit), + MMTk_MIN_OBJ_ALIGN, + payload_size, + total_size, + MMTK_ALLOCATION_SEMANTICS_DEFAULT, + (uintptr_t)zjit_mmtk_gc_stress_p, + (uintptr_t)zjit_mmtk_newobj_tracing_p, + (uintptr_t)mmtk_post_alloc, + OBJ_FREE_BUF_CAPACITY - 1, + value_size_shift, + flags, + klass + }; + + memset(fastpath, 0, sizeof(*fastpath)); + fastpath->kind = RB_GC_ZJIT_FASTPATH_MMTK; + memcpy(fastpath->data.words, &mmtk_fastpath, sizeof(mmtk_fastpath)); + + return true; +#else + return false; +#endif +} + void rb_gc_impl_init(void) { @@ -670,7 +744,7 @@ rb_gc_impl_init(void) rb_hash_aset(gc_constants, ID2SYM(rb_intern("RVALUE_SIZE")), SIZET2NUM(SIZEOF_VALUE >= 8 ? 64 : 32)); rb_hash_aset(gc_constants, ID2SYM(rb_intern("RBASIC_SIZE")), SIZET2NUM(sizeof(struct RBasic))); rb_hash_aset(gc_constants, ID2SYM(rb_intern("RVALUE_OVERHEAD")), INT2NUM(0)); - rb_hash_aset(gc_constants, ID2SYM(rb_intern("RVARGC_MAX_ALLOCATE_SIZE")), LONG2FIX(MMTK_MAX_OBJ_SIZE)); + rb_hash_aset(gc_constants, ID2SYM(rb_intern("RVARGC_MAX_ALLOCATE_SIZE")), SIZET2NUM(rb_gc_impl_max_allocation_size())); rb_hash_aset(gc_constants, ID2SYM(rb_intern("HEAP_COUNT")), LONG2FIX(MMTK_HEAP_COUNT)); // TODO: correctly set RVALUE_OLD_AGE when we have generational GC support rb_hash_aset(gc_constants, ID2SYM(rb_intern("RVALUE_OLD_AGE")), INT2FIX(0)); @@ -898,7 +972,6 @@ mmtk_post_alloc_fast_immix(struct objspace *objspace, struct MMTk_ractor_cache * VALUE rb_gc_impl_new_obj(void *objspace_ptr, void *cache_ptr, VALUE klass, VALUE flags, bool wb_protected, size_t alloc_size, size_t *actual_alloc_size) { -#define MMTK_ALLOCATION_SEMANTICS_DEFAULT 0 struct objspace *objspace = objspace_ptr; struct MMTk_ractor_cache *ractor_cache = cache_ptr; @@ -969,7 +1042,13 @@ rb_gc_impl_size_slot_size(void *objspace_ptr, size_t size) bool rb_gc_impl_size_allocatable_p(size_t size) { - return size <= MMTK_MAX_OBJ_SIZE; + return size <= rb_gc_impl_max_allocation_size(); +} + +size_t +rb_gc_impl_max_allocation_size(void) +{ + return MMTK_MAX_OBJ_SIZE; } // Malloc diff --git a/gc/mmtk/zjit_fastpath.h b/gc/mmtk/zjit_fastpath.h new file mode 100644 index 00000000000000..b2a106ba19cd55 --- /dev/null +++ b/gc/mmtk/zjit_fastpath.h @@ -0,0 +1,36 @@ +#ifndef RUBY_GC_MMTK_ZJIT_FASTPATH_H +#define RUBY_GC_MMTK_ZJIT_FASTPATH_H + +#include +#include + +#include "gc/gc_impl.h" +#include "ruby/internal/static_assert.h" +#include "ruby/ruby.h" + +struct rb_gc_zjit_mmtk_new_obj_fastpath { + const void *objspace; + size_t objspace_total_allocated_objects_offset; + size_t ractor_cache_mutator_offset; + size_t ractor_cache_bump_pointer_offset; + size_t ractor_cache_obj_free_parallel_buf_offset; + size_t ractor_cache_obj_free_parallel_count_offset; + size_t bump_pointer_cursor_offset; + size_t bump_pointer_limit_offset; + size_t min_obj_align; + size_t payload_size; + size_t total_alloc_size; + uint32_t allocation_semantics_default; + uintptr_t gc_stress_p_func; + uintptr_t newobj_tracing_p_func; + uintptr_t post_alloc_func; + size_t obj_free_buf_capacity_minus_one; + size_t value_size_shift; + VALUE flags; + VALUE klass; +}; + +RBIMPL_STATIC_ASSERT(zjit_mmtk_fastpath_fits, + sizeof(struct rb_gc_zjit_mmtk_new_obj_fastpath) <= sizeof(union rb_gc_zjit_fastpath_data)); + +#endif /* RUBY_GC_MMTK_ZJIT_FASTPATH_H */ diff --git a/gc/wbcheck/wbcheck.c b/gc/wbcheck/wbcheck.c index 5da87f5762e7c5..86ab19f87ecc5c 100644 --- a/gc/wbcheck/wbcheck.c +++ b/gc/wbcheck/wbcheck.c @@ -498,6 +498,13 @@ rb_gc_impl_ractor_cache_alloc(void *objspace_ptr, void *ractor) return NULL; } +bool +rb_gc_impl_zjit_new_obj_fastpath(void *objspace_ptr, size_t alloc_size, VALUE flags, VALUE klass, + struct rb_gc_zjit_fastpath *fastpath) +{ + return false; +} + void rb_gc_impl_set_params(void *objspace_ptr) { @@ -518,7 +525,7 @@ rb_gc_impl_init(void) rb_hash_aset(gc_constants, ID2SYM(rb_intern("RVALUE_SIZE")), SIZET2NUM(sizeof(struct RBasic) + sizeof(VALUE[RBIMPL_RVALUE_EMBED_LEN_MAX]))); rb_hash_aset(gc_constants, ID2SYM(rb_intern("RBASIC_SIZE")), SIZET2NUM(sizeof(struct RBasic))); rb_hash_aset(gc_constants, ID2SYM(rb_intern("RVALUE_OVERHEAD")), INT2NUM(0)); - rb_hash_aset(gc_constants, ID2SYM(rb_intern("RVARGC_MAX_ALLOCATE_SIZE")), LONG2FIX(MAX_HEAP_SIZE)); + rb_hash_aset(gc_constants, ID2SYM(rb_intern("RVARGC_MAX_ALLOCATE_SIZE")), SIZET2NUM(rb_gc_impl_max_allocation_size())); rb_hash_aset(gc_constants, ID2SYM(rb_intern("HEAP_COUNT")), LONG2FIX(HEAP_COUNT)); rb_hash_aset(gc_constants, ID2SYM(rb_intern("SIZE_POOL_COUNT")), LONG2FIX(HEAP_COUNT)); rb_hash_aset(gc_constants, ID2SYM(rb_intern("RVALUE_OLD_AGE")), INT2FIX(3)); @@ -1127,7 +1134,13 @@ bool rb_gc_impl_size_allocatable_p(size_t size) { // Only allow sizes up to the largest heap size - return size <= MAX_HEAP_SIZE; + return size <= rb_gc_impl_max_allocation_size(); +} + +size_t +rb_gc_impl_max_allocation_size(void) +{ + return MAX_HEAP_SIZE; } // Malloc diff --git a/imemo.c b/imemo.c index a823b74b5b4525..a70ae1a5523fcd 100644 --- a/imemo.c +++ b/imemo.c @@ -130,33 +130,40 @@ rb_imemo_cdhash_new(size_t size, const struct st_hash_type *type) return (VALUE)memo; } -VALUE -rb_imemo_fields_new(VALUE owner, shape_id_t shape_id, bool shareable) +static VALUE +imemo_fields_new(VALUE owner, VALUE flags, shape_id_t shape_id, size_t size, bool is_shareable) { - size_t capa = RSHAPE(shape_id)->capacity; - size_t embedded_size = offsetof(struct rb_fields, as.embed) + capa * sizeof(VALUE); - RUBY_ASSERT(rb_gc_size_allocatable_p(embedded_size)); - VALUE fields = rb_imemo_new(imemo_fields, owner, embedded_size, shareable); + RUBY_ASSERT(rb_gc_size_allocatable_p(size)); + + flags |= T_IMEMO | (imemo_fields << FL_USHIFT) | (is_shareable ? FL_SHAREABLE : 0); // imemo fields objects should always have "RObject" layout. The // layout in the shape describes the layout of the thing on which it is set. // Imemo fields have the same layout as robject, therefore the layout // should reflect that fact. - RBASIC_SET_SHAPE_ID(fields, rb_shape_id_with_robject_layout(shape_id)); + shape_id = rb_shape_transition_robject(shape_id); + return rb_newobj(GET_EC(), owner, flags, shape_id, true, size); +} + +VALUE +rb_imemo_fields_new(VALUE owner, shape_id_t shape_id, bool shareable) +{ + size_t capa = RSHAPE(shape_id)->capacity; + size_t embedded_size = offsetof(struct rb_fields, as.embed) + capa * sizeof(VALUE); + + VALUE fields = imemo_fields_new(owner, 0, shape_id, embedded_size, shareable); + RUBY_ASSERT(IMEMO_TYPE_P(fields, imemo_fields)); + RUBY_ASSERT(rb_shape_embedded_capacity(RBASIC_SHAPE_ID(fields)) >= capa); + return fields; } VALUE rb_imemo_fields_new_complex(VALUE owner, shape_id_t shape_id, size_t capa, bool shareable) { - VALUE fields = rb_imemo_new(imemo_fields, owner, sizeof(struct rb_fields), shareable); - IMEMO_OBJ_FIELDS(fields)->as.complex.table = st_init_numtable_with_size(capa); - FL_SET_RAW(fields, OBJ_FIELD_HEAP); - // imemo fields objects should always have "RObject" layout. The - // layout in the shape describes the layout of the thing on which it is set. - // Imemo fields have the same layout as robject, therefore the layout - // should reflect that fact. - RBASIC_SET_SHAPE_ID(fields, rb_shape_id_with_robject_layout(shape_id)); + st_table *tbl = st_init_numtable_with_size(capa); + VALUE fields = imemo_fields_new(owner, OBJ_FIELD_HEAP, shape_id, sizeof(struct rb_fields), shareable); + IMEMO_OBJ_FIELDS(fields)->as.complex.table = tbl; return fields; } @@ -178,14 +185,8 @@ imemo_fields_complex_wb_i(st_data_t key, st_data_t value, st_data_t arg) VALUE rb_imemo_fields_new_complex_tbl(VALUE owner, shape_id_t shape_id, st_table *tbl, bool shareable) { - VALUE fields = rb_imemo_new(imemo_fields, owner, sizeof(struct rb_fields), shareable); + VALUE fields = imemo_fields_new(owner, OBJ_FIELD_HEAP, shape_id, sizeof(struct rb_fields), shareable); IMEMO_OBJ_FIELDS(fields)->as.complex.table = tbl; - FL_SET_RAW(fields, OBJ_FIELD_HEAP); - // imemo fields objects should always have "RObject" layout. The - // layout in the shape describes the layout of the thing on which it is set. - // Imemo fields have the same layout as robject, therefore the layout - // should reflect that fact. - RBASIC_SET_SHAPE_ID(fields, rb_shape_id_with_robject_layout(shape_id)); st_foreach(tbl, imemo_fields_trigger_wb_i, (st_data_t)fields); return fields; } diff --git a/include/ruby/internal/core/rregexp.h b/include/ruby/internal/core/rregexp.h index 063f8695f7d868..664fa77a582075 100644 --- a/include/ruby/internal/core/rregexp.h +++ b/include/ruby/internal/core/rregexp.h @@ -27,7 +27,6 @@ #include "ruby/internal/core/rstring.h" #include "ruby/internal/value.h" #include "ruby/internal/value_type.h" -#include "ruby/onigmo.h" /** * Convenient casting macro. @@ -37,13 +36,6 @@ */ #define RREGEXP(obj) RBIMPL_CAST((struct RRegexp *)(obj)) -/** - * Convenient accessor macro. - * - * @param obj An object, which is in fact an ::RRegexp. - * @return The passed object's pattern buffer. - */ -#define RREGEXP_PTR(obj) (&RREGEXP(obj)->pattern) /** @cond INTERNAL_MACRO */ #define RREGEXP_SRC RREGEXP_SRC #define RREGEXP_SRC_PTR RREGEXP_SRC_PTR @@ -79,16 +71,24 @@ struct RRegexp { * catastrophic effects. Just leave it. */ unsigned long usecnt; - - /** - * The pattern buffer. This is a quasi-opaque struct that holds compiled - * intermediate representation of the regular expression. - * - * @note Compilation of a regexp could be delayed until actual match. - */ - struct re_pattern_buffer pattern; /* a.k.a. OnigRegexType, defined in onigmo.h */ }; +RBIMPL_ATTR_PURE_UNLESS_DEBUG() +RBIMPL_ATTR_ARTIFICIAL() +/** + * Convenient getter function. + * + * @param[in] rexp The regular expression in question. + * @return The pattern buffer of the regular expression. + * @pre `rexp` must be of ::RRegexp. + */ +static inline struct re_pattern_buffer * +RREGEXP_PTR(VALUE rexp) +{ + RBIMPL_ASSERT_TYPE(rexp, RUBY_T_REGEXP); + return (struct re_pattern_buffer *)(((struct RRegexp *)rexp) + 1); +} + RBIMPL_ATTR_PURE_UNLESS_DEBUG() RBIMPL_ATTR_ARTIFICIAL() /** diff --git a/internal/gc.h b/internal/gc.h index 6d1df9363fe5e1..8a3dbd1884b4bf 100644 --- a/internal/gc.h +++ b/internal/gc.h @@ -16,6 +16,8 @@ #include "ruby/ruby.h" /* for rb_event_flag_t */ #include "vm_core.h" /* for GET_EC() */ +struct rb_gc_zjit_fastpath; + #ifndef USE_MODULAR_GC # define USE_MODULAR_GC 0 #endif @@ -203,9 +205,11 @@ rb_execution_context_t *rb_gc_get_ec(void); void *rb_gc_ractor_cache_alloc(rb_ractor_t *ractor); void rb_gc_ractor_cache_free(void *cache); +bool rb_gc_zjit_new_obj_fastpath(size_t alloc_size, VALUE flags, VALUE klass, struct rb_gc_zjit_fastpath *fastpath); bool rb_gc_size_allocatable_p(size_t size); size_t rb_gc_size_slot_size(size_t size); +size_t rb_gc_max_allocation_size(void); void rb_gc_mark_and_move(VALUE *ptr); diff --git a/parse.y b/parse.y index 55403f7bde96fa..b6fc74c5a0af3a 100644 --- a/parse.y +++ b/parse.y @@ -6062,6 +6062,10 @@ string_content : tSTRING_CONTENT[content] $$ = p->lex.brace_nest; p->lex.brace_nest = 0; }[brace] + { + $$ = p->lex.lpar_beg; + p->lex.lpar_beg = -1; + }[lpar] { $$ = p->heredoc_indent; p->heredoc_indent = 0; @@ -6073,6 +6077,7 @@ string_content : tSTRING_CONTENT[content] p->lex.strterm = $term; SET_LEX_STATE($state); p->lex.brace_nest = $brace; + p->lex.lpar_beg = $lpar; p->heredoc_indent = $indent; p->heredoc_line_indent = -1; if ($compstmt) nd_unset_fl_newline($compstmt); diff --git a/probes.d b/probes.d index 0762a2d25f3e6d..cfe28838343992 100644 --- a/probes.d +++ b/probes.d @@ -214,6 +214,123 @@ provider ruby { Fired at the end of a sweep phase. */ probe gc__sweep__end(); + + /* + ruby:::gc-enter(event); + + Fired when the `gc_enter` function in default.c is called. + + * `event` the `event` argument passed to gc_enter + */ + probe gc__enter(int event); + + /* + ruby:::gc-exit(event); + + Fired when the `gc_exit` function in default.c is called. + + * `event` the `event` argument passed to gc_exit + */ + probe gc__exit(int event); + + /* + ruby:::gc-mark-stacked-objects(popped_count); + + Fired for every invocation of `gc_mark_stacked_objects` in default.c. + + * `popped_count` the number of objects popped from the mark stack in that invocation + */ + probe gc__mark_stacked_objects(size_t popped_count); + + /* + ruby:::gc-sweep_page(slot_size, final_slots, freed_slots, empty_slots); + + Fired for every page swept in `gc_sweep_step` in default.c. + + * `slot_size` is the slot size of the page. + * Other arguments are from the `gc_sweep_context` struct. + */ + probe gc__sweep_page(int slot_size, int final_slots, int freed_slots, int empty_slots); + + /* + ruby:::gc-obj_new(); + + Fired when an object is allocated + + * `obj` the pointer to the allocated object + * `flags` the initial flags of the object + */ + probe gc__obj_new(void *obj, uintptr_t flags); + + /* + ruby:::gc-obj_free(); + + Fired when finalizing an object with `rb_gc_obj_free`. + + * `obj` the pointer to the finalized object + * `flags` the flags of the object when it is finalized + */ + probe gc__obj_free(void *obj, uintptr_t flags); + + /* + ruby:::gc-xmalloc(n, size); + + Fired when allocating memory with `ruby_xmalloc` or `ruby_xmalloc2`. + + * `n` the number of elements. For `ruby_xmalloc` it is 1. + * `size` the size of each element + */ + probe gc__xmalloc(size_t n, size_t size); + + /* + ruby:::gc-xcalloc(); + + Fired when allocating memory with `ruby_xcalloc`. + + * `n` the number of elements. For `ruby_xmalloc` it is 1. + * `size` the size of each element + */ + probe gc__xcalloc(size_t n, size_t size); + + /* + ruby:::gc-xfree(ptr, size); + + Fired when de-allocating memory with `ruby_xfree` or `ruby_xfree_sized`. + + * `ptr` the pointer to the object + * `size` the size of the object. 0 if called with `xfree` + */ + probe gc__xfree(void *obj, size_t size); + + /* + ruby:::gvl-acquire(); + + Fired the global VM lock is acquired + */ + probe gvl__acquire(); + + /* + ruby:::gvl-release(); + + Fired the global VM lock is release + */ + probe gvl__release(); + + /* + ruby:::rts-set_running(); + + Fired when setting the running thread of a Ractor (`rb_thread_sched::running`). + + This probe is mainly used to identify the duration in which a thread occupies a Ractor. If the + `old_thread` is NULL and the `new_thread` is not NULL, it means the `new_thread` is scheduled + onto a Ractor. If the `old_thread` is not NULL but the `new_thread` is NULL, it means the + `old_thread` is de-scheduled form a Ractor. + + * `sched` the `rb_thread_sched` instance + * `old_thread` the old thread running on the ractor + * `new_thread` the new thread running on the ractor + */ + probe rts__set_running(void *sched, void *old_thread, void *new_thread); }; #pragma D attributes Stable/Evolving/Common provider ruby provider diff --git a/process.c b/process.c index dc7199cba21c94..ebc73ff07ae6bc 100644 --- a/process.c +++ b/process.c @@ -3852,6 +3852,7 @@ getresgid(rb_gid_t *rgid, rb_gid_t *egid, rb_gid_t *sgid) #define HAVE_GETRESGID #endif +#if !defined(RUBY_ASAN_ENABLED) static int has_privilege(void) { @@ -3914,6 +3915,7 @@ has_privilege(void) return 0; } #endif +#endif struct child_handler_disabler_state { diff --git a/re.c b/re.c index 9fbdb68c50c668..4c566f478fc906 100644 --- a/re.c +++ b/re.c @@ -32,6 +32,11 @@ #include "ruby/util.h" #include "ractor_core.h" +struct RRegexp_and_re_pattern_buffer { + struct RRegexp re; + struct re_pattern_buffer pattern; /* a.k.a. OnigRegexType, defined in onigmo.h */ +}; + /* Flags of RRegexp * * 4: KCODE_FIXED @@ -3502,10 +3507,10 @@ rb_reg_initialize_str(VALUE obj, VALUE str, int options, onig_errmsg_buffer err, VALUE rb_reg_s_alloc(VALUE klass) { - NEWOBJ_OF(re, struct RRegexp, klass, T_REGEXP, sizeof(struct RRegexp)); + NEWOBJ_OF(re, struct RRegexp, klass, T_REGEXP, sizeof(struct RRegexp_and_re_pattern_buffer)); - MEMZERO(RREGEXP_PTR(re), struct re_pattern_buffer, 1); - RB_OBJ_WRITE(re, &re->src, 0); + MEMZERO(RREGEXP_PTR((VALUE)re), struct re_pattern_buffer, 1); + RB_OBJ_WRITE((VALUE)re, &re->src, 0); re->usecnt = 0; return (VALUE)re; diff --git a/regcomp.c b/regcomp.c index ec41dbe4a02fdc..d4188087ea377f 100644 --- a/regcomp.c +++ b/regcomp.c @@ -5615,7 +5615,7 @@ onig_reg_copy_body(regex_t* nreg, regex_t* oreg) size_t exact_size = oreg->exact_end - oreg->exact; if (COPY_FAILED(exact, exact_size)) goto err; - (nreg)->exact_end = (oreg)->exact + exact_size; + (nreg)->exact_end = (nreg)->exact + exact_size; } if (IS_NOT_NULL(oreg->p)) { diff --git a/set.c b/set.c index 3d88d8d2ca10ae..9a9a7636f87367 100644 --- a/set.c +++ b/set.c @@ -804,7 +804,7 @@ set_i_add_p(VALUE set, VALUE item) * call-seq: * delete(object) -> self * - * Removes the given +object+ from +self+, if +self+ includes the object; + * Removes the given +object+ from +self+ if +self+ includes the object; * returns +self+: * * set = Set[0, 'zero', :zero] @@ -2472,21 +2472,23 @@ rb_set_size(VALUE set) * === Methods for Deleting * * - #clear: - * Removes all elements in the set; returns +self+. + * Removes all elements from +self+; returns +self+. * - #delete: - * Removes a given object from the set; returns +self+. + * Removes the given object from +self+ if +self+ includes the object; returns +self+. * - #delete?: - * If the given object is an element in the set, - * removes it and returns +self+; otherwise, returns +nil+. - * - #subtract: - * Removes each given object from the set; returns +self+. - * - #delete_if - Removes elements specified by a given block. - * - #select! (aliased as #filter!): - * Removes elements not specified by a given block. + * Like #delete, but returns +nil+ if the object is not in +self+. + * - #delete_if: + * Calls the block with each element in +self+; + * removes the element if the block returns a truthy value. * - #keep_if: - * Removes elements not specified by a given block. + * Calls the block with each element in +self+, + * deleting the element if the block returns +false+ or +nil+; returns +self+. * - #reject! - * Removes elements specified by a given block. + * Like #delete_if, but returns +nil+ if no changes were made. + * - #select! (aliased as #filter!): + * Like #keep_if, but returns +nil+ if no changes were made. + * - #subtract: + * Deletes from +self+ every element found in the given enumerable; returns +self+: * * === Methods for Converting * @@ -2500,29 +2502,26 @@ rb_set_size(VALUE set) * as determined by the given block. * - #flatten: * Returns a new set that is a recursive flattening of +self+. - * - #flatten!: - * Replaces each nested set in +self+ with the elements from that set. + * - #flatten!: Like #flatten, but if any changes were made + * replaces +self+ with the result and returns +self+. * - #inspect (aliased as #to_s): - * Returns a string displaying the elements. + * Returns a string representation of +self+. * - #join: - * Returns a string containing all elements, converted to strings - * as needed, and joined by the given record separator. + * Returns the string formed by joining the string-converted elements of +self+ + * with the given separator. * - #to_a: - * Returns an array containing all set elements. + * Returns an array containing the elements of +self+. * - #to_set: - * Returns +self+ if given no arguments and no block; - * with a block given, returns a new set consisting of block - * return values. - * - * === Methods for Iterating - * - * - #each: - * Calls the block with each successive element; returns +self+. + * With a block given, creates and returns a new set; + * calls the block with each element of +self+, + * and adds the block's returns value to the new set. * * === Other Methods * * - #compare_by_identity: * Sets +self+ to compare by object identity (rather than by object content). + * - #each: + * Calls the block with each successive element of +self+; returns +self+. * - #reset: * Resets the internal state; useful if an element * has been modified while an element in the set. diff --git a/shape.c b/shape.c index 875b62099b7dbc..7e48654c7c5c96 100644 --- a/shape.c +++ b/shape.c @@ -516,7 +516,7 @@ shape_grow_capa(attr_index_t current_capa) { size_t next_size = rb_obj_embedded_size(current_capa + 1); if (UNLIKELY(!rb_gc_size_allocatable_p(next_size))) { - return SHAPE_MAX_CAPACITY; + return rb_shape_max_capacity(); } attr_index_t next_capa = rb_shape_capacity_for_slot_size(rb_gc_size_slot_size(next_size)); @@ -700,7 +700,7 @@ rb_shape_transition_object_id(shape_id_t original_shape_id) bool dont_care; rb_shape_t *shape = NULL; - if (LIKELY(original_shape->next_field_index < SHAPE_MAX_CAPACITY)) { + if (LIKELY(original_shape->next_field_index < rb_shape_max_capacity())) { shape = get_next_shape_internal(original_shape, id_object_id, SHAPE_OBJ_ID, &dont_care, true); } if (!shape) { @@ -765,8 +765,9 @@ shape_get_next(rb_shape_t *shape, enum shape_type shape_type, VALUE klass, ID id } #endif - RUBY_ASSERT(SHAPE_MAX_CAPACITY > 0); - if (UNLIKELY(shape->next_field_index >= SHAPE_MAX_CAPACITY)) { + RUBY_ASSERT(SHAPE_ID_CAPACITY_MAX > 0); + RUBY_ASSERT(rb_shape_max_capacity() > 0); + if (UNLIKELY(shape->next_field_index >= rb_shape_max_capacity())) { return NULL; } @@ -1304,9 +1305,10 @@ rb_shape_verify_consistency(VALUE obj, shape_id_t shape_id) } } - attr_index_t shape_id_capacity = rb_shape_capacity(shape_id); - if (RB_TYPE_P(obj, T_OBJECT)) { + attr_index_t shape_id_capacity = rb_shape_embedded_capacity(shape_id); + if (RB_TYPE_P(obj, T_OBJECT) || IMEMO_TYPE_P(obj, imemo_fields)) { RUBY_ASSERT(shape_id_capacity > 0); + size_t shape_id_slot_size = shape_id_capacity * sizeof(VALUE) + sizeof(struct RBasic); size_t actual_slot_size = rb_gc_obj_slot_size(obj); @@ -1388,7 +1390,7 @@ shape_id_t_to_rb_cShape(shape_id_t shape_id) INT2NUM(shape->parent_offset), rb_shape_edge_name(shape), INT2NUM(shape->next_field_index), - INT2NUM(rb_shape_capacity(shape_id)), + INT2NUM(rb_shape_embedded_capacity(shape_id)), INT2NUM(shape->type), INT2NUM(RSHAPE_CAPACITY(shape_id))); rb_obj_freeze(obj); @@ -1558,6 +1560,10 @@ rb_shape_find_by_id(VALUE mod, VALUE id) void Init_default_shapes(void) { + attr_index_t max_capacity = (attr_index_t)((rb_gc_max_allocation_size() - sizeof(struct RBasic)) / sizeof(VALUE)); + if (max_capacity > SHAPE_ID_CAPACITY_MAX) max_capacity = SHAPE_ID_CAPACITY_MAX; + rb_shape_tree.max_capacity = max_capacity; + #ifdef HAVE_MMAP size_t shape_list_mmap_size = rb_size_mul_or_raise(SHAPE_BUFFER_SIZE, sizeof(rb_shape_t), rb_eRuntimeError); rb_shape_tree.shape_list = (rb_shape_t *)mmap(NULL, shape_list_mmap_size, @@ -1651,7 +1657,7 @@ Init_shape(void) rb_define_const(rb_cShape, "SHAPE_ID_NUM_BITS", INT2NUM(SHAPE_ID_NUM_BITS)); rb_define_const(rb_cShape, "SHAPE_FLAG_SHIFT", INT2NUM(SHAPE_FLAG_SHIFT)); rb_define_const(rb_cShape, "SHAPE_MAX_VARIATIONS", INT2NUM(SHAPE_MAX_VARIATIONS)); - rb_define_const(rb_cShape, "SHAPE_MAX_FIELDS", INT2NUM(SHAPE_MAX_CAPACITY)); + rb_define_const(rb_cShape, "SHAPE_MAX_FIELDS", INT2NUM(rb_shape_max_capacity())); rb_define_const(rb_cShape, "SIZEOF_RB_SHAPE_T", INT2NUM(sizeof(rb_shape_t))); rb_define_const(rb_cShape, "SIZEOF_REDBLACK_NODE_T", INT2NUM(sizeof(redblack_node_t))); rb_define_const(rb_cShape, "SHAPE_BUFFER_SIZE", INT2NUM(sizeof(rb_shape_t) * SHAPE_BUFFER_SIZE)); diff --git a/shape.h b/shape.h index ab126b5a89d0f8..fb5a9616e0ca13 100644 --- a/shape.h +++ b/shape.h @@ -89,18 +89,9 @@ typedef uint32_t redblack_id_t; #define SHAPE_MAX_VARIATIONS 8 -// TODO: Fix this so that the max capacity does not depend on the CPU architecture -#if RBASIC_SHAPE_ID_FIELD -# define SHAPE_MAX_CAPACITY 125 -#else -# define SHAPE_MAX_CAPACITY 126 -#endif - #define INVALID_SHAPE_ID (SHAPE_BUFFER_SIZE - 1) #define ATTR_INDEX_NOT_SET ((attr_index_t)-1) -STATIC_ASSERT(shape_max_capacity, SHAPE_MAX_CAPACITY <= SHAPE_ID_CAPACITY_MAX); - #define ROOT_SHAPE_ID 0x0 #define ROOT_SHAPE_WITH_OBJ_ID 0x1 #define ROOT_COMPLEX_SHAPE_ID (ROOT_SHAPE_ID | SHAPE_ID_FL_COMPLEX) @@ -134,6 +125,7 @@ enum shape_flags { typedef struct { rb_shape_t *shape_list; + attr_index_t max_capacity; } rb_shape_tree_t; RUBY_SYMBOL_EXPORT_BEGIN @@ -143,6 +135,12 @@ RUBY_SYMBOL_EXPORT_END size_t rb_shapes_cache_size(void); size_t rb_shapes_count(void); +static inline attr_index_t +rb_shape_max_capacity(void) +{ + return rb_shape_tree.max_capacity; +} + static inline shape_id_t RBASIC_SHAPE_ID(VALUE obj) { @@ -168,7 +166,7 @@ bool rb_shape_verify_consistency(VALUE obj, shape_id_t shape_id); #endif static inline void -RBASIC_SET_SHAPE_ID_NO_CHECKS(VALUE obj, shape_id_t shape_id) +RBASIC_SET_FULL_SHAPE_ID_NO_CHECKS(VALUE obj, shape_id_t shape_id) { #if RBASIC_SHAPE_ID_FIELD RBASIC(obj)->shape_id = (VALUE)shape_id; @@ -185,14 +183,20 @@ rb_shape_layout(shape_id_t shape_id) return shape_id & SHAPE_ID_LAYOUT_MASK; } +// Assigns the entire shape_id. +// shape_id_t is composed of two parts: +// - The layout and capacity part, which never changes except on GC compaction. +// - All the other bits that regularly change. +// In the overwhelming majority of cases, you want to use RBASIC_SET_SHAPE_ID +// which preserves the object's layout and capacity bits. +// In rare cases you may want to set all bits. static inline void -RBASIC_SET_SHAPE_ID_WITH_CAPACITY(VALUE obj, shape_id_t shape_id) +RBASIC_SET_FULL_SHAPE_ID(VALUE obj, shape_id_t shape_id) { RUBY_ASSERT(!RB_SPECIAL_CONST_P(obj)); RUBY_ASSERT(!RB_TYPE_P(obj, T_IMEMO) || IMEMO_TYPE_P(obj, imemo_fields)); - RUBY_ASSERT(!IMEMO_TYPE_P(obj, imemo_fields) || rb_shape_layout(shape_id) == SHAPE_ID_LAYOUT_ROBJECT); - RBASIC_SET_SHAPE_ID_NO_CHECKS(obj, shape_id); + RBASIC_SET_FULL_SHAPE_ID_NO_CHECKS(obj, shape_id); RUBY_ASSERT(rb_shape_verify_consistency(obj, shape_id)); } @@ -202,8 +206,11 @@ RBASIC_SET_SHAPE_ID(VALUE obj, shape_id_t shape_id) { RUBY_ASSERT(!RB_SPECIAL_CONST_P(obj)); - shape_id = (shape_id & ~SHAPE_ID_CAPACITY_MASK) | (RBASIC_SHAPE_ID(obj) & SHAPE_ID_CAPACITY_MASK); - RBASIC_SET_SHAPE_ID_WITH_CAPACITY(obj, shape_id); + shape_id = ( + (shape_id & ~(SHAPE_ID_CAPACITY_MASK|SHAPE_ID_LAYOUT_MASK)) | + (RBASIC_SHAPE_ID(obj) & (SHAPE_ID_CAPACITY_MASK|SHAPE_ID_LAYOUT_MASK)) + ); + RBASIC_SET_FULL_SHAPE_ID(obj, shape_id); } static inline shape_id_t @@ -273,30 +280,12 @@ rb_shape_canonical_p(shape_id_t shape_id) return !(shape_id & SHAPE_ID_FL_NON_CANONICAL_MASK); } -static inline shape_id_t -rb_shape_id_with_robject_layout(shape_id_t shape_id) -{ - return (shape_id & ~SHAPE_ID_LAYOUT_MASK) | SHAPE_ID_LAYOUT_ROBJECT; -} - static inline attr_index_t -rb_shape_capacity(shape_id_t shape_id) +rb_shape_embedded_capacity(shape_id_t shape_id) { return (attr_index_t)((shape_id & SHAPE_ID_CAPACITY_MASK) >> SHAPE_ID_CAPACITY_OFFSET); } -static inline shape_id_t -rb_shape_id_with_capacity(size_t capacity) -{ - shape_id_t capacity_flags = (shape_id_t)capacity << SHAPE_ID_CAPACITY_OFFSET; - - RUBY_ASSERT(capacity <= SHAPE_ID_CAPACITY_MAX); - RUBY_ASSERT((capacity_flags & SHAPE_ID_CAPACITY_MASK) == capacity_flags); - RUBY_ASSERT(rb_shape_capacity(capacity_flags) == capacity); - - return ROOT_SHAPE_ID | capacity_flags; -} - static inline attr_index_t rb_shape_capacity_for_slot_size(size_t slot_size) { @@ -332,7 +321,7 @@ RSHAPE_TYPE_P(shape_id_t shape_id, enum shape_type type) static inline attr_index_t RSHAPE_CAPACITY(shape_id_t shape_id) { - attr_index_t embedded_capacity = rb_shape_capacity(shape_id); + attr_index_t embedded_capacity = rb_shape_embedded_capacity(shape_id); if (embedded_capacity > RSHAPE(shape_id)->capacity) { return embedded_capacity; @@ -486,6 +475,12 @@ rb_obj_using_gen_fields_table_p(VALUE obj) return rb_obj_gen_fields_p(obj); } +static inline shape_id_t +rb_shape_transition_robject(shape_id_t shape_id) +{ + return (shape_id & ~SHAPE_ID_LAYOUT_MASK) | SHAPE_ID_LAYOUT_ROBJECT; +} + static inline shape_id_t rb_shape_transition_frozen(shape_id_t shape_id) { @@ -519,7 +514,16 @@ rb_shape_transition_offset(shape_id_t shape_id, shape_id_t offset) static inline shape_id_t rb_shape_transition_capacity(shape_id_t shape_id, size_t capacity) { - return (shape_id & (~SHAPE_ID_CAPACITY_MASK)) | rb_shape_id_with_capacity(capacity); + RUBY_ASSERT(capacity <= SHAPE_ID_CAPACITY_MAX); + + shape_id_t capacity_flags = (shape_id_t)capacity << SHAPE_ID_CAPACITY_OFFSET; + return (shape_id & (~SHAPE_ID_CAPACITY_MASK)) | capacity_flags; +} + +static inline shape_id_t +rb_shape_transition_slot_size(shape_id_t shape_id, size_t slot_size) +{ + return rb_shape_transition_capacity(shape_id, rb_shape_capacity_for_slot_size(slot_size)); } shape_id_t rb_shape_transition_object_id(shape_id_t shape_id); @@ -543,6 +547,12 @@ rb_obj_shape_transition_capacity(VALUE obj, size_t capacity) return rb_shape_transition_capacity(RBASIC_SHAPE_ID(obj), capacity); } +static inline shape_id_t +rb_obj_shape_transition_slot_size(VALUE obj, size_t slot_size) +{ + return rb_shape_transition_slot_size(RBASIC_SHAPE_ID(obj), slot_size); +} + static inline shape_id_t rb_obj_shape_transition_object_id(VALUE obj) { diff --git a/string.c b/string.c index a499c60a817a28..73e16b031d3a9b 100644 --- a/string.c +++ b/string.c @@ -630,7 +630,7 @@ static VALUE setup_fake_str(struct RString *fake_str, const char *name, long len, int encidx) { fake_str->basic.flags = T_STRING|RSTRING_NOEMBED|STR_NOFREE|STR_FAKESTR; - RBASIC_SET_SHAPE_ID((VALUE)fake_str, ROOT_SHAPE_ID | SHAPE_ID_LAYOUT_OTHER); + RBASIC_SET_FULL_SHAPE_ID((VALUE)fake_str, ROOT_SHAPE_ID | SHAPE_ID_LAYOUT_OTHER); if (!name) { RUBY_ASSERT_ALWAYS(len == 0); diff --git a/test/-ext-/string/test_capacity.rb b/test/-ext-/string/test_capacity.rb index a23892142afa94..3766dd3d303218 100644 --- a/test/-ext-/string/test_capacity.rb +++ b/test/-ext-/string/test_capacity.rb @@ -8,7 +8,7 @@ class Test_StringCapacity < Test::Unit::TestCase def test_capacity_embedded assert_equal pool_slot_size(0) - embed_header_size - 1, capa('foo') assert_equal max_embed_len, capa('1' * max_embed_len) - assert_equal max_embed_len, capa('1' * (max_embed_len - 1)) + assert_include ((max_embed_len - 1)..max_embed_len), capa('1' * (max_embed_len - 1)) end def test_capacity_shared diff --git a/test/-ext-/string/test_set_len.rb b/test/-ext-/string/test_set_len.rb index 41e14a293ac3c5..1ffa6e77341767 100644 --- a/test/-ext-/string/test_set_len.rb +++ b/test/-ext-/string/test_set_len.rb @@ -4,8 +4,7 @@ class Test_StrSetLen < Test::Unit::TestCase def setup - # Make string long enough so that it is not embedded - @range_end = ("0".ord + GC.stat_heap(0, :slot_size)).chr + @range_end = ("0".ord + 40).chr @s0 = [*"0"..@range_end].join("").freeze @s1 = Bug::String.new(@s0) end diff --git a/test/ruby/test_parse.rb b/test/ruby/test_parse.rb index f1a7b9a311a328..e9e274a32dd2ab 100644 --- a/test/ruby/test_parse.rb +++ b/test/ruby/test_parse.rb @@ -323,6 +323,12 @@ def test_do_lambda end a.call assert_equal(42, b) + + obj = BasicObject.new + assert_nothing_raised do + a = obj.instance_eval('-> a = "#{foo do end}" do end', __FILE__, __LINE__) + end + assert_raise_with_message(NoMethodError, /foo/) {a.call} end def test_block_call_colon2 diff --git a/test/ruby/test_regexp.rb b/test/ruby/test_regexp.rb index 250956dd3a009d..0518f5828e6c4e 100644 --- a/test/ruby/test_regexp.rb +++ b/test/ruby/test_regexp.rb @@ -740,6 +740,7 @@ def test_initialize assert_equal(/foo/, assert_warning(/ignored/) {Regexp.new(/foo/, Regexp::IGNORECASE)}) assert_equal(/foo/, assert_no_warning(/ignored/) {Regexp.new(/foo/)}) assert_equal(/foo/, assert_no_warning(/ignored/) {Regexp.new(/foo/, timeout: nil)}) + assert_equal(/foo/, Regexp.new(Regexp.new("foo"))) arg_encoding_none = //n.options # ARG_ENCODING_NONE is implementation defined value diff --git a/thread_pthread.c b/thread_pthread.c index f819a0030e2d3b..e1f3f7e668d9ba 100644 --- a/thread_pthread.c +++ b/thread_pthread.c @@ -40,6 +40,8 @@ #include #include +#include "probes.h" + #if defined __APPLE__ # include #endif @@ -689,6 +691,11 @@ thread_sched_set_running(struct rb_thread_sched *sched, rb_thread_t *th) RUBY_DEBUG_LOG("th:%u->th:%u", rb_th_serial(sched->running), rb_th_serial(th)); VM_ASSERT(sched->running != th); + if (RUBY_DTRACE_RTS_SET_RUNNING_ENABLED()) { + rb_thread_t *old = sched->running; + RUBY_DTRACE_RTS_SET_RUNNING(sched, old, th); + } + sched->running = th; } diff --git a/tool/timeline/README.md b/tool/timeline/README.md new file mode 100644 index 00000000000000..df752faecf71a3 --- /dev/null +++ b/tool/timeline/README.md @@ -0,0 +1,214 @@ +# eBPF-based timeline visualization tool + +This directory contains timeline visualization tool based on [eBPF] and [bpftrace]. It sets up +probes that attach to the Userspace Statically Defined Tracepoints (USDT) in the Ruby executable or +library, records events during the execution of a Ruby program, and outputs a log file in the [Trace +Event Format] which can be visualized on a timeline in the [Perfetto UI] web frontend. + +This tool is primarily intended for analyzing garbage collection performance, but it can also +visualize other events, such as the acquisition of the global VM lock, and can be extended. + +[eBPF]: https://ebpf.io/what-is-ebpf/ +[bpftrace]: https://bpftrace.org/ +[Trace Event Format]: https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/edit?usp=sharing +[Perfetto UI]: https://www.ui.perfetto.dev/ + +## How to use? + +### Prepare and build + +You need to run the tool on a Linux distribution, and you need the following command line tools. + +- `bpftrace`: The `capture.rb` script uses `bpftrace` to capture events. +- `dtrace` from [SystemTap]: CRuby uses the `dtrace` command line tool during build time to + generate USDT trace points. Because `bpftrace` can only work with SystemTap's USDT format, you + need to install the `dtrace` command line tool from SystemTap, not the [`dtrace` tool from + Oracle][dtrace-oracle] + + CAUTION: Ubuntu 26.04 provides both the `dtrace` from SystemTap (package name is + `systemtap-sdt-dev`) and the `dtrace` from Oracle (package name is `dtrace`), and they can + coexist (installed as `/usr/bin/dtrace` and `/usr/sbin/dtrace`, respectively). Make sure CRuby + is using the one from SystemTap. + +[SystemTap]: https://sourceware.org/systemtap/ +[dtrace-oracle]: https://github.com/oracle/dtrace + +On Ubuntu, you can use the following commands: + +```shell +sudo apt install bpftrace systemtap-sdt-dev +sudo apt remove dtrace +``` + +Build the `ruby` executable. Make sure the `ruby` executable is built with USDT trace points. If +the `configure` command detectes the `dtrace` command line tool, it should be enabled by default. If +not, add `--with-dtrace` to the `configure` command. You can use the `readelf -n` command to check +if the trace points exist. It should show `stapstd` entries with `Provider: ruby`. + +```shell +$ readelf -n /path/to/ruby +Displaying notes found in: .note.stapsdt + Owner Data size Description + stapsdt 0x00000045 NT_STAPSDT (SystemTap probe descriptors) + Provider: ruby + Name: array__create + Location: 0x000000000006ba92, Base: 0x00000000007abe48, Semaphore: 0x000000000090a658 + Arguments: -4@$0 8@-16(%rbp) -4@%eax +... +``` + +### Capture and visualize + +Open one terminal and run + +```shell +/path/to/capture.rb -r /path/to/ruby +``` + +The `-r` option points to the `ruby` executable. You will be prompted to enter the sudo password. +Then you will see output on the terminal: + +``` +Attaching 'begin' probe +Trying to attach probe: usdt:/path/to/ruby:ruby:gc__exit +Trying to attach probe: usdt:/path/to/ruby:ruby:gc__enter +Trying to attach probe: usdt:/path/to/ruby:ruby:gc__sweep__end +Trying to attach probe: usdt:/path/to/ruby:ruby:gc__sweep__begin +Trying to attach probe: usdt:/path/to/ruby:ruby:gc__mark__end +Trying to attach probe: usdt:/path/to/ruby:ruby:gc__mark__begin +Attached 7 probes +====RUBY_TRACING_LOG_START==== +``` + +Then open another terminal and run a Ruby program using *the same* `ruby` executable specified +above. Be careful if you have multiple Ruby builds in your filesystem. + +```shell +/path/to/ruby some_script.rb +``` + +Go back to the first terminal. If everything goes well, you should see output from `capture.rb` in +the CSV format like this: + +``` +... +GCEnterExit,B,18498,2093498438581,1 +gc_sweep,B,18498,2093498439826 +gc_sweep,E,18498,2093498444465 +GCEnterExit,E,18498,2093498445798,1 +GCEnterExit,B,18498,2093498629067,1 +gc_sweep,B,18498,2093498630379 +gc_sweep,E,18498,2093498682380 +GCEnterExit,E,18498,2093498683848,1 +GCEnterExit,B,18498,2093501215787,3 +GCEnterExit,E,18498,2093501641157,3 +``` + +Then press CTRL+C to interrupt the `capture.rb` script. (More precisely, it interrupts the +underlying `bpftrace` program which `capture.rb` invoked.) + +If everything went as expected, we repeat the `capture.rb`, but pipe the output into a log file. + +```shell +/path/to/capture.rb -r /path/to/ruby > running_some_script.log +``` + +Then use the other terminal to run the script again + +```shell +/path/to/ruby some_script.rb +``` + +Go back to the first terminal and use CTRL+C to interrupt `capture.rb`. You should see the standard +output captured in the `running_some_script.log` file. + +Then use the `visualize.rb` script to convert the log file into a JSON file. + +```shell +/path/to/visualize.rb running_some_script.log +``` + +It should generate a file named `running_some_script.log.json.gz`. + +Open a browser and go to . Click "open trace file" and select the +`running_some_script.log.json.gz` file. Then you will be able to see the timeline. Duration +events, such as `GCEnterExit`, `gc_mark` and `gc_sweep`, are displayed as bars, and instant events +are displayed as arrows. Some events, such as `GCEnterExit` and `gc_mark`, have arguments. If you +click an event, the arguments will be shown on the bottom part of the window. + +### Enabling additional probes + +The supported USDT trace points are organized into groups, and the default group is enabled by +default. To enable additional groups of trace points, use the `-g` option of `capture.rb`. For +example, if you want to monitor the number of objects swept during sweeping, you can enable the +`sweep_details` group. + +```shell +/path/to/capture.rb -r /path/to/ruby -g sweep_details > running_some_script_with_sweep_details.log +``` + +There is no additional options needed for the `visualize.rb` script. Just run it as usual. + +See `lib/tracepoint_defs.rb` for a complete list of groups and their trace points. + +### Working with GC modules + +The default GC in CRuby can be compiled as a GC module. If DTrace support is enabled when building +`ruby`, the USDT trace points will be automatically built into the GC module of the default GC. + +When capturing, add the `-m` option to specify the path of the GC module. + +```shell +/path/to/capture.rb -r /path/to/ruby -m /path/to/librubygc.default.so > running_some_script.log +``` + +Then run `ruby` with the GC module. + +```shell +RUBY_GC_LIBRARY=default /path/to/ruby some_script.rb +``` + +Then visualize in the usual way. + +## How to extend? + +You can introduce more trace points by editing the `probes.d` file. + +Then you can insert the trace points into the program in the form of + +```c +RUBY_DTRACE_XXX_XXX_XXX(/* parameters */) +``` + +To capture and visualize those events, you need to edit the script `lib/tracepoint_defs.rb`. It +will be read by both the `capture.rb` and the `visualize.rb` scripts. After adding the definition +of your added trace points, the events and the arguments will be displayed on the timeline. + +In rare cases, you can hack `visualize.rb` directly to do post-processing on each event. For +example, you can combine the numbers of objects marked in multiple invocations of +`gc_mark_stacked_objects` and add it as one argument of the currnet `GCEnterExit` event in the +timeline. + +### Performance concerns + +USDT trace points are no-op instructions and have negligible overhead when not attached. Therefore, +it is safe to insert the trace points even in the hot paths of hot functions. + +However, when a trace point is attached by `bpftrace` (and therefore our capturing tool), it will +introduce an overhead whenever it is fired. Different trace points are also fired at different +frequencies. For example, `gc_enter` and `gc_exit` events are much less frequent than `obj_new` and +`obj_free`. So you should avoid enabling high-frequency trace points which you are not interested +in in order not to reduce the fidelity of the measurement. You can do this by grouping the trace +points by freqneucy in `lib/tracepoint_defs.rb` so that you can selectively enable the trace points +you are interested in with the `-g` option of `capture.rb`. + +## Acknowledgement + +This timeline tracing tool is inspired by [a similar tracing tool][mmtk-timeline] from the [Memory +Management Toolkit (MMTK)][mmtk] project. The methodology was developed by Claire Huang, Steve +Blackburn, and Zixian Cai, and is described in details in the paper *[Improving Garbage Collection +Observability with Performance Tracing][HBC23]*. + +[mmtk-timeline]: https://github.com/mmtk/mmtk-core/tree/master/tools/tracing/timeline +[mmtk]: https://www.mmtk.io/ +[HBC23]: https://doi.org/10.1145/3617651.3622986 diff --git a/tool/timeline/capture.bt b/tool/timeline/capture.bt new file mode 100644 index 00000000000000..f3059e22715b76 --- /dev/null +++ b/tool/timeline/capture.bt @@ -0,0 +1,9 @@ +BEGIN { + printf("====RUBY_TRACING_LOG_START====\n"); +} + +% usdt_entries.each do |entry| +usdt:<%=entry.file%>:ruby:<%=entry.probe_name%> { + printf("<%=entry.probe_name%>,%d,%d,%lu<%=",%lu"*entry.nargs%>\n", pid, tid, nsecs<%=(0...entry.nargs).map{|i| ", arg#{i}"}.join%>); +} +% end diff --git a/tool/timeline/capture.rb b/tool/timeline/capture.rb new file mode 100755 index 00000000000000..f43ae6ac4dbe82 --- /dev/null +++ b/tool/timeline/capture.rb @@ -0,0 +1,119 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +require 'erb' +require 'optparse' +require 'pathname' + +require_relative 'lib/tracepoint_defs' + +EXTRA_GROUPS = RubyTimelineTool::USDT_DEFS.keys - RubyTimelineTool::DEFAULT_GROUPS + +options = {} + +OptionParser.new do |parser| + parser.accept(Pathname) do |value| + Pathname.new(value) + end + parser.on('-r', '--ruby-bin RUBY', Pathname, 'Path to the ruby executable') + parser.on('-m', '--gc-module-so GC_MODULE', Pathname, 'Path to the GC module .so') + parser.on('-e', '--erb-debug', TrueClass, 'Print the Ruby script generated by ERB. For debugging.') + parser.on('-p', '--print-script', TrueClass, 'Print the content of the bpftrace script') + parser.on('-d', '--dry-run', TrueClass, 'Dry run. Print the bpftrace command to be executed, but do not actually execute it.') + parser.on('-g', '--extra-groups=', "Enable extra USDT groups, separated by comma. Available groups: #{EXTRA_GROUPS.join(', ')}") +end.parse!(into: options) + +[:'ruby-bin'].each do |k| + if !options.include?(k) + raise "Option --#{k} is required" + end +end + +ruby_bin = options[:'ruby-bin'] +if !ruby_bin.file? + raise "Ruby executable '#{ruby_bin}' does not exist" +end + +gc_module_so = options[:'gc-module-so'] + +gc_module_kind = case +when gc_module_so.nil? + nil +when m = /librubygc\.(\w+)/.match(gc_module_so.basename.to_s) + m[1] +else + raise "Unexpected gc module so name: #{gc_module_so}" +end + +script_path = Pathname(__dir__) / 'capture.bt' +script = File.read(script_path) +template = ERB.new(script, trim_mode: '%<>') +template.location = [script_path.to_s, 1] + +if options[:'erb-debug'] + $stderr.puts template.src +end + +extra_groups_opt = options[:'extra-groups'] + +selected_groups = RubyTimelineTool::DEFAULT_GROUPS.dup + +if !extra_groups_opt.nil? + extra_groups_opt.split(',').each do |group| + if !EXTRA_GROUPS.include?(group) + raise "Unknown USDT group #{group}" + end + + selected_groups << group + end +end + +selected_groups.uniq! + +$stderr.puts "Selected groups: #{selected_groups.join(',')}" + +usdts = RubyTimelineTool::USDT_DEFS.values_at(*selected_groups).flatten + +ScriptUsdtEntry = Struct.new('ScriptUsdtEntry', :file, :probe_name, :nargs) + +usdt_entries = [] + +usdts.each do |t| + file = case [gc_module_kind, t.where] + in nil, 'ruby' then ruby_bin + in nil, 'default' then ruby_bin + in x, 'ruby' then ruby_bin + in x, y if x == y then gc_module_so + else nil + end + + if file.nil? + @stderr.puts "Skipped probe '#{probe_name}' which is for '#{location}'. Current GC module: '#{gc_module_kind}'." + next + end + + nargs = t.args.length + + usdt_entries << ScriptUsdtEntry.new(file, t.probe_name, nargs) +end + +content = template.result_with_hash({ + usdt_entries:, +}) + +if options[:'print-script'] + $stderr.puts content +end + +IO.write('capture.out.bt', content) + +command_line = ['sudo', 'bpftrace', '-v', '--unsafe', 'capture.out.bt'] +$stderr.puts 'Command to execute:' +$stderr.puts command_line.map { |s| "'#{s}'" }.join(' ') + +if options[:'dry-run'] + $stderr.puts 'Dry run. Exit...' + exit 0 +end + +exec(*command_line) diff --git a/tool/timeline/lib/converter.rb b/tool/timeline/lib/converter.rb new file mode 100644 index 00000000000000..49c3fbe6e9c03f --- /dev/null +++ b/tool/timeline/lib/converter.rb @@ -0,0 +1,58 @@ +# frozen_string_literal: true + +module RubyTimelineTool + class Converter + def convert_arg(_raw_value) + raise 'Not implemented' + end + end + + class EnumConverter < Converter + def initialize(hash) + super() + @hash = hash + @ihash = hash.invert + end + + def convert_arg(raw_value) + value = raw_value.to_i + @ihash[value] + end + + def [](key) + @hash[key] + end + end + + class FlagsConverter < Converter + def initialize(hash) + super() + @hash = hash + end + + def convert_arg(raw_value) + value = raw_value.to_i + # Output {foo: true, bar: false, ...} + @hash.transform_values do |bit_value| + (value & bit_value) != 0 + end + end + + def [](key) + @hash[key] + end + end + + def self.convert_arg(raw_value, converter) + case + when converter.is_a?(Converter) + converter.convert_arg(raw_value) + when converter.is_a?(Symbol) + raw_value.send(converter) + when converter.respond_to?(:call) + converter.call(raw_value) + else + raise "Unexpected converter #{@converter.inspect}" + end + end +end diff --git a/tool/timeline/lib/converter_defs.rb b/tool/timeline/lib/converter_defs.rb new file mode 100644 index 00000000000000..eeb61c9aee57c9 --- /dev/null +++ b/tool/timeline/lib/converter_defs.rb @@ -0,0 +1,133 @@ +# frozen_string_literal: true + +require_relative 'converter' + +module RubyTimelineTool + # Keep in sync with `enum gc_enter_event` in `gc/default/default.c`. + GCEnterEvent = EnumConverter.new({ + start: 0, + continue: 1, + rest: 2, + finalizer: 3, + }) + + # Keep in sync with `enum ruby_value_type` in `include/ruby/internal/value_type.h`. + RubyBuiltinType = EnumConverter.new({ + RUBY_T_NONE: 0x00, # /**< Non-object (swept etc.) */: + RUBY_T_OBJECT: 0x01, # /**< @see struct ::RObject */ + RUBY_T_CLASS: 0x02, # /**< @see struct ::RClass and ::rb_cClass */ + RUBY_T_MODULE: 0x03, # /**< @see struct ::RClass and ::rb_cModule */ + RUBY_T_FLOAT: 0x04, # /**< @see struct ::RFloat */ + RUBY_T_STRING: 0x05, # /**< @see struct ::RString */ + RUBY_T_REGEXP: 0x06, # /**< @see struct ::RRegexp */ + RUBY_T_ARRAY: 0x07, # /**< @see struct ::RArray */ + RUBY_T_HASH: 0x08, # /**< @see struct ::RHash */ + RUBY_T_STRUCT: 0x09, # /**< @see struct ::RStruct */ + RUBY_T_BIGNUM: 0x0a, # /**< @see struct ::RBignum */ + RUBY_T_FILE: 0x0b, # /**< @see struct ::RFile */ + RUBY_T_DATA: 0x0c, # /**< @see struct ::RTypedData */ + RUBY_T_MATCH: 0x0d, # /**< @see struct ::RMatch */ + RUBY_T_COMPLEX: 0x0e, # /**< @see struct ::RComplex */ + RUBY_T_RATIONAL: 0x0f, # /**< @see struct ::RRational */: + RUBY_T_NIL: 0x11, # /**< @see ::RUBY_Qnil */ + RUBY_T_TRUE: 0x12, # /**< @see ::RUBY_Qtrue */ + RUBY_T_FALSE: 0x13, # /**< @see ::RUBY_Qfalse */ + RUBY_T_SYMBOL: 0x14, # /**< @see struct ::RSymbol */ + RUBY_T_FIXNUM: 0x15, # /**< Integers formerly known as Fixnums. */ + RUBY_T_UNDEF: 0x16, # /**< @see ::RUBY_Qundef */: + RUBY_T_IMEMO: 0x1a, # /**< @see struct ::RIMemo */ + RUBY_T_NODE: 0x1b, # /**< @see struct ::RNode */ + RUBY_T_ICLASS: 0x1c, # /**< Hidden classes known as IClasses. */ + RUBY_T_ZOMBIE: 0x1d, # /**< @see struct ::RZombie */ + RUBY_T_MOVED: 0x1e, # /**< @see struct ::RMoved */ + }) + + # Keep in sync with `enum ruby_value_type` in `include/ruby/internal/value_type.h`. + RUBY_T_MASK = 0x1f + + # Keep in sync with `enum ruby_fl_type` in `include/ruby/internal/fl_type.h`. + RubyFlType = FlagsConverter.new({ + RUBY_FL_PROMOTED: (1 << 5), + RUBY_FL_UNUSED6: (1 << 6), + RUBY_FL_FINALIZE: (1 << 7), + RUBY_FL_SHAREABLE: (1 << 8), + RUBY_FL_WEAK_REFERENCE: (1 << 9), + RUBY_FL_UNUSED10: (1 << 10), + RUBY_FL_FREEZE: (1 << 11), + }) + + # Keep in sync with `enum ruby_fl_ushift` in `include/ruby/internal/fl_type.h`. + RUBY_FL_USHIFT = 12 + + # Keep in sync with `include/ruby/internal/fl_type.h` + def self.FL_USER_N(n) + 1 << (RUBY_FL_USHIFT + n) + end + + # Keep in sync with `enum imemo_type` in `internal/imemo.h`. + ImemoType = EnumConverter.new({ + imemo_env: 0, + imemo_cref: 1, # /*!< class reference */ + imemo_svar: 2, # /*!< special variable */ + imemo_throw_data: 3, + imemo_ifunc: 4, # /*!< iterator function */ + imemo_memo: 5, + imemo_ment: 6, + imemo_iseq: 7, + imemo_tmpbuf: 8, + imemo_cvar_entry: 9, + imemo_callinfo: 10, + imemo_callcache: 11, + imemo_constcache: 12, + imemo_fields: 13, + imemo_subclasses: 14, + imemo_cdhash: 15, + }) + + # Keep in sync with `IMEMO_MASK` in `internal/imemo.h`. + IMEMO_MASK = 0x0f + + # Keep in sync with both `internal/string.h` and `include/ruby/internal/core/rstring.h`. + StringFlags = FlagsConverter.new({ + STR_SHARED: FL_USER_N(0), + RSTRING_NOEMBED: FL_USER_N(1), + STR_CHILLED_LITERAL: FL_USER_N(2), + STR_CHILLED_SYMBOL_TO_S: FL_USER_N(3), + RSTRING_FSTR: FL_USER_N(17), + }) + + # Keep in sync with both `internal/array.h` and `include/ruby/internal/core/rarray.h`. + ArrayFlags = FlagsConverter.new({ + RARRAY_SHARED_FLAG: FL_USER_N(0), + RARRAY_EMBED_FLAG: FL_USER_N(1), + RARRAY_SHARED_ROOT_FLAG: FL_USER_N(12), + RARRAY_PTR_IN_USE_FLAG: FL_USER_N(14), + }) + + RubyFlags = proc do |raw_value| + value = raw_value.to_i + builtin_type = RubyBuiltinType.convert_arg(value & RUBY_T_MASK) + result = { + raw_value: value, + raw_value_binary: value.to_s(2), + builtin_type:, + } + + if builtin_type == :RUBY_T_IMEMO + result[:imemo_type] = ImemoType.convert_arg((value >> RUBY_FL_USHIFT) & IMEMO_MASK) + end + + result[:flags] = RubyFlType.convert_arg(value) + + case builtin_type + when :RUBY_T_STRING + result[:string_args] = StringFlags.convert_arg(value) + when :RUBY_T_ARRAY + result[:array_args] = ArrayFlags.convert_arg(value) + + # TODO: Decode the flags for more types of interest. + end + + result + end +end diff --git a/tool/timeline/lib/tracepoint.rb b/tool/timeline/lib/tracepoint.rb new file mode 100644 index 00000000000000..e24ae6283de6cb --- /dev/null +++ b/tool/timeline/lib/tracepoint.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +module RubyTimelineTool + class TracePoint + def initialize(probe_name, where, vis_name, ph, args: nil, visualize: true) + @probe_name = probe_name + @where = where + @vis_name = vis_name + @ph = ph + @args = args || {} + @visualize = visualize + end + + attr_reader :probe_name, :where, :vis_name, :ph, :args, :visualize + end + + def self.tp(*args, **kwargs) + TracePoint.new(*args, **kwargs) + end +end diff --git a/tool/timeline/lib/tracepoint_defs.rb b/tool/timeline/lib/tracepoint_defs.rb new file mode 100644 index 00000000000000..db0868ff20dc8c --- /dev/null +++ b/tool/timeline/lib/tracepoint_defs.rb @@ -0,0 +1,105 @@ +# frozen_string_literal: true + +require_relative 'tracepoint' +require_relative 'converter_defs' + +module RubyTimelineTool + # All USDT trace points. + # + # It maps each group to an array of trace points. The `default` group is always enabled, and + # other groups can be enabled using the `-g` command line option of `capture.rb`. + # + # `tp(...)` defines a trace point. It has four compulsory arguments. + # + # 1. The USDT probe name. It is the `xxx` in `probe xxx()` in `probes.d`, and it is also the + # `Name:` field of the output of `readelf -n`. The `capture.rb` tool assumes the "provider + # (the `Provider:` field of `readelf -n`) of the USDT is `ruby`, and we don't need to specify + # it here. + # 2. The place the probe is defined. Possible values are: + # - `ruby`: It is part of the Ruby runtime, and will always be compiled into the `ruby` + # executable. + # - `default`: It is part of the default GC (`default.c`). It will be compiled into the + # `ruby` executable and the default GC module if modular GC is enabled. + # 3. The event name in the output timeline. + # 4. The event type, as specified by the Trace Event Format. Common types include + # - 'B' and 'E': The beginning and the end of a duration event. + # - 'i': An instant event. + # - 'c': A counter event. + # + # It can also have a special value 'meta' (not specified in the Trace Event Format) which + # means it will not be added to the output JSON file, but will still be available for + # `visualize.rb` for post-processing. + # + # For more information about the Trace Event Format, see: + # https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/edit?usp=sharing + # + # `tp(...)` also has some optional keyword argument. + # + # - `args`: It is used by the `capture.rb` script to set up the arguments of the USDT probes, + # and used by `visualize.rb` to convert the argument values from string (read from the log) to + # JSON values. It has the form: + # + # ```ruby + # args: {arg1: converter1, arg2: converter2, ...} + # ``` + # + # The order of the key-value pairs must match the order of the arguments of the USDT trace + # points (as defined in `probes.d`). + # + # Each converter can be one of the following + # + # - An instance of `Converter`. + # - A symbol, such as `:to_i`, to be sent to the argument string. + # - An object that responds to `call`. + # + # There are some converters defined in `converter_defs.rb`. + USDT_DEFS = { + 'default' => [ + # The default group visualizes the duration of each GC, each marking and each sweeping event. + tp('gc__mark__begin', 'default', 'gc_mark', 'B'), + tp('gc__mark__end', 'default', 'gc_mark', 'E'), + tp('gc__sweep__begin', 'default', 'gc_sweep', 'B'), + tp('gc__sweep__end', 'default', 'gc_sweep', 'E'), + tp('gc__enter', 'default', 'GCEnterExit', 'B', args: {event: GCEnterEvent}), + tp('gc__exit', 'default', 'GCEnterExit', 'E', args: {event: GCEnterEvent}), + ].freeze, + 'mark_details' => [ + # This group collects more detals of marking events, such as the number of objects visited. + tp('gc__mark_stacked_objects', 'default', 'gc_mark_stacked_objects', 'meta', args: {popped_count: :to_i}), + ].freeze, + 'sweep_details' => [ + # This group collects more detals of sweeping events, such as the number of objects swept. + tp('gc__sweep_page', 'default', 'gc_sweep_page', 'i', args: {slot_size: :to_i, final_slots: :to_i, freed_slots: :to_i, empty_slots: :to_i}), + ].freeze, + 'obj_new' => [ + # This group traces the creation of GC-managed objects. + tp('gc__obj_new', 'ruby', 'gc_obj_new', 'i', args: {obj: :to_i, flags: RubyFlags}), + ].freeze, + 'obj_free' => [ + # This group traces the invocation of `rb_gc_obj_free` which finalizes the objects when they are swept. + tp('gc__obj_free', 'ruby', 'gc_obj_free', 'i', args: {obj: :to_i, flags: RubyFlags}), + ].freeze, + 'xmalloc' => [ + # This group traces the invocation of `xmalloc` and `xcalloc`. + tp('gc__xmalloc', 'ruby', 'gc_xmalloc', 'i', args: {n: :to_i, size: :to_i}), + tp('gc__xcalloc', 'ruby', 'gc_xcalloc', 'i', args: {n: :to_i, size: :to_i}), + ].freeze, + 'xfree' => [ + # This group traces the invocation of `xfree`. + tp('gc__xfree', 'ruby', 'gc_xfree', 'i', args: {obj: :to_i, size: :to_i}), + ].freeze, + 'gvl' => [ + # This group visualizes the durations in which a thread holds the global VM lock. + tp('gvl__acquire', 'ruby', 'GVL', 'B'), + tp('gvl__release', 'ruby', 'GVL', 'E'), + ].freeze, + 'rts' => [ + # This group visualizes the event where a thread is scheduled on or off a Ractor. + # "RTS" stands for `ractor.thread.sched`. + tp('rts__set_running', 'ruby', 'rts_set_running', 'i', args: {sched: :to_i, old_thread: :to_i, new_thread: :to_i}), + ].freeze + }.freeze + + # The default groups are enabled by default + DEFAULT_GROUPS = ['default'].freeze +end diff --git a/tool/timeline/visualize.rb b/tool/timeline/visualize.rb new file mode 100755 index 00000000000000..dae41ca8a3812b --- /dev/null +++ b/tool/timeline/visualize.rb @@ -0,0 +1,246 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +require 'json' +require 'optparse' +require 'pathname' +require 'zlib' + +require_relative 'lib/tracepoint_defs' +require_relative 'lib/converter_defs' +require_relative 'lib/converter' + +PROBE_NAME_TO_USDT = RubyTimelineTool::USDT_DEFS.values.flatten.to_h { |t| [t.probe_name, t] } + +module FetchStore + refine Hash do + def fetch_store(key) + if include?(key) + self[key] + else + self[key] = yield + end + end + end +end + +using FetchStore + +class LogProcessor + def initialize(verbose: false) + @verbose = verbose + @type_id_name = {} + @start_time = nil + @results = [] + # @current maps [pid, tid, block_name] to block. + @current = {} + @started = false + end + + attr_accessor :started + + def process_line(line) + if !@started + if line == '====RUBY_TRACING_LOG_START====' + @started = true + end + return + end + + if line.include?(',') + process_log_line(line) + else + puts "Discarded line '#{line}'" if @verbose + end + end + + def output(outfile) + json_str = JSON.generate(@results) + Zlib::GzipWriter.open(outfile) do |gz| + gz.write(json_str) + end + end + + private + + def process_log_line(line) + parts = line.split(',') + probe_name, pid, tid, ts = parts[...4] + pid = pid.to_i + tid = tid.to_i + ts = resolve_time(ts.to_i) + raw_args = parts[4...] + + puts "probe_name: #{probe_name}, pid: #{pid}, tid: #{tid}, ts: #{ts}, raw_args: #{raw_args}" if @verbose + + if @start_time.nil? + @start_time = ts + end + + usdt_def = PROBE_NAME_TO_USDT[probe_name] + + ph = usdt_def.ph + vis_name = usdt_def.vis_name + + args = {} + usdt_def.args.each_pair.zip(raw_args) do |arg_def, arg_val| + arg_name, arg_converter = arg_def + begin + converted_val = RubyTimelineTool.convert_arg(arg_val, arg_converter) + rescue + puts "error converting argument #{arg_name}, value: [#{arg_val}]" + puts "line: #{line}" + raise + end + + args[arg_name] = converted_val + end + + result = { name: vis_name, ph:, pid:, tid:, ts:, args: } + + if ph == 'B' || ph == 'E' + # Register the current block so that other events can "enrich" it. + set_current_block(pid, tid, result) + end + + # Some results need special treatment. + case vis_name + when 'GCEnterExit' + # Register to the virtual :global TID, too. + set_current_block(pid, :global, result) + when 'gc_mark_stacked_objects' + enrich([pid, :global, 'GCEnterExit'], [pid, tid, 'gc_mark']) do |old_result| + old_result[:args].fetch_store(:gc_mark_stacked_objects) do + { popped_count: 0 } + end[:popped_count] += args[:popped_count] + end + when 'gc_sweep_page' + args[:free_slots] = args[:freed_slots] + args[:empty_slots] + enrich([pid, :global, 'GCEnterExit'], [pid, tid, 'gc_sweep']) do |old_result| + old_dict = old_result[:args].fetch_store(:gc_sweep_page) do + { swept_pages: 0, final_slots: 0, freed_slots: 0, empty_slots: 0, free_slots: 0 } + end + old_dict[:swept_pages] += 1 + old_dict[:final_slots] += args[:final_slots] + old_dict[:freed_slots] += args[:freed_slots] + old_dict[:empty_slots] += args[:empty_slots] + old_dict[:free_slots] += args[:free_slots] + end + when 'rts_set_running' + sched = args[:sched] + sched_hex = "0x#{sched.to_s(16)}" + # A virtual TID for the rb_thread_sched instance. + sched_id = "sched-#{sched_hex}" + prev = get_current(pid, sched_id, 'RTS') + if !prev.nil? + block_end = result.dup.update({ + name: 'RTS', + ph: 'E', + tid: sched_id, + args: {} + }) + @results << block_end + clear_current(pid, sched_id, 'RTS') + end + + if args[:new_thread] != 0 + block_begin = result.dup.update({ + name: 'RTS', + ph: 'B', + tid: sched_id, + args: { + sched:, + sched_hex:, + thread: args[:new_thread], + } + }) + @results << block_begin + set_current(pid, sched_id, 'RTS', block_begin) + end + end + + if result[:ph] != 'meta' + @results << result + end + end + + def resolve_time(ts) + if @start_time.nil? + @start_time = ts + end + (ts - @start_time) / 1000.0 + end + + def set_current(pid, tid, key, value) + @current[[pid, tid, key]] = value + end + + def get_current(pid, tid, key) + @current[[pid, tid, key]] + end + + def clear_current(pid, tid, key) + @current.delete([pid, tid, key]) + end + + def set_current_block(pid, tid, result) + case result[:ph] + when 'B' + set_current(pid, tid, result[:name], result) + when 'E' + clear_current(pid, tid, result[:name]) + else + raise "unexpected ph: #{result}" + end + end + + # Look up an entry in the `@current` hash so that + # you can add more arguments or make adjustments to it. + def enrich(*targets) + targets.each do |target| + case target + in [pid, tid, key] + result = get_current(pid, tid, key) + if !result.nil? + yield result + end + end + end + end +end + +def main + options = {} + + OptionParser.new do |parser| + parser.on('-v', '--verbose', TrueClass, 'Print verbose messages. For debugging.') + parser.on('-d', '--dry-run', TrueClass, 'Dry run. DO not actually write into output file.') + end.parse!(into: options) + + input = ARGV[0] + if input.nil? + raise 'Need positional argument' + end + + input_path = Pathname.new(input) + if !input_path.file? + raise "File #{input_path} does not exist" + end + + output_path = input_path.dirname / "#{input_path.basename}.json.gz" + + log_processor = LogProcessor.new(verbose: options[:verbose]) + + input_path.each_line(chomp: true) do |line| + log_processor.process_line(line) + end + + if options[:'dry-run'] + puts "Dry run. Output file: #{output_path}" + else + puts "Writing to output file: #{output_path}" + log_processor.output(output_path) + end +end + +main diff --git a/variable.c b/variable.c index dc015b4cbce168..55e9e2f9335a9f 100644 --- a/variable.c +++ b/variable.c @@ -1343,7 +1343,7 @@ rb_free_generic_ivar(VALUE obj) } } } - RBASIC_SET_SHAPE_ID(obj, rb_shape_layout(RBASIC_SHAPE_ID(obj)) | ROOT_SHAPE_ID); + RBASIC_SET_SHAPE_ID(obj, ROOT_SHAPE_ID); } } @@ -1395,7 +1395,7 @@ rb_obj_set_fields(VALUE obj, VALUE fields_obj, ID field_name, VALUE original_fie } } - RBASIC_SET_SHAPE_ID(obj, rb_shape_layout(RBASIC_SHAPE_ID(obj)) | RBASIC_SHAPE_ID(fields_obj)); + RBASIC_SET_SHAPE_ID(obj, RBASIC_SHAPE_ID(fields_obj)); } void @@ -1710,7 +1710,6 @@ rb_ivar_delete(VALUE obj, ID id, VALUE undef) size_t trailing_fields = new_fields_count - removed_index; MEMMOVE(&fields[removed_index], &fields[removed_index + 1], VALUE, trailing_fields); - RUBY_ASSERT(rb_shape_layout(next_shape_id) == SHAPE_ID_LAYOUT_ROBJECT); RBASIC_SET_SHAPE_ID(fields_obj, next_shape_id); if (FL_TEST_RAW(fields_obj, OBJ_FIELD_HEAP)) { @@ -1733,7 +1732,7 @@ rb_ivar_delete(VALUE obj, ID id, VALUE undef) } } - RBASIC_SET_SHAPE_ID(obj, rb_shape_layout(RBASIC_SHAPE_ID(obj)) | next_shape_id); + RBASIC_SET_SHAPE_ID(obj, next_shape_id); if (fields_obj != original_fields_obj) { switch (type) { case T_OBJECT: @@ -1844,10 +1843,11 @@ imemo_fields_set(VALUE owner, VALUE fields_obj, shape_id_t target_shape_id, ID f RUBY_ASSERT(field_name); st_insert(table, (st_data_t)field_name, (st_data_t)val); RB_OBJ_WRITTEN(fields_obj, Qundef, val); - RBASIC_SET_SHAPE_ID(fields_obj, rb_shape_id_with_robject_layout(target_shape_id)); + RBASIC_SET_SHAPE_ID(fields_obj, target_shape_id); } else { attr_index_t index = RSHAPE_INDEX(target_shape_id); + if (concurrent || index >= RSHAPE_CAPACITY(current_shape_id)) { return imemo_fields_copy_append(owner, original_fields_obj, current_shape_id, target_shape_id, val); } @@ -1856,7 +1856,7 @@ imemo_fields_set(VALUE owner, VALUE fields_obj, shape_id_t target_shape_id, ID f RB_OBJ_WRITE(fields_obj, &table[index], val); if (index >= RSHAPE_LEN(current_shape_id)) { - RBASIC_SET_SHAPE_ID(fields_obj, rb_shape_id_with_robject_layout(target_shape_id)); + RBASIC_SET_SHAPE_ID(fields_obj, target_shape_id); } } @@ -2305,7 +2305,7 @@ rb_copy_generic_ivar(VALUE dest, VALUE obj) } if (!RSHAPE_LEN(dest_shape_id)) { - RBASIC_SET_SHAPE_ID(dest, rb_shape_layout(RBASIC_SHAPE_ID(dest)) | dest_shape_id); + RBASIC_SET_SHAPE_ID(dest, dest_shape_id); return; } @@ -4688,7 +4688,7 @@ class_ivar_set(VALUE obj, ID id, VALUE val, bool *new_ivar) // TODO: What should we set as the T_CLASS shape_id? // In most case we can replicate the single `fields_obj` shape // but in namespaced case? Perhaps INVALID_SHAPE_ID? - RBASIC_SET_SHAPE_ID(obj, rb_shape_layout(RBASIC_SHAPE_ID(obj)) | RBASIC_SHAPE_ID(new_fields_obj)); + RBASIC_SET_SHAPE_ID(obj, RBASIC_SHAPE_ID(new_fields_obj)); return index; } @@ -4713,7 +4713,7 @@ rb_fields_tbl_copy(VALUE dst, VALUE src) VALUE fields_obj = RCLASS_WRITABLE_FIELDS_OBJ(src); if (fields_obj) { RCLASS_WRITABLE_SET_FIELDS_OBJ(dst, rb_imemo_fields_clone(fields_obj)); - RBASIC_SET_SHAPE_ID(dst, rb_shape_layout(RBASIC_SHAPE_ID(dst)) | RBASIC_SHAPE_ID(src)); + RBASIC_SET_SHAPE_ID(dst, RBASIC_SHAPE_ID(src)); } } diff --git a/vm_insnhelper.c b/vm_insnhelper.c index 8abbfb15099379..57a56e6a628d43 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -1412,8 +1412,7 @@ vm_setivar_class(VALUE obj, VALUE val, rb_setivar_cache cache) RB_OBJ_WRITE(fields_obj, &rb_imemo_fields_ptr(fields_obj)[cache.index], val); if (shape_id != dest_shape_id) { - // The dest_shape_id comes from the fields_obj - RBASIC_SET_SHAPE_ID(obj, SHAPE_ID_LAYOUT_RCLASS | (dest_shape_id & ~SHAPE_ID_LAYOUT_MASK)); + RBASIC_SET_SHAPE_ID(obj, dest_shape_id); RBASIC_SET_SHAPE_ID(fields_obj, dest_shape_id); } @@ -1441,9 +1440,7 @@ vm_setivar_default(VALUE obj, ID id, VALUE val, rb_setivar_cache cache) if (shape_id != dest_shape_id) { RBASIC_SET_SHAPE_ID(obj, dest_shape_id); - // The dest_shape_id comes from the owner, but fields_obj must always - // have layout RObject, so give the fields_object the right layout. - RBASIC_SET_SHAPE_ID(fields_obj, rb_shape_id_with_robject_layout(dest_shape_id)); + RBASIC_SET_SHAPE_ID(fields_obj, dest_shape_id); } RB_DEBUG_COUNTER_INC(ivar_set_ic_hit); diff --git a/vm_sync.c b/vm_sync.c index aca83dde5a73aa..d6eb47dfe725cf 100644 --- a/vm_sync.c +++ b/vm_sync.c @@ -4,6 +4,7 @@ #include "vm_sync.h" #include "ractor_core.h" #include "vm_debug.h" +#include "probes.h" void rb_ractor_sched_barrier_start(rb_vm_t *vm, rb_ractor_t *cr); void rb_ractor_sched_barrier_join(rb_vm_t *vm, rb_ractor_t *cr); @@ -115,6 +116,10 @@ vm_lock_enter(rb_ractor_t *cr, rb_vm_t *vm, bool locked, bool no_barrier, unsign RUBY_DEBUG_LOG2(file, line, "rec:%u owner:%u", vm->ractor.sync.lock_rec, (unsigned int)rb_ractor_id(vm->ractor.sync.lock_owner)); + + if (RUBY_DTRACE_GVL_ACQUIRE_ENABLED()) { + RUBY_DTRACE_GVL_ACQUIRE(); + } } static void @@ -139,6 +144,10 @@ vm_lock_leave(rb_vm_t *vm, bool no_barrier, unsigned int *lev APPEND_LOCATION_AR } #endif + if (RUBY_DTRACE_GVL_RELEASE_ENABLED()) { + RUBY_DTRACE_GVL_RELEASE(); + } + vm->ractor.sync.lock_rec--; *lev = vm->ractor.sync.lock_rec; diff --git a/zjit.c b/zjit.c index 082a9038066723..2953a694fd3c83 100644 --- a/zjit.c +++ b/zjit.c @@ -23,6 +23,7 @@ #include "iseq.h" #include "ruby/debug.h" #include "internal/cont.h" +#include "ractor_core.h" // This build config impacts the pointer tagging scheme and we only want to // support one scheme for simplicity. @@ -30,7 +31,8 @@ STATIC_ASSERT(pointer_tagging_scheme, USE_FLONUM); enum zjit_struct_offsets { ISEQ_BODY_OFFSET_PARAM = offsetof(struct rb_iseq_constant_body, param), - ISEQ_BODY_OFFSET_OUTER_VARIABLES = offsetof(struct rb_iseq_constant_body, outer_variables) + ISEQ_BODY_OFFSET_OUTER_VARIABLES = offsetof(struct rb_iseq_constant_body, outer_variables), + RUBY_OFFSET_THREAD_RACTOR = offsetof(rb_thread_t, ractor), }; // Special JITFrame used by all C method calls. We don't control the native @@ -166,6 +168,12 @@ rb_zjit_singleton_class_p(VALUE klass) return RCLASS_SINGLETON_P(klass); } +size_t +rb_zjit_offset_ractor_newobj_cache(void) +{ + return offsetof(rb_ractor_t, newobj_cache); +} + VALUE rb_zjit_defined_ivar(VALUE obj, ID id, VALUE pushval) { diff --git a/zjit/bindgen/src/main.rs b/zjit/bindgen/src/main.rs index 55f784bd03965e..4bad82b4e1e9c8 100644 --- a/zjit/bindgen/src/main.rs +++ b/zjit/bindgen/src/main.rs @@ -53,6 +53,10 @@ fn main() { .header(src_root.join(c_file).to_str().unwrap()) .header(src_root.join("jit.c").to_str().unwrap()) + .header(src_root.join("gc/gc_impl.h").to_str().unwrap()) + .header(src_root.join("gc/default/zjit_fastpath.h").to_str().unwrap()) + .header(src_root.join("gc/mmtk/zjit_fastpath.h").to_str().unwrap()) + // Don't want to copy over C comment .generate_comments(false) @@ -86,6 +90,15 @@ fn main() { // This struct is public to Ruby C extensions .allowlist_type("RBasic") + .allowlist_type("RArray") + .allowlist_type("gc_bump_pointer_heap") + .allowlist_type("rb_gc_zjit_fastpath_kind") + .allowlist_type("rb_gc_zjit_fastpath") + .allowlist_type("rb_gc_zjit_fastpath_data") + .allowlist_type("rb_gc_zjit_default_new_obj_fastpath") + .allowlist_type("rb_gc_zjit_mmtk_new_obj_fastpath") + .allowlist_var("RB_GC_ZJIT_FASTPATH_.*") + .allowlist_type("ruby_rstring_flags") // This function prints info about a value and is useful for debugging diff --git a/zjit/src/codegen.rs b/zjit/src/codegen.rs index 511fa9d34c2a13..4df06236bbc0b3 100644 --- a/zjit/src/codegen.rs +++ b/zjit/src/codegen.rs @@ -2,6 +2,8 @@ #![allow(clippy::let_and_return)] +mod gc_fastpath; + use std::cell::{Cell, RefCell}; use std::rc::Rc; use std::ffi::{c_int, c_long, c_void}; @@ -1965,7 +1967,7 @@ fn gen_array_dup( /// Compile a new array instruction fn gen_new_array( - jit: &JITState, + jit: &mut JITState, asm: &mut Assembler, elements: Vec, state: &FrameState, @@ -1974,12 +1976,19 @@ fn gen_new_array( let num: c_long = elements.len().try_into().expect("Unable to fit length of elements into c_long"); - if elements.is_empty() { - asm_ccall!(asm, rb_ec_ary_new_from_values, EC, 0i64.into(), Opnd::UImm(0)) - } else { + if !elements.is_empty() { let argv = gen_push_opnds(jit, asm, &elements); - asm_ccall!(asm, rb_ec_ary_new_from_values, EC, num.into(), argv) + return asm_ccall!(asm, rb_ec_ary_new_from_values, EC, num.into(), argv); } + + let alloc_size = std::mem::size_of::(); + + let flags = (RUBY_T_ARRAY as u64) | (RARRAY_EMBED_FLAG as u64); + let klass = unsafe { rb_cArray }; + + gc_fastpath::gc_fast_path_new_obj(jit, asm, alloc_size, flags, klass, |asm| { + asm_ccall!(asm, rb_ec_ary_new_from_values, EC, 0i64.into(), Opnd::UImm(0)) + }) } /// Adjust potentially-negative index by the given length, returning the adjusted index. If still negative, diff --git a/zjit/src/codegen/gc_fastpath.rs b/zjit/src/codegen/gc_fastpath.rs new file mode 100644 index 00000000000000..ad109440d14d8b --- /dev/null +++ b/zjit/src/codegen/gc_fastpath.rs @@ -0,0 +1,367 @@ +use std::ffi::c_void; + +use crate::backend::lir::{self, Assembler, EC, Opnd, Target, asm_comment}; +use crate::cruby::{ + RB_GC_ZJIT_FASTPATH_DEFAULT, RB_GC_ZJIT_FASTPATH_MMTK, + RUBY_OFFSET_EC_THREAD_PTR, RUBY_OFFSET_RBASIC_FLAGS, RUBY_OFFSET_RBASIC_KLASS, + RUBY_OFFSET_THREAD_RACTOR, VALUE, VALUE_BITS, rb_zjit_offset_ractor_newobj_cache, +}; +use super::JITState; + +#[repr(C)] +#[derive(Clone, Copy)] +struct RbGcZjitDefaultNewObjFastpath { + cursor_offset: usize, + jit_cursor_end_offset: usize, + slot_size: usize, + flags: VALUE, + klass: VALUE, +} + +#[repr(C)] +#[derive(Clone, Copy)] +struct RbGcZjitMmtkNewObjFastpath { + objspace: *const c_void, + objspace_total_allocated_objects_offset: usize, + ractor_cache_mutator_offset: usize, + ractor_cache_bump_pointer_offset: usize, + ractor_cache_obj_free_parallel_buf_offset: usize, + ractor_cache_obj_free_parallel_count_offset: usize, + bump_pointer_cursor_offset: usize, + bump_pointer_limit_offset: usize, + min_obj_align: usize, + payload_size: usize, + total_alloc_size: usize, + allocation_semantics_default: u32, + gc_stress_p_func: usize, + newobj_tracing_p_func: usize, + post_alloc_func: usize, + obj_free_buf_capacity_minus_one: usize, + value_size_shift: usize, + flags: VALUE, + klass: VALUE, +} + +#[repr(C)] +union RbGcZjitFastpathData { + default_gc: RbGcZjitDefaultNewObjFastpath, + mmtk: RbGcZjitMmtkNewObjFastpath, +} + +#[repr(C)] +struct RbGcZjitFastpath { + kind: u32, + data: RbGcZjitFastpathData, +} + +unsafe extern "C" { + fn rb_gc_zjit_new_obj_fastpath( + alloc_size: usize, + flags: VALUE, + klass: VALUE, + fastpath: *mut RbGcZjitFastpath, + ) -> bool; +} + +enum PreparedNewObjFastpath { + Default(RbGcZjitDefaultNewObjFastpath), + Mmtk(RbGcZjitMmtkNewObjFastpath), +} + +pub(super) fn gc_fast_path_new_obj( + jit: &mut JITState, + asm: &mut Assembler, + alloc_size: usize, + flags: u64, + klass: VALUE, + slow_path: impl Fn(&mut Assembler) -> lir::Opnd, +) -> lir::Opnd { + let Some(fastpath) = prepare_new_obj_fastpath(alloc_size, flags, klass) else { + return slow_path(asm); + }; + + asm_comment!(asm, "GC inline allocation"); + + let hir_block_id = asm.current_block().hir_block_id; + let rpo_idx = asm.current_block().rpo_index; + + let result_block = asm.new_block(hir_block_id, false, rpo_idx); + let miss_block = asm.new_block(hir_block_id, false, rpo_idx); + + let result_edge = |v: Opnd| Target::Block(Box::new(lir::BranchEdge { target: result_block, args: vec![v] })); + + let obj = emit_new_obj_fastpath(jit, asm, &fastpath, miss_block) + .expect("validated GC fastpath must return an object"); + asm.jmp(result_edge(obj)); + + asm.set_current_block(miss_block); + let label = jit.get_label(asm, miss_block, hir_block_id); + asm.write_label(label); + let obj = slow_path(asm); + asm.jmp(result_edge(obj)); + + asm.set_current_block(result_block); + let label = jit.get_label(asm, result_block, hir_block_id); + asm.write_label(label); + let param = asm.new_block_param(VALUE_BITS); + asm.current_block().add_parameter(param); + param +} + +fn prepare_new_obj_fastpath(alloc_size: usize, flags: u64, klass: VALUE) -> Option { + let mut fastpath: RbGcZjitFastpath = unsafe { std::mem::zeroed() }; + let has_fastpath = unsafe { + rb_gc_zjit_new_obj_fastpath(alloc_size, VALUE(flags as usize), klass, &mut fastpath) + }; + + if !has_fastpath { + return None; + } + + match fastpath.kind { + RB_GC_ZJIT_FASTPATH_DEFAULT => { + let fastpath = unsafe { fastpath.data.default_gc }; + Some(PreparedNewObjFastpath::Default(fastpath)) + } + RB_GC_ZJIT_FASTPATH_MMTK => { + let fastpath = unsafe { fastpath.data.mmtk }; + if fastpath.objspace.is_null() + || fastpath.gc_stress_p_func == 0 + || fastpath.newobj_tracing_p_func == 0 + || fastpath.post_alloc_func == 0 + || fastpath.min_obj_align == 0 + || !fastpath.min_obj_align.is_power_of_two() + { + return None; + } + + Some(PreparedNewObjFastpath::Mmtk(fastpath)) + } + _ => None, + } +} + +fn emit_new_obj_fastpath( + jit: &mut JITState, + asm: &mut Assembler, + prepared: &PreparedNewObjFastpath, + miss_block: lir::BlockId, +) -> Option { + let miss = Target::Block(Box::new(lir::BranchEdge { + target: miss_block, + args: vec![], + })); + + match prepared { + PreparedNewObjFastpath::Default(fastpath) => { + emit_default_new_obj_fastpath(jit, asm, fastpath, &miss) + } + PreparedNewObjFastpath::Mmtk(fastpath) => { + emit_mmtk_new_obj_fastpath(jit, asm, fastpath, &miss) + } + } +} + +/* This function implements the GC fast path for the default GC. It implements + * the fast path defined in function ractor_cache_allocate_slot (but not the + * medium path in ractor_cache_advance_region). It also implements newobj_init + * to write the flags and klass in the object. */ +fn emit_default_new_obj_fastpath( + jit: &mut JITState, + asm: &mut Assembler, + fastpath: &RbGcZjitDefaultNewObjFastpath, + miss: &Target, +) -> Option { + let cursor_offset: i32 = fastpath.cursor_offset.try_into().ok()?; + let jit_cursor_end_offset: i32 = fastpath.jit_cursor_end_offset.try_into().ok()?; + let slot_size: u64 = fastpath.slot_size.try_into().ok()?; + + let thread = asm.load(Opnd::mem(64, EC, RUBY_OFFSET_EC_THREAD_PTR as i32)); + let ractor = asm.load(Opnd::mem(64, thread, RUBY_OFFSET_THREAD_RACTOR as i32)); + let ractor_newobj_cache_offset: i32 = unsafe { rb_zjit_offset_ractor_newobj_cache() } + .try_into() + .expect("ractor newobj cache offset fits in i32"); + let gc_cache = asm.load(Opnd::mem(64, ractor, ractor_newobj_cache_offset)); + + let cursor = asm.load(Opnd::mem(64, gc_cache, cursor_offset)); + let cursor_end = asm.load(Opnd::mem(64, gc_cache, jit_cursor_end_offset)); + + let new_cursor = asm.add(cursor, Opnd::UImm(slot_size)); + asm.cmp(cursor_end, new_cursor); + asm.jl(jit, miss.clone()); + + asm.store(Opnd::mem(64, gc_cache, cursor_offset), new_cursor); + asm.store( + Opnd::mem(VALUE_BITS, cursor, RUBY_OFFSET_RBASIC_FLAGS), + fastpath.flags.into(), + ); + asm.store( + Opnd::mem(VALUE_BITS, cursor, RUBY_OFFSET_RBASIC_KLASS), + fastpath.klass.into(), + ); + + Some(cursor) +} + +/* This function implements the GC fast path for MMTk. It implements the fast + * path defined in function rb_mmtk_alloc_fast_path, as well as writing the + * flags and klass into the object. */ +fn emit_mmtk_new_obj_fastpath( + jit: &mut JITState, + asm: &mut Assembler, + fastpath: &RbGcZjitMmtkNewObjFastpath, + miss: &Target, +) -> Option { + let objspace_total_allocated_objects_offset: i32 = fastpath + .objspace_total_allocated_objects_offset + .try_into() + .ok()?; + let ractor_cache_mutator_offset: i32 = fastpath.ractor_cache_mutator_offset.try_into().ok()?; + let ractor_cache_bump_pointer_offset: i32 = fastpath + .ractor_cache_bump_pointer_offset + .try_into() + .ok()?; + let ractor_cache_obj_free_parallel_buf_offset: u64 = fastpath + .ractor_cache_obj_free_parallel_buf_offset + .try_into() + .ok()?; + let ractor_cache_obj_free_parallel_count_offset: i32 = fastpath + .ractor_cache_obj_free_parallel_count_offset + .try_into() + .ok()?; + let bump_pointer_cursor_offset: i32 = fastpath.bump_pointer_cursor_offset.try_into().ok()?; + let bump_pointer_limit_offset: i32 = fastpath.bump_pointer_limit_offset.try_into().ok()?; + let payload_size: u64 = fastpath.payload_size.try_into().ok()?; + let total_alloc_size: u64 = fastpath.total_alloc_size.try_into().ok()?; + let obj_free_buf_capacity_minus_one: u64 = fastpath + .obj_free_buf_capacity_minus_one + .try_into() + .ok()?; + let value_size_shift: u64 = fastpath.value_size_shift.try_into().ok()?; + let newobj_tracing_p_func = (fastpath.newobj_tracing_p_func != 0) + .then_some(fastpath.newobj_tracing_p_func as *const u8)?; + let gc_stress_p_func = (fastpath.gc_stress_p_func != 0) + .then_some(fastpath.gc_stress_p_func as *const u8)?; + let post_alloc_func = (fastpath.post_alloc_func != 0) + .then_some(fastpath.post_alloc_func as *const u8)?; + + let event_hook = asm.ccall(newobj_tracing_p_func, vec![]); + asm.test(event_hook, event_hook); + asm.jnz(jit, miss.clone()); + + let objspace_const = Opnd::const_ptr(fastpath.objspace); + let gc_stress = asm.ccall(gc_stress_p_func, vec![objspace_const]); + asm.test(gc_stress, gc_stress); + asm.jnz(jit, miss.clone()); + + let objspace = asm.load(objspace_const); + let thread = asm.load(Opnd::mem(64, EC, RUBY_OFFSET_EC_THREAD_PTR as i32)); + let ractor = asm.load(Opnd::mem(64, thread, RUBY_OFFSET_THREAD_RACTOR as i32)); + let ractor_newobj_cache_offset: i32 = unsafe { rb_zjit_offset_ractor_newobj_cache() } + .try_into() + .expect("ractor newobj cache offset fits in i32"); + let ractor_cache = asm.load(Opnd::mem(64, ractor, ractor_newobj_cache_offset)); + + let bump_pointer = asm.load(Opnd::mem( + 64, + ractor_cache, + ractor_cache_bump_pointer_offset, + )); + asm.test(bump_pointer, bump_pointer); + asm.jz(jit, miss.clone()); + + let obj_free_count = asm.load(Opnd::mem( + 64, + ractor_cache, + ractor_cache_obj_free_parallel_count_offset, + )); + asm.cmp(obj_free_count, Opnd::UImm(obj_free_buf_capacity_minus_one)); + asm.jge(jit, miss.clone()); + + let cursor = asm.load(Opnd::mem( + 64, + bump_pointer, + bump_pointer_cursor_offset, + )); + let align_mask: i64 = (fastpath.min_obj_align - 1).try_into().ok()?; + let adjusted = asm.add(cursor, Opnd::UImm(align_mask as u64)); + let aligned = asm.and(adjusted, Opnd::Imm(!align_mask)); + let new_cursor = asm.add(aligned, Opnd::UImm(total_alloc_size)); + let limit = asm.load(Opnd::mem( + 64, + bump_pointer, + bump_pointer_limit_offset, + )); + asm.cmp(limit, new_cursor); + asm.jl(jit, miss.clone()); + + asm.store( + Opnd::mem( + 64, + bump_pointer, + bump_pointer_cursor_offset, + ), + new_cursor, + ); + + let value_size: u64 = std::mem::size_of::().try_into().ok()?; + let obj = asm.add(aligned, Opnd::UImm(value_size)); + asm.store(Opnd::mem(VALUE_BITS, aligned, 0), Opnd::UImm(payload_size)); + asm.store( + Opnd::mem(VALUE_BITS, obj, RUBY_OFFSET_RBASIC_FLAGS), + fastpath.flags.into(), + ); + asm.store( + Opnd::mem(VALUE_BITS, obj, RUBY_OFFSET_RBASIC_KLASS), + fastpath.klass.into(), + ); + + let mutator = asm.load(Opnd::mem( + 64, + ractor_cache, + ractor_cache_mutator_offset, + )); + asm.ccall( + post_alloc_func, + vec![ + mutator, + obj, + Opnd::UImm(total_alloc_size), + Opnd::UImm(u64::from(fastpath.allocation_semantics_default)), + ], + ); + + let obj_free_index = asm.lshift(obj_free_count, Opnd::UImm(value_size_shift)); + let obj_free_buf = asm.add( + ractor_cache, + Opnd::UImm(ractor_cache_obj_free_parallel_buf_offset), + ); + let obj_free_slot = asm.add(obj_free_buf, obj_free_index); + asm.store(Opnd::mem(64, obj_free_slot, 0), obj); + let new_obj_free_count = asm.add(obj_free_count, Opnd::UImm(1)); + asm.store( + Opnd::mem( + 64, + ractor_cache, + ractor_cache_obj_free_parallel_count_offset, + ), + new_obj_free_count, + ); + + let total_allocated_objects = asm.load(Opnd::mem( + 64, + objspace, + objspace_total_allocated_objects_offset, + )); + let new_total_allocated_objects = asm.add(total_allocated_objects, Opnd::UImm(1)); + asm.store( + Opnd::mem( + 64, + objspace, + objspace_total_allocated_objects_offset, + ), + new_total_allocated_objects, + ); + + Some(obj) +} diff --git a/zjit/src/cruby.rs b/zjit/src/cruby.rs index b798fe45d8bbf9..cc5bc35f8c8d10 100644 --- a/zjit/src/cruby.rs +++ b/zjit/src/cruby.rs @@ -122,6 +122,8 @@ unsafe extern "C" { ci: *const rb_callinfo, ) -> *const rb_callable_method_entry_t; + pub fn rb_zjit_offset_ractor_newobj_cache() -> usize; + // Floats within range will be encoded without creating objects in the heap. // (Range is 0x3000000000000001 to 0x4fffffffffffffff (1.7272337110188893E-77 to 2.3158417847463237E+77). pub fn rb_float_new(d: f64) -> VALUE; diff --git a/zjit/src/cruby_bindings.inc.rs b/zjit/src/cruby_bindings.inc.rs index a2f71ef8fb6f6f..69e5a2b6fe0e01 100644 --- a/zjit/src/cruby_bindings.inc.rs +++ b/zjit/src/cruby_bindings.inc.rs @@ -237,6 +237,7 @@ pub const SHAPE_ID_NUM_BITS: u32 = 32; pub const ZJIT_STACK_MAP_VREG_TAG: u32 = 8; pub const ZJIT_STACK_MAP_SHIFT: u32 = 8; pub const ZJIT_JIT_RETURN_C_FRAME: u32 = 1; +pub const RB_GC_ZJIT_FASTPATH_DATA_WORDS: u32 = 19; pub type rb_alloc_func_t = ::std::option::Option VALUE>; pub const RUBY_Qfalse: ruby_special_consts = 0; pub const RUBY_Qnil: ruby_special_consts = 4; @@ -340,6 +341,29 @@ pub const RARRAY_EMBED_LEN_MASK: ruby_rarray_flags = 4161536; pub type ruby_rarray_flags = u32; pub const RARRAY_EMBED_LEN_SHIFT: ruby_rarray_consts = 15; pub type ruby_rarray_consts = u32; +#[repr(C)] +pub struct RArray { + pub basic: RBasic, + pub as_: RArray__bindgen_ty_1, +} +#[repr(C)] +pub struct RArray__bindgen_ty_1 { + pub heap: __BindgenUnionField, + pub ary: __BindgenUnionField<[VALUE; 1usize]>, + pub bindgen_union_field: [u64; 3usize], +} +#[repr(C)] +pub struct RArray__bindgen_ty_1__bindgen_ty_1 { + pub len: ::std::os::raw::c_long, + pub aux: RArray__bindgen_ty_1__bindgen_ty_1__bindgen_ty_1, + pub ptr: *const VALUE, +} +#[repr(C)] +pub struct RArray__bindgen_ty_1__bindgen_ty_1__bindgen_ty_1 { + pub capa: __BindgenUnionField<::std::os::raw::c_long>, + pub shared_root: __BindgenUnionField, + pub bindgen_union_field: u64, +} pub const RMODULE_IS_REFINEMENT: ruby_rmodule_flags = 8192; pub type ruby_rmodule_flags = u32; pub const ROBJECT_HEAP: ruby_robject_flags = 65536; @@ -1925,6 +1949,7 @@ pub struct zjit_jit_frame { } pub const ISEQ_BODY_OFFSET_PARAM: zjit_struct_offsets = 16; pub const ISEQ_BODY_OFFSET_OUTER_VARIABLES: zjit_struct_offsets = 288; +pub const RUBY_OFFSET_THREAD_RACTOR: zjit_struct_offsets = 24; pub type zjit_struct_offsets = u32; pub const ROBJECT_OFFSET_AS_HEAP_FIELDS: jit_bindgen_constants = 16; pub const ROBJECT_OFFSET_AS_ARY: jit_bindgen_constants = 16; @@ -1943,6 +1968,59 @@ pub type rb_iseq_param_keyword_struct = rb_iseq_constant_body_rb_iseq_parameters_rb_iseq_param_keyword; #[repr(C)] #[derive(Debug, Copy, Clone)] +pub struct gc_bump_pointer_heap { + pub cursor: usize, + pub cursor_end: usize, + pub jit_cursor_end: usize, + pub region_start: usize, + pub slot_size: usize, +} +pub const RB_GC_ZJIT_FASTPATH_DEFAULT: rb_gc_zjit_fastpath_kind = 1; +pub const RB_GC_ZJIT_FASTPATH_MMTK: rb_gc_zjit_fastpath_kind = 2; +pub type rb_gc_zjit_fastpath_kind = u32; +#[repr(C)] +#[derive(Copy, Clone)] +pub union rb_gc_zjit_fastpath_data { + pub words: [usize; 19usize], +} +#[repr(C)] +#[derive(Copy, Clone)] +pub struct rb_gc_zjit_fastpath { + pub kind: rb_gc_zjit_fastpath_kind, + pub data: rb_gc_zjit_fastpath_data, +} +#[repr(C)] +pub struct rb_gc_zjit_default_new_obj_fastpath { + pub cursor_offset: usize, + pub jit_cursor_end_offset: usize, + pub slot_size: usize, + pub flags: VALUE, + pub klass: VALUE, +} +#[repr(C)] +pub struct rb_gc_zjit_mmtk_new_obj_fastpath { + pub objspace: *const ::std::os::raw::c_void, + pub objspace_total_allocated_objects_offset: usize, + pub ractor_cache_mutator_offset: usize, + pub ractor_cache_bump_pointer_offset: usize, + pub ractor_cache_obj_free_parallel_buf_offset: usize, + pub ractor_cache_obj_free_parallel_count_offset: usize, + pub bump_pointer_cursor_offset: usize, + pub bump_pointer_limit_offset: usize, + pub min_obj_align: usize, + pub payload_size: usize, + pub total_alloc_size: usize, + pub allocation_semantics_default: u32, + pub gc_stress_p_func: usize, + pub newobj_tracing_p_func: usize, + pub post_alloc_func: usize, + pub obj_free_buf_capacity_minus_one: usize, + pub value_size_shift: usize, + pub flags: VALUE, + pub klass: VALUE, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] pub struct succ_index_table { pub _address: u8, }