summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common.mk236
-rw-r--r--configure.ac7
-rw-r--r--ext/digest/defs.h22
-rw-r--r--ext/digest/digest_conf.rb18
-rw-r--r--ext/digest/md5/md5cc.h8
-rw-r--r--ext/digest/md5/md5init.c1
-rw-r--r--ext/digest/sha1/sha1.c8
-rw-r--r--ext/socket/ipsocket.c16
-rw-r--r--ext/socket/raddrinfo.c22
-rw-r--r--gc.c12
-rw-r--r--jit.c423
-rw-r--r--template/Makefile.in1
-rw-r--r--tool/ruby_vm/views/insns_info.inc.erb3
-rw-r--r--vm_method.c1
-rw-r--r--wasm/setjmp.h2
-rw-r--r--yjit.c403
-rw-r--r--yjit/bindgen/src/main.rs1
-rw-r--r--yjit/src/cruby_bindings.inc.rs133
-rw-r--r--zjit.c408
-rw-r--r--zjit/bindgen/src/main.rs1
-rw-r--r--zjit/src/cruby_bindings.inc.rs96
-rw-r--r--zjit/src/hir.rs84
22 files changed, 929 insertions, 977 deletions
diff --git a/common.mk b/common.mk
index c1fa9ae438..7337f8ad62 100644
--- a/common.mk
+++ b/common.mk
@@ -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);
}
diff --git a/gc.c b/gc.c
index 6e4c7ff74b..3f5bc5cea5 100644
--- a/gc.c
+++ b/gc.c
@@ -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
diff --git a/jit.c b/jit.c
new file mode 100644
index 0000000000..d2147a9d7f
--- /dev/null
+++ b/jit.c
@@ -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 {
diff --git a/yjit.c b/yjit.c
index 04231a0491..e11a30a6f8 100644
--- a/yjit.c
+++ b/yjit.c
@@ -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,
- );
}
diff --git a/zjit.c b/zjit.c
index 32ccf521ad..620b9d6af3 100644
--- a/zjit.c
+++ b/zjit.c
@@ -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)]