diff options
39 files changed, 1025 insertions, 1030 deletions
@@ -68,7 +68,7 @@ The following default gems are updated. * prism 1.4.0 * psych 5.2.4 * stringio 3.1.8.dev -* strscan 3.1.4.dev +* strscan 3.1.5.dev * uri 1.0.3 The following bundled gems are added. diff --git a/addr2line.c b/addr2line.c index dc0892e308..745364cc0f 100644 --- a/addr2line.c +++ b/addr2line.c @@ -2175,9 +2175,8 @@ fill_lines(int num_traces, void **traces, int check_debuglink, } } - if (offset == -1) { + if (offset == 0) { /* main executable */ - offset = 0; if (dynsym_shdr && dynstr_shdr) { char *strtab = file + dynstr_shdr->sh_offset; ElfW(Sym) *symtab = (ElfW(Sym) *)(file + dynsym_shdr->sh_offset); @@ -5613,7 +5613,7 @@ rb_ary_difference_multi(int argc, VALUE *argv, VALUE ary) VALUE elt = rb_ary_elt(ary, i); for (j = 0; j < argc; j++) { if (is_hash[j]) { - if (rb_hash_stlike_lookup(argv[j], RARRAY_AREF(ary, i), NULL)) + if (rb_hash_stlike_lookup(argv[j], elt, NULL)) break; } else { @@ -189,6 +189,7 @@ COMMONOBJS = array.$(OBJEXT) \ $(YJIT_LIBOBJ) \ $(ZJIT_OBJ) \ $(ZJIT_LIBOBJ) \ + $(JIT_OBJ) \ $(COROUTINE_OBJ) \ $(DTRACE_OBJ) \ $(BUILTIN_ENCOBJS) \ @@ -9156,6 +9157,241 @@ iseq.$(OBJEXT): {$(VPATH)}vm_debug.h iseq.$(OBJEXT): {$(VPATH)}vm_opts.h iseq.$(OBJEXT): {$(VPATH)}vm_sync.h iseq.$(OBJEXT): {$(VPATH)}yjit.h +jit.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h +jit.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h +jit.$(OBJEXT): $(CCAN_DIR)/list/list.h +jit.$(OBJEXT): $(CCAN_DIR)/str/str.h +jit.$(OBJEXT): $(hdrdir)/ruby/ruby.h +jit.$(OBJEXT): $(top_srcdir)/internal/array.h +jit.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h +jit.$(OBJEXT): $(top_srcdir)/internal/class.h +jit.$(OBJEXT): $(top_srcdir)/internal/compilers.h +jit.$(OBJEXT): $(top_srcdir)/internal/gc.h +jit.$(OBJEXT): $(top_srcdir)/internal/imemo.h +jit.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h +jit.$(OBJEXT): $(top_srcdir)/internal/serial.h +jit.$(OBJEXT): $(top_srcdir)/internal/set_table.h +jit.$(OBJEXT): $(top_srcdir)/internal/static_assert.h +jit.$(OBJEXT): $(top_srcdir)/internal/variable.h +jit.$(OBJEXT): $(top_srcdir)/internal/vm.h +jit.$(OBJEXT): $(top_srcdir)/internal/warnings.h +jit.$(OBJEXT): $(top_srcdir)/prism/defines.h +jit.$(OBJEXT): $(top_srcdir)/prism/encoding.h +jit.$(OBJEXT): $(top_srcdir)/prism/node.h +jit.$(OBJEXT): $(top_srcdir)/prism/options.h +jit.$(OBJEXT): $(top_srcdir)/prism/pack.h +jit.$(OBJEXT): $(top_srcdir)/prism/parser.h +jit.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h +jit.$(OBJEXT): $(top_srcdir)/prism/prism.h +jit.$(OBJEXT): $(top_srcdir)/prism/regexp.h +jit.$(OBJEXT): $(top_srcdir)/prism/static_literals.h +jit.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h +jit.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h +jit.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h +jit.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h +jit.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h +jit.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h +jit.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h +jit.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h +jit.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h +jit.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h +jit.$(OBJEXT): {$(VPATH)}assert.h +jit.$(OBJEXT): {$(VPATH)}atomic.h +jit.$(OBJEXT): {$(VPATH)}backward/2/assume.h +jit.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +jit.$(OBJEXT): {$(VPATH)}backward/2/bool.h +jit.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h +jit.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +jit.$(OBJEXT): {$(VPATH)}backward/2/limits.h +jit.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +jit.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +jit.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h +jit.$(OBJEXT): {$(VPATH)}builtin.h +jit.$(OBJEXT): {$(VPATH)}config.h +jit.$(OBJEXT): {$(VPATH)}constant.h +jit.$(OBJEXT): {$(VPATH)}debug_counter.h +jit.$(OBJEXT): {$(VPATH)}defines.h +jit.$(OBJEXT): {$(VPATH)}encoding.h +jit.$(OBJEXT): {$(VPATH)}id.h +jit.$(OBJEXT): {$(VPATH)}id_table.h +jit.$(OBJEXT): {$(VPATH)}insns.def +jit.$(OBJEXT): {$(VPATH)}insns.inc +jit.$(OBJEXT): {$(VPATH)}insns_info.inc +jit.$(OBJEXT): {$(VPATH)}intern.h +jit.$(OBJEXT): {$(VPATH)}internal.h +jit.$(OBJEXT): {$(VPATH)}internal/abi.h +jit.$(OBJEXT): {$(VPATH)}internal/anyargs.h +jit.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +jit.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +jit.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +jit.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +jit.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +jit.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +jit.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +jit.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +jit.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +jit.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +jit.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +jit.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +jit.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +jit.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +jit.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +jit.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +jit.$(OBJEXT): {$(VPATH)}internal/assume.h +jit.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +jit.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +jit.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +jit.$(OBJEXT): {$(VPATH)}internal/attr/const.h +jit.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +jit.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +jit.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +jit.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +jit.$(OBJEXT): {$(VPATH)}internal/attr/error.h +jit.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +jit.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +jit.$(OBJEXT): {$(VPATH)}internal/attr/format.h +jit.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +jit.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +jit.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +jit.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +jit.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +jit.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +jit.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +jit.$(OBJEXT): {$(VPATH)}internal/attr/packed_struct.h +jit.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +jit.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +jit.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +jit.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +jit.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +jit.$(OBJEXT): {$(VPATH)}internal/cast.h +jit.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +jit.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +jit.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +jit.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +jit.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +jit.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +jit.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +jit.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +jit.$(OBJEXT): {$(VPATH)}internal/config.h +jit.$(OBJEXT): {$(VPATH)}internal/constant_p.h +jit.$(OBJEXT): {$(VPATH)}internal/core.h +jit.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +jit.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +jit.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +jit.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +jit.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +jit.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +jit.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +jit.$(OBJEXT): {$(VPATH)}internal/core/robject.h +jit.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +jit.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +jit.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +jit.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +jit.$(OBJEXT): {$(VPATH)}internal/ctype.h +jit.$(OBJEXT): {$(VPATH)}internal/dllexport.h +jit.$(OBJEXT): {$(VPATH)}internal/dosish.h +jit.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h +jit.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h +jit.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h +jit.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h +jit.$(OBJEXT): {$(VPATH)}internal/encoding/re.h +jit.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h +jit.$(OBJEXT): {$(VPATH)}internal/encoding/string.h +jit.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h +jit.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h +jit.$(OBJEXT): {$(VPATH)}internal/error.h +jit.$(OBJEXT): {$(VPATH)}internal/eval.h +jit.$(OBJEXT): {$(VPATH)}internal/event.h +jit.$(OBJEXT): {$(VPATH)}internal/fl_type.h +jit.$(OBJEXT): {$(VPATH)}internal/gc.h +jit.$(OBJEXT): {$(VPATH)}internal/glob.h +jit.$(OBJEXT): {$(VPATH)}internal/globals.h +jit.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +jit.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +jit.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +jit.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +jit.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +jit.$(OBJEXT): {$(VPATH)}internal/has/extension.h +jit.$(OBJEXT): {$(VPATH)}internal/has/feature.h +jit.$(OBJEXT): {$(VPATH)}internal/has/warning.h +jit.$(OBJEXT): {$(VPATH)}internal/intern/array.h +jit.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +jit.$(OBJEXT): {$(VPATH)}internal/intern/class.h +jit.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +jit.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +jit.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +jit.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +jit.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +jit.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +jit.$(OBJEXT): {$(VPATH)}internal/intern/error.h +jit.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +jit.$(OBJEXT): {$(VPATH)}internal/intern/file.h +jit.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +jit.$(OBJEXT): {$(VPATH)}internal/intern/io.h +jit.$(OBJEXT): {$(VPATH)}internal/intern/load.h +jit.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +jit.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +jit.$(OBJEXT): {$(VPATH)}internal/intern/object.h +jit.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +jit.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +jit.$(OBJEXT): {$(VPATH)}internal/intern/process.h +jit.$(OBJEXT): {$(VPATH)}internal/intern/random.h +jit.$(OBJEXT): {$(VPATH)}internal/intern/range.h +jit.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +jit.$(OBJEXT): {$(VPATH)}internal/intern/re.h +jit.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h +jit.$(OBJEXT): {$(VPATH)}internal/intern/select.h +jit.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +jit.$(OBJEXT): {$(VPATH)}internal/intern/signal.h +jit.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +jit.$(OBJEXT): {$(VPATH)}internal/intern/string.h +jit.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +jit.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +jit.$(OBJEXT): {$(VPATH)}internal/intern/time.h +jit.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +jit.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +jit.$(OBJEXT): {$(VPATH)}internal/interpreter.h +jit.$(OBJEXT): {$(VPATH)}internal/iterator.h +jit.$(OBJEXT): {$(VPATH)}internal/memory.h +jit.$(OBJEXT): {$(VPATH)}internal/method.h +jit.$(OBJEXT): {$(VPATH)}internal/module.h +jit.$(OBJEXT): {$(VPATH)}internal/newobj.h +jit.$(OBJEXT): {$(VPATH)}internal/scan_args.h +jit.$(OBJEXT): {$(VPATH)}internal/special_consts.h +jit.$(OBJEXT): {$(VPATH)}internal/static_assert.h +jit.$(OBJEXT): {$(VPATH)}internal/stdalign.h +jit.$(OBJEXT): {$(VPATH)}internal/stdbool.h +jit.$(OBJEXT): {$(VPATH)}internal/stdckdint.h +jit.$(OBJEXT): {$(VPATH)}internal/symbol.h +jit.$(OBJEXT): {$(VPATH)}internal/value.h +jit.$(OBJEXT): {$(VPATH)}internal/value_type.h +jit.$(OBJEXT): {$(VPATH)}internal/variable.h +jit.$(OBJEXT): {$(VPATH)}internal/warning_push.h +jit.$(OBJEXT): {$(VPATH)}internal/xmalloc.h +jit.$(OBJEXT): {$(VPATH)}iseq.h +jit.$(OBJEXT): {$(VPATH)}jit.c +jit.$(OBJEXT): {$(VPATH)}method.h +jit.$(OBJEXT): {$(VPATH)}missing.h +jit.$(OBJEXT): {$(VPATH)}node.h +jit.$(OBJEXT): {$(VPATH)}onigmo.h +jit.$(OBJEXT): {$(VPATH)}oniguruma.h +jit.$(OBJEXT): {$(VPATH)}prism/ast.h +jit.$(OBJEXT): {$(VPATH)}prism/diagnostic.h +jit.$(OBJEXT): {$(VPATH)}prism/version.h +jit.$(OBJEXT): {$(VPATH)}prism_compile.h +jit.$(OBJEXT): {$(VPATH)}ruby_assert.h +jit.$(OBJEXT): {$(VPATH)}ruby_atomic.h +jit.$(OBJEXT): {$(VPATH)}rubyparser.h +jit.$(OBJEXT): {$(VPATH)}shape.h +jit.$(OBJEXT): {$(VPATH)}st.h +jit.$(OBJEXT): {$(VPATH)}subst.h +jit.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h +jit.$(OBJEXT): {$(VPATH)}thread_native.h +jit.$(OBJEXT): {$(VPATH)}vm_callinfo.h +jit.$(OBJEXT): {$(VPATH)}vm_core.h +jit.$(OBJEXT): {$(VPATH)}vm_debug.h +jit.$(OBJEXT): {$(VPATH)}vm_opts.h +jit.$(OBJEXT): {$(VPATH)}vm_sync.h load.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h load.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h load.$(OBJEXT): $(CCAN_DIR)/list/list.h diff --git a/configure.ac b/configure.ac index c76db94d84..4bcd614f44 100644 --- a/configure.ac +++ b/configure.ac @@ -3967,6 +3967,7 @@ AS_CASE(["${YJIT_SUPPORT}"], LDFLAGS="$LDFLAGS -lpthread -lc++abi" ]) YJIT_OBJ='yjit.$(OBJEXT)' + JIT_OBJ='jit.$(OBJEXT)' AS_IF([test x"$YJIT_SUPPORT" != "xyes" ], [ AC_DEFINE_UNQUOTED(YJIT_SUPPORT, [$YJIT_SUPPORT]) ]) @@ -4008,6 +4009,7 @@ AS_CASE(["${ZJIT_SUPPORT}"], LDFLAGS="$LDFLAGS -lpthread -lc++abi" ]) ZJIT_OBJ='zjit.$(OBJEXT)' + JIT_OBJ='jit.$(OBJEXT)' AS_IF([test x"$ZJIT_SUPPORT" != "xyes" ], [ AC_DEFINE_UNQUOTED(ZJIT_SUPPORT, [$ZJIT_SUPPORT]) ]) @@ -4025,8 +4027,9 @@ AC_SUBST(ZJIT_CARGO_BUILD_ARGS)dnl for selecting Rust build profiles AC_SUBST(YJIT_LIBS)dnl for optionally building the Rust parts of YJIT AC_SUBST(YJIT_OBJ)dnl for optionally building the C parts of YJIT AC_SUBST(ZJIT_SUPPORT)dnl what flavor of ZJIT the Ruby build includes -AC_SUBST(ZJIT_LIBS)dnl for optionally building the Rust parts of YJIT -AC_SUBST(ZJIT_OBJ)dnl for optionally building the C parts of YJIT +AC_SUBST(ZJIT_LIBS)dnl for optionally building the Rust parts of ZJIT +AC_SUBST(ZJIT_OBJ)dnl for optionally building the C parts of ZJIT +AC_SUBST(JIT_OBJ)dnl for optionally building C glue code for Rust FFI } [begin]_group "build section" && { diff --git a/ext/digest/defs.h b/ext/digest/defs.h index 77a134f364..9b11f4eca9 100644 --- a/ext/digest/defs.h +++ b/ext/digest/defs.h @@ -16,4 +16,26 @@ # define __END_DECLS #endif +#define RB_DIGEST_DIAGNOSTIC(compiler, op, flag) _Pragma(STRINGIZE(compiler diagnostic op flag)) +#ifdef RBIMPL_WARNING_IGNORED +# define RB_DIGEST_WARNING_IGNORED(flag) RBIMPL_WARNING_IGNORED(flag) +# define RB_DIGEST_WARNING_PUSH() RBIMPL_WARNING_PUSH() +# define RB_DIGEST_WARNING_POP() RBIMPL_WARNING_POP() +#elif defined(__clang__) +# define RB_DIGEST_WARNING_IGNORED(flag) RB_DIGEST_DIAGNOSTIC(clang, ignored, #flag) +# define RB_DIGEST_WARNING_PUSH() _Pragma("clang diagnostic push") +# define RB_DIGEST_WARNING_POP() _Pragma("clang diagnostic pop") +#else /* __GNUC__ */ +# define RB_DIGEST_WARNING_IGNORED(flag) RB_DIGEST_DIAGNOSTIC(GCC, ignored, #flag) +# define RB_DIGEST_WARNING_PUSH() _Pragma("GCC diagnostic push") +# define RB_DIGEST_WARNING_POP() _Pragma("GCC diagnostic pop") +#endif +#ifdef RBIMPL_HAS_WARNING +# define RB_DIGEST_HAS_WARNING(_) RBIMPL_HAS_WARNING(_) +#elif defined(__has_warning) +# define RB_DIGEST_HAS_WARNING(_) __has_warning(_) +#else +# define RB_DIGEST_HAS_WARNING(_) 0 +#endif + #endif /* DEFS_H */ diff --git a/ext/digest/digest_conf.rb b/ext/digest/digest_conf.rb index 36a7d75289..099d20fcbe 100644 --- a/ext/digest/digest_conf.rb +++ b/ext/digest/digest_conf.rb @@ -2,14 +2,16 @@ def digest_conf(name) unless with_config("bundled-#{name}") - cc = with_config("common-digest") - if cc != false or /\b#{name}\b/ =~ cc - if File.exist?("#$srcdir/#{name}cc.h") and - have_header("CommonCrypto/CommonDigest.h") - $defs << "-D#{name.upcase}_USE_COMMONDIGEST" - $headers << "#{name}cc.h" - return :commondigest - end + case cc = with_config("common-digest", true) + when true, false + else + cc = cc.split(/[\s,]++/).any? {|pat| File.fnmatch?(pat, name)} + end + if cc and File.exist?("#$srcdir/#{name}cc.h") and + have_header("CommonCrypto/CommonDigest.h") + $defs << "-D#{name.upcase}_USE_COMMONDIGEST" + $headers << "#{name}cc.h" + return :commondigest end end $objs << "#{name}.#{$OBJEXT}" diff --git a/ext/digest/md5/md5cc.h b/ext/digest/md5/md5cc.h index 657f573f85..a002c17604 100644 --- a/ext/digest/md5/md5cc.h +++ b/ext/digest/md5/md5cc.h @@ -2,14 +2,6 @@ #include <CommonCrypto/CommonDigest.h> #ifdef __GNUC__ -# define RB_DIGEST_DIAGNOSTIC(compiler, op, flag) _Pragma(STRINGIZE(compiler diagnostic op flag)) -# ifdef RBIMPL_WARNING_IGNORED -# define RB_DIGEST_WARNING_IGNORED(flag) RBIMPL_WARNING_IGNORED(flag) -# elif defined(__clang__) -# define RB_DIGEST_WARNING_IGNORED(flag) RB_DIGEST_DIAGNOSTIC(clang, ignored, #flag) -# else /* __GNUC__ */ -# define RB_DIGEST_WARNING_IGNORED(flag) RB_DIGEST_DIAGNOSTIC(GCC, ignored, #flag) -# endif RB_DIGEST_WARNING_IGNORED(-Wdeprecated-declarations) /* Suppress deprecation warnings of MD5 from Xcode 11.1 */ /* Although we know MD5 is deprecated too, provide just for backward diff --git a/ext/digest/md5/md5init.c b/ext/digest/md5/md5init.c index b81fd94864..c919060587 100644 --- a/ext/digest/md5/md5init.c +++ b/ext/digest/md5/md5init.c @@ -3,6 +3,7 @@ #include <ruby/ruby.h> #include "../digest.h" +#include "../defs.h" #if defined(MD5_USE_COMMONDIGEST) #include "md5cc.h" #else diff --git a/ext/digest/sha1/sha1.c b/ext/digest/sha1/sha1.c index 5311227549..244fed7a3e 100644 --- a/ext/digest/sha1/sha1.c +++ b/ext/digest/sha1/sha1.c @@ -232,8 +232,14 @@ void SHA1_Update(SHA1_CTX *context, const uint8_t *data, size_t len) if ((j + len) > 63) { (void)memcpy(&context->buffer[j], data, (i = 64-j)); SHA1_Transform(context->state, context->buffer); - for ( ; i + 63 < len; i += 64) + for ( ; i + 63 < len; i += 64) { + RB_DIGEST_WARNING_PUSH(); +#if defined(__GNUC__) && !defined(__clang__) + RB_DIGEST_WARNING_IGNORED(-Wstringop-overread); +#endif SHA1_Transform(context->state, &data[i]); + RB_DIGEST_WARNING_POP(); + } j = 0; } else { i = 0; diff --git a/ext/psych/lib/psych/visitors/to_ruby.rb b/ext/psych/lib/psych/visitors/to_ruby.rb index 5adefde3bd..580a74e9fb 100644 --- a/ext/psych/lib/psych/visitors/to_ruby.rb +++ b/ext/psych/lib/psych/visitors/to_ruby.rb @@ -219,7 +219,8 @@ module Psych revive_data_members(members, o) end data ||= allocate_anon_data(o, members) - data.send(:initialize, **members) + init_struct(data, **members) + data.freeze data when /^!ruby\/object:?(.*)?$/ diff --git a/ext/psych/lib/psych/visitors/yaml_tree.rb b/ext/psych/lib/psych/visitors/yaml_tree.rb index 2229655b78..d7958a8431 100644 --- a/ext/psych/lib/psych/visitors/yaml_tree.rb +++ b/ext/psych/lib/psych/visitors/yaml_tree.rb @@ -73,7 +73,7 @@ module Psych method = respond_to?(method) ? method : h[klass.superclass] - raise(TypeError, "Can't dump #{target.class}") unless method + raise(TypeError, "can't dump #{klass.name}") unless method h[klass] = method end.compare_by_identity diff --git a/ext/psych/psych_to_ruby.c b/ext/psych/psych_to_ruby.c index ffe0c69c7f..d473a5f840 100644 --- a/ext/psych/psych_to_ruby.c +++ b/ext/psych/psych_to_ruby.c @@ -24,6 +24,15 @@ static VALUE path2class(VALUE self, VALUE path) return rb_path_to_class(path); } +static VALUE init_struct(VALUE self, VALUE data, VALUE attrs) +{ + VALUE args = rb_ary_new2(1); + rb_ary_push(args, attrs); + rb_struct_initialize(data, args); + + return data; +} + void Init_psych_to_ruby(void) { VALUE psych = rb_define_module("Psych"); @@ -33,6 +42,7 @@ void Init_psych_to_ruby(void) VALUE visitor = rb_define_class_under(visitors, "Visitor", rb_cObject); cPsychVisitorsToRuby = rb_define_class_under(visitors, "ToRuby", visitor); + rb_define_private_method(cPsychVisitorsToRuby, "init_struct", init_struct, 2); rb_define_private_method(cPsychVisitorsToRuby, "build_exception", build_exception, 2); rb_define_private_method(class_loader, "path2class", path2class, 1); } diff --git a/ext/socket/ipsocket.c b/ext/socket/ipsocket.c index 4dfd9c8a56..da42fbd27b 100644 --- a/ext/socket/ipsocket.c +++ b/ext/socket/ipsocket.c @@ -1159,13 +1159,19 @@ fast_fallback_inetsock_cleanup(VALUE v) getaddrinfo_shared->notify = -1; int shared_need_free = 0; - int need_free[2] = { 0, 0 }; + struct addrinfo *ais[arg->family_size]; + for (int i = 0; i < arg->family_size; i++) ais[i] = NULL; rb_nativethread_lock_lock(&getaddrinfo_shared->lock); { for (int i = 0; i < arg->family_size; i++) { - if (arg->getaddrinfo_entries[i] && --(arg->getaddrinfo_entries[i]->refcount) == 0) { - need_free[i] = 1; + struct fast_fallback_getaddrinfo_entry *getaddrinfo_entry = arg->getaddrinfo_entries[i]; + + if (!getaddrinfo_entry) continue; + + if (--(getaddrinfo_entry->refcount) == 0) { + ais[i] = getaddrinfo_entry->ai; + getaddrinfo_entry->ai = NULL; } } if (--(getaddrinfo_shared->refcount) == 0) { @@ -1175,9 +1181,7 @@ fast_fallback_inetsock_cleanup(VALUE v) rb_nativethread_lock_unlock(&getaddrinfo_shared->lock); for (int i = 0; i < arg->family_size; i++) { - if (arg->getaddrinfo_entries[i] && need_free[i]) { - free_fast_fallback_getaddrinfo_entry(&arg->getaddrinfo_entries[i]); - } + if (ais[i]) freeaddrinfo(ais[i]); } if (getaddrinfo_shared && shared_need_free) { free_fast_fallback_getaddrinfo_shared(&getaddrinfo_shared); diff --git a/ext/socket/raddrinfo.c b/ext/socket/raddrinfo.c index ac47b5b256..91e2be1148 100644 --- a/ext/socket/raddrinfo.c +++ b/ext/socket/raddrinfo.c @@ -3038,22 +3038,13 @@ free_fast_fallback_getaddrinfo_shared(struct fast_fallback_getaddrinfo_shared ** *shared = NULL; } -void -free_fast_fallback_getaddrinfo_entry(struct fast_fallback_getaddrinfo_entry **entry) -{ - if ((*entry)->ai) { - freeaddrinfo((*entry)->ai); - (*entry)->ai = NULL; - } - *entry = NULL; -} - static void * do_fast_fallback_getaddrinfo(void *ptr) { struct fast_fallback_getaddrinfo_entry *entry = (struct fast_fallback_getaddrinfo_entry *)ptr; struct fast_fallback_getaddrinfo_shared *shared = entry->shared; - int err = 0, need_free = 0, shared_need_free = 0; + int err = 0, shared_need_free = 0; + struct addrinfo *ai = NULL; sigset_t set; sigemptyset(&set); @@ -3102,14 +3093,15 @@ do_fast_fallback_getaddrinfo(void *ptr) entry->err = errno; entry->has_syserr = true; } - if (--(entry->refcount) == 0) need_free = 1; + if (--(entry->refcount) == 0) { + ai = entry->ai; + entry->ai = NULL; + } if (--(shared->refcount) == 0) shared_need_free = 1; } rb_nativethread_lock_unlock(&shared->lock); - if (need_free && entry) { - free_fast_fallback_getaddrinfo_entry(&entry); - } + if (ai) freeaddrinfo(ai); if (shared_need_free && shared) { free_fast_fallback_getaddrinfo_shared(&shared); } diff --git a/ext/strscan/strscan.c b/ext/strscan/strscan.c index 5a6446adb3..e094e2f55a 100644 --- a/ext/strscan/strscan.c +++ b/ext/strscan/strscan.c @@ -22,7 +22,7 @@ extern size_t onig_region_memsize(const struct re_registers *regs); #include <stdbool.h> -#define STRSCAN_VERSION "3.1.4.dev" +#define STRSCAN_VERSION "3.1.5.dev" /* ======================================================================= Data Type Definitions @@ -2211,7 +2211,10 @@ named_captures_iter(const OnigUChar *name, VALUE value = RUBY_Qnil; int i; for (i = 0; i < back_num; i++) { - value = strscan_aref(data->self, INT2NUM(back_refs[i])); + VALUE v = strscan_aref(data->self, INT2NUM(back_refs[i])); + if (!RB_NIL_P(v)) { + value = v; + } } rb_hash_aset(data->captures, key, value); return 0; @@ -1216,14 +1216,14 @@ rb_data_free(void *objspace, VALUE obj) void rb_gc_obj_free_vm_weak_references(VALUE obj) { - if (FL_TEST(obj, FL_EXIVAR)) { + if (FL_TEST_RAW(obj, FL_EXIVAR)) { rb_free_generic_ivar((VALUE)obj); FL_UNSET(obj, FL_EXIVAR); } switch (BUILTIN_TYPE(obj)) { case T_STRING: - if (FL_TEST(obj, RSTRING_FSTR)) { + if (FL_TEST_RAW(obj, RSTRING_FSTR)) { rb_gc_free_fstring(obj); } break; @@ -1458,7 +1458,7 @@ rb_gc_obj_free(void *objspace, VALUE obj) BUILTIN_TYPE(obj), (void*)obj, RBASIC(obj)->flags); } - if (FL_TEST(obj, FL_FINALIZE)) { + if (FL_TEST_RAW(obj, FL_FINALIZE)) { rb_gc_impl_make_zombie(objspace, obj, 0, 0); return FALSE; } @@ -2665,7 +2665,7 @@ rb_gc_mark_roots(void *objspace, const char **categoryp) void rb_gc_mark_children(void *objspace, VALUE obj) { - if (FL_TEST(obj, FL_EXIVAR)) { + if (FL_TEST_RAW(obj, FL_EXIVAR)) { rb_mark_generic_ivar(obj); } @@ -2700,7 +2700,7 @@ rb_gc_mark_children(void *objspace, VALUE obj) switch (BUILTIN_TYPE(obj)) { case T_CLASS: - if (FL_TEST(obj, FL_SINGLETON)) { + if (FL_TEST_RAW(obj, FL_SINGLETON)) { gc_mark_internal(RCLASS_ATTACHED_OBJECT(obj)); } // Continue to the shared T_CLASS/T_MODULE @@ -3635,7 +3635,7 @@ rb_gc_update_object_references(void *objspace, VALUE obj) { switch (BUILTIN_TYPE(obj)) { case T_CLASS: - if (FL_TEST(obj, FL_SINGLETON)) { + if (FL_TEST_RAW(obj, FL_SINGLETON)) { UPDATE_IF_MOVED(objspace, RCLASS_ATTACHED_OBJECT(obj)); } // Continue to the shared T_CLASS/T_MODULE @@ -0,0 +1,423 @@ +// Glue code shared between YJIT and ZJIT for use from Rust. +// For FFI safety and bindgen compatibility reasons, certain types of C +// functions require wrapping before they can be called from Rust. Those show +// up here. +// +// Code specific to YJIT and ZJIT should go to yjit.c and zjit.c respectively. + +#include "internal.h" +#include "vm_core.h" +#include "vm_callinfo.h" +#include "builtin.h" +#include "insns.inc" +#include "insns_info.inc" +#include "iseq.h" +#include "internal/gc.h" + +unsigned int +rb_iseq_encoded_size(const rb_iseq_t *iseq) +{ + return iseq->body->iseq_size; +} + +// Get the PC for a given index in an iseq +VALUE * +rb_iseq_pc_at_idx(const rb_iseq_t *iseq, uint32_t insn_idx) +{ + RUBY_ASSERT_ALWAYS(IMEMO_TYPE_P(iseq, imemo_iseq)); + RUBY_ASSERT_ALWAYS(insn_idx < iseq->body->iseq_size); + VALUE *encoded = iseq->body->iseq_encoded; + VALUE *pc = &encoded[insn_idx]; + return pc; +} + +// Get the opcode given a program counter. Can return trace opcode variants. +int +rb_iseq_opcode_at_pc(const rb_iseq_t *iseq, const VALUE *pc) +{ + // YJIT should only use iseqs after AST to bytecode compilation + RUBY_ASSERT_ALWAYS(FL_TEST_RAW((VALUE)iseq, ISEQ_TRANSLATED)); + + const VALUE at_pc = *pc; + return rb_vm_insn_addr2opcode((const void *)at_pc); +} + +unsigned long +rb_RSTRING_LEN(VALUE str) +{ + return RSTRING_LEN(str); +} + +char * +rb_RSTRING_PTR(VALUE str) +{ + return RSTRING_PTR(str); +} + +const char * +rb_insn_name(VALUE insn) +{ + return insn_name(insn); +} + +unsigned int +rb_vm_ci_argc(const struct rb_callinfo *ci) +{ + return vm_ci_argc(ci); +} + +ID +rb_vm_ci_mid(const struct rb_callinfo *ci) +{ + return vm_ci_mid(ci); +} + +unsigned int +rb_vm_ci_flag(const struct rb_callinfo *ci) +{ + return vm_ci_flag(ci); +} + +const struct rb_callinfo_kwarg * +rb_vm_ci_kwarg(const struct rb_callinfo *ci) +{ + return vm_ci_kwarg(ci); +} + +int +rb_get_cikw_keyword_len(const struct rb_callinfo_kwarg *cikw) +{ + return cikw->keyword_len; +} + +VALUE +rb_get_cikw_keywords_idx(const struct rb_callinfo_kwarg *cikw, int idx) +{ + return cikw->keywords[idx]; +} + +rb_method_visibility_t +rb_METHOD_ENTRY_VISI(const rb_callable_method_entry_t *me) +{ + return METHOD_ENTRY_VISI(me); +} + +rb_method_type_t +rb_get_cme_def_type(const rb_callable_method_entry_t *cme) +{ + if (UNDEFINED_METHOD_ENTRY_P(cme)) { + return VM_METHOD_TYPE_UNDEF; + } + else { + return cme->def->type; + } +} + +ID +rb_get_cme_def_body_attr_id(const rb_callable_method_entry_t *cme) +{ + return cme->def->body.attr.id; +} + +enum method_optimized_type +rb_get_cme_def_body_optimized_type(const rb_callable_method_entry_t *cme) +{ + return cme->def->body.optimized.type; +} + +unsigned int +rb_get_cme_def_body_optimized_index(const rb_callable_method_entry_t *cme) +{ + return cme->def->body.optimized.index; +} + +rb_method_cfunc_t * +rb_get_cme_def_body_cfunc(const rb_callable_method_entry_t *cme) +{ + return UNALIGNED_MEMBER_PTR(cme->def, body.cfunc); +} + +uintptr_t +rb_get_def_method_serial(const rb_method_definition_t *def) +{ + return def->method_serial; +} + +ID +rb_get_def_original_id(const rb_method_definition_t *def) +{ + return def->original_id; +} + +int +rb_get_mct_argc(const rb_method_cfunc_t *mct) +{ + return mct->argc; +} + +void * +rb_get_mct_func(const rb_method_cfunc_t *mct) +{ + return (void*)(uintptr_t)mct->func; // this field is defined as type VALUE (*func)(ANYARGS) +} + +const rb_iseq_t * +rb_get_def_iseq_ptr(rb_method_definition_t *def) +{ + return def_iseq_ptr(def); +} + +const rb_iseq_t * +rb_get_iseq_body_local_iseq(const rb_iseq_t *iseq) +{ + return iseq->body->local_iseq; +} + +unsigned int +rb_get_iseq_body_local_table_size(const rb_iseq_t *iseq) +{ + return iseq->body->local_table_size; +} + +VALUE * +rb_get_iseq_body_iseq_encoded(const rb_iseq_t *iseq) +{ + return iseq->body->iseq_encoded; +} + +unsigned +rb_get_iseq_body_stack_max(const rb_iseq_t *iseq) +{ + return iseq->body->stack_max; +} + +enum rb_iseq_type +rb_get_iseq_body_type(const rb_iseq_t *iseq) +{ + return iseq->body->type; +} + +bool +rb_get_iseq_flags_has_lead(const rb_iseq_t *iseq) +{ + return iseq->body->param.flags.has_lead; +} + +bool +rb_get_iseq_flags_has_opt(const rb_iseq_t *iseq) +{ + return iseq->body->param.flags.has_opt; +} + +bool +rb_get_iseq_flags_has_kw(const rb_iseq_t *iseq) +{ + return iseq->body->param.flags.has_kw; +} + +bool +rb_get_iseq_flags_has_post(const rb_iseq_t *iseq) +{ + return iseq->body->param.flags.has_post; +} + +bool +rb_get_iseq_flags_has_kwrest(const rb_iseq_t *iseq) +{ + return iseq->body->param.flags.has_kwrest; +} + +bool +rb_get_iseq_flags_anon_kwrest(const rb_iseq_t *iseq) +{ + return iseq->body->param.flags.anon_kwrest; +} + +bool +rb_get_iseq_flags_has_rest(const rb_iseq_t *iseq) +{ + return iseq->body->param.flags.has_rest; +} + +bool +rb_get_iseq_flags_ruby2_keywords(const rb_iseq_t *iseq) +{ + return iseq->body->param.flags.ruby2_keywords; +} + +bool +rb_get_iseq_flags_has_block(const rb_iseq_t *iseq) +{ + return iseq->body->param.flags.has_block; +} + +bool +rb_get_iseq_flags_ambiguous_param0(const rb_iseq_t *iseq) +{ + return iseq->body->param.flags.ambiguous_param0; +} + +bool +rb_get_iseq_flags_accepts_no_kwarg(const rb_iseq_t *iseq) +{ + return iseq->body->param.flags.accepts_no_kwarg; +} + +bool +rb_get_iseq_flags_forwardable(const rb_iseq_t *iseq) +{ + return iseq->body->param.flags.forwardable; +} + +// This is defined only as a named struct inside rb_iseq_constant_body. +// By giving it a separate typedef, we make it nameable by rust-bindgen. +// Bindgen's temp/anon name isn't guaranteed stable. +typedef struct rb_iseq_param_keyword rb_iseq_param_keyword_struct; + +const rb_iseq_param_keyword_struct * +rb_get_iseq_body_param_keyword(const rb_iseq_t *iseq) +{ + return iseq->body->param.keyword; +} + +unsigned +rb_get_iseq_body_param_size(const rb_iseq_t *iseq) +{ + return iseq->body->param.size; +} + +int +rb_get_iseq_body_param_lead_num(const rb_iseq_t *iseq) +{ + return iseq->body->param.lead_num; +} + +int +rb_get_iseq_body_param_opt_num(const rb_iseq_t *iseq) +{ + return iseq->body->param.opt_num; +} + +const VALUE * +rb_get_iseq_body_param_opt_table(const rb_iseq_t *iseq) +{ + return iseq->body->param.opt_table; +} + +struct rb_control_frame_struct * +rb_get_ec_cfp(const rb_execution_context_t *ec) +{ + return ec->cfp; +} + +const rb_iseq_t * +rb_get_cfp_iseq(struct rb_control_frame_struct *cfp) +{ + return cfp->iseq; +} + +VALUE * +rb_get_cfp_pc(struct rb_control_frame_struct *cfp) +{ + return (VALUE*)cfp->pc; +} + +VALUE * +rb_get_cfp_sp(struct rb_control_frame_struct *cfp) +{ + return cfp->sp; +} + +VALUE +rb_get_cfp_self(struct rb_control_frame_struct *cfp) +{ + return cfp->self; +} + +VALUE * +rb_get_cfp_ep(struct rb_control_frame_struct *cfp) +{ + return (VALUE*)cfp->ep; +} + +const VALUE * +rb_get_cfp_ep_level(struct rb_control_frame_struct *cfp, uint32_t lv) +{ + uint32_t i; + const VALUE *ep = (VALUE*)cfp->ep; + for (i = 0; i < lv; i++) { + ep = VM_ENV_PREV_EP(ep); + } + return ep; +} + +VALUE +rb_yarv_class_of(VALUE obj) +{ + return rb_class_of(obj); +} + +// The FL_TEST() macro +VALUE +rb_FL_TEST(VALUE obj, VALUE flags) +{ + return RB_FL_TEST(obj, flags); +} + +// The FL_TEST_RAW() macro, normally an internal implementation detail +VALUE +rb_FL_TEST_RAW(VALUE obj, VALUE flags) +{ + return FL_TEST_RAW(obj, flags); +} + +// The RB_TYPE_P macro +bool +rb_RB_TYPE_P(VALUE obj, enum ruby_value_type t) +{ + return RB_TYPE_P(obj, t); +} + +long +rb_RSTRUCT_LEN(VALUE st) +{ + return RSTRUCT_LEN(st); +} + +const struct rb_callinfo * +rb_get_call_data_ci(const struct rb_call_data *cd) +{ + return cd->ci; +} + +bool +rb_BASIC_OP_UNREDEFINED_P(enum ruby_basic_operators bop, uint32_t klass) +{ + return BASIC_OP_UNREDEFINED_P(bop, klass); +} + +VALUE +rb_RCLASS_ORIGIN(VALUE c) +{ + return RCLASS_ORIGIN(c); +} + +// For debug builds +void +rb_assert_iseq_handle(VALUE handle) +{ + RUBY_ASSERT_ALWAYS(IMEMO_TYPE_P(handle, imemo_iseq)); +} + +int +rb_IMEMO_TYPE_P(VALUE imemo, enum imemo_type imemo_type) +{ + return IMEMO_TYPE_P(imemo, imemo_type); +} + +void +rb_assert_cme_handle(VALUE handle) +{ + RUBY_ASSERT_ALWAYS(!rb_objspace_garbage_object_p(handle)); + RUBY_ASSERT_ALWAYS(IMEMO_TYPE_P(handle, imemo_ment)); +} diff --git a/lib/rubygems/gemcutter_utilities.rb b/lib/rubygems/gemcutter_utilities.rb index d3176d4564..8d9a9b2d35 100644 --- a/lib/rubygems/gemcutter_utilities.rb +++ b/lib/rubygems/gemcutter_utilities.rb @@ -263,7 +263,10 @@ module Gem::GemcutterUtilities port = server.addr[1].to_s url_with_port = "#{webauthn_url}?port=#{port}" - say "You have enabled multi-factor authentication. Please visit #{url_with_port} to authenticate via security device. If you can't verify using WebAuthn but have OTP enabled, you can re-run the gem signin command with the `--otp [your_code]` option." + say "You have enabled multi-factor authentication. Please visit the following URL to authenticate via security device. If you can't verify using WebAuthn but have OTP enabled, you can re-run the gem signin command with the `--otp [your_code]` option." + say "" + say url_with_port + say "" threads = [WebauthnListener.listener_thread(host, server), WebauthnPoller.poll_thread(options, host, webauthn_url, credentials)] otp_thread = wait_for_otp_thread(*threads) @@ -494,18 +494,13 @@ set_i_initialize(int argc, VALUE *argv, VALUE set) if (argc > 0 && (other = argv[0]) != Qnil) { if (RB_TYPE_P(other, T_ARRAY)) { - long len = RARRAY_LEN(other); - if (RARRAY_LEN(other) != 0) { - set_table *into = RSET_TABLE(set); - VALUE key; - int block_given = rb_block_given_p(); - RARRAY_PTR_USE(other, ptr, { - for(; len > 0; len--, ptr++) { - key = *ptr; - if (block_given) key = rb_yield(key); - set_table_insert_wb(into, set, key, NULL); - } - }); + long i; + int block_given = rb_block_given_p(); + set_table *into = RSET_TABLE(set); + for (i=0; i<RARRAY_LEN(other); i++) { + VALUE key = RARRAY_AREF(other, i); + if (block_given) key = rb_yield(key); + set_table_insert_wb(into, set, key, NULL); } } else { @@ -1120,14 +1115,10 @@ set_merge_enum_into(VALUE set, VALUE arg) set_iter(arg, set_merge_i, (st_data_t)&args); } else if (RB_TYPE_P(arg, T_ARRAY)) { - long len = RARRAY_LEN(arg); - if (RARRAY_LEN(arg) != 0) { - set_table *into = RSET_TABLE(set); - RARRAY_PTR_USE(arg, ptr, { - for(; len > 0; len--, ptr++) { - set_table_insert_wb(into, set, *ptr, NULL); - } - }); + long i; + set_table *into = RSET_TABLE(set); + for (i=0; i<RARRAY_LEN(arg); i++) { + set_table_insert_wb(into, set, RARRAY_AREF(arg, i), NULL); } } else { diff --git a/template/Makefile.in b/template/Makefile.in index 7e88f94c7a..743971abcb 100644 --- a/template/Makefile.in +++ b/template/Makefile.in @@ -102,6 +102,7 @@ USE_RUBYGEMS = @USE_RUBYGEMS@ USE_RUBYGEMS_ = $(USE_RUBYGEMS:yes=) CPPFLAGS = @CPPFLAGS@ $(USE_RUBYGEMS_:no=-DDISABLE_RUBYGEMS=1) TOP_BUILD_DIR=@abs_top_builddir@ +JIT_OBJ=@JIT_OBJ@ YJIT_SUPPORT=@YJIT_SUPPORT@ YJIT_LIBS=@YJIT_LIBS@ YJIT_OBJ=@YJIT_OBJ@ diff --git a/test/psych/test_yaml.rb b/test/psych/test_yaml.rb index 89bd3130e3..134c346c90 100644 --- a/test/psych/test_yaml.rb +++ b/test/psych/test_yaml.rb @@ -1042,7 +1042,6 @@ EOY end def test_ruby_struct - Struct.send(:remove_const, :MyBookStruct) if Struct.const_defined?(:MyBookStruct) # Ruby structures book_struct = Struct::new( "MyBookStruct", :author, :title, :year, :isbn ) assert_to_yaml( @@ -1074,11 +1073,12 @@ EOY c: 123 EOY + ensure + Struct.__send__(:remove_const, :MyBookStruct) if book_struct end def test_ruby_data omit "Data requires ruby >= 3.2" if RUBY_VERSION < "3.2" - Object.remove_const :MyBookData if Object.const_defined?(:MyBookData) # Ruby Data value objects book_class = Data.define(:author, :title, :year, :isbn) Object.const_set(:MyBookData, book_class) @@ -1112,6 +1112,8 @@ EOY c: 123 EOY + ensure + Object.__send__(:remove_const, :MyBookData) if book_class end def test_ruby_rational diff --git a/test/ruby/test_set.rb b/test/ruby/test_set.rb index 2de6cdaaee..2bb7858eb2 100644 --- a/test/ruby/test_set.rb +++ b/test/ruby/test_set.rb @@ -632,6 +632,22 @@ class TC_Set < Test::Unit::TestCase } end + def test_merge_mutating_hash_bug_21305 + a = (1..100).to_a + o = Object.new + o.define_singleton_method(:hash) do + a.clear + 0 + end + a.unshift o + assert_equal([o], Set.new.merge(a).to_a) + end + + def test_initialize_mutating_array_bug_21306 + a = (1..100).to_a + assert_equal(Set[0], Set.new(a){a.clear; 0}) + end + def test_subtract set = Set[1,2,3] diff --git a/test/rubygems/test_gem_commands_owner_command.rb b/test/rubygems/test_gem_commands_owner_command.rb index bc4f13ff2a..ac18699736 100644 --- a/test/rubygems/test_gem_commands_owner_command.rb +++ b/test/rubygems/test_gem_commands_owner_command.rb @@ -386,9 +386,10 @@ EOF end end - assert_match "You have enabled multi-factor authentication. Please visit #{@stub_fetcher.webauthn_url_with_port(server.port)} " \ + assert_match "You have enabled multi-factor authentication. Please visit the following URL " \ "to authenticate via security device. If you can't verify using WebAuthn but have OTP enabled, " \ "you can re-run the gem signin command with the `--otp [your_code]` option.", @stub_ui.output + assert_match @stub_fetcher.webauthn_url_with_port(server.port), @stub_ui.output assert_match "You are verified with a security device. You may close the browser window.", @stub_ui.output assert_equal "Uvh6T57tkWuUnWYo", @stub_fetcher.last_request["OTP"] assert_match response_success, @stub_ui.output @@ -413,9 +414,10 @@ EOF end assert_match @stub_fetcher.last_request["Authorization"], Gem.configuration.rubygems_api_key - assert_match "You have enabled multi-factor authentication. Please visit #{@stub_fetcher.webauthn_url_with_port(server.port)} " \ + assert_match "You have enabled multi-factor authentication. Please visit the following URL " \ "to authenticate via security device. If you can't verify using WebAuthn but have OTP enabled, " \ "you can re-run the gem signin command with the `--otp [your_code]` option.", @stub_ui.output + assert_match @stub_fetcher.webauthn_url_with_port(server.port), @stub_ui.output assert_match "ERROR: Security device verification failed: Something went wrong", @stub_ui.error refute_match "You are verified with a security device. You may close the browser window.", @stub_ui.output refute_match response_success, @stub_ui.output @@ -435,9 +437,10 @@ EOF end end - assert_match "You have enabled multi-factor authentication. Please visit #{@stub_fetcher.webauthn_url_with_port(server.port)} " \ + assert_match "You have enabled multi-factor authentication. Please visit the following URL " \ "to authenticate via security device. If you can't verify using WebAuthn but have OTP enabled, you can re-run the gem signin " \ "command with the `--otp [your_code]` option.", @stub_ui.output + assert_match @stub_fetcher.webauthn_url_with_port(server.port), @stub_ui.output assert_match "You are verified with a security device. You may close the browser window.", @stub_ui.output assert_equal "Uvh6T57tkWuUnWYo", @stub_fetcher.last_request["OTP"] assert_match response_success, @stub_ui.output @@ -463,9 +466,10 @@ EOF end assert_match @stub_fetcher.last_request["Authorization"], Gem.configuration.rubygems_api_key - assert_match "You have enabled multi-factor authentication. Please visit #{@stub_fetcher.webauthn_url_with_port(server.port)} " \ + assert_match "You have enabled multi-factor authentication. Please visit the following URL " \ "to authenticate via security device. If you can't verify using WebAuthn but have OTP enabled, you can re-run the gem signin " \ "command with the `--otp [your_code]` option.", @stub_ui.output + assert_match @stub_fetcher.webauthn_url_with_port(server.port), @stub_ui.output assert_match "ERROR: Security device verification failed: The token in the link you used has either expired " \ "or been used already.", @stub_ui.error refute_match "You are verified with a security device. You may close the browser window.", @stub_ui.output diff --git a/test/rubygems/test_gem_commands_push_command.rb b/test/rubygems/test_gem_commands_push_command.rb index 2d0190b49f..bedc8e0d58 100644 --- a/test/rubygems/test_gem_commands_push_command.rb +++ b/test/rubygems/test_gem_commands_push_command.rb @@ -477,9 +477,10 @@ class TestGemCommandsPushCommand < Gem::TestCase end end - assert_match "You have enabled multi-factor authentication. Please visit #{@fetcher.webauthn_url_with_port(server.port)} " \ + assert_match "You have enabled multi-factor authentication. Please visit the following URL " \ "to authenticate via security device. If you can't verify using WebAuthn but have OTP enabled, " \ "you can re-run the gem signin command with the `--otp [your_code]` option.", @ui.output + assert_match @fetcher.webauthn_url_with_port(server.port), @ui.output assert_match "You are verified with a security device. You may close the browser window.", @ui.output assert_equal "Uvh6T57tkWuUnWYo", @fetcher.last_request["OTP"] assert_match response_success, @ui.output @@ -505,9 +506,10 @@ class TestGemCommandsPushCommand < Gem::TestCase assert_equal 1, error.exit_code assert_match @fetcher.last_request["Authorization"], Gem.configuration.rubygems_api_key - assert_match "You have enabled multi-factor authentication. Please visit #{@fetcher.webauthn_url_with_port(server.port)} " \ + assert_match "You have enabled multi-factor authentication. Please visit the following URL " \ "to authenticate via security device. If you can't verify using WebAuthn but have OTP enabled, " \ "you can re-run the gem signin command with the `--otp [your_code]` option.", @ui.output + assert_match @fetcher.webauthn_url_with_port(server.port), @ui.output assert_match "ERROR: Security device verification failed: Something went wrong", @ui.error refute_match "You are verified with a security device. You may close the browser window.", @ui.output refute_match response_success, @ui.output @@ -527,9 +529,10 @@ class TestGemCommandsPushCommand < Gem::TestCase end end - assert_match "You have enabled multi-factor authentication. Please visit #{@fetcher.webauthn_url_with_port(server.port)} " \ + assert_match "You have enabled multi-factor authentication. Please visit the following URL " \ "to authenticate via security device. If you can't verify using WebAuthn but have OTP enabled, " \ "you can re-run the gem signin command with the `--otp [your_code]` option.", @ui.output + assert_match @fetcher.webauthn_url_with_port(server.port), @ui.output assert_match "You are verified with a security device. You may close the browser window.", @ui.output assert_equal "Uvh6T57tkWuUnWYo", @fetcher.last_request["OTP"] assert_match response_success, @ui.output @@ -553,9 +556,10 @@ class TestGemCommandsPushCommand < Gem::TestCase assert_equal 1, error.exit_code assert_match @fetcher.last_request["Authorization"], Gem.configuration.rubygems_api_key - assert_match "You have enabled multi-factor authentication. Please visit #{@fetcher.webauthn_url_with_port(server.port)} " \ - "to authenticate via security device. If you can't verify using WebAuthn but have OTP enabled, you can re-run the gem signin " \ - "command with the `--otp [your_code]` option.", @ui.output + assert_match "You have enabled multi-factor authentication. Please visit the following URL " \ + "to authenticate via security device. If you can't verify using WebAuthn but have OTP enabled, " \ + "you can re-run the gem signin command with the `--otp [your_code]` option.", @ui.output + assert_match @fetcher.webauthn_url_with_port(server.port), @ui.output assert_match "ERROR: Security device verification failed: The token in the link you used has either expired " \ "or been used already.", @ui.error refute_match "You are verified with a security device. You may close the browser window.", @ui.output diff --git a/test/rubygems/test_gem_commands_yank_command.rb b/test/rubygems/test_gem_commands_yank_command.rb index eb78e3a542..213f098374 100644 --- a/test/rubygems/test_gem_commands_yank_command.rb +++ b/test/rubygems/test_gem_commands_yank_command.rb @@ -131,9 +131,10 @@ class TestGemCommandsYankCommand < Gem::TestCase end assert_match %r{Yanking gem from http://example}, @ui.output - assert_match "You have enabled multi-factor authentication. Please visit #{@fetcher.webauthn_url_with_port(server.port)} " \ + assert_match "You have enabled multi-factor authentication. Please visit the following URL " \ "to authenticate via security device. If you can't verify using WebAuthn but have OTP enabled, " \ "you can re-run the gem signin command with the `--otp [your_code]` option.", @ui.output + assert_match @fetcher.webauthn_url_with_port(server.port), @ui.output assert_match "You are verified with a security device. You may close the browser window.", @ui.output assert_equal "Uvh6T57tkWuUnWYo", @fetcher.last_request["OTP"] assert_match "Successfully yanked", @ui.output @@ -163,9 +164,10 @@ class TestGemCommandsYankCommand < Gem::TestCase assert_match @fetcher.last_request["Authorization"], Gem.configuration.rubygems_api_key assert_match %r{Yanking gem from http://example}, @ui.output - assert_match "You have enabled multi-factor authentication. Please visit #{@fetcher.webauthn_url_with_port(server.port)} " \ + assert_match "You have enabled multi-factor authentication. Please visit the following URL " \ "to authenticate via security device. If you can't verify using WebAuthn but have OTP enabled, " \ "you can re-run the gem signin command with the `--otp [your_code]` option.", @ui.output + assert_match @fetcher.webauthn_url_with_port(server.port), @ui.output assert_match "ERROR: Security device verification failed: Something went wrong", @ui.error refute_match "You are verified with a security device. You may close the browser window.", @ui.output refute_match "Successfully yanked", @ui.output @@ -189,9 +191,10 @@ class TestGemCommandsYankCommand < Gem::TestCase end assert_match %r{Yanking gem from http://example}, @ui.output - assert_match "You have enabled multi-factor authentication. Please visit #{@fetcher.webauthn_url_with_port(server.port)} " \ + assert_match "You have enabled multi-factor authentication. Please visit the following URL " \ "to authenticate via security device. If you can't verify using WebAuthn but have OTP enabled, " \ "you can re-run the gem signin command with the `--otp [your_code]` option.", @ui.output + assert_match @fetcher.webauthn_url_with_port(server.port), @ui.output assert_match "You are verified with a security device. You may close the browser window.", @ui.output assert_equal "Uvh6T57tkWuUnWYo", @fetcher.last_request["OTP"] assert_match "Successfully yanked", @ui.output @@ -219,9 +222,10 @@ class TestGemCommandsYankCommand < Gem::TestCase assert_match @fetcher.last_request["Authorization"], Gem.configuration.rubygems_api_key assert_match %r{Yanking gem from http://example}, @ui.output - assert_match "You have enabled multi-factor authentication. Please visit #{@fetcher.webauthn_url_with_port(server.port)} " \ + assert_match "You have enabled multi-factor authentication. Please visit the following URL " \ "to authenticate via security device. If you can't verify using WebAuthn but have OTP enabled, " \ "you can re-run the gem signin command with the `--otp [your_code]` option.", @ui.output + assert_match @fetcher.webauthn_url_with_port(server.port), @ui.output assert_match "ERROR: Security device verification failed: The token in the link you used has either expired " \ "or been used already.", @ui.error refute_match "You are verified with a security device. You may close the browser window.", @ui.output diff --git a/test/rubygems/test_gem_gemcutter_utilities.rb b/test/rubygems/test_gem_gemcutter_utilities.rb index a3236e6276..9204dc5f20 100644 --- a/test/rubygems/test_gem_gemcutter_utilities.rb +++ b/test/rubygems/test_gem_gemcutter_utilities.rb @@ -233,9 +233,10 @@ class TestGemGemcutterUtilities < Gem::TestCase end end - assert_match "You have enabled multi-factor authentication. Please visit #{@fetcher.webauthn_url_with_port(server.port)} " \ + assert_match "You have enabled multi-factor authentication. Please visit the following URL " \ "to authenticate via security device. If you can't verify using WebAuthn but have OTP enabled, " \ "you can re-run the gem signin command with the `--otp [your_code]` option.", @sign_in_ui.output + assert_match @fetcher.webauthn_url_with_port(server.port), @sign_in_ui.output assert_match "You are verified with a security device. You may close the browser window.", @sign_in_ui.output assert_equal "Uvh6T57tkWuUnWYo", @fetcher.last_request["OTP"] end @@ -255,9 +256,10 @@ class TestGemGemcutterUtilities < Gem::TestCase end assert_equal 1, error.exit_code - assert_match "You have enabled multi-factor authentication. Please visit #{@fetcher.webauthn_url_with_port(server.port)} " \ + assert_match "You have enabled multi-factor authentication. Please visit the following URL " \ "to authenticate via security device. If you can't verify using WebAuthn but have OTP enabled, " \ "you can re-run the gem signin command with the `--otp [your_code]` option.", @sign_in_ui.output + assert_match @fetcher.webauthn_url_with_port(server.port), @sign_in_ui.output assert_match "ERROR: Security device verification failed: Something went wrong", @sign_in_ui.error refute_match "You are verified with a security device. You may close the browser window.", @sign_in_ui.output refute_match "Signed in with API key:", @sign_in_ui.output @@ -273,9 +275,10 @@ class TestGemGemcutterUtilities < Gem::TestCase util_sign_in end - assert_match "You have enabled multi-factor authentication. Please visit #{@fetcher.webauthn_url_with_port(server.port)} " \ + assert_match "You have enabled multi-factor authentication. Please visit the following URL " \ "to authenticate via security device. If you can't verify using WebAuthn but have OTP enabled, " \ "you can re-run the gem signin command with the `--otp [your_code]` option.", @sign_in_ui.output + assert_match @fetcher.webauthn_url_with_port(server.port), @sign_in_ui.output assert_match "You are verified with a security device. You may close the browser window.", @sign_in_ui.output assert_equal "Uvh6T57tkWuUnWYo", @fetcher.last_request["OTP"] end @@ -292,9 +295,10 @@ class TestGemGemcutterUtilities < Gem::TestCase end end - assert_match "You have enabled multi-factor authentication. Please visit #{@fetcher.webauthn_url_with_port(server.port)} " \ + assert_match "You have enabled multi-factor authentication. Please visit the following URL " \ "to authenticate via security device. If you can't verify using WebAuthn but have OTP enabled, " \ "you can re-run the gem signin command with the `--otp [your_code]` option.", @sign_in_ui.output + assert_match @fetcher.webauthn_url_with_port(server.port), @sign_in_ui.output assert_match "ERROR: Security device verification failed: " \ "The token in the link you used has either expired or been used already.", @sign_in_ui.error end diff --git a/test/strscan/test_stringscanner.rb b/test/strscan/test_stringscanner.rb index 0a28d92368..e895a8382b 100644 --- a/test/strscan/test_stringscanner.rb +++ b/test/strscan/test_stringscanner.rb @@ -967,6 +967,12 @@ module StringScannerTests assert_equal({}, scan.named_captures) end + def test_named_captures_same_name_union + scan = StringScanner.new("123") + assert_equal(1, scan.match?(/(?<number>0)|(?<number>1)|(?<number>2)/)) + assert_equal({"number" => "1"}, scan.named_captures) + end + def test_scan_integer s = create_string_scanner('abc') assert_equal(3, s.match?(/(?<a>abc)/)) # set named_captures diff --git a/tool/ruby_vm/views/insns_info.inc.erb b/tool/ruby_vm/views/insns_info.inc.erb index 6ba12a856e..0a6f71fee3 100644 --- a/tool/ruby_vm/views/insns_info.inc.erb +++ b/tool/ruby_vm/views/insns_info.inc.erb @@ -11,6 +11,8 @@ this_file: 'contains instruction information for yarv instruction sequence.', edit: __FILE__, } %> +#ifndef INSNS_INFO_INC +#define INSNS_INFO_INC 1 <%= render 'insn_type_chars' %> <%= render 'insn_name_info' %> <%= render 'insn_len_info' %> @@ -20,3 +22,4 @@ <%= render 'zjit_helpers' %> <%= render 'attributes' %> <%= render 'comptime_insn_stack_increase' %> +#endif diff --git a/tool/sync_default_gems.rb b/tool/sync_default_gems.rb index 903baf49dd..5b0bca72b7 100755 --- a/tool/sync_default_gems.rb +++ b/tool/sync_default_gems.rb @@ -46,7 +46,6 @@ module SyncDefaultGems resolv: "ruby/resolv", rubygems: 'rubygems/rubygems', securerandom: "ruby/securerandom", - set: "ruby/set", shellwords: "ruby/shellwords", singleton: "ruby/singleton", stringio: 'ruby/stringio', @@ -295,9 +294,6 @@ module SyncDefaultGems cp_r("#{upstream}/test/digest", "test") cp_r("#{upstream}/digest.gemspec", "ext/digest") `git checkout ext/digest/depend ext/digest/*/depend` - when "set" - sync_lib gem, upstream - cp_r(Dir.glob("#{upstream}/test/*"), "test/set") when "optparse" sync_lib gem, upstream rm_rf(%w[doc/optparse]) diff --git a/vm_method.c b/vm_method.c index 22adc469f7..7288fdd2ec 100644 --- a/vm_method.c +++ b/vm_method.c @@ -1371,7 +1371,6 @@ prepare_callable_method_entry(VALUE defined_class, ID id, const rb_method_entry_ if (me->defined_class == 0) { RB_DEBUG_COUNTER_INC(mc_cme_complement); VM_ASSERT_TYPE2(defined_class, T_ICLASS, T_MODULE); - VM_ASSERT(me->defined_class == 0, "me->defined_class: %s", rb_obj_info(me->defined_class)); mtbl = RCLASS_CALLABLE_M_TBL(defined_class); diff --git a/wasm/setjmp.h b/wasm/setjmp.h index e65bfc0ca0..82cfff1d00 100644 --- a/wasm/setjmp.h +++ b/wasm/setjmp.h @@ -5,7 +5,7 @@ #include <stdbool.h> #ifndef WASM_SETJMP_STACK_BUFFER_SIZE -# define WASM_SETJMP_STACK_BUFFER_SIZE 6144 +# define WASM_SETJMP_STACK_BUFFER_SIZE 8192 #endif struct __rb_wasm_asyncify_jmp_buf { @@ -396,12 +396,6 @@ rb_full_cfunc_return(rb_execution_context_t *ec, VALUE return_value) ec->cfp->sp++; } -unsigned int -rb_iseq_encoded_size(const rb_iseq_t *iseq) -{ - return iseq->body->iseq_size; -} - // TODO(alan): consider using an opaque pointer for the payload rather than a void pointer void * rb_iseq_get_yjit_payload(const rb_iseq_t *iseq) @@ -437,40 +431,6 @@ rb_iseq_reset_jit_func(const rb_iseq_t *iseq) iseq->body->jit_exception_calls = 0; } -// Get the PC for a given index in an iseq -VALUE * -rb_iseq_pc_at_idx(const rb_iseq_t *iseq, uint32_t insn_idx) -{ - RUBY_ASSERT_ALWAYS(IMEMO_TYPE_P(iseq, imemo_iseq)); - RUBY_ASSERT_ALWAYS(insn_idx < iseq->body->iseq_size); - VALUE *encoded = iseq->body->iseq_encoded; - VALUE *pc = &encoded[insn_idx]; - return pc; -} - -// Get the opcode given a program counter. Can return trace opcode variants. -int -rb_iseq_opcode_at_pc(const rb_iseq_t *iseq, const VALUE *pc) -{ - // YJIT should only use iseqs after AST to bytecode compilation - RUBY_ASSERT_ALWAYS(FL_TEST_RAW((VALUE)iseq, ISEQ_TRANSLATED)); - - const VALUE at_pc = *pc; - return rb_vm_insn_addr2opcode((const void *)at_pc); -} - -unsigned long -rb_RSTRING_LEN(VALUE str) -{ - return RSTRING_LEN(str); -} - -char * -rb_RSTRING_PTR(VALUE str) -{ - return RSTRING_PTR(str); -} - rb_proc_t * rb_yjit_get_proc_ptr(VALUE procv) { @@ -484,121 +444,8 @@ rb_yjit_get_proc_ptr(VALUE procv) // Bindgen's temp/anon name isn't guaranteed stable. typedef struct rb_iseq_param_keyword rb_seq_param_keyword_struct; -const char * -rb_insn_name(VALUE insn) -{ - return insn_name(insn); -} - -unsigned int -rb_vm_ci_argc(const struct rb_callinfo *ci) -{ - return vm_ci_argc(ci); -} - -ID -rb_vm_ci_mid(const struct rb_callinfo *ci) -{ - return vm_ci_mid(ci); -} - -unsigned int -rb_vm_ci_flag(const struct rb_callinfo *ci) -{ - return vm_ci_flag(ci); -} - -const struct rb_callinfo_kwarg * -rb_vm_ci_kwarg(const struct rb_callinfo *ci) -{ - return vm_ci_kwarg(ci); -} - -int -rb_get_cikw_keyword_len(const struct rb_callinfo_kwarg *cikw) -{ - return cikw->keyword_len; -} - -VALUE -rb_get_cikw_keywords_idx(const struct rb_callinfo_kwarg *cikw, int idx) -{ - return cikw->keywords[idx]; -} - -rb_method_visibility_t -rb_METHOD_ENTRY_VISI(const rb_callable_method_entry_t *me) -{ - return METHOD_ENTRY_VISI(me); -} - -rb_method_type_t -rb_get_cme_def_type(const rb_callable_method_entry_t *cme) -{ - if (UNDEFINED_METHOD_ENTRY_P(cme)) { - return VM_METHOD_TYPE_UNDEF; - } - else { - return cme->def->type; - } -} - -ID -rb_get_cme_def_body_attr_id(const rb_callable_method_entry_t *cme) -{ - return cme->def->body.attr.id; -} - ID rb_get_symbol_id(VALUE namep); -enum method_optimized_type -rb_get_cme_def_body_optimized_type(const rb_callable_method_entry_t *cme) -{ - return cme->def->body.optimized.type; -} - -unsigned int -rb_get_cme_def_body_optimized_index(const rb_callable_method_entry_t *cme) -{ - return cme->def->body.optimized.index; -} - -rb_method_cfunc_t * -rb_get_cme_def_body_cfunc(const rb_callable_method_entry_t *cme) -{ - return UNALIGNED_MEMBER_PTR(cme->def, body.cfunc); -} - -uintptr_t -rb_get_def_method_serial(const rb_method_definition_t *def) -{ - return def->method_serial; -} - -ID -rb_get_def_original_id(const rb_method_definition_t *def) -{ - return def->original_id; -} - -int -rb_get_mct_argc(const rb_method_cfunc_t *mct) -{ - return mct->argc; -} - -void * -rb_get_mct_func(const rb_method_cfunc_t *mct) -{ - return (void*)(uintptr_t)mct->func; // this field is defined as type VALUE (*func)(ANYARGS) -} - -const rb_iseq_t * -rb_get_def_iseq_ptr(rb_method_definition_t *def) -{ - return def_iseq_ptr(def); -} - VALUE rb_get_def_bmethod_proc(rb_method_definition_t *def) { @@ -607,143 +454,11 @@ rb_get_def_bmethod_proc(rb_method_definition_t *def) } const rb_iseq_t * -rb_get_iseq_body_local_iseq(const rb_iseq_t *iseq) -{ - return iseq->body->local_iseq; -} - -const rb_iseq_t * rb_get_iseq_body_parent_iseq(const rb_iseq_t *iseq) { return iseq->body->parent_iseq; } -unsigned int -rb_get_iseq_body_local_table_size(const rb_iseq_t *iseq) -{ - return iseq->body->local_table_size; -} - -VALUE * -rb_get_iseq_body_iseq_encoded(const rb_iseq_t *iseq) -{ - return iseq->body->iseq_encoded; -} - -unsigned -rb_get_iseq_body_stack_max(const rb_iseq_t *iseq) -{ - return iseq->body->stack_max; -} - -enum rb_iseq_type -rb_get_iseq_body_type(const rb_iseq_t *iseq) -{ - return iseq->body->type; -} - -bool -rb_get_iseq_flags_has_lead(const rb_iseq_t *iseq) -{ - return iseq->body->param.flags.has_lead; -} - -bool -rb_get_iseq_flags_has_opt(const rb_iseq_t *iseq) -{ - return iseq->body->param.flags.has_opt; -} - -bool -rb_get_iseq_flags_has_kw(const rb_iseq_t *iseq) -{ - return iseq->body->param.flags.has_kw; -} - -bool -rb_get_iseq_flags_has_post(const rb_iseq_t *iseq) -{ - return iseq->body->param.flags.has_post; -} - -bool -rb_get_iseq_flags_has_kwrest(const rb_iseq_t *iseq) -{ - return iseq->body->param.flags.has_kwrest; -} - -bool -rb_get_iseq_flags_anon_kwrest(const rb_iseq_t *iseq) -{ - return iseq->body->param.flags.anon_kwrest; -} - -bool -rb_get_iseq_flags_has_rest(const rb_iseq_t *iseq) -{ - return iseq->body->param.flags.has_rest; -} - -bool -rb_get_iseq_flags_ruby2_keywords(const rb_iseq_t *iseq) -{ - return iseq->body->param.flags.ruby2_keywords; -} - -bool -rb_get_iseq_flags_has_block(const rb_iseq_t *iseq) -{ - return iseq->body->param.flags.has_block; -} - -bool -rb_get_iseq_flags_ambiguous_param0(const rb_iseq_t *iseq) -{ - return iseq->body->param.flags.ambiguous_param0; -} - -bool -rb_get_iseq_flags_accepts_no_kwarg(const rb_iseq_t *iseq) -{ - return iseq->body->param.flags.accepts_no_kwarg; -} - -bool -rb_get_iseq_flags_forwardable(const rb_iseq_t *iseq) -{ - return iseq->body->param.flags.forwardable; -} - -const rb_seq_param_keyword_struct * -rb_get_iseq_body_param_keyword(const rb_iseq_t *iseq) -{ - return iseq->body->param.keyword; -} - -unsigned -rb_get_iseq_body_param_size(const rb_iseq_t *iseq) -{ - return iseq->body->param.size; -} - -int -rb_get_iseq_body_param_lead_num(const rb_iseq_t *iseq) -{ - return iseq->body->param.lead_num; -} - -int -rb_get_iseq_body_param_opt_num(const rb_iseq_t *iseq) -{ - return iseq->body->param.opt_num; -} - -const VALUE * -rb_get_iseq_body_param_opt_table(const rb_iseq_t *iseq) -{ - return iseq->body->param.opt_table; -} - VALUE rb_optimized_call(VALUE *recv, rb_execution_context_t *ec, int argc, VALUE *argv, int kw_splat, VALUE block_handler) { @@ -789,30 +504,6 @@ rb_yjit_str_simple_append(VALUE str1, VALUE str2) return rb_str_cat(str1, RSTRING_PTR(str2), RSTRING_LEN(str2)); } -struct rb_control_frame_struct * -rb_get_ec_cfp(const rb_execution_context_t *ec) -{ - return ec->cfp; -} - -const rb_iseq_t * -rb_get_cfp_iseq(struct rb_control_frame_struct *cfp) -{ - return cfp->iseq; -} - -VALUE * -rb_get_cfp_pc(struct rb_control_frame_struct *cfp) -{ - return (VALUE*)cfp->pc; -} - -VALUE * -rb_get_cfp_sp(struct rb_control_frame_struct *cfp) -{ - return cfp->sp; -} - void rb_set_cfp_pc(struct rb_control_frame_struct *cfp, const VALUE *pc) { @@ -825,37 +516,8 @@ rb_set_cfp_sp(struct rb_control_frame_struct *cfp, VALUE *sp) cfp->sp = sp; } -VALUE -rb_get_cfp_self(struct rb_control_frame_struct *cfp) -{ - return cfp->self; -} - -VALUE * -rb_get_cfp_ep(struct rb_control_frame_struct *cfp) -{ - return (VALUE*)cfp->ep; -} - -const VALUE * -rb_get_cfp_ep_level(struct rb_control_frame_struct *cfp, uint32_t lv) -{ - uint32_t i; - const VALUE *ep = (VALUE*)cfp->ep; - for (i = 0; i < lv; i++) { - ep = VM_ENV_PREV_EP(ep); - } - return ep; -} - extern VALUE *rb_vm_base_ptr(struct rb_control_frame_struct *cfp); -VALUE -rb_yarv_class_of(VALUE obj) -{ - return rb_class_of(obj); -} - // YJIT needs this function to never allocate and never raise VALUE rb_yarv_str_eql_internal(VALUE str1, VALUE str2) @@ -989,33 +651,6 @@ rb_yjit_iseq_inspect(const rb_iseq_t *iseq) return buf; } -// The FL_TEST() macro -VALUE -rb_FL_TEST(VALUE obj, VALUE flags) -{ - return RB_FL_TEST(obj, flags); -} - -// The FL_TEST_RAW() macro, normally an internal implementation detail -VALUE -rb_FL_TEST_RAW(VALUE obj, VALUE flags) -{ - return FL_TEST_RAW(obj, flags); -} - -// The RB_TYPE_P macro -bool -rb_RB_TYPE_P(VALUE obj, enum ruby_value_type t) -{ - return RB_TYPE_P(obj, t); -} - -long -rb_RSTRUCT_LEN(VALUE st) -{ - return RSTRUCT_LEN(st); -} - // There are RSTRUCT_SETs in ruby/internal/core/rstruct.h and internal/struct.h // with different types (int vs long) for k. Here we use the one from ruby/internal/core/rstruct.h, // which takes an int. @@ -1025,24 +660,6 @@ rb_RSTRUCT_SET(VALUE st, int k, VALUE v) RSTRUCT_SET(st, k, v); } -const struct rb_callinfo * -rb_get_call_data_ci(const struct rb_call_data *cd) -{ - return cd->ci; -} - -bool -rb_BASIC_OP_UNREDEFINED_P(enum ruby_basic_operators bop, uint32_t klass) -{ - return BASIC_OP_UNREDEFINED_P(bop, klass); -} - -VALUE -rb_RCLASS_ORIGIN(VALUE c) -{ - return RCLASS_ORIGIN(c); -} - // Return the string encoding index int rb_ENCODING_GET(VALUE obj) @@ -1056,32 +673,12 @@ rb_yjit_multi_ractor_p(void) return rb_multi_ractor_p(); } -// For debug builds -void -rb_assert_iseq_handle(VALUE handle) -{ - RUBY_ASSERT_ALWAYS(IMEMO_TYPE_P(handle, imemo_iseq)); -} - -int -rb_IMEMO_TYPE_P(VALUE imemo, enum imemo_type imemo_type) -{ - return IMEMO_TYPE_P(imemo, imemo_type); -} - bool rb_yjit_constcache_shareable(const struct iseq_inline_constant_cache_entry *ice) { return (ice->flags & IMEMO_CONST_CACHE_SHAREABLE) != 0; } -void -rb_assert_cme_handle(VALUE handle) -{ - RUBY_ASSERT_ALWAYS(!rb_objspace_garbage_object_p(handle)); - RUBY_ASSERT_ALWAYS(IMEMO_TYPE_P(handle, imemo_ment)); -} - // Used for passing a callback and other data over rb_objspace_each_objects struct iseq_callback_data { rb_iseq_callback callback; diff --git a/yjit/bindgen/src/main.rs b/yjit/bindgen/src/main.rs index 9305a50cc9..9ee6fc7b8f 100644 --- a/yjit/bindgen/src/main.rs +++ b/yjit/bindgen/src/main.rs @@ -47,6 +47,7 @@ fn main() { // Our C file for glue code .header(src_root.join("yjit.c").to_str().unwrap()) + .header(src_root.join("jit.c").to_str().unwrap()) // Don't want to copy over C comment .generate_comments(false) diff --git a/yjit/src/cruby_bindings.inc.rs b/yjit/src/cruby_bindings.inc.rs index db4f75e39b..490a61226a 100644 --- a/yjit/src/cruby_bindings.inc.rs +++ b/yjit/src/cruby_bindings.inc.rs @@ -979,6 +979,7 @@ pub type robject_offsets = u32; pub const RUBY_OFFSET_RSTRING_LEN: rstring_offsets = 16; pub type rstring_offsets = u32; pub type rb_seq_param_keyword_struct = rb_iseq_constant_body__bindgen_ty_1_rb_iseq_param_keyword; +pub type rb_iseq_param_keyword_struct = rb_iseq_constant_body__bindgen_ty_1_rb_iseq_param_keyword; extern "C" { pub fn ruby_xfree(ptr: *mut ::std::os::raw::c_void); pub fn rb_class_attached_object(klass: VALUE) -> VALUE; @@ -1163,15 +1164,78 @@ extern "C" { pub fn rb_yjit_reserve_addr_space(mem_size: u32) -> *mut u8; pub fn rb_c_method_tracing_currently_enabled(ec: *const rb_execution_context_t) -> bool; pub fn rb_full_cfunc_return(ec: *mut rb_execution_context_t, return_value: VALUE); - pub fn rb_iseq_encoded_size(iseq: *const rb_iseq_t) -> ::std::os::raw::c_uint; pub fn rb_iseq_get_yjit_payload(iseq: *const rb_iseq_t) -> *mut ::std::os::raw::c_void; pub fn rb_iseq_set_yjit_payload(iseq: *const rb_iseq_t, payload: *mut ::std::os::raw::c_void); pub fn rb_iseq_reset_jit_func(iseq: *const rb_iseq_t); + pub fn rb_yjit_get_proc_ptr(procv: VALUE) -> *mut rb_proc_t; + pub fn rb_get_symbol_id(namep: VALUE) -> ID; + pub fn rb_get_def_bmethod_proc(def: *mut rb_method_definition_t) -> VALUE; + pub fn rb_get_iseq_body_parent_iseq(iseq: *const rb_iseq_t) -> *const rb_iseq_t; + pub fn rb_optimized_call( + recv: *mut VALUE, + ec: *mut rb_execution_context_t, + argc: ::std::os::raw::c_int, + argv: *mut VALUE, + kw_splat: ::std::os::raw::c_int, + block_handler: VALUE, + ) -> VALUE; + pub fn rb_yjit_iseq_builtin_attrs(iseq: *const rb_iseq_t) -> ::std::os::raw::c_uint; + pub fn rb_yjit_builtin_function(iseq: *const rb_iseq_t) -> *const rb_builtin_function; + pub fn rb_yjit_str_simple_append(str1: VALUE, str2: VALUE) -> VALUE; + pub fn rb_set_cfp_pc(cfp: *mut rb_control_frame_struct, pc: *const VALUE); + pub fn rb_set_cfp_sp(cfp: *mut rb_control_frame_struct, sp: *mut VALUE); + pub fn rb_vm_base_ptr(cfp: *mut rb_control_frame_struct) -> *mut VALUE; + pub fn rb_yarv_str_eql_internal(str1: VALUE, str2: VALUE) -> VALUE; + pub fn rb_str_neq_internal(str1: VALUE, str2: VALUE) -> VALUE; + pub fn rb_yarv_ary_entry_internal(ary: VALUE, offset: ::std::os::raw::c_long) -> VALUE; + pub fn rb_ary_unshift_m(argc: ::std::os::raw::c_int, argv: *mut VALUE, ary: VALUE) -> VALUE; + pub fn rb_yjit_rb_ary_subseq_length(ary: VALUE, beg: ::std::os::raw::c_long) -> VALUE; + pub fn rb_yjit_fix_div_fix(recv: VALUE, obj: VALUE) -> VALUE; + pub fn rb_yjit_fix_mod_fix(recv: VALUE, obj: VALUE) -> VALUE; + pub fn rb_yjit_ruby2_keywords_splat_p(obj: VALUE) -> usize; + pub fn rb_yjit_splat_varg_checks( + sp: *mut VALUE, + splat_array: VALUE, + cfp: *mut rb_control_frame_t, + ) -> VALUE; + pub fn rb_yjit_splat_varg_cfunc(stack_splat_array: *mut VALUE) -> ::std::os::raw::c_int; + pub fn rb_yjit_dump_iseq_loc(iseq: *const rb_iseq_t, insn_idx: u32); + pub fn rb_yjit_iseq_inspect(iseq: *const rb_iseq_t) -> *mut ::std::os::raw::c_char; + pub fn rb_RSTRUCT_SET(st: VALUE, k: ::std::os::raw::c_int, v: VALUE); + pub fn rb_ENCODING_GET(obj: VALUE) -> ::std::os::raw::c_int; + pub fn rb_yjit_multi_ractor_p() -> bool; + pub fn rb_yjit_constcache_shareable(ice: *const iseq_inline_constant_cache_entry) -> bool; + pub fn rb_yjit_for_each_iseq(callback: rb_iseq_callback, data: *mut ::std::os::raw::c_void); + pub fn rb_yjit_obj_written( + old: VALUE, + young: VALUE, + file: *const ::std::os::raw::c_char, + line: ::std::os::raw::c_int, + ); + pub fn rb_yjit_vm_lock_then_barrier( + recursive_lock_level: *mut ::std::os::raw::c_uint, + file: *const ::std::os::raw::c_char, + line: ::std::os::raw::c_int, + ); + pub fn rb_yjit_vm_unlock( + recursive_lock_level: *mut ::std::os::raw::c_uint, + file: *const ::std::os::raw::c_char, + line: ::std::os::raw::c_int, + ); + pub fn rb_object_shape_count() -> VALUE; + pub fn rb_yjit_assert_holding_vm_lock(); + pub fn rb_yjit_sendish_sp_pops(ci: *const rb_callinfo) -> usize; + pub fn rb_yjit_invokeblock_sp_pops(ci: *const rb_callinfo) -> usize; + pub fn rb_yjit_set_exception_return( + cfp: *mut rb_control_frame_t, + leave_exit: *mut ::std::os::raw::c_void, + leave_exception: *mut ::std::os::raw::c_void, + ); + pub fn rb_iseq_encoded_size(iseq: *const rb_iseq_t) -> ::std::os::raw::c_uint; pub fn rb_iseq_pc_at_idx(iseq: *const rb_iseq_t, insn_idx: u32) -> *mut VALUE; pub fn rb_iseq_opcode_at_pc(iseq: *const rb_iseq_t, pc: *const VALUE) -> ::std::os::raw::c_int; pub fn rb_RSTRING_LEN(str_: VALUE) -> ::std::os::raw::c_ulong; pub fn rb_RSTRING_PTR(str_: VALUE) -> *mut ::std::os::raw::c_char; - pub fn rb_yjit_get_proc_ptr(procv: VALUE) -> *mut rb_proc_t; pub fn rb_insn_name(insn: VALUE) -> *const ::std::os::raw::c_char; pub fn rb_vm_ci_argc(ci: *const rb_callinfo) -> ::std::os::raw::c_uint; pub fn rb_vm_ci_mid(ci: *const rb_callinfo) -> ID; @@ -1185,7 +1249,6 @@ extern "C" { pub fn rb_METHOD_ENTRY_VISI(me: *const rb_callable_method_entry_t) -> rb_method_visibility_t; pub fn rb_get_cme_def_type(cme: *const rb_callable_method_entry_t) -> rb_method_type_t; pub fn rb_get_cme_def_body_attr_id(cme: *const rb_callable_method_entry_t) -> ID; - pub fn rb_get_symbol_id(namep: VALUE) -> ID; pub fn rb_get_cme_def_body_optimized_type( cme: *const rb_callable_method_entry_t, ) -> method_optimized_type; @@ -1200,9 +1263,7 @@ extern "C" { pub fn rb_get_mct_argc(mct: *const rb_method_cfunc_t) -> ::std::os::raw::c_int; pub fn rb_get_mct_func(mct: *const rb_method_cfunc_t) -> *mut ::std::os::raw::c_void; pub fn rb_get_def_iseq_ptr(def: *mut rb_method_definition_t) -> *const rb_iseq_t; - pub fn rb_get_def_bmethod_proc(def: *mut rb_method_definition_t) -> VALUE; pub fn rb_get_iseq_body_local_iseq(iseq: *const rb_iseq_t) -> *const rb_iseq_t; - pub fn rb_get_iseq_body_parent_iseq(iseq: *const rb_iseq_t) -> *const rb_iseq_t; pub fn rb_get_iseq_body_local_table_size(iseq: *const rb_iseq_t) -> ::std::os::raw::c_uint; pub fn rb_get_iseq_body_iseq_encoded(iseq: *const rb_iseq_t) -> *mut VALUE; pub fn rb_get_iseq_body_stack_max(iseq: *const rb_iseq_t) -> ::std::os::raw::c_uint; @@ -1221,87 +1282,27 @@ extern "C" { pub fn rb_get_iseq_flags_forwardable(iseq: *const rb_iseq_t) -> bool; pub fn rb_get_iseq_body_param_keyword( iseq: *const rb_iseq_t, - ) -> *const rb_seq_param_keyword_struct; + ) -> *const rb_iseq_param_keyword_struct; pub fn rb_get_iseq_body_param_size(iseq: *const rb_iseq_t) -> ::std::os::raw::c_uint; pub fn rb_get_iseq_body_param_lead_num(iseq: *const rb_iseq_t) -> ::std::os::raw::c_int; pub fn rb_get_iseq_body_param_opt_num(iseq: *const rb_iseq_t) -> ::std::os::raw::c_int; pub fn rb_get_iseq_body_param_opt_table(iseq: *const rb_iseq_t) -> *const VALUE; - pub fn rb_optimized_call( - recv: *mut VALUE, - ec: *mut rb_execution_context_t, - argc: ::std::os::raw::c_int, - argv: *mut VALUE, - kw_splat: ::std::os::raw::c_int, - block_handler: VALUE, - ) -> VALUE; - pub fn rb_yjit_iseq_builtin_attrs(iseq: *const rb_iseq_t) -> ::std::os::raw::c_uint; - pub fn rb_yjit_builtin_function(iseq: *const rb_iseq_t) -> *const rb_builtin_function; - pub fn rb_yjit_str_simple_append(str1: VALUE, str2: VALUE) -> VALUE; pub fn rb_get_ec_cfp(ec: *const rb_execution_context_t) -> *mut rb_control_frame_struct; pub fn rb_get_cfp_iseq(cfp: *mut rb_control_frame_struct) -> *const rb_iseq_t; pub fn rb_get_cfp_pc(cfp: *mut rb_control_frame_struct) -> *mut VALUE; pub fn rb_get_cfp_sp(cfp: *mut rb_control_frame_struct) -> *mut VALUE; - pub fn rb_set_cfp_pc(cfp: *mut rb_control_frame_struct, pc: *const VALUE); - pub fn rb_set_cfp_sp(cfp: *mut rb_control_frame_struct, sp: *mut VALUE); pub fn rb_get_cfp_self(cfp: *mut rb_control_frame_struct) -> VALUE; pub fn rb_get_cfp_ep(cfp: *mut rb_control_frame_struct) -> *mut VALUE; pub fn rb_get_cfp_ep_level(cfp: *mut rb_control_frame_struct, lv: u32) -> *const VALUE; - pub fn rb_vm_base_ptr(cfp: *mut rb_control_frame_struct) -> *mut VALUE; pub fn rb_yarv_class_of(obj: VALUE) -> VALUE; - pub fn rb_yarv_str_eql_internal(str1: VALUE, str2: VALUE) -> VALUE; - pub fn rb_str_neq_internal(str1: VALUE, str2: VALUE) -> VALUE; - pub fn rb_yarv_ary_entry_internal(ary: VALUE, offset: ::std::os::raw::c_long) -> VALUE; - pub fn rb_ary_unshift_m(argc: ::std::os::raw::c_int, argv: *mut VALUE, ary: VALUE) -> VALUE; - pub fn rb_yjit_rb_ary_subseq_length(ary: VALUE, beg: ::std::os::raw::c_long) -> VALUE; - pub fn rb_yjit_fix_div_fix(recv: VALUE, obj: VALUE) -> VALUE; - pub fn rb_yjit_fix_mod_fix(recv: VALUE, obj: VALUE) -> VALUE; - pub fn rb_yjit_ruby2_keywords_splat_p(obj: VALUE) -> usize; - pub fn rb_yjit_splat_varg_checks( - sp: *mut VALUE, - splat_array: VALUE, - cfp: *mut rb_control_frame_t, - ) -> VALUE; - pub fn rb_yjit_splat_varg_cfunc(stack_splat_array: *mut VALUE) -> ::std::os::raw::c_int; - pub fn rb_yjit_dump_iseq_loc(iseq: *const rb_iseq_t, insn_idx: u32); - pub fn rb_yjit_iseq_inspect(iseq: *const rb_iseq_t) -> *mut ::std::os::raw::c_char; pub fn rb_FL_TEST(obj: VALUE, flags: VALUE) -> VALUE; pub fn rb_FL_TEST_RAW(obj: VALUE, flags: VALUE) -> VALUE; pub fn rb_RB_TYPE_P(obj: VALUE, t: ruby_value_type) -> bool; pub fn rb_RSTRUCT_LEN(st: VALUE) -> ::std::os::raw::c_long; - pub fn rb_RSTRUCT_SET(st: VALUE, k: ::std::os::raw::c_int, v: VALUE); pub fn rb_get_call_data_ci(cd: *const rb_call_data) -> *const rb_callinfo; pub fn rb_BASIC_OP_UNREDEFINED_P(bop: ruby_basic_operators, klass: u32) -> bool; pub fn rb_RCLASS_ORIGIN(c: VALUE) -> VALUE; - pub fn rb_ENCODING_GET(obj: VALUE) -> ::std::os::raw::c_int; - pub fn rb_yjit_multi_ractor_p() -> bool; pub fn rb_assert_iseq_handle(handle: VALUE); pub fn rb_IMEMO_TYPE_P(imemo: VALUE, imemo_type: imemo_type) -> ::std::os::raw::c_int; - pub fn rb_yjit_constcache_shareable(ice: *const iseq_inline_constant_cache_entry) -> bool; pub fn rb_assert_cme_handle(handle: VALUE); - pub fn rb_yjit_for_each_iseq(callback: rb_iseq_callback, data: *mut ::std::os::raw::c_void); - pub fn rb_yjit_obj_written( - old: VALUE, - young: VALUE, - file: *const ::std::os::raw::c_char, - line: ::std::os::raw::c_int, - ); - pub fn rb_yjit_vm_lock_then_barrier( - recursive_lock_level: *mut ::std::os::raw::c_uint, - file: *const ::std::os::raw::c_char, - line: ::std::os::raw::c_int, - ); - pub fn rb_yjit_vm_unlock( - recursive_lock_level: *mut ::std::os::raw::c_uint, - file: *const ::std::os::raw::c_char, - line: ::std::os::raw::c_int, - ); - pub fn rb_object_shape_count() -> VALUE; - pub fn rb_yjit_assert_holding_vm_lock(); - pub fn rb_yjit_sendish_sp_pops(ci: *const rb_callinfo) -> usize; - pub fn rb_yjit_invokeblock_sp_pops(ci: *const rb_callinfo) -> usize; - pub fn rb_yjit_set_exception_return( - cfp: *mut rb_control_frame_t, - leave_exit: *mut ::std::os::raw::c_void, - leave_exception: *mut ::std::os::raw::c_void, - ); } @@ -156,18 +156,6 @@ rb_zjit_reserve_addr_space(uint32_t mem_size) #endif } -unsigned long -rb_RSTRING_LEN(VALUE str) -{ - return RSTRING_LEN(str); -} - -char * -rb_RSTRING_PTR(VALUE str) -{ - return RSTRING_PTR(str); -} - void rb_zjit_profile_disable(const rb_iseq_t *iseq); void @@ -189,374 +177,20 @@ rb_zjit_compile_iseq(const rb_iseq_t *iseq, rb_execution_context_t *ec, bool jit RB_VM_LOCK_LEAVE(); } -unsigned int -rb_iseq_encoded_size(const rb_iseq_t *iseq) -{ - return iseq->body->iseq_size; -} - -// Get the opcode given a program counter. Can return trace opcode variants. -int -rb_iseq_opcode_at_pc(const rb_iseq_t *iseq, const VALUE *pc) -{ - // ZJIT should only use iseqs after AST to bytecode compilation - RUBY_ASSERT_ALWAYS(FL_TEST_RAW((VALUE)iseq, ISEQ_TRANSLATED)); - - const VALUE at_pc = *pc; - return rb_vm_insn_addr2opcode((const void *)at_pc); -} - -// Get the PC for a given index in an iseq -VALUE * -rb_iseq_pc_at_idx(const rb_iseq_t *iseq, uint32_t insn_idx) -{ - RUBY_ASSERT_ALWAYS(IMEMO_TYPE_P(iseq, imemo_iseq)); - RUBY_ASSERT_ALWAYS(insn_idx < iseq->body->iseq_size); - VALUE *encoded = iseq->body->iseq_encoded; - VALUE *pc = &encoded[insn_idx]; - return pc; -} - -const char * -rb_insn_name(VALUE insn) -{ - return insn_name(insn); -} - -struct rb_control_frame_struct * -rb_get_ec_cfp(const rb_execution_context_t *ec) -{ - return ec->cfp; -} - -const rb_iseq_t * -rb_get_cfp_iseq(struct rb_control_frame_struct *cfp) -{ - return cfp->iseq; -} - -VALUE * -rb_get_cfp_pc(struct rb_control_frame_struct *cfp) -{ - return (VALUE*)cfp->pc; -} - -VALUE * -rb_get_cfp_sp(struct rb_control_frame_struct *cfp) -{ - return cfp->sp; -} - -VALUE -rb_get_cfp_self(struct rb_control_frame_struct *cfp) -{ - return cfp->self; -} - -VALUE * -rb_get_cfp_ep(struct rb_control_frame_struct *cfp) -{ - return (VALUE*)cfp->ep; -} - -const VALUE * -rb_get_cfp_ep_level(struct rb_control_frame_struct *cfp, uint32_t lv) -{ - uint32_t i; - const VALUE *ep = (VALUE*)cfp->ep; - for (i = 0; i < lv; i++) { - ep = VM_ENV_PREV_EP(ep); - } - return ep; -} - extern VALUE *rb_vm_base_ptr(struct rb_control_frame_struct *cfp); -rb_method_type_t -rb_get_cme_def_type(const rb_callable_method_entry_t *cme) -{ - if (UNDEFINED_METHOD_ENTRY_P(cme)) { - return VM_METHOD_TYPE_UNDEF; - } - else { - return cme->def->type; - } -} - -ID -rb_get_cme_def_body_attr_id(const rb_callable_method_entry_t *cme) -{ - return cme->def->body.attr.id; -} - -enum method_optimized_type -rb_get_cme_def_body_optimized_type(const rb_callable_method_entry_t *cme) -{ - return cme->def->body.optimized.type; -} - -unsigned int -rb_get_cme_def_body_optimized_index(const rb_callable_method_entry_t *cme) -{ - return cme->def->body.optimized.index; -} - -rb_method_cfunc_t * -rb_get_cme_def_body_cfunc(const rb_callable_method_entry_t *cme) -{ - return UNALIGNED_MEMBER_PTR(cme->def, body.cfunc); -} - -uintptr_t -rb_get_def_method_serial(const rb_method_definition_t *def) -{ - return def->method_serial; -} - -ID -rb_get_def_original_id(const rb_method_definition_t *def) -{ - return def->original_id; -} - -int -rb_get_mct_argc(const rb_method_cfunc_t *mct) -{ - return mct->argc; -} - -void * -rb_get_mct_func(const rb_method_cfunc_t *mct) -{ - return (void*)(uintptr_t)mct->func; // this field is defined as type VALUE (*func)(ANYARGS) -} - -const rb_iseq_t * -rb_get_def_iseq_ptr(rb_method_definition_t *def) -{ - return def_iseq_ptr(def); -} - -const rb_iseq_t * -rb_get_iseq_body_local_iseq(const rb_iseq_t *iseq) -{ - return iseq->body->local_iseq; -} - -VALUE * -rb_get_iseq_body_iseq_encoded(const rb_iseq_t *iseq) -{ - return iseq->body->iseq_encoded; -} - -unsigned -rb_get_iseq_body_stack_max(const rb_iseq_t *iseq) -{ - return iseq->body->stack_max; -} - -enum rb_iseq_type -rb_get_iseq_body_type(const rb_iseq_t *iseq) -{ - return iseq->body->type; -} - -bool -rb_get_iseq_flags_has_lead(const rb_iseq_t *iseq) -{ - return iseq->body->param.flags.has_lead; -} - -bool -rb_get_iseq_flags_has_opt(const rb_iseq_t *iseq) -{ - return iseq->body->param.flags.has_opt; -} - -bool -rb_get_iseq_flags_has_kw(const rb_iseq_t *iseq) -{ - return iseq->body->param.flags.has_kw; -} - -bool -rb_get_iseq_flags_has_post(const rb_iseq_t *iseq) -{ - return iseq->body->param.flags.has_post; -} - -bool -rb_get_iseq_flags_has_kwrest(const rb_iseq_t *iseq) -{ - return iseq->body->param.flags.has_kwrest; -} - -bool -rb_get_iseq_flags_anon_kwrest(const rb_iseq_t *iseq) -{ - return iseq->body->param.flags.anon_kwrest; -} - -bool -rb_get_iseq_flags_has_rest(const rb_iseq_t *iseq) -{ - return iseq->body->param.flags.has_rest; -} - -bool -rb_get_iseq_flags_ruby2_keywords(const rb_iseq_t *iseq) -{ - return iseq->body->param.flags.ruby2_keywords; -} - -bool -rb_get_iseq_flags_has_block(const rb_iseq_t *iseq) -{ - return iseq->body->param.flags.has_block; -} - -bool -rb_get_iseq_flags_ambiguous_param0(const rb_iseq_t *iseq) -{ - return iseq->body->param.flags.ambiguous_param0; -} - -bool -rb_get_iseq_flags_accepts_no_kwarg(const rb_iseq_t *iseq) -{ - return iseq->body->param.flags.accepts_no_kwarg; -} - -bool -rb_get_iseq_flags_forwardable(const rb_iseq_t *iseq) -{ - return iseq->body->param.flags.forwardable; -} - -// This is defined only as a named struct inside rb_iseq_constant_body. -// By giving it a separate typedef, we make it nameable by rust-bindgen. -// Bindgen's temp/anon name isn't guaranteed stable. -typedef struct rb_iseq_param_keyword rb_iseq_param_keyword_struct; - -const rb_iseq_param_keyword_struct * -rb_get_iseq_body_param_keyword(const rb_iseq_t *iseq) -{ - return iseq->body->param.keyword; -} - -unsigned -rb_get_iseq_body_param_size(const rb_iseq_t *iseq) -{ - return iseq->body->param.size; -} - -int -rb_get_iseq_body_param_lead_num(const rb_iseq_t *iseq) -{ - return iseq->body->param.lead_num; -} - -int -rb_get_iseq_body_param_opt_num(const rb_iseq_t *iseq) -{ - return iseq->body->param.opt_num; -} - -const VALUE * -rb_get_iseq_body_param_opt_table(const rb_iseq_t *iseq) -{ - return iseq->body->param.opt_table; -} - -unsigned int -rb_get_iseq_body_local_table_size(const rb_iseq_t *iseq) -{ - return iseq->body->local_table_size; -} - -int -rb_get_cikw_keyword_len(const struct rb_callinfo_kwarg *cikw) -{ - return cikw->keyword_len; -} - -VALUE -rb_get_cikw_keywords_idx(const struct rb_callinfo_kwarg *cikw, int idx) -{ - return cikw->keywords[idx]; -} - -const struct rb_callinfo * -rb_get_call_data_ci(const struct rb_call_data *cd) -{ - return cd->ci; -} - -// The FL_TEST() macro -VALUE -rb_FL_TEST(VALUE obj, VALUE flags) -{ - return RB_FL_TEST(obj, flags); -} - -// The FL_TEST_RAW() macro, normally an internal implementation detail -VALUE -rb_FL_TEST_RAW(VALUE obj, VALUE flags) -{ - return FL_TEST_RAW(obj, flags); -} - -// The RB_TYPE_P macro -bool -rb_RB_TYPE_P(VALUE obj, enum ruby_value_type t) -{ - return RB_TYPE_P(obj, t); -} - -long -rb_RSTRUCT_LEN(VALUE st) -{ - return RSTRUCT_LEN(st); -} - -bool -rb_BASIC_OP_UNREDEFINED_P(enum ruby_basic_operators bop, uint32_t klass) -{ - return BASIC_OP_UNREDEFINED_P(bop, klass); -} - bool rb_zjit_multi_ractor_p(void) { return rb_multi_ractor_p(); } -// For debug builds -void -rb_assert_iseq_handle(VALUE handle) -{ - RUBY_ASSERT_ALWAYS(IMEMO_TYPE_P(handle, imemo_iseq)); -} - bool rb_zjit_constcache_shareable(const struct iseq_inline_constant_cache_entry *ice) { return (ice->flags & IMEMO_CONST_CACHE_SHAREABLE) != 0; } -void -rb_assert_cme_handle(VALUE handle) -{ - RUBY_ASSERT_ALWAYS(!rb_objspace_garbage_object_p(handle)); - RUBY_ASSERT_ALWAYS(IMEMO_TYPE_P(handle, imemo_ment)); -} - -int -rb_IMEMO_TYPE_P(VALUE imemo, enum imemo_type imemo_type) -{ - return IMEMO_TYPE_P(imemo, imemo_type); -} - // Release the VM lock. The lock level must point to the same integer used to // acquire the lock. void @@ -614,42 +248,6 @@ rb_zjit_icache_invalidate(void *start, void *end) #endif } -unsigned int -rb_vm_ci_argc(const struct rb_callinfo *ci) -{ - return vm_ci_argc(ci); -} - -ID -rb_vm_ci_mid(const struct rb_callinfo *ci) -{ - return vm_ci_mid(ci); -} - -unsigned int -rb_vm_ci_flag(const struct rb_callinfo *ci) -{ - return vm_ci_flag(ci); -} - -const struct rb_callinfo_kwarg * -rb_vm_ci_kwarg(const struct rb_callinfo *ci) -{ - return vm_ci_kwarg(ci); -} - -rb_method_visibility_t -rb_METHOD_ENTRY_VISI(const rb_callable_method_entry_t *me) -{ - return METHOD_ENTRY_VISI(me); -} - -VALUE -rb_yarv_class_of(VALUE obj) -{ - return rb_class_of(obj); -} - // Acquire the VM lock and then signal all other Ruby threads (ractors) to // contend for the VM lock, putting them to sleep. ZJIT uses this to evict // threads running inside generated code so among other things, it can @@ -661,12 +259,6 @@ rb_zjit_vm_lock_then_barrier(unsigned int *recursive_lock_level, const char *fil rb_vm_barrier(); } -VALUE -rb_RCLASS_ORIGIN(VALUE c) -{ - return RCLASS_ORIGIN(c); -} - // Convert a given ISEQ's instructions to zjit_* instructions void rb_zjit_profile_enable(const rb_iseq_t *iseq) diff --git a/zjit/bindgen/src/main.rs b/zjit/bindgen/src/main.rs index 5372ead3e5..f47dff744c 100644 --- a/zjit/bindgen/src/main.rs +++ b/zjit/bindgen/src/main.rs @@ -51,6 +51,7 @@ fn main() { // Our C file for glue code .header(src_root.join(c_file).to_str().unwrap()) + .header(src_root.join("jit.c").to_str().unwrap()) // Don't want to copy over C comment .generate_comments(false) diff --git a/zjit/src/cruby_bindings.inc.rs b/zjit/src/cruby_bindings.inc.rs index 169789ef77..88532abb63 100644 --- a/zjit/src/cruby_bindings.inc.rs +++ b/zjit/src/cruby_bindings.inc.rs @@ -929,21 +929,46 @@ unsafe extern "C" { pub fn rb_jit_cont_each_iseq(callback: rb_iseq_callback, data: *mut ::std::os::raw::c_void); pub fn rb_zjit_get_page_size() -> u32; pub fn rb_zjit_reserve_addr_space(mem_size: u32) -> *mut u8; - pub fn rb_RSTRING_LEN(str_: VALUE) -> ::std::os::raw::c_ulong; - pub fn rb_RSTRING_PTR(str_: VALUE) -> *mut ::std::os::raw::c_char; pub fn rb_zjit_profile_disable(iseq: *const rb_iseq_t); + pub fn rb_vm_base_ptr(cfp: *mut rb_control_frame_struct) -> *mut VALUE; + pub fn rb_zjit_multi_ractor_p() -> bool; + pub fn rb_zjit_constcache_shareable(ice: *const iseq_inline_constant_cache_entry) -> bool; + pub fn rb_zjit_vm_unlock( + recursive_lock_level: *mut ::std::os::raw::c_uint, + file: *const ::std::os::raw::c_char, + line: ::std::os::raw::c_int, + ); + pub fn rb_zjit_mark_writable(mem_block: *mut ::std::os::raw::c_void, mem_size: u32) -> bool; + pub fn rb_zjit_mark_executable(mem_block: *mut ::std::os::raw::c_void, mem_size: u32); + pub fn rb_zjit_mark_unused(mem_block: *mut ::std::os::raw::c_void, mem_size: u32) -> bool; + pub fn rb_zjit_icache_invalidate( + start: *mut ::std::os::raw::c_void, + end: *mut ::std::os::raw::c_void, + ); + pub fn rb_zjit_vm_lock_then_barrier( + recursive_lock_level: *mut ::std::os::raw::c_uint, + file: *const ::std::os::raw::c_char, + line: ::std::os::raw::c_int, + ); + pub fn rb_iseq_get_zjit_payload(iseq: *const rb_iseq_t) -> *mut ::std::os::raw::c_void; + pub fn rb_iseq_set_zjit_payload(iseq: *const rb_iseq_t, payload: *mut ::std::os::raw::c_void); + pub fn rb_zjit_print_exception(); pub fn rb_iseq_encoded_size(iseq: *const rb_iseq_t) -> ::std::os::raw::c_uint; - pub fn rb_iseq_opcode_at_pc(iseq: *const rb_iseq_t, pc: *const VALUE) -> ::std::os::raw::c_int; pub fn rb_iseq_pc_at_idx(iseq: *const rb_iseq_t, insn_idx: u32) -> *mut VALUE; + pub fn rb_iseq_opcode_at_pc(iseq: *const rb_iseq_t, pc: *const VALUE) -> ::std::os::raw::c_int; + pub fn rb_RSTRING_LEN(str_: VALUE) -> ::std::os::raw::c_ulong; + pub fn rb_RSTRING_PTR(str_: VALUE) -> *mut ::std::os::raw::c_char; pub fn rb_insn_name(insn: VALUE) -> *const ::std::os::raw::c_char; - pub fn rb_get_ec_cfp(ec: *const rb_execution_context_t) -> *mut rb_control_frame_struct; - pub fn rb_get_cfp_iseq(cfp: *mut rb_control_frame_struct) -> *const rb_iseq_t; - pub fn rb_get_cfp_pc(cfp: *mut rb_control_frame_struct) -> *mut VALUE; - pub fn rb_get_cfp_sp(cfp: *mut rb_control_frame_struct) -> *mut VALUE; - pub fn rb_get_cfp_self(cfp: *mut rb_control_frame_struct) -> VALUE; - pub fn rb_get_cfp_ep(cfp: *mut rb_control_frame_struct) -> *mut VALUE; - pub fn rb_get_cfp_ep_level(cfp: *mut rb_control_frame_struct, lv: u32) -> *const VALUE; - pub fn rb_vm_base_ptr(cfp: *mut rb_control_frame_struct) -> *mut VALUE; + pub fn rb_vm_ci_argc(ci: *const rb_callinfo) -> ::std::os::raw::c_uint; + pub fn rb_vm_ci_mid(ci: *const rb_callinfo) -> ID; + pub fn rb_vm_ci_flag(ci: *const rb_callinfo) -> ::std::os::raw::c_uint; + pub fn rb_vm_ci_kwarg(ci: *const rb_callinfo) -> *const rb_callinfo_kwarg; + pub fn rb_get_cikw_keyword_len(cikw: *const rb_callinfo_kwarg) -> ::std::os::raw::c_int; + pub fn rb_get_cikw_keywords_idx( + cikw: *const rb_callinfo_kwarg, + idx: ::std::os::raw::c_int, + ) -> VALUE; + pub fn rb_METHOD_ENTRY_VISI(me: *const rb_callable_method_entry_t) -> rb_method_visibility_t; pub fn rb_get_cme_def_type(cme: *const rb_callable_method_entry_t) -> rb_method_type_t; pub fn rb_get_cme_def_body_attr_id(cme: *const rb_callable_method_entry_t) -> ID; pub fn rb_get_cme_def_body_optimized_type( @@ -961,6 +986,7 @@ unsafe extern "C" { pub fn rb_get_mct_func(mct: *const rb_method_cfunc_t) -> *mut ::std::os::raw::c_void; pub fn rb_get_def_iseq_ptr(def: *mut rb_method_definition_t) -> *const rb_iseq_t; pub fn rb_get_iseq_body_local_iseq(iseq: *const rb_iseq_t) -> *const rb_iseq_t; + pub fn rb_get_iseq_body_local_table_size(iseq: *const rb_iseq_t) -> ::std::os::raw::c_uint; pub fn rb_get_iseq_body_iseq_encoded(iseq: *const rb_iseq_t) -> *mut VALUE; pub fn rb_get_iseq_body_stack_max(iseq: *const rb_iseq_t) -> ::std::os::raw::c_uint; pub fn rb_get_iseq_body_type(iseq: *const rb_iseq_t) -> rb_iseq_type; @@ -983,48 +1009,22 @@ unsafe extern "C" { pub fn rb_get_iseq_body_param_lead_num(iseq: *const rb_iseq_t) -> ::std::os::raw::c_int; pub fn rb_get_iseq_body_param_opt_num(iseq: *const rb_iseq_t) -> ::std::os::raw::c_int; pub fn rb_get_iseq_body_param_opt_table(iseq: *const rb_iseq_t) -> *const VALUE; - pub fn rb_get_iseq_body_local_table_size(iseq: *const rb_iseq_t) -> ::std::os::raw::c_uint; - pub fn rb_get_cikw_keyword_len(cikw: *const rb_callinfo_kwarg) -> ::std::os::raw::c_int; - pub fn rb_get_cikw_keywords_idx( - cikw: *const rb_callinfo_kwarg, - idx: ::std::os::raw::c_int, - ) -> VALUE; - pub fn rb_get_call_data_ci(cd: *const rb_call_data) -> *const rb_callinfo; + pub fn rb_get_ec_cfp(ec: *const rb_execution_context_t) -> *mut rb_control_frame_struct; + pub fn rb_get_cfp_iseq(cfp: *mut rb_control_frame_struct) -> *const rb_iseq_t; + pub fn rb_get_cfp_pc(cfp: *mut rb_control_frame_struct) -> *mut VALUE; + pub fn rb_get_cfp_sp(cfp: *mut rb_control_frame_struct) -> *mut VALUE; + pub fn rb_get_cfp_self(cfp: *mut rb_control_frame_struct) -> VALUE; + pub fn rb_get_cfp_ep(cfp: *mut rb_control_frame_struct) -> *mut VALUE; + pub fn rb_get_cfp_ep_level(cfp: *mut rb_control_frame_struct, lv: u32) -> *const VALUE; + pub fn rb_yarv_class_of(obj: VALUE) -> VALUE; pub fn rb_FL_TEST(obj: VALUE, flags: VALUE) -> VALUE; pub fn rb_FL_TEST_RAW(obj: VALUE, flags: VALUE) -> VALUE; pub fn rb_RB_TYPE_P(obj: VALUE, t: ruby_value_type) -> bool; pub fn rb_RSTRUCT_LEN(st: VALUE) -> ::std::os::raw::c_long; + pub fn rb_get_call_data_ci(cd: *const rb_call_data) -> *const rb_callinfo; pub fn rb_BASIC_OP_UNREDEFINED_P(bop: ruby_basic_operators, klass: u32) -> bool; - pub fn rb_zjit_multi_ractor_p() -> bool; + pub fn rb_RCLASS_ORIGIN(c: VALUE) -> VALUE; pub fn rb_assert_iseq_handle(handle: VALUE); - pub fn rb_zjit_constcache_shareable(ice: *const iseq_inline_constant_cache_entry) -> bool; - pub fn rb_assert_cme_handle(handle: VALUE); pub fn rb_IMEMO_TYPE_P(imemo: VALUE, imemo_type: imemo_type) -> ::std::os::raw::c_int; - pub fn rb_zjit_vm_unlock( - recursive_lock_level: *mut ::std::os::raw::c_uint, - file: *const ::std::os::raw::c_char, - line: ::std::os::raw::c_int, - ); - pub fn rb_zjit_mark_writable(mem_block: *mut ::std::os::raw::c_void, mem_size: u32) -> bool; - pub fn rb_zjit_mark_executable(mem_block: *mut ::std::os::raw::c_void, mem_size: u32); - pub fn rb_zjit_mark_unused(mem_block: *mut ::std::os::raw::c_void, mem_size: u32) -> bool; - pub fn rb_zjit_icache_invalidate( - start: *mut ::std::os::raw::c_void, - end: *mut ::std::os::raw::c_void, - ); - pub fn rb_vm_ci_argc(ci: *const rb_callinfo) -> ::std::os::raw::c_uint; - pub fn rb_vm_ci_mid(ci: *const rb_callinfo) -> ID; - pub fn rb_vm_ci_flag(ci: *const rb_callinfo) -> ::std::os::raw::c_uint; - pub fn rb_vm_ci_kwarg(ci: *const rb_callinfo) -> *const rb_callinfo_kwarg; - pub fn rb_METHOD_ENTRY_VISI(me: *const rb_callable_method_entry_t) -> rb_method_visibility_t; - pub fn rb_yarv_class_of(obj: VALUE) -> VALUE; - pub fn rb_zjit_vm_lock_then_barrier( - recursive_lock_level: *mut ::std::os::raw::c_uint, - file: *const ::std::os::raw::c_char, - line: ::std::os::raw::c_int, - ); - pub fn rb_RCLASS_ORIGIN(c: VALUE) -> VALUE; - pub fn rb_iseq_get_zjit_payload(iseq: *const rb_iseq_t) -> *mut ::std::os::raw::c_void; - pub fn rb_iseq_set_zjit_payload(iseq: *const rb_iseq_t, payload: *mut ::std::os::raw::c_void); - pub fn rb_zjit_print_exception(); + pub fn rb_assert_cme_handle(handle: VALUE); } diff --git a/zjit/src/hir.rs b/zjit/src/hir.rs index d54617efe4..da56738231 100644 --- a/zjit/src/hir.rs +++ b/zjit/src/hir.rs @@ -141,6 +141,7 @@ impl<'a> std::fmt::Display for InvariantPrinter<'a> { write!(f, "BOPRedefined(")?; match klass { INTEGER_REDEFINED_OP_FLAG => write!(f, "INTEGER_REDEFINED_OP_FLAG")?, + ARRAY_REDEFINED_OP_FLAG => write!(f, "ARRAY_REDEFINED_OP_FLAG")?, _ => write!(f, "{klass}")?, } write!(f, ", ")?; @@ -156,6 +157,7 @@ impl<'a> std::fmt::Display for InvariantPrinter<'a> { BOP_LE => write!(f, "BOP_LE")?, BOP_GT => write!(f, "BOP_GT")?, BOP_GE => write!(f, "BOP_GE")?, + BOP_MAX => write!(f, "BOP_MAX")?, _ => write!(f, "{bop}")?, } write!(f, ")") @@ -310,6 +312,7 @@ pub enum Insn { NewArray { elements: Vec<InsnId>, state: InsnId }, ArraySet { array: InsnId, idx: usize, val: InsnId }, ArrayDup { val: InsnId, state: InsnId }, + ArrayMax { elements: Vec<InsnId>, state: InsnId }, // Check if the value is truthy and "return" a C boolean. In reality, we will likely fuse this // with IfTrue/IfFalse in the backend to generate jcc. @@ -441,6 +444,15 @@ impl<'a> std::fmt::Display for InsnPrinter<'a> { } Ok(()) } + Insn::ArrayMax { elements, .. } => { + write!(f, "ArrayMax")?; + let mut prefix = " "; + for element in elements { + write!(f, "{prefix}{element}")?; + prefix = ", "; + } + Ok(()) + } Insn::ArraySet { array, idx, val } => { write!(f, "ArraySet {array}, {idx}, {val}") } Insn::ArrayDup { val, .. } => { write!(f, "ArrayDup {val}") } Insn::StringCopy { val } => { write!(f, "StringCopy {val}") } @@ -744,12 +756,19 @@ impl Function { } }; } + macro_rules! find_vec { + ( $x:expr ) => { + { + $x.iter().map(|arg| find!(*arg)).collect() + } + }; + } macro_rules! find_branch_edge { ( $edge:ident ) => { { BranchEdge { target: $edge.target, - args: $edge.args.iter().map(|x| find!(*x)).collect(), + args: find_vec!($edge.args), } } }; @@ -757,7 +776,7 @@ impl Function { let insn_id = self.union_find.borrow_mut().find(insn_id); use Insn::*; match &self.insns[insn_id.0] { - result@(PutSelf | Const {..} | Param {..} | NewArray {..} | GetConstantPath {..} + result@(PutSelf | Const {..} | Param {..} | GetConstantPath {..} | PatchPoint {..}) => result.clone(), Snapshot { state: FrameState { iseq, insn_idx, pc, stack, locals } } => Snapshot { @@ -816,6 +835,8 @@ impl Function { ArrayDup { val , state } => ArrayDup { val: find!(*val), state: *state }, CCall { cfun, args, name, return_type } => CCall { cfun: *cfun, args: args.iter().map(|arg| find!(*arg)).collect(), name: *name, return_type: *return_type }, Defined { .. } => todo!("find(Defined)"), + NewArray { elements, state } => NewArray { elements: find_vec!(*elements), state: find!(*state) }, + ArrayMax { elements, state } => ArrayMax { elements: find_vec!(*elements), state: find!(*state) }, } } @@ -882,6 +903,7 @@ impl Function { Insn::PutSelf => types::BasicObject, Insn::Defined { .. } => types::BasicObject, Insn::GetConstantPath { .. } => types::BasicObject, + Insn::ArrayMax { .. } => types::BasicObject, } } @@ -1309,9 +1331,13 @@ impl Function { necessary[insn_id.0] = true; match self.find(insn_id) { Insn::PutSelf | Insn::Const { .. } | Insn::Param { .. } - | Insn::NewArray { .. } | Insn::PatchPoint(..) - | Insn::GetConstantPath { .. } => + | Insn::PatchPoint(..) | Insn::GetConstantPath { .. } => {} + Insn::ArrayMax { elements, state } + | Insn::NewArray { elements, state } => { + worklist.extend(elements); + worklist.push_back(state); + } Insn::StringCopy { val } | Insn::StringIntern { val } | Insn::Return { val } @@ -1636,6 +1662,7 @@ pub enum CallType { pub enum ParseError { StackUnderflow(FrameState), UnknownOpcode(String), + UnknownNewArraySend(String), UnhandledCallType(CallType), } @@ -1755,6 +1782,26 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> { elements.reverse(); state.stack_push(fun.push_insn(block, Insn::NewArray { elements, state: exit_id })); } + YARVINSN_opt_newarray_send => { + let count = get_arg(pc, 0).as_usize(); + let method = get_arg(pc, 1).as_u32(); + let mut elements = vec![]; + for _ in 0..count { + elements.push(state.stack_pop()?); + } + elements.reverse(); + let exit_id = fun.push_insn(block, Insn::Snapshot { state: exit_state.clone() }); + let (bop, insn) = match method { + VM_OPT_NEWARRAY_SEND_MAX => (BOP_MAX, Insn::ArrayMax { elements, state: exit_id }), + VM_OPT_NEWARRAY_SEND_MIN => return Err(ParseError::UnknownNewArraySend("min".into())), + VM_OPT_NEWARRAY_SEND_HASH => return Err(ParseError::UnknownNewArraySend("hash".into())), + VM_OPT_NEWARRAY_SEND_PACK => return Err(ParseError::UnknownNewArraySend("pack".into())), + VM_OPT_NEWARRAY_SEND_PACK_BUFFER => return Err(ParseError::UnknownNewArraySend("pack_buffer".into())), + _ => return Err(ParseError::UnknownNewArraySend(format!("{method}"))), + }; + fun.push_insn(block, Insn::PatchPoint(Invariant::BOPRedefined { klass: ARRAY_REDEFINED_OP_FLAG, bop })); + state.stack_push(fun.push_insn(block, insn)); + } YARVINSN_duparray => { let val = fun.push_insn(block, Insn::Const { val: Const::Value(get_arg(pc, 0)) }); let exit_id = fun.push_insn(block, Insn::Snapshot { state: exit_state.clone() }); @@ -2831,6 +2878,35 @@ mod tests { Return v10 "#]]); } + + #[test] + fn test_opt_newarray_send_max_no_elements() { + eval(" + def test = [].max + "); + // TODO(max): Rewrite to nil + assert_method_hir("test", expect![[r#" + fn test: + bb0(): + PatchPoint BOPRedefined(ARRAY_REDEFINED_OP_FLAG, BOP_MAX) + v3:BasicObject = ArrayMax + Return v3 + "#]]); + } + + #[test] + fn test_opt_newarray_send_max() { + eval(" + def test(a,b) = [a,b].max + "); + assert_method_hir("test", expect![[r#" + fn test: + bb0(v0:BasicObject, v1:BasicObject): + PatchPoint BOPRedefined(ARRAY_REDEFINED_OP_FLAG, BOP_MAX) + v5:BasicObject = ArrayMax v0, v1 + Return v5 + "#]]); + } } #[cfg(test)] |