diff options
-rw-r--r-- | common.mk | 236 | ||||
-rw-r--r-- | configure.ac | 7 | ||||
-rw-r--r-- | ext/digest/defs.h | 22 | ||||
-rw-r--r-- | ext/digest/digest_conf.rb | 18 | ||||
-rw-r--r-- | ext/digest/md5/md5cc.h | 8 | ||||
-rw-r--r-- | ext/digest/md5/md5init.c | 1 | ||||
-rw-r--r-- | ext/digest/sha1/sha1.c | 8 | ||||
-rw-r--r-- | ext/socket/ipsocket.c | 16 | ||||
-rw-r--r-- | ext/socket/raddrinfo.c | 22 | ||||
-rw-r--r-- | gc.c | 12 | ||||
-rw-r--r-- | jit.c | 423 | ||||
-rw-r--r-- | template/Makefile.in | 1 | ||||
-rw-r--r-- | tool/ruby_vm/views/insns_info.inc.erb | 3 | ||||
-rw-r--r-- | vm_method.c | 1 | ||||
-rw-r--r-- | wasm/setjmp.h | 2 | ||||
-rw-r--r-- | yjit.c | 403 | ||||
-rw-r--r-- | yjit/bindgen/src/main.rs | 1 | ||||
-rw-r--r-- | yjit/src/cruby_bindings.inc.rs | 133 | ||||
-rw-r--r-- | zjit.c | 408 | ||||
-rw-r--r-- | zjit/bindgen/src/main.rs | 1 | ||||
-rw-r--r-- | zjit/src/cruby_bindings.inc.rs | 96 | ||||
-rw-r--r-- | zjit/src/hir.rs | 84 |
22 files changed, 929 insertions, 977 deletions
@@ -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/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); } @@ -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/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/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/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)] |