diff --git a/.github/workflows/cygwin.yml b/.github/workflows/cygwin.yml index 2d7f36a3c29432..126aa8546c69c5 100644 --- a/.github/workflows/cygwin.yml +++ b/.github/workflows/cygwin.yml @@ -47,10 +47,15 @@ jobs: - name: Setup Cygwin uses: cygwin/cygwin-install-action@3f0a3f9f988f7e96b8c18098ae05eaec175f5b52 # v6.1 with: - packages: ruby gcc-core make autoconf libtool libssl-devel libyaml-devel libffi-devel zlib-devel rubygems + packages: ruby gcc-core make autoconf libtool libssl-devel libyaml-devel libffi-devel zlib-devel rubygems ruby-devel site: | https://cygwin.osuosl.org/ + - name: Install fiddle + run: | + gem install fiddle + shell: C:\cygwin\bin\bash.EXE --noprofile --norc -e -o igncr -o pipefail {0} + - name: configure run: | ./autogen.sh diff --git a/compile.c b/compile.c index 32e367f41b53c4..3269645e3d8d85 100644 --- a/compile.c +++ b/compile.c @@ -3698,8 +3698,9 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal if (IS_INSN(&nobj->link) && IS_INSN_ID(nobj, jump)) { if (!replace_destination(iobj, nobj)) break; } - else if (prev_dup && IS_INSN_ID(nobj, dup) && + else if (prev_dup && IS_INSN(&nobj->link) && IS_INSN_ID(nobj, dup) && !!(nobj = (INSN *)nobj->link.next) && + IS_INSN(&nobj->link) && /* basic blocks, with no labels in the middle */ nobj->insn_id == iobj->insn_id) { /* @@ -3786,7 +3787,11 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal break; } else break; - nobj = (INSN *)get_destination_insn(nobj); + { + LINK_ELEMENT *dest = get_destination_insn(nobj); + if (!dest || !IS_INSN(dest)) break; + nobj = (INSN *)dest; + } } } } diff --git a/ext/-test-/regexp/depend b/ext/-test-/regexp/depend index 5ba1b92f18898c..6e2b24ac27ec1c 100644 --- a/ext/-test-/regexp/depend +++ b/ext/-test-/regexp/depend @@ -160,6 +160,167 @@ init.o: $(hdrdir)/ruby/ruby.h init.o: $(hdrdir)/ruby/st.h init.o: $(hdrdir)/ruby/subst.h init.o: init.c +new.o: $(RUBY_EXTCONF_H) +new.o: $(arch_hdrdir)/ruby/config.h +new.o: $(hdrdir)/ruby.h +new.o: $(hdrdir)/ruby/assert.h +new.o: $(hdrdir)/ruby/backward.h +new.o: $(hdrdir)/ruby/backward/2/assume.h +new.o: $(hdrdir)/ruby/backward/2/attributes.h +new.o: $(hdrdir)/ruby/backward/2/bool.h +new.o: $(hdrdir)/ruby/backward/2/inttypes.h +new.o: $(hdrdir)/ruby/backward/2/limits.h +new.o: $(hdrdir)/ruby/backward/2/long_long.h +new.o: $(hdrdir)/ruby/backward/2/stdalign.h +new.o: $(hdrdir)/ruby/backward/2/stdarg.h +new.o: $(hdrdir)/ruby/defines.h +new.o: $(hdrdir)/ruby/intern.h +new.o: $(hdrdir)/ruby/internal/abi.h +new.o: $(hdrdir)/ruby/internal/anyargs.h +new.o: $(hdrdir)/ruby/internal/arithmetic.h +new.o: $(hdrdir)/ruby/internal/arithmetic/char.h +new.o: $(hdrdir)/ruby/internal/arithmetic/double.h +new.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +new.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +new.o: $(hdrdir)/ruby/internal/arithmetic/int.h +new.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +new.o: $(hdrdir)/ruby/internal/arithmetic/long.h +new.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +new.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +new.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +new.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +new.o: $(hdrdir)/ruby/internal/arithmetic/short.h +new.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +new.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +new.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +new.o: $(hdrdir)/ruby/internal/assume.h +new.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +new.o: $(hdrdir)/ruby/internal/attr/artificial.h +new.o: $(hdrdir)/ruby/internal/attr/cold.h +new.o: $(hdrdir)/ruby/internal/attr/const.h +new.o: $(hdrdir)/ruby/internal/attr/constexpr.h +new.o: $(hdrdir)/ruby/internal/attr/deprecated.h +new.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +new.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +new.o: $(hdrdir)/ruby/internal/attr/error.h +new.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +new.o: $(hdrdir)/ruby/internal/attr/forceinline.h +new.o: $(hdrdir)/ruby/internal/attr/format.h +new.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +new.o: $(hdrdir)/ruby/internal/attr/noalias.h +new.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +new.o: $(hdrdir)/ruby/internal/attr/noexcept.h +new.o: $(hdrdir)/ruby/internal/attr/noinline.h +new.o: $(hdrdir)/ruby/internal/attr/nonnull.h +new.o: $(hdrdir)/ruby/internal/attr/noreturn.h +new.o: $(hdrdir)/ruby/internal/attr/packed_struct.h +new.o: $(hdrdir)/ruby/internal/attr/pure.h +new.o: $(hdrdir)/ruby/internal/attr/restrict.h +new.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +new.o: $(hdrdir)/ruby/internal/attr/warning.h +new.o: $(hdrdir)/ruby/internal/attr/weakref.h +new.o: $(hdrdir)/ruby/internal/cast.h +new.o: $(hdrdir)/ruby/internal/compiler_is.h +new.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +new.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +new.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +new.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +new.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +new.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +new.o: $(hdrdir)/ruby/internal/compiler_since.h +new.o: $(hdrdir)/ruby/internal/config.h +new.o: $(hdrdir)/ruby/internal/constant_p.h +new.o: $(hdrdir)/ruby/internal/core.h +new.o: $(hdrdir)/ruby/internal/core/rarray.h +new.o: $(hdrdir)/ruby/internal/core/rbasic.h +new.o: $(hdrdir)/ruby/internal/core/rbignum.h +new.o: $(hdrdir)/ruby/internal/core/rclass.h +new.o: $(hdrdir)/ruby/internal/core/rdata.h +new.o: $(hdrdir)/ruby/internal/core/rfile.h +new.o: $(hdrdir)/ruby/internal/core/rhash.h +new.o: $(hdrdir)/ruby/internal/core/robject.h +new.o: $(hdrdir)/ruby/internal/core/rregexp.h +new.o: $(hdrdir)/ruby/internal/core/rstring.h +new.o: $(hdrdir)/ruby/internal/core/rstruct.h +new.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +new.o: $(hdrdir)/ruby/internal/ctype.h +new.o: $(hdrdir)/ruby/internal/dllexport.h +new.o: $(hdrdir)/ruby/internal/dosish.h +new.o: $(hdrdir)/ruby/internal/error.h +new.o: $(hdrdir)/ruby/internal/eval.h +new.o: $(hdrdir)/ruby/internal/event.h +new.o: $(hdrdir)/ruby/internal/fl_type.h +new.o: $(hdrdir)/ruby/internal/gc.h +new.o: $(hdrdir)/ruby/internal/glob.h +new.o: $(hdrdir)/ruby/internal/globals.h +new.o: $(hdrdir)/ruby/internal/has/attribute.h +new.o: $(hdrdir)/ruby/internal/has/builtin.h +new.o: $(hdrdir)/ruby/internal/has/c_attribute.h +new.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +new.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +new.o: $(hdrdir)/ruby/internal/has/extension.h +new.o: $(hdrdir)/ruby/internal/has/feature.h +new.o: $(hdrdir)/ruby/internal/has/warning.h +new.o: $(hdrdir)/ruby/internal/intern/array.h +new.o: $(hdrdir)/ruby/internal/intern/bignum.h +new.o: $(hdrdir)/ruby/internal/intern/class.h +new.o: $(hdrdir)/ruby/internal/intern/compar.h +new.o: $(hdrdir)/ruby/internal/intern/complex.h +new.o: $(hdrdir)/ruby/internal/intern/cont.h +new.o: $(hdrdir)/ruby/internal/intern/dir.h +new.o: $(hdrdir)/ruby/internal/intern/enum.h +new.o: $(hdrdir)/ruby/internal/intern/enumerator.h +new.o: $(hdrdir)/ruby/internal/intern/error.h +new.o: $(hdrdir)/ruby/internal/intern/eval.h +new.o: $(hdrdir)/ruby/internal/intern/file.h +new.o: $(hdrdir)/ruby/internal/intern/hash.h +new.o: $(hdrdir)/ruby/internal/intern/io.h +new.o: $(hdrdir)/ruby/internal/intern/load.h +new.o: $(hdrdir)/ruby/internal/intern/marshal.h +new.o: $(hdrdir)/ruby/internal/intern/numeric.h +new.o: $(hdrdir)/ruby/internal/intern/object.h +new.o: $(hdrdir)/ruby/internal/intern/parse.h +new.o: $(hdrdir)/ruby/internal/intern/proc.h +new.o: $(hdrdir)/ruby/internal/intern/process.h +new.o: $(hdrdir)/ruby/internal/intern/random.h +new.o: $(hdrdir)/ruby/internal/intern/range.h +new.o: $(hdrdir)/ruby/internal/intern/rational.h +new.o: $(hdrdir)/ruby/internal/intern/re.h +new.o: $(hdrdir)/ruby/internal/intern/ruby.h +new.o: $(hdrdir)/ruby/internal/intern/select.h +new.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +new.o: $(hdrdir)/ruby/internal/intern/set.h +new.o: $(hdrdir)/ruby/internal/intern/signal.h +new.o: $(hdrdir)/ruby/internal/intern/sprintf.h +new.o: $(hdrdir)/ruby/internal/intern/string.h +new.o: $(hdrdir)/ruby/internal/intern/struct.h +new.o: $(hdrdir)/ruby/internal/intern/thread.h +new.o: $(hdrdir)/ruby/internal/intern/time.h +new.o: $(hdrdir)/ruby/internal/intern/variable.h +new.o: $(hdrdir)/ruby/internal/intern/vm.h +new.o: $(hdrdir)/ruby/internal/interpreter.h +new.o: $(hdrdir)/ruby/internal/iterator.h +new.o: $(hdrdir)/ruby/internal/memory.h +new.o: $(hdrdir)/ruby/internal/method.h +new.o: $(hdrdir)/ruby/internal/module.h +new.o: $(hdrdir)/ruby/internal/newobj.h +new.o: $(hdrdir)/ruby/internal/scan_args.h +new.o: $(hdrdir)/ruby/internal/special_consts.h +new.o: $(hdrdir)/ruby/internal/static_assert.h +new.o: $(hdrdir)/ruby/internal/stdalign.h +new.o: $(hdrdir)/ruby/internal/stdbool.h +new.o: $(hdrdir)/ruby/internal/stdckdint.h +new.o: $(hdrdir)/ruby/internal/symbol.h +new.o: $(hdrdir)/ruby/internal/value.h +new.o: $(hdrdir)/ruby/internal/value_type.h +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/ruby.h +new.o: $(hdrdir)/ruby/st.h +new.o: $(hdrdir)/ruby/subst.h +new.o: new.c parse_depth_limit.o: $(RUBY_EXTCONF_H) parse_depth_limit.o: $(arch_hdrdir)/ruby/config.h parse_depth_limit.o: $(hdrdir)/ruby.h diff --git a/ext/-test-/regexp/new.c b/ext/-test-/regexp/new.c new file mode 100644 index 00000000000000..9e8c9854062ffe --- /dev/null +++ b/ext/-test-/regexp/new.c @@ -0,0 +1,14 @@ +#include + +static VALUE +reg_new_binary(VALUE self, VALUE src) +{ + StringValue(src); + return rb_reg_new(RSTRING_PTR(src), RSTRING_LEN(src), 0); +} + +void +Init_new(VALUE klass) +{ + rb_define_singleton_method(klass, "new_binary", reg_new_binary, 1); +} diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c index 3d913a396844cf..27a811b5a716c7 100644 --- a/ext/openssl/ossl_ssl.c +++ b/ext/openssl/ossl_ssl.c @@ -56,7 +56,7 @@ static void ossl_sslctx_mark(void *ptr) { SSL_CTX *ctx = ptr; - rb_gc_mark((VALUE)SSL_CTX_get_ex_data(ctx, ossl_sslctx_ex_ptr_idx)); + rb_gc_mark_movable((VALUE)SSL_CTX_get_ex_data(ctx, ossl_sslctx_ex_ptr_idx)); } static void @@ -65,12 +65,25 @@ ossl_sslctx_free(void *ptr) SSL_CTX_free(ptr); } +static void +ossl_sslctx_compact(void *ptr) +{ + SSL_CTX *ctx = ptr; + VALUE self = (VALUE)SSL_CTX_get_ex_data(ctx, ossl_sslctx_ex_ptr_idx); + if (self) { + (void)SSL_CTX_set_ex_data(ctx, ossl_sslctx_ex_ptr_idx, + (void *)rb_gc_location(self)); + } +} + static const rb_data_type_t ossl_sslctx_type = { - "OpenSSL/SSL/CTX", - { - ossl_sslctx_mark, ossl_sslctx_free, + .wrap_struct_name = "OpenSSL/SSL/CTX", + .function = { + .dmark = ossl_sslctx_mark, + .dfree = ossl_sslctx_free, + .dcompact = ossl_sslctx_compact, }, - 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED, + .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED, }; static VALUE @@ -1567,7 +1580,7 @@ static void ossl_ssl_mark(void *ptr) { SSL *ssl = ptr; - rb_gc_mark((VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx)); + rb_gc_mark_movable((VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx)); } static void @@ -1576,12 +1589,25 @@ ossl_ssl_free(void *ssl) SSL_free(ssl); } +static void +ossl_ssl_compact(void *ptr) +{ + SSL *ssl = ptr; + VALUE self = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx); + if (self) { + (void)SSL_set_ex_data(ssl, ossl_ssl_ex_ptr_idx, + (void *)rb_gc_location(self)); + } +} + const rb_data_type_t ossl_ssl_type = { - "OpenSSL/SSL", - { - ossl_ssl_mark, ossl_ssl_free, + .wrap_struct_name = "OpenSSL/SSL", + .function = { + .dmark = ossl_ssl_mark, + .dfree = ossl_ssl_free, + .dcompact = ossl_ssl_compact, }, - 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED, + .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED, }; static VALUE diff --git a/ext/openssl/ossl_x509store.c b/ext/openssl/ossl_x509store.c index bed124dc3ed454..ee9f3d0e370eb2 100644 --- a/ext/openssl/ossl_x509store.c +++ b/ext/openssl/ossl_x509store.c @@ -116,10 +116,9 @@ static void ossl_x509store_mark(void *ptr) { X509_STORE *store = ptr; - // Note: this reference is stored as @verify_callback so we don't need to mark it. - // However we do need to ensure GC compaction won't move it, hence why - // we call rb_gc_mark here. - rb_gc_mark((VALUE)X509_STORE_get_ex_data(store, store_ex_verify_cb_idx)); + VALUE verify_cb = + (VALUE)X509_STORE_get_ex_data(store, store_ex_verify_cb_idx); + rb_gc_mark_movable(verify_cb); } static void @@ -128,12 +127,26 @@ ossl_x509store_free(void *ptr) X509_STORE_free(ptr); } +static void +ossl_x509store_compact(void *ptr) +{ + X509_STORE *store = ptr; + VALUE verify_cb = + (VALUE)X509_STORE_get_ex_data(store, store_ex_verify_cb_idx); + if (verify_cb) { + (void)X509_STORE_set_ex_data(store, store_ex_verify_cb_idx, + (void *)rb_gc_location(verify_cb)); + } +} + static const rb_data_type_t ossl_x509store_type = { - "OpenSSL/X509/STORE", - { - ossl_x509store_mark, ossl_x509store_free, + .wrap_struct_name = "OpenSSL/X509/STORE", + .function = { + .dmark = ossl_x509store_mark, + .dfree = ossl_x509store_free, + .dcompact = ossl_x509store_compact, }, - 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED, + .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED, }; /* @@ -570,10 +583,9 @@ static void ossl_x509stctx_mark(void *ptr) { X509_STORE_CTX *ctx = ptr; - // Note: this reference is stored as @verify_callback so we don't need to mark it. - // However we do need to ensure GC compaction won't move it, hence why - // we call rb_gc_mark here. - rb_gc_mark((VALUE)X509_STORE_CTX_get_ex_data(ctx, stctx_ex_verify_cb_idx)); + VALUE verify_cb = + (VALUE)X509_STORE_CTX_get_ex_data(ctx, stctx_ex_verify_cb_idx); + rb_gc_mark_movable(verify_cb); } static void @@ -585,12 +597,26 @@ ossl_x509stctx_free(void *ptr) X509_STORE_CTX_free(ctx); } +static void +ossl_x509stctx_compact(void *ptr) +{ + X509_STORE_CTX *ctx = ptr; + VALUE verify_cb = + (VALUE)X509_STORE_CTX_get_ex_data(ctx, stctx_ex_verify_cb_idx); + if (verify_cb) { + (void)X509_STORE_CTX_set_ex_data(ctx, stctx_ex_verify_cb_idx, + (void *)rb_gc_location(verify_cb)); + } +} + static const rb_data_type_t ossl_x509stctx_type = { - "OpenSSL/X509/STORE_CTX", - { - ossl_x509stctx_mark, ossl_x509stctx_free, + .wrap_struct_name = "OpenSSL/X509/STORE_CTX", + .function = { + .dmark = ossl_x509stctx_mark, + .dfree = ossl_x509stctx_free, + .dcompact = ossl_x509stctx_compact, }, - 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED, + .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED, }; static VALUE diff --git a/re.c b/re.c index 68c6b45235f5b0..1d88ca02bbf542 100644 --- a/re.c +++ b/re.c @@ -3655,11 +3655,15 @@ rb_reg_equal(VALUE re1, VALUE re2) // src is a fstring, so a pointer comparison is enough RUBY_ASSERT(FL_TEST_RAW(RREGEXP_SRC(re1), RSTRING_FSTR)); RUBY_ASSERT(FL_TEST_RAW(RREGEXP_SRC(re2), RSTRING_FSTR)); - if (RREGEXP_SRC(re1) != RREGEXP_SRC(re2)) return Qfalse; if (FL_TEST(re1, KCODE_FIXED) != FL_TEST(re2, KCODE_FIXED)) return Qfalse; if (RREGEXP_PTR(re1)->options != RREGEXP_PTR(re2)->options) return Qfalse; - return RBOOL(ENCODING_GET(re1) == ENCODING_GET(re2)); + if (RREGEXP_SRC_LEN(re1) != RREGEXP_SRC_LEN(re2)) return Qfalse; + if (ENCODING_GET(re1) != ENCODING_GET(re2)) return Qfalse; + + if (RREGEXP_SRC(re1) == RREGEXP_SRC(re2)) return Qtrue; + if (RREGEXP_SRC_PTR(re1) == RREGEXP_SRC_PTR(re2)) return Qtrue; + return RBOOL(memcmp(RREGEXP_SRC_PTR(re1), RREGEXP_SRC_PTR(re2), RREGEXP_SRC_LEN(re1)) == 0); } /* diff --git a/test/ruby/test_optimization.rb b/test/ruby/test_optimization.rb index d34e490d589126..4e9fd5cf0bdd27 100644 --- a/test/ruby/test_optimization.rb +++ b/test/ruby/test_optimization.rb @@ -1047,6 +1047,21 @@ def x.bug assert_equal(:ok, x.bug) end + def test_peephole_branch_dup_with_label_after_dup + assert_ruby_status [], <<-END + src = <<~'SRC' + $g&.call&.to_s + [*d, [__dir__].each(&:each), C1.value(/ab/o, &b)].each {} + begin + ((-243 != qux) ? (1..2) : 8i&.value) => ^([1].select(&:to_s)) + rescue + ((-243 != qux) ? (1..2) : 8i&.value) => ^([1].select(&:to_s)) + end + SRC + RubyVM::InstructionSequence.compile(src) + END + end + def test_peephole_jump_after_newarray i = 0 %w(1) || 2 while (i += 1) < 100 diff --git a/test/ruby/test_regexp.rb b/test/ruby/test_regexp.rb index cf989615e031f1..250956dd3a009d 100644 --- a/test/ruby/test_regexp.rb +++ b/test/ruby/test_regexp.rb @@ -938,6 +938,13 @@ def test_eqq assert_equal(false, /../ === nil) end + def test_eql + require '-test-/regexp' + rescue LoadError + else + assert_equal(/^[0-9]/, Bug::Regexp.new_binary("^[0-9]")) + end + def test_quote assert_equal("\xff", Regexp.quote([0xff].pack("C"))) assert_equal("\\ ", Regexp.quote("\ "))