From: Eli Zaretskii Date: Thu, 23 Aug 2018 16:40:19 +0000 (+0300) Subject: Fix MS-Windows build with libjit X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=39c6bef85897bd45753d9ee3a1e19d9a161f16ce;p=emacs.git Fix MS-Windows build with libjit This fixes 32-bit MS-Windows build and hopefully also 64-bit MS-Windows build (not tested). 32-bit MS-Windows build with wide ints still doesn't work: I get invalid Lisp objects after JIT compiled code is invoked. * configure.ac (HAVE_LIBJIT) [mingw32]: Remove -ljit from LIBJIT_LIBS, to avoid linking against libjit at build time and allow loading libjit dynamically at run time. * src/jit.c [WINDOWSNT]: Include w32.h and w32common.h. [WINDOWSNT] (DEF_DLL_VAR, LOAD_DLL_VAR): New macros. (init_libjit_functions) [WINDOWSNT]: New function. (CONSTANT): A separate version for builds where EMACS_INT_MAX is equal to INT_MAX (32-bit builds without wide ints). Use XLI when assigning Lisp objects to integer values. (untag, compile_make_natnum, compile_make_number) (unary_intmath): Handle the case of EMACS_INT_MAX > LONG_MAX. (compile_current_thread, compile): Don't use CONSTANT for anything that is not a Lisp object. (emacs_jit_compile): Do nothing if jit-disable is non-nil. Use XLP to assign and compare Lisp objects to pointers. (syms_of_jit): New boolean variable jit-disable, by default nil. (init_jit) [WINDOWSNT]: Call init_libjit_functions. Define lisp_object_type separately for 64-bit Windows builds and 32-bit builds with wide ints. Fix some signatures to use lisp_object_type and correct some that deviated from the actual functions. * src/lisp.h (USE_STACK_LISP_OBJECTS): Define to false for 32-bit MinGW builds with libjit. * src/w32fns.c (syms_of_w32fns) : New symbol. * src/eval.c (Ffuncall, funcall_lambda): Use XLP to compare Lisp_Object vs a pointer. * src/emacs.c (main): Move the call to init_jit to before init_buffer, as the latter calls Lisp and could use JIT. * src/alloc.c (Fmake_byte_code): Use XPL to assign pointer to a Lisp_Object field. * lisp/term/w32-win.el (dynamic-library-alist): Add libjit-0.dll. --- diff --git a/configure.ac b/configure.ac index 8baeba72846..9b4bcf837f3 100644 --- a/configure.ac +++ b/configure.ac @@ -3534,6 +3534,10 @@ if test "${with_libjit}" != "no"; then EMACS_CHECK_MODULES([LIBJIT], [$LIBJIT_MODULES]) if test "${HAVE_LIBJIT}" = "yes"; then AC_DEFINE([HAVE_LIBJIT], 1, [Define to 1 if you have the libjit library (-ljit).]) + ### mingw32 doesn't use -ljit, since it loads the library dynamically. + if test "${opsys}" = "mingw32"; then + LIBJIT_LIBS= + fi fi fi diff --git a/lisp/term/w32-win.el b/lisp/term/w32-win.el index dc57160d04f..3d167b1a469 100644 --- a/lisp/term/w32-win.el +++ b/lisp/term/w32-win.el @@ -277,7 +277,8 @@ See the documentation of `create-fontset-from-fontset-spec' for the format.") '(libxml2 "libxml2-2.dll" "libxml2.dll") '(zlib "zlib1.dll" "libz-1.dll") '(lcms2 "liblcms2-2.dll") - '(json "libjansson-4.dll"))) + '(json "libjansson-4.dll") + '(libjit "libjit-0.dll"))) ;;; multi-tty support (defvar w32-initialized nil diff --git a/src/alloc.c b/src/alloc.c index ca70c0c145d..bc50c707fa6 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -3555,7 +3555,7 @@ usage: (make-byte-code ARGLIST BYTE-CODE CONSTANTS DEPTH &optional DOCSTRING INT p->contents[i] = Qnil; /* Not really a Lisp_Object. */ - p->contents[COMPILED_JIT_CODE] = (Lisp_Object) NULL; + p->contents[COMPILED_JIT_CODE] = XPL (NULL); if (STRINGP (p->contents[COMPILED_BYTECODE]) && STRING_MULTIBYTE (p->contents[COMPILED_BYTECODE])) diff --git a/src/emacs.c b/src/emacs.c index 25493c2d85b..ca76bb5fe4f 100644 --- a/src/emacs.c +++ b/src/emacs.c @@ -1464,6 +1464,12 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem xputenv ("LANG=C"); #endif +#ifdef HAVE_LIBJIT + /* This is here because init_buffer can already call Lisp. */ + if (initialized) + init_jit (); +#endif + /* Init buffer storage and default directory of main buffer. */ init_buffer (initialized); @@ -1667,10 +1673,6 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem #if defined WINDOWSNT || defined HAVE_NTGUI globals_of_w32select (); #endif - -#ifdef HAVE_LIBJIT - init_jit (); -#endif } init_charset (); diff --git a/src/eval.c b/src/eval.c index de87f9b9532..6066a40a99b 100644 --- a/src/eval.c +++ b/src/eval.c @@ -2825,9 +2825,9 @@ usage: (funcall FUNCTION &rest ARGUMENTS) */) if (SUBRP (fun)) val = funcall_subr (fun, &XSUBR (fun)->function, numargs, args + 1); else if (COMPILEDP (fun) - && XVECTOR (fun)->contents[COMPILED_JIT_CODE] != NULL) + && XLP (XVECTOR (fun)->contents[COMPILED_JIT_CODE]) != NULL) val = funcall_subr (fun, - (struct subr_function *) XVECTOR (fun)->contents[COMPILED_JIT_CODE], + (struct subr_function *) XLP (XVECTOR (fun)->contents[COMPILED_JIT_CODE]), numargs, args + 1); else if (COMPILEDP (fun) || MODULE_FUNCTIONP (fun)) val = funcall_lambda (fun, numargs, args + 1); @@ -3026,12 +3026,12 @@ funcall_lambda (Lisp_Object fun, ptrdiff_t nargs, { struct Lisp_Vector *vec = XVECTOR (fun); - if (vec->contents[COMPILED_JIT_CODE] == NULL) + if (XLP (vec->contents[COMPILED_JIT_CODE]) == NULL) emacs_jit_compile (fun); - if (vec->contents[COMPILED_JIT_CODE] != NULL) + if (XLP (vec->contents[COMPILED_JIT_CODE]) != NULL) return funcall_subr (fun, - (struct subr_function *) vec->contents[COMPILED_JIT_CODE], + (struct subr_function *) XLP (vec->contents[COMPILED_JIT_CODE]), nargs, arg_vector); } #endif /* HAVE_LIBJIT */ diff --git a/src/jit.c b/src/jit.c index ebca343dc32..c561bfefb20 100644 --- a/src/jit.c +++ b/src/jit.c @@ -33,6 +33,299 @@ along with GNU Emacs. If not, see . */ #include #include +#ifdef WINDOWSNT +# include +# include "w32common.h" +# include "w32.h" + +/* Define a variable that will be loaded from a DLL. */ +#define DEF_DLL_VAR(type, var) static type *pv_##var + +/* Load a variable from the DLL. */ +#define LOAD_DLL_VAR(lib, var) \ + do \ + { \ + pv_##var = (void *) GetProcAddress (lib, #var); \ + if (!pv_##var) \ + return false; \ + } \ + while (false) + + +DEF_DLL_FN (jit_value_t, jit_value_create_nint_constant, + (jit_function_t, jit_type_t, jit_nint)); +# if EMACS_INT_MAX > LONG_MAX +DEF_DLL_FN (jit_value_t, jit_value_create_long_constant, + (jit_function_t, jit_type_t, jit_long)); +# endif +DEF_DLL_FN (void, jit_insn_store, (jit_function_t, jit_value_t, jit_value_t)); +DEF_DLL_FN (jit_value_t, jit_insn_and, + (jit_function_t, jit_value_t, jit_value_t)); +# if !USE_LSB_TAG +DEF_DLL_FN (jit_value_t, jit_insn_ushr, + (jit_function_t, jit_value_t, jit_value_t)); +# endif +DEF_DLL_FN (jit_value_t, jit_insn_sub, + (jit_function_t, jit_value_t, jit_value_t)); +DEF_DLL_FN (jit_value_t, jit_insn_sshr, + (jit_function_t, jit_value_t, jit_value_t)); +DEF_DLL_FN (jit_value_t, jit_insn_eq, + (jit_function_t, jit_value_t, jit_value_t)); +DEF_DLL_FN (int, jit_insn_branch_if_not, + (jit_function_t, jit_value_t, jit_label_t *)); +DEF_DLL_FN (int, jit_insn_branch_if, + (jit_function_t, jit_value_t, jit_label_t *)); +DEF_DLL_FN (int, jit_insn_branch, (jit_function_t, jit_label_t *)); +DEF_DLL_FN (void, jit_insn_label, (jit_function_t, jit_label_t *)); +DEF_DLL_FN (jit_value_t, jit_insn_call_native, + (jit_function_t, const char *, void *, jit_type_t, jit_value_t *, + unsigned, int)); +DEF_DLL_FN (jit_value_t, jit_insn_shl, + (jit_function_t, jit_value_t, jit_value_t)); +DEF_DLL_FN (jit_value_t, jit_insn_add, + (jit_function_t, jit_value_t, jit_value_t)); +DEF_DLL_FN (jit_value_t, jit_insn_load_relative, + (jit_function_t, jit_value_t, jit_nint, jit_type_t)); +DEF_DLL_FN (jit_value_t, jit_insn_neg, (jit_function_t, jit_value_t)); +DEF_DLL_FN (int, jit_insn_store_relative, + (jit_function_t, jit_value_t, jit_nint, jit_value_t)); +DEF_DLL_FN (jit_function_t, jit_function_create, (jit_context_t, jit_type_t)); +DEF_DLL_FN (int, jit_function_set_meta, + (jit_function_t, int, void *, jit_meta_free_func, int)); +DEF_DLL_FN (jit_value_t, jit_value_create, (jit_function_t, jit_type_t)); +DEF_DLL_FN (jit_value_t, jit_value_get_param, (jit_function_t, unsigned)); +DEF_DLL_FN (jit_value_t, jit_insn_gt, + (jit_function_t, jit_value_t, jit_value_t)); +DEF_DLL_FN (jit_value_t, jit_insn_lt, + (jit_function_t, jit_value_t, jit_value_t)); +DEF_DLL_FN (jit_value_t, jit_insn_le, + (jit_function_t, jit_value_t, jit_value_t)); +DEF_DLL_FN (jit_value_t, jit_insn_load_elem_address, + (jit_function_t, jit_value_t, jit_value_t, jit_type_t)); +DEF_DLL_FN (int, jit_insn_return, (jit_function_t, jit_value_t)); +DEF_DLL_FN (jit_value_t, jit_insn_add_relative, + (jit_function_t, jit_value_t, jit_nint)); +DEF_DLL_FN (jit_label_t, jit_function_reserve_label, (jit_function_t)); +DEF_DLL_FN (int, jit_insn_jump_table, + (jit_function_t, jit_value_t, jit_label_t *, unsigned)); +DEF_DLL_FN (jit_value_t, jit_insn_alloca, (jit_function_t, jit_value_t)); +DEF_DLL_FN (int, jit_insn_move_blocks_to_start, + (jit_function_t, jit_label_t, jit_label_t)); +DEF_DLL_FN (int, jit_function_compile, (jit_function_t)); +DEF_DLL_FN (void, jit_function_abandon, (jit_function_t)); +DEF_DLL_FN (void *, jit_function_to_closure, (jit_function_t)); +DEF_DLL_FN (void, jit_context_build_start, (jit_context_t)); +DEF_DLL_FN (void, jit_context_build_end, (jit_context_t)); +DEF_DLL_FN (jit_function_t, jit_function_from_closure, (jit_context_t, void *)); +DEF_DLL_FN (void, jit_dump_function, (FILE *, jit_function_t, const char *)); +DEF_DLL_FN (void, jit_init, (void)); +DEF_DLL_FN (jit_context_t, jit_context_create, (void)); +DEF_DLL_FN (jit_type_t, jit_type_create_signature, + (jit_abi_t, jit_type_t, jit_type_t *, unsigned, int)); + +DEF_DLL_VAR (jit_type_t, jit_type_void_ptr); +DEF_DLL_VAR (jit_type_t, jit_type_uint); +DEF_DLL_VAR (jit_type_t, jit_type_nint); +DEF_DLL_VAR (jit_type_t, jit_type_sys_int); +DEF_DLL_VAR (jit_type_t, jit_type_int); +DEF_DLL_VAR (jit_type_t, jit_type_void); +# if EMACS_INT_MAX > LONG_MAX +DEF_DLL_VAR (jit_type_t, jit_type_sys_longlong); +DEF_DLL_VAR (jit_type_t, jit_type_long); +# endif +DEF_DLL_VAR (jit_type_t, jit_type_ulong); + +static bool +init_libjit_functions (void) +{ + HMODULE library = w32_delayed_load (Qlibjit); + + if (!library) + return false; + + LOAD_DLL_FN (library, jit_value_create_nint_constant); +# if EMACS_INT_MAX > LONG_MAX + LOAD_DLL_FN (library, jit_value_create_long_constant); +# endif + LOAD_DLL_FN (library, jit_insn_store); + LOAD_DLL_FN (library, jit_insn_and); +# if !USE_LSB_TAG + LOAD_DLL_FN (library, jit_insn_ushr); +# endif + LOAD_DLL_FN (library, jit_insn_sub); + LOAD_DLL_FN (library, jit_insn_sshr); + LOAD_DLL_FN (library, jit_insn_eq); + LOAD_DLL_FN (library, jit_insn_branch_if_not); + LOAD_DLL_FN (library, jit_insn_branch_if); + LOAD_DLL_FN (library, jit_insn_branch); + LOAD_DLL_FN (library, jit_insn_label); + LOAD_DLL_FN (library, jit_insn_call_native); + LOAD_DLL_FN (library, jit_insn_shl); + LOAD_DLL_FN (library, jit_insn_add); + LOAD_DLL_FN (library, jit_insn_load_relative); + LOAD_DLL_FN (library, jit_insn_neg); + LOAD_DLL_FN (library, jit_insn_store_relative); + LOAD_DLL_FN (library, jit_function_create); + LOAD_DLL_FN (library, jit_function_set_meta); + LOAD_DLL_FN (library, jit_value_create); + LOAD_DLL_FN (library, jit_value_get_param); + LOAD_DLL_FN (library, jit_insn_gt); + LOAD_DLL_FN (library, jit_insn_lt); + LOAD_DLL_FN (library, jit_insn_le); + LOAD_DLL_FN (library, jit_insn_load_elem_address); + LOAD_DLL_FN (library, jit_insn_return); + LOAD_DLL_FN (library, jit_insn_add_relative); + LOAD_DLL_FN (library, jit_function_reserve_label); + LOAD_DLL_FN (library, jit_insn_jump_table); + LOAD_DLL_FN (library, jit_insn_alloca); + LOAD_DLL_FN (library, jit_insn_move_blocks_to_start); + LOAD_DLL_FN (library, jit_function_compile); + LOAD_DLL_FN (library, jit_function_abandon); + LOAD_DLL_FN (library, jit_function_to_closure); + LOAD_DLL_FN (library, jit_context_build_start); + LOAD_DLL_FN (library, jit_context_build_end); + LOAD_DLL_FN (library, jit_function_from_closure); + LOAD_DLL_FN (library, jit_dump_function); + LOAD_DLL_FN (library, jit_init); + LOAD_DLL_FN (library, jit_context_create); + LOAD_DLL_FN (library, jit_type_create_signature); + + LOAD_DLL_VAR (library, jit_type_void_ptr); + LOAD_DLL_VAR (library, jit_type_uint); + LOAD_DLL_VAR (library, jit_type_nint); + LOAD_DLL_VAR (library, jit_type_sys_int); + LOAD_DLL_VAR (library, jit_type_int); + LOAD_DLL_VAR (library, jit_type_void); +# if EMACS_INT_MAX > LONG_MAX + LOAD_DLL_VAR (library, jit_type_sys_longlong); + LOAD_DLL_VAR (library, jit_type_long); +# endif + LOAD_DLL_VAR (library, jit_type_ulong); + + return true; +} + + +# undef jit_value_create_nint_constant +# if EMACS_INT_MAX > LONG_MAX +# undef jit_value_create_long_constant +# endif +# undef jit_insn_store +# undef jit_insn_and +# if !USE_LSB_TAG +# undef jit_insn_ushr +# endif +# undef jit_insn_sub +# undef jit_insn_sshr +# undef jit_insn_eq +# undef jit_insn_branch_if_not +# undef jit_insn_branch_if +# undef jit_insn_branch +# undef jit_insn_label +# undef jit_insn_call_native +# undef jit_insn_shl +# undef jit_insn_add +# undef jit_insn_load_relative +# undef jit_insn_neg +# undef jit_insn_store_relative +# undef jit_function_create +# undef jit_function_set_meta +# undef jit_value_create +# undef jit_value_get_param +# undef jit_insn_gt +# undef jit_insn_lt +# undef jit_insn_le +# undef jit_insn_load_elem_address +# undef jit_insn_return +# undef jit_insn_add_relative +# undef jit_function_reserve_label +# undef jit_insn_jump_table +# undef jit_insn_alloca +# undef jit_insn_move_blocks_to_start +# undef jit_function_compile +# undef jit_function_abandon +# undef jit_function_to_closure +# undef jit_context_build_start +# undef jit_context_build_end +# undef jit_function_from_closure +# undef jit_dump_function +# undef jit_init +# undef jit_context_create +# undef jit_type_create_signature + +# define jit_value_create_nint_constant fn_jit_value_create_nint_constant +# if EMACS_INT_MAX > LONG_MAX +# define jit_value_create_long_constant fn_jit_value_create_long_constant +# endif +# define jit_insn_store fn_jit_insn_store +# define jit_insn_and fn_jit_insn_and +# if !USE_LSB_TAG +# define jit_insn_ushr fn_jit_insn_ushr +# endif +# define jit_insn_sub fn_jit_insn_sub +# define jit_insn_sshr fn_jit_insn_sshr +# define jit_insn_eq fn_jit_insn_eq +# define jit_insn_branch_if_not fn_jit_insn_branch_if_not +# define jit_insn_branch_if fn_jit_insn_branch_if +# define jit_insn_branch fn_jit_insn_branch +# define jit_insn_label fn_jit_insn_label +# define jit_insn_call_native fn_jit_insn_call_native +# define jit_insn_shl fn_jit_insn_shl +# define jit_insn_add fn_jit_insn_add +# define jit_insn_load_relative fn_jit_insn_load_relative +# define jit_insn_neg fn_jit_insn_neg +# define jit_insn_store_relative fn_jit_insn_store_relative +# define jit_function_create fn_jit_function_create +# define jit_function_set_meta fn_jit_function_set_meta +# define jit_value_create fn_jit_value_create +# define jit_value_get_param fn_jit_value_get_param +# define jit_insn_gt fn_jit_insn_gt +# define jit_insn_lt fn_jit_insn_lt +# define jit_insn_le fn_jit_insn_le +# define jit_insn_load_elem_address fn_jit_insn_load_elem_address +# define jit_insn_return fn_jit_insn_return +# define jit_insn_add_relative fn_jit_insn_add_relative +# define jit_function_reserve_label fn_jit_function_reserve_label +# define jit_insn_jump_table fn_jit_insn_jump_table +# define jit_insn_alloca fn_jit_insn_alloca +# define jit_insn_move_blocks_to_start fn_jit_insn_move_blocks_to_start +# define jit_function_compile fn_jit_function_compile +# define jit_function_abandon fn_jit_function_abandon +# define jit_function_to_closure fn_jit_function_to_closure +# define jit_context_build_start fn_jit_context_build_start +# define jit_context_build_end fn_jit_context_build_end +# define jit_function_from_closure fn_jit_function_from_closure +# define jit_dump_function fn_jit_dump_function +# define jit_init fn_jit_init +# define jit_context_create fn_jit_context_create +# define jit_type_create_signature fn_jit_type_create_signature + +# undef jit_type_void_ptr +# undef jit_type_uint +# undef jit_type_nint +# undef jit_type_sys_int +# undef jit_type_int +# undef jit_type_void +# if EMACS_INT_MAX > LONG_MAX +# undef jit_type_sys_longlong +# undef jit_type_long +# endif +# undef jit_type_ulong + +# define jit_type_void_ptr *pv_jit_type_void_ptr +# define jit_type_uint *pv_jit_type_uint +# define jit_type_nint *pv_jit_type_nint +# define jit_type_sys_int *pv_jit_type_sys_int +# define jit_type_int *pv_jit_type_int +# define jit_type_void *pv_jit_type_void +# if EMACS_INT_MAX > LONG_MAX +# define jit_type_sys_longlong *pv_jit_type_sys_longlong +# define jit_type_long *pv_jit_type_long +# endif +# define jit_type_ulong *pv_jit_type_ulong + +#endif /* WINDOWSNT */ + static bool emacs_jit_initialized; jit_context_t emacs_jit_context; @@ -52,6 +345,7 @@ static jit_type_t specbind_signature; static jit_type_t record_unwind_protect_excursion_signature; static jit_type_t record_unwind_protect_signature; static jit_type_t void_void_signature; +static jit_type_t lisp_void_signature; static jit_type_t push_handler_signature; static jit_type_t setjmp_signature; @@ -61,8 +355,13 @@ static jit_type_t ptrdiff_t_type; /* Make a pointer constant. */ +#if EMACS_INT_MAX == INT_MAX #define CONSTANT(FUNC, VAL) \ - jit_value_create_long_constant (FUNC, jit_type_void_ptr, (jit_long) (uintptr_t) (VAL)) + jit_value_create_nint_constant (FUNC, jit_type_nint, XLI (VAL)) +#else +#define CONSTANT(FUNC, VAL) \ + jit_value_create_long_constant (FUNC, jit_type_long, (jit_long) XLI (VAL)) +#endif /* Fetch the next byte from the bytecode stream. */ @@ -110,7 +409,11 @@ untag (jit_function_t func, jit_value_t val, EMACS_UINT utype) utype = utype << (USE_LSB_TAG ? 0 : VALBITS); +#if EMACS_INT_MAX <= LONG_MAX tem = jit_value_create_nint_constant (func, jit_type_void_ptr, utype); +#else + tem = jit_value_create_long_constant (func, jit_type_ulong, (jit_ulong)utype); +#endif return jit_insn_sub (func, val, tem); } @@ -314,9 +617,15 @@ compile_make_natnum (jit_function_t func, jit_value_t untagged_int) = jit_value_create_nint_constant (func, jit_type_void_ptr, Lisp_Int0); return jit_insn_add (func, val, tag); #else /* USE_LSB_TAG */ +# if EMACS_INT_MAX <= LONG_MAX jit_value_t tag = jit_value_create_nint_constant (func, jit_type_void_ptr, ((EMACS_INT) Lisp_Int0) << VALBITS); +# else + jit_value_t tag + = jit_value_create_long_constant (func, jit_type_ulong, + ((EMACS_INT) Lisp_Int0) << VALBITS); +# endif return jit_insn_add (func, untagged_int, tag); #endif /* not USE_LSB_TAG */ } @@ -332,11 +641,19 @@ compile_make_number (jit_function_t func, jit_value_t untagged_int) = jit_value_create_nint_constant (func, jit_type_void_ptr, Lisp_Int0); return jit_insn_add (func, val, tag); #else /* USE_LSB_TAG */ +# if EMACS_INT_MAX <= LONG_MAX jit_value_t mask = jit_value_create_nint_constant (func, jit_type_void_ptr, INTMASK); jit_value_t tag = jit_value_create_nint_constant (func, jit_type_void_ptr, ((EMACS_INT) Lisp_Int0) << VALBITS); +# else + jit_value_t mask + = jit_value_create_long_constant (func, jit_type_ulong, INTMASK); + jit_value_t tag + = jit_value_create_long_constant (func, jit_type_ulong, + ((EMACS_INT) Lisp_Int0) << VALBITS); +# endif jit_value_t val = jit_insn_and (func, untagged_int, mask); return jit_insn_add (func, val, tag); #endif /* not USE_LSB_TAG */ @@ -345,7 +662,9 @@ compile_make_number (jit_function_t func, jit_value_t untagged_int) static jit_value_t compile_current_thread (jit_function_t func) { - jit_value_t thread_ptr = CONSTANT (func, ¤t_thread); + jit_value_t thread_ptr = + jit_value_create_nint_constant (func, jit_type_void_ptr, + (jit_nint) ¤t_thread); return jit_insn_load_relative (func, thread_ptr, 0, jit_type_void_ptr); } @@ -487,8 +806,13 @@ unary_intmath (jit_function_t func, jit_value_t val, enum math_op op, { case SUB1: /* Don't allow (1- most-negative-fixnum). */ +#if EMACS_INT_MAX <= LONG_MAX tem = jit_value_create_nint_constant (func, jit_type_sys_int, MOST_NEGATIVE_FIXNUM); +#else + tem = jit_value_create_long_constant (func, jit_type_sys_longlong, + MOST_NEGATIVE_FIXNUM); +#endif compare = jit_insn_eq (func, result, tem); jit_insn_branch_if (func, compare, ¬_an_int); @@ -498,8 +822,13 @@ unary_intmath (jit_function_t func, jit_value_t val, enum math_op op, case ADD1: /* Don't allow (1+ most-positive-fixnum). */ +#if EMACS_INT_MAX <= LONG_MAX tem = jit_value_create_nint_constant (func, jit_type_sys_int, MOST_POSITIVE_FIXNUM); +#else + tem = jit_value_create_long_constant (func, jit_type_sys_longlong, + MOST_POSITIVE_FIXNUM); +#endif compare = jit_insn_eq (func, result, tem); jit_insn_branch_if (func, compare, ¬_an_int); @@ -509,8 +838,13 @@ unary_intmath (jit_function_t func, jit_value_t val, enum math_op op, case NEGATE: /* Don't allow (- most-negative-fixnum). */ +#if EMACS_INT_MAX <= LONG_MAX tem = jit_value_create_nint_constant (func, jit_type_sys_int, MOST_NEGATIVE_FIXNUM); +#else + tem = jit_value_create_long_constant (func, jit_type_sys_longlong, + MOST_NEGATIVE_FIXNUM); +#endif compare = jit_insn_eq (func, result, tem); jit_insn_branch_if (func, compare, ¬_an_int); @@ -794,7 +1128,7 @@ compile (ptrdiff_t bytestr_length, unsigned char *bytestr_data, ptrdiff_t nonrest = at >> 8; mandatory_val - = jit_value_create_long_constant (func, ptrdiff_t_type, mandatory); + = jit_value_create_nint_constant (func, ptrdiff_t_type, mandatory); nonrest_val = jit_value_create_nint_constant (func, ptrdiff_t_type, nonrest); @@ -1268,10 +1602,11 @@ compile (ptrdiff_t bytestr_length, unsigned char *bytestr_data, { jit_value_t vals[2]; - vals[0] = CONSTANT (func, save_restriction_restore); + vals[0] = jit_value_create_nint_constant (func, jit_type_void_ptr, + (jit_nint) save_restriction_restore); vals[1] = jit_insn_call_native (func, "save_restriction_save", (void *) save_restriction_save, - void_void_signature, + lisp_void_signature, NULL, 0, JIT_CALL_NOTHROW); jit_insn_call_native (func, "record_unwind_protect", (void *) record_unwind_protect, @@ -1284,7 +1619,8 @@ compile (ptrdiff_t bytestr_length, unsigned char *bytestr_data, { jit_value_t args[3]; - args[1] = CONSTANT (func, eval_sub); + args[1] = jit_value_create_nint_constant (func, jit_type_void_ptr, + (jit_nint) eval_sub); args[2] = POP; args[0] = POP; @@ -1360,7 +1696,8 @@ compile (ptrdiff_t bytestr_length, unsigned char *bytestr_data, { jit_value_t args[2]; - args[0] = CONSTANT (func, bcall0); + args[0] = jit_value_create_nint_constant (func, jit_type_void_ptr, + (jit_nint) bcall0); args[1] = POP; jit_insn_call_native (func, "record_unwind_protect", (void *) record_unwind_protect, @@ -2187,7 +2524,7 @@ compile (ptrdiff_t bytestr_length, unsigned char *bytestr_data, void emacs_jit_compile (Lisp_Object func) { - if (!emacs_jit_initialized) + if (!emacs_jit_initialized || jit_disable) return; Lisp_Object bytestr = AREF (func, COMPILED_BYTECODE); @@ -2215,7 +2552,7 @@ emacs_jit_compile (Lisp_Object func) vectorp, ASIZE (vector), AREF (func, COMPILED_ARGLIST)); - XVECTOR (func)->contents[COMPILED_JIT_CODE] = (Lisp_Object) subr; + XVECTOR (func)->contents[COMPILED_JIT_CODE] = XPL (subr); jit_context_build_end (emacs_jit_context); } @@ -2231,7 +2568,7 @@ DEFUN ("jit-compile", Fjit_compile, Sjit_compile, error ("Not a byte-compiled function"); vec = XVECTOR (func); - if (vec->contents[COMPILED_JIT_CODE] == NULL) + if (XLP (vec->contents[COMPILED_JIT_CODE]) == NULL) emacs_jit_compile (func); return Qnil; @@ -2253,7 +2590,7 @@ DEFUN ("jit-disassemble-to-string", Fjit_disassemble_to_string, if (!COMPILEDP (func)) error ("Not a byte-compiled function"); vec = XVECTOR (func); - sfunc = (struct subr_function *) vec->contents[COMPILED_JIT_CODE]; + sfunc = (struct subr_function *) XLP (vec->contents[COMPILED_JIT_CODE]); if (sfunc == NULL) error ("Not JIT-compiled"); @@ -2304,6 +2641,10 @@ syms_of_jit (void) defsubr (&Sjit_compile); defsubr (&Sjit_disassemble_to_string); DEFSYM (Qinteractive_p, "interactive-p"); + + DEFVAR_BOOL ("jit-disable", jit_disable, + doc: /* Non-nil means disable JIT compilation even if supported. */); + jit_disable = 0; } void @@ -2311,9 +2652,23 @@ init_jit (void) { #define LEN SUBR_MAX_ARGS - jit_type_t params[LEN]; + jit_type_t params[LEN], lisp_object_type; int i; +#ifdef WINDOWSNT + if (!init_libjit_functions ()) + return; + Vlibrary_cache = Fcons (Fcons (Qlibjit, Qt), Vlibrary_cache); +#endif + +#if EMACS_INT_MAX <= LONG_MAX + /* 32-bit builds without wide ints, 64-bit builds on Posix hosts. */ + lisp_object_type = jit_type_void_ptr; +#else + /* 64-bit builds on MS-Windows, 32-bit builds with wide ints. */ + lisp_object_type = jit_type_sys_longlong; +#endif + jit_init (); emacs_jit_context = jit_context_create (); @@ -2326,51 +2681,56 @@ init_jit (void) } for (i = 0; i < LEN; ++i) - params[i] = jit_type_void_ptr; + params[i] = lisp_object_type; for (i = 0; i < SUBR_MAX_ARGS; ++i) subr_signature[i] = jit_type_create_signature (jit_abi_cdecl, - jit_type_void_ptr, + lisp_object_type, params, i, 1); nullary_signature = jit_type_create_signature (jit_abi_cdecl, - jit_type_void_ptr, params, 0, + lisp_object_type, params, 0, 1); unary_signature = jit_type_create_signature (jit_abi_cdecl, - jit_type_void_ptr, params, 1, + lisp_object_type, params, 1, 1); binary_signature = jit_type_create_signature (jit_abi_cdecl, - jit_type_void_ptr, params, 2, + lisp_object_type, params, 2, 1); ternary_signature = jit_type_create_signature (jit_abi_cdecl, - jit_type_void_ptr, params, 3, + lisp_object_type, params, 3, 1); specbind_signature = jit_type_create_signature (jit_abi_cdecl, jit_type_void, params, 2, 1); record_unwind_protect_excursion_signature - = jit_type_create_signature (jit_abi_cdecl, jit_type_void_ptr, NULL, 0, 1); - record_unwind_protect_signature - = jit_type_create_signature (jit_abi_cdecl, jit_type_void, params, 2, 1); + = jit_type_create_signature (jit_abi_cdecl, jit_type_void, NULL, 0, 1); + lisp_void_signature = jit_type_create_signature (jit_abi_cdecl, + lisp_object_type, NULL, 0, 1); void_void_signature = jit_type_create_signature (jit_abi_cdecl, jit_type_void, NULL, 0, 1); temp_output_buffer_show_signature - = jit_type_create_signature (jit_abi_cdecl, jit_type_void_ptr, - params, 1, 1); + = jit_type_create_signature (jit_abi_cdecl, jit_type_void, params, 1, 1); + params[0] = jit_type_void_ptr; + record_unwind_protect_signature + = jit_type_create_signature (jit_abi_cdecl, jit_type_void, params, 2, 1); + + params[0] = lisp_object_type; params[2] = jit_type_sys_int; arithcompare_signature = jit_type_create_signature (jit_abi_cdecl, - jit_type_void_ptr, + lisp_object_type, params, 3, 1); params[0] = jit_type_sys_int; unbind_n_signature = jit_type_create_signature (jit_abi_cdecl, - jit_type_void_ptr, params, 1, + lisp_object_type, params, 1, 1); params[0] = ptrdiff_t_type; + params[1] = jit_type_void_ptr; callN_signature = jit_type_create_signature (jit_abi_cdecl, - jit_type_void_ptr, params, 2, + lisp_object_type, params, 2, 1); compiled_signature = callN_signature; @@ -2380,9 +2740,9 @@ init_jit (void) wrong_number_of_arguments_signature = jit_type_create_signature (jit_abi_cdecl, jit_type_void, params, 3, 1); - params[0] = jit_type_void_ptr; - params[1] = jit_type_void_ptr; - params[2] = jit_type_void_ptr; + params[0] = lisp_object_type; + params[1] = lisp_object_type; + params[2] = lisp_object_type; params[3] = jit_type_sys_int; set_internal_signature = jit_type_create_signature (jit_abi_cdecl, jit_type_void, params, 4, 1); diff --git a/src/lisp.h b/src/lisp.h index b44d6325ba8..67fa18eaa3c 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -4631,8 +4631,13 @@ safe_free_unbind_to (ptrdiff_t count, ptrdiff_t sa_count, Lisp_Object val) Build with CPPFLAGS='-DUSE_STACK_LISP_OBJECTS=0' to disable it. */ #if (!defined USE_STACK_LISP_OBJECTS \ - && defined __GNUC__ && !defined __clang__ && ! GNUC_PREREQ (4, 3, 2)) - /* Work around GCC bugs 36584 and 35271, which were fixed in GCC 4.3.2. */ + && defined __GNUC__ && !defined __clang__ \ + && (! GNUC_PREREQ (4, 3, 2) \ + || (defined __MINGW32__ && INTPTR_MAX <= INT_MAX && HAVE_LIBJIT))) + /* Work around GCC bugs 36584 and 35271, which were fixed in GCC 4.3.2. + Using libjit in 32-bit MS-Windows builds cannot ensure proper stack + alignment when JIT code calls back into Emacs, so disable stack-based + objects. */ # define USE_STACK_LISP_OBJECTS false #endif #ifndef USE_STACK_LISP_OBJECTS diff --git a/src/w32fns.c b/src/w32fns.c index 8d5293c1af0..4ac9f109994 100644 --- a/src/w32fns.c +++ b/src/w32fns.c @@ -10258,6 +10258,7 @@ syms_of_w32fns (void) DEFSYM (Qzlib, "zlib"); DEFSYM (Qlcms2, "lcms2"); DEFSYM (Qjson, "json"); + DEFSYM (Qlibjit, "libjit"); Fput (Qundefined_color, Qerror_conditions, listn (CONSTYPE_PURE, 2, Qundefined_color, Qerror));