Compare commits

...

10 commits

Author SHA1 Message Date
Eli Zaretskii
a25a9896d5 Minor type and signature fixes in jit.c
* src/jit.c (get_type) [!USE_LSB_TAG]: Use jit_type_void_ptr
for 'shift'.
(compile_wrong_type_argument): Use the correct signature for
wrong_type_argument native calls.
2018-09-09 19:10:36 +03:00
Eli Zaretskii
9efa35eea0 Fix types of Lisp objects in values and function calls
* src/jit.c (car_or_cdr, compile): Use lisp_object_type for
Lisp objects.
(init_jit): Define internal_catch_signature.
(compile): Use internal_catch_signature for 'internal_catch',
as ternary_signature doesn't fit.
2018-08-29 19:58:20 +03:00
Ken Brown
f6c33b4518 Fix 32-bit Cygwin builds with libjit
* src/lisp.h (USE_STACK_LISP_OBJECTS): Define to false for
32-bit Cygwin builds with libjit.
2018-08-27 10:03:54 -04:00
Eli Zaretskii
39c6bef858 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) <libjit>: 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.
2018-08-23 19:40:19 +03:00
Eli Zaretskii
7fbcc5b533 Improve jit-disassemble-to-string
* src/jit.c (Fjit_disassemble_to_string) [!HAVE_OPEN_MEMSTREAM]:
Provide working code for systems that don't have 'open_memstream'.
2018-08-18 13:47:27 +03:00
Eli Zaretskii
9c0ed03e52 Fix 32-bit compilation on MS-Windows
* src/jit.c (CONSTANT): Avoid compilation warning on 32-bit
systems about casting a pointer to an integer of a different
size.
(compile) [HAVE__SETJMP]: Use _setjmp instead of setjmp, when
the latter is a macro.  Fixes a compilation error on system
that use _setjmp.
(Fjit_disassemble_to_string): Rearrange declaration to avoid
compilation warnings on systems that don't have open_memstream.
2018-08-18 12:18:54 +03:00
Tom Tromey
a166e8fabd JIT compiler
* lisp/emacs-lisp/jit-support.el: New file.
* src/alloc.c (make_byte_code): Remove.
(Fmake_byte_code): Rewrite.
* src/data.c (Fsubr_arity, notify_variable_watchers): Update.
* src/emacs.c (main): Call syms_of_jit, init_jit.
* src/eval.c (eval_sub, Fapply, FUNCTIONP, Ffuncall, funcall_subr)
(funcall_lambda): Update.
* src/jit.c: New file.
* src/lisp.h (struct subr_function): New struct, extracted from
Lisp_Subr.
(SUBR_MAX_ARGS): New define.
(struct Lisp_Subr): Use struct subr_function.
(COMPILED_JIT_CODE): New constant.
(DEFUN): Update.
(make_byte_code): Don't declare.
(funcall_subr): Add error_obj argument.
(syms_of_jit, init_jit, emacs_jit_compile): Declare.
* src/lread.c (read1): Use Fmake_byte_code.
* test/src/jit-tests.el: New file.
2018-08-13 18:11:39 -06:00
Tom Tromey
62d9c0cf9c Remove obsolete comment
* lisp/emacs-lisp/bytecomp.el (byte-compile-out-tag): Remove comment.
2018-08-13 18:11:39 -06:00
Tom Tromey
1bdba1a714 Add configury for JIT
* configure.ac: Add --with-libjit.  Check for open_memstream.
* src/Makefile.in (LIBJIT, LIBJIT_CFLAGS): New variables.
(EMACS_CFLAGS): Use LIBJIT_CFLAGS.
(base_obj): Add jit.o.
(LIBES): Use LIBJIT.
2018-08-13 18:11:39 -06:00
Tom Tromey
864fd8f133 Create bytecode.h
* src/bytecode.h: New file.
* src/bytecode.c: Move bytecode definitions to bytecode.h.
2018-08-13 18:11:39 -06:00
16 changed files with 3493 additions and 287 deletions

View file

@ -384,6 +384,7 @@ OPTION_DEFAULT_ON([gnutls],[don't use -lgnutls for SSL/TLS support])
OPTION_DEFAULT_ON([zlib],[don't compile with zlib decompression support])
OPTION_DEFAULT_OFF([modules],[compile with dynamic modules support])
OPTION_DEFAULT_ON([threads],[don't compile with elisp threading support])
OPTION_DEFAULT_ON([libjit],[compile with emacs lisp jit support])
AC_ARG_WITH([file-notification],[AS_HELP_STRING([--with-file-notification=LIB],
[use a file notification library (LIB one of: yes, inotify, kqueue, gfile, w32, no)])],
@ -3525,6 +3526,21 @@ if test "${HAVE_ZLIB}" = "yes"; then
fi
AC_SUBST(LIBZ)
HAVE_LIBJIT=no
LIBJIT=
if test "${with_libjit}" != "no"; then
LIBJIT_REQUIRED=0.0.1
LIBJIT_MODULES="libjit >= $LIBJIT_REQUIRED"
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
### Dynamic modules support
LIBMODULES=
HAVE_MODULES=no
@ -4013,7 +4029,8 @@ pthread_sigmask strsignal setitimer \
sendto recvfrom getsockname getifaddrs freeifaddrs \
gai_strerror sync \
getpwent endpwent getgrent endgrent \
cfmakeraw cfsetspeed __executable_start log2 prctl)
cfmakeraw cfsetspeed __executable_start log2 prctl \
open_memstream)
LIBS=$OLD_LIBS
dnl No need to check for posix_memalign if aligned_alloc works.
@ -5483,6 +5500,7 @@ AS_ECHO([" Does Emacs use -lXaw3d? ${HAVE_XAW3D
Does Emacs use toolkit scroll bars? ${USE_TOOLKIT_SCROLL_BARS}
Does Emacs support Xwidgets (requires gtk3)? ${HAVE_XWIDGETS}
Does Emacs have threading support in lisp? ${threads_enabled}
Does Emacs have lisp JIT support? ${HAVE_LIBJIT}
"])
if test -n "${EMACSDATA}"; then

View file

@ -4819,7 +4819,6 @@ binding slots have been popped."
(setq byte-compile-output (cons tag byte-compile-output))
(if (cdr (cdr tag))
(progn
;; ## remove this someday
(and byte-compile-depth
(not (= (cdr (cdr tag)) byte-compile-depth))
(error "Compiler bug: depth conflict at tag %d" (car (cdr tag))))

View file

@ -0,0 +1,37 @@
;;; jit-support.el --- helper functions for JIT compilation -*- lexical-binding: t -*-
;; Copyright (C) 2018 Free Software Foundation, Inc.
;; Keywords: lisp
;; Package: emacs
;; This file is part of GNU Emacs.
;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;;###autoload
(defun jit-disassemble (func)
(interactive "aDisassemble function: ")
(when (symbolp func)
(setf func (symbol-function func)))
(let ((str (jit-disassemble-to-string func)))
(with-current-buffer (get-buffer-create "*JIT*")
(erase-buffer)
(save-excursion
(insert str))
(pop-to-buffer (current-buffer)))))
(provide 'jit-support)
;;; jit-support.el ends here

View file

@ -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

View file

@ -239,6 +239,9 @@ LCMS2_CFLAGS = @LCMS2_CFLAGS@
LIBZ = @LIBZ@
LIBJIT = @LIBJIT_LIBS@
LIBJIT_CFLAGS = @LIBJIT_CFLAGS@
## system-specific libs for dynamic modules, else empty
LIBMODULES = @LIBMODULES@
## dynlib.o emacs-module.o if modules enabled, else empty
@ -369,7 +372,7 @@ EMACS_CFLAGS=-Demacs $(MYCPPFLAGS) -I. -I$(srcdir) \
$(GNUSTEP_CFLAGS) $(CFLAGS_SOUND) $(RSVG_CFLAGS) $(IMAGEMAGICK_CFLAGS) \
$(PNG_CFLAGS) $(LIBXML2_CFLAGS) $(DBUS_CFLAGS) \
$(XRANDR_CFLAGS) $(XINERAMA_CFLAGS) $(XFIXES_CFLAGS) $(XDBE_CFLAGS) \
$(WEBKIT_CFLAGS) $(LCMS2_CFLAGS) \
$(WEBKIT_CFLAGS) $(LCMS2_CFLAGS) $(LIBJIT_CFLAGS) \
$(SETTINGS_CFLAGS) $(FREETYPE_CFLAGS) $(FONTCONFIG_CFLAGS) \
$(LIBOTF_CFLAGS) $(M17N_FLT_CFLAGS) $(DEPFLAGS) \
$(LIBSYSTEMD_CFLAGS) $(JSON_CFLAGS) \
@ -397,7 +400,7 @@ base_obj = dispnew.o frame.o scroll.o xdisp.o menu.o $(XMENU_OBJ) window.o \
cmds.o casetab.o casefiddle.o indent.o search.o regex-emacs.o undo.o \
alloc.o data.o doc.o editfns.o callint.o \
eval.o floatfns.o fns.o font.o print.o lread.o $(MODULES_OBJ) \
syntax.o $(UNEXEC_OBJ) bytecode.o \
syntax.o $(UNEXEC_OBJ) bytecode.o jit.o \
process.o gnutls.o callproc.o \
region-cache.o sound.o atimer.o \
doprnt.o intervals.o textprop.o composite.o xml.o lcms.o $(NOTIFY_OBJ) \
@ -504,7 +507,7 @@ LIBES = $(LIBS) $(W32_LIBS) $(LIBS_GNUSTEP) $(LIBX_BASE) $(LIBIMAGE) \
$(FREETYPE_LIBS) $(FONTCONFIG_LIBS) $(LIBOTF_LIBS) $(M17N_FLT_LIBS) \
$(LIBGNUTLS_LIBS) $(LIB_PTHREAD) $(GETADDRINFO_A_LIBS) $(LCMS2_LIBS) \
$(NOTIFY_LIBS) $(LIB_MATH) $(LIBZ) $(LIBMODULES) $(LIBSYSTEMD_LIBS) \
$(JSON_LIBS) $(GMP_LIB)
$(JSON_LIBS) $(GMP_LIB) $(LIBJIT)
## FORCE it so that admin/unidata can decide whether these files
## are up-to-date. Although since charprop depends on bootstrap-emacs,

View file

@ -3515,23 +3515,6 @@ usage: (vector &rest OBJECTS) */)
return val;
}
void
make_byte_code (struct Lisp_Vector *v)
{
/* Don't allow the global zero_vector to become a byte code object. */
eassert (0 < v->header.size);
if (v->header.size > 1 && STRINGP (v->contents[1])
&& STRING_MULTIBYTE (v->contents[1]))
/* BYTECODE-STRING must have been produced by Emacs 20.2 or the
earlier because they produced a raw 8-bit string for byte-code
and now such a byte-code string is loaded as multibyte while
raw 8-bit characters converted to multibyte form. Thus, now we
must convert them back to the original unibyte form. */
v->contents[1] = Fstring_as_unibyte (v->contents[1]);
XSETPVECTYPE (v, PVEC_COMPILED);
}
DEFUN ("make-byte-code", Fmake_byte_code, Smake_byte_code, 4, MANY, 0,
doc: /* Create a byte-code object with specified arguments as elements.
The arguments should be the ARGLIST, bytecode-string BYTE-CODE, constant
@ -3550,8 +3533,14 @@ stack before executing the byte-code.
usage: (make-byte-code ARGLIST BYTE-CODE CONSTANTS DEPTH &optional DOCSTRING INTERACTIVE-SPEC &rest ELEMENTS) */)
(ptrdiff_t nargs, Lisp_Object *args)
{
Lisp_Object val = make_uninit_vector (nargs);
struct Lisp_Vector *p = XVECTOR (val);
Lisp_Object val;
struct Lisp_Vector *p = allocate_pseudovector (COMPILED_JIT_CODE + 1,
COMPILED_JIT_CODE,
COMPILED_JIT_CODE + 1,
PVEC_COMPILED);
/* Don't allow the global zero_vector to become a byte code object. */
eassert (0 < nargs);
/* We used to purecopy everything here, if purify-flag was set. This worked
OK for Emacs-23, but with Emacs-24's lexical binding code, it can be
@ -3562,7 +3551,21 @@ usage: (make-byte-code ARGLIST BYTE-CODE CONSTANTS DEPTH &optional DOCSTRING INT
to be setcar'd). */
memcpy (p->contents, args, nargs * sizeof *args);
make_byte_code (p);
for (int i = nargs; i < COMPILED_JIT_CODE; ++i)
p->contents[i] = Qnil;
/* Not really a Lisp_Object. */
p->contents[COMPILED_JIT_CODE] = XPL (NULL);
if (STRINGP (p->contents[COMPILED_BYTECODE])
&& STRING_MULTIBYTE (p->contents[COMPILED_BYTECODE]))
/* BYTECODE-STRING must have been produced by Emacs 20.2 or the
earlier because they produced a raw 8-bit string for byte-code
and now such a byte-code string is loaded as multibyte while
raw 8-bit characters converted to multibyte form. Thus, now we
must convert them back to the original unibyte form. */
p->contents[COMPILED_BYTECODE] = Fstring_as_unibyte (p->contents[COMPILED_BYTECODE]);
XSETCOMPILED (val, p);
return val;
}

View file

@ -27,6 +27,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "ptr-bounds.h"
#include "syntax.h"
#include "window.h"
#include "bytecode.h"
/* Work around GCC bug 54561. */
#if GNUC_PREREQ (4, 3, 0)
@ -77,212 +78,6 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#endif /* BYTE_CODE_METER */
/* Byte codes: */
#define BYTE_CODES \
DEFINE (Bstack_ref, 0) /* Actually, Bstack_ref+0 is not implemented: use dup. */ \
DEFINE (Bstack_ref1, 1) \
DEFINE (Bstack_ref2, 2) \
DEFINE (Bstack_ref3, 3) \
DEFINE (Bstack_ref4, 4) \
DEFINE (Bstack_ref5, 5) \
DEFINE (Bstack_ref6, 6) \
DEFINE (Bstack_ref7, 7) \
DEFINE (Bvarref, 010) \
DEFINE (Bvarref1, 011) \
DEFINE (Bvarref2, 012) \
DEFINE (Bvarref3, 013) \
DEFINE (Bvarref4, 014) \
DEFINE (Bvarref5, 015) \
DEFINE (Bvarref6, 016) \
DEFINE (Bvarref7, 017) \
DEFINE (Bvarset, 020) \
DEFINE (Bvarset1, 021) \
DEFINE (Bvarset2, 022) \
DEFINE (Bvarset3, 023) \
DEFINE (Bvarset4, 024) \
DEFINE (Bvarset5, 025) \
DEFINE (Bvarset6, 026) \
DEFINE (Bvarset7, 027) \
DEFINE (Bvarbind, 030) \
DEFINE (Bvarbind1, 031) \
DEFINE (Bvarbind2, 032) \
DEFINE (Bvarbind3, 033) \
DEFINE (Bvarbind4, 034) \
DEFINE (Bvarbind5, 035) \
DEFINE (Bvarbind6, 036) \
DEFINE (Bvarbind7, 037) \
DEFINE (Bcall, 040) \
DEFINE (Bcall1, 041) \
DEFINE (Bcall2, 042) \
DEFINE (Bcall3, 043) \
DEFINE (Bcall4, 044) \
DEFINE (Bcall5, 045) \
DEFINE (Bcall6, 046) \
DEFINE (Bcall7, 047) \
DEFINE (Bunbind, 050) \
DEFINE (Bunbind1, 051) \
DEFINE (Bunbind2, 052) \
DEFINE (Bunbind3, 053) \
DEFINE (Bunbind4, 054) \
DEFINE (Bunbind5, 055) \
DEFINE (Bunbind6, 056) \
DEFINE (Bunbind7, 057) \
\
DEFINE (Bpophandler, 060) \
DEFINE (Bpushconditioncase, 061) \
DEFINE (Bpushcatch, 062) \
\
DEFINE (Bnth, 070) \
DEFINE (Bsymbolp, 071) \
DEFINE (Bconsp, 072) \
DEFINE (Bstringp, 073) \
DEFINE (Blistp, 074) \
DEFINE (Beq, 075) \
DEFINE (Bmemq, 076) \
DEFINE (Bnot, 077) \
DEFINE (Bcar, 0100) \
DEFINE (Bcdr, 0101) \
DEFINE (Bcons, 0102) \
DEFINE (Blist1, 0103) \
DEFINE (Blist2, 0104) \
DEFINE (Blist3, 0105) \
DEFINE (Blist4, 0106) \
DEFINE (Blength, 0107) \
DEFINE (Baref, 0110) \
DEFINE (Baset, 0111) \
DEFINE (Bsymbol_value, 0112) \
DEFINE (Bsymbol_function, 0113) \
DEFINE (Bset, 0114) \
DEFINE (Bfset, 0115) \
DEFINE (Bget, 0116) \
DEFINE (Bsubstring, 0117) \
DEFINE (Bconcat2, 0120) \
DEFINE (Bconcat3, 0121) \
DEFINE (Bconcat4, 0122) \
DEFINE (Bsub1, 0123) \
DEFINE (Badd1, 0124) \
DEFINE (Beqlsign, 0125) \
DEFINE (Bgtr, 0126) \
DEFINE (Blss, 0127) \
DEFINE (Bleq, 0130) \
DEFINE (Bgeq, 0131) \
DEFINE (Bdiff, 0132) \
DEFINE (Bnegate, 0133) \
DEFINE (Bplus, 0134) \
DEFINE (Bmax, 0135) \
DEFINE (Bmin, 0136) \
DEFINE (Bmult, 0137) \
\
DEFINE (Bpoint, 0140) \
/* Was Bmark in v17. */ \
DEFINE (Bsave_current_buffer, 0141) /* Obsolete. */ \
DEFINE (Bgoto_char, 0142) \
DEFINE (Binsert, 0143) \
DEFINE (Bpoint_max, 0144) \
DEFINE (Bpoint_min, 0145) \
DEFINE (Bchar_after, 0146) \
DEFINE (Bfollowing_char, 0147) \
DEFINE (Bpreceding_char, 0150) \
DEFINE (Bcurrent_column, 0151) \
DEFINE (Bindent_to, 0152) \
DEFINE (Beolp, 0154) \
DEFINE (Beobp, 0155) \
DEFINE (Bbolp, 0156) \
DEFINE (Bbobp, 0157) \
DEFINE (Bcurrent_buffer, 0160) \
DEFINE (Bset_buffer, 0161) \
DEFINE (Bsave_current_buffer_1, 0162) /* Replacing Bsave_current_buffer. */ \
DEFINE (Binteractive_p, 0164) /* Obsolete since Emacs-24.1. */ \
\
DEFINE (Bforward_char, 0165) \
DEFINE (Bforward_word, 0166) \
DEFINE (Bskip_chars_forward, 0167) \
DEFINE (Bskip_chars_backward, 0170) \
DEFINE (Bforward_line, 0171) \
DEFINE (Bchar_syntax, 0172) \
DEFINE (Bbuffer_substring, 0173) \
DEFINE (Bdelete_region, 0174) \
DEFINE (Bnarrow_to_region, 0175) \
DEFINE (Bwiden, 0176) \
DEFINE (Bend_of_line, 0177) \
\
DEFINE (Bconstant2, 0201) \
DEFINE (Bgoto, 0202) \
DEFINE (Bgotoifnil, 0203) \
DEFINE (Bgotoifnonnil, 0204) \
DEFINE (Bgotoifnilelsepop, 0205) \
DEFINE (Bgotoifnonnilelsepop, 0206) \
DEFINE (Breturn, 0207) \
DEFINE (Bdiscard, 0210) \
DEFINE (Bdup, 0211) \
\
DEFINE (Bsave_excursion, 0212) \
DEFINE (Bsave_window_excursion, 0213) /* Obsolete since Emacs-24.1. */ \
DEFINE (Bsave_restriction, 0214) \
DEFINE (Bcatch, 0215) \
\
DEFINE (Bunwind_protect, 0216) \
DEFINE (Bcondition_case, 0217) \
DEFINE (Btemp_output_buffer_setup, 0220) /* Obsolete since Emacs-24.1. */ \
DEFINE (Btemp_output_buffer_show, 0221) /* Obsolete since Emacs-24.1. */ \
\
DEFINE (Bunbind_all, 0222) /* Obsolete. Never used. */ \
\
DEFINE (Bset_marker, 0223) \
DEFINE (Bmatch_beginning, 0224) \
DEFINE (Bmatch_end, 0225) \
DEFINE (Bupcase, 0226) \
DEFINE (Bdowncase, 0227) \
\
DEFINE (Bstringeqlsign, 0230) \
DEFINE (Bstringlss, 0231) \
DEFINE (Bequal, 0232) \
DEFINE (Bnthcdr, 0233) \
DEFINE (Belt, 0234) \
DEFINE (Bmember, 0235) \
DEFINE (Bassq, 0236) \
DEFINE (Bnreverse, 0237) \
DEFINE (Bsetcar, 0240) \
DEFINE (Bsetcdr, 0241) \
DEFINE (Bcar_safe, 0242) \
DEFINE (Bcdr_safe, 0243) \
DEFINE (Bnconc, 0244) \
DEFINE (Bquo, 0245) \
DEFINE (Brem, 0246) \
DEFINE (Bnumberp, 0247) \
DEFINE (Bintegerp, 0250) \
\
DEFINE (BRgoto, 0252) \
DEFINE (BRgotoifnil, 0253) \
DEFINE (BRgotoifnonnil, 0254) \
DEFINE (BRgotoifnilelsepop, 0255) \
DEFINE (BRgotoifnonnilelsepop, 0256) \
\
DEFINE (BlistN, 0257) \
DEFINE (BconcatN, 0260) \
DEFINE (BinsertN, 0261) \
\
/* Bstack_ref is code 0. */ \
DEFINE (Bstack_set, 0262) \
DEFINE (Bstack_set2, 0263) \
DEFINE (BdiscardN, 0266) \
\
DEFINE (Bswitch, 0267) \
\
DEFINE (Bconstant, 0300)
enum byte_code_op
{
#define DEFINE(name, value) name = value,
BYTE_CODES
#undef DEFINE
#if BYTE_CODE_SAFE
Bscan_buffer = 0153, /* No longer generated as of v18. */
Bset_mark = 0163, /* this loser is no longer generated as of v18 */
#endif
};
/* Fetch the next byte from the bytecode stream. */

230
src/bytecode.h Normal file
View file

@ -0,0 +1,230 @@
/* Byte code definitions
Copyright (C) 1985-1988, 1993, 2000-2018 Free Software Foundation,
Inc.
This file is part of GNU Emacs.
GNU Emacs is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at
your option) any later version.
GNU Emacs is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#ifndef EMACS_BYTECODE_H
#define EMACS_BYTECODE_H
/* Byte codes: */
#define BYTE_CODES \
DEFINE (Bstack_ref, 0) /* Actually, Bstack_ref+0 is not implemented: use dup. */ \
DEFINE (Bstack_ref1, 1) \
DEFINE (Bstack_ref2, 2) \
DEFINE (Bstack_ref3, 3) \
DEFINE (Bstack_ref4, 4) \
DEFINE (Bstack_ref5, 5) \
DEFINE (Bstack_ref6, 6) \
DEFINE (Bstack_ref7, 7) \
DEFINE (Bvarref, 010) \
DEFINE (Bvarref1, 011) \
DEFINE (Bvarref2, 012) \
DEFINE (Bvarref3, 013) \
DEFINE (Bvarref4, 014) \
DEFINE (Bvarref5, 015) \
DEFINE (Bvarref6, 016) \
DEFINE (Bvarref7, 017) \
DEFINE (Bvarset, 020) \
DEFINE (Bvarset1, 021) \
DEFINE (Bvarset2, 022) \
DEFINE (Bvarset3, 023) \
DEFINE (Bvarset4, 024) \
DEFINE (Bvarset5, 025) \
DEFINE (Bvarset6, 026) \
DEFINE (Bvarset7, 027) \
DEFINE (Bvarbind, 030) \
DEFINE (Bvarbind1, 031) \
DEFINE (Bvarbind2, 032) \
DEFINE (Bvarbind3, 033) \
DEFINE (Bvarbind4, 034) \
DEFINE (Bvarbind5, 035) \
DEFINE (Bvarbind6, 036) \
DEFINE (Bvarbind7, 037) \
DEFINE (Bcall, 040) \
DEFINE (Bcall1, 041) \
DEFINE (Bcall2, 042) \
DEFINE (Bcall3, 043) \
DEFINE (Bcall4, 044) \
DEFINE (Bcall5, 045) \
DEFINE (Bcall6, 046) \
DEFINE (Bcall7, 047) \
DEFINE (Bunbind, 050) \
DEFINE (Bunbind1, 051) \
DEFINE (Bunbind2, 052) \
DEFINE (Bunbind3, 053) \
DEFINE (Bunbind4, 054) \
DEFINE (Bunbind5, 055) \
DEFINE (Bunbind6, 056) \
DEFINE (Bunbind7, 057) \
\
DEFINE (Bpophandler, 060) \
DEFINE (Bpushconditioncase, 061) \
DEFINE (Bpushcatch, 062) \
\
DEFINE (Bnth, 070) \
DEFINE (Bsymbolp, 071) \
DEFINE (Bconsp, 072) \
DEFINE (Bstringp, 073) \
DEFINE (Blistp, 074) \
DEFINE (Beq, 075) \
DEFINE (Bmemq, 076) \
DEFINE (Bnot, 077) \
DEFINE (Bcar, 0100) \
DEFINE (Bcdr, 0101) \
DEFINE (Bcons, 0102) \
DEFINE (Blist1, 0103) \
DEFINE (Blist2, 0104) \
DEFINE (Blist3, 0105) \
DEFINE (Blist4, 0106) \
DEFINE (Blength, 0107) \
DEFINE (Baref, 0110) \
DEFINE (Baset, 0111) \
DEFINE (Bsymbol_value, 0112) \
DEFINE (Bsymbol_function, 0113) \
DEFINE (Bset, 0114) \
DEFINE (Bfset, 0115) \
DEFINE (Bget, 0116) \
DEFINE (Bsubstring, 0117) \
DEFINE (Bconcat2, 0120) \
DEFINE (Bconcat3, 0121) \
DEFINE (Bconcat4, 0122) \
DEFINE (Bsub1, 0123) \
DEFINE (Badd1, 0124) \
DEFINE (Beqlsign, 0125) \
DEFINE (Bgtr, 0126) \
DEFINE (Blss, 0127) \
DEFINE (Bleq, 0130) \
DEFINE (Bgeq, 0131) \
DEFINE (Bdiff, 0132) \
DEFINE (Bnegate, 0133) \
DEFINE (Bplus, 0134) \
DEFINE (Bmax, 0135) \
DEFINE (Bmin, 0136) \
DEFINE (Bmult, 0137) \
\
DEFINE (Bpoint, 0140) \
/* Was Bmark in v17. */ \
DEFINE (Bsave_current_buffer, 0141) /* Obsolete. */ \
DEFINE (Bgoto_char, 0142) \
DEFINE (Binsert, 0143) \
DEFINE (Bpoint_max, 0144) \
DEFINE (Bpoint_min, 0145) \
DEFINE (Bchar_after, 0146) \
DEFINE (Bfollowing_char, 0147) \
DEFINE (Bpreceding_char, 0150) \
DEFINE (Bcurrent_column, 0151) \
DEFINE (Bindent_to, 0152) \
DEFINE (Beolp, 0154) \
DEFINE (Beobp, 0155) \
DEFINE (Bbolp, 0156) \
DEFINE (Bbobp, 0157) \
DEFINE (Bcurrent_buffer, 0160) \
DEFINE (Bset_buffer, 0161) \
DEFINE (Bsave_current_buffer_1, 0162) /* Replacing Bsave_current_buffer. */ \
DEFINE (Binteractive_p, 0164) /* Obsolete since Emacs-24.1. */ \
\
DEFINE (Bforward_char, 0165) \
DEFINE (Bforward_word, 0166) \
DEFINE (Bskip_chars_forward, 0167) \
DEFINE (Bskip_chars_backward, 0170) \
DEFINE (Bforward_line, 0171) \
DEFINE (Bchar_syntax, 0172) \
DEFINE (Bbuffer_substring, 0173) \
DEFINE (Bdelete_region, 0174) \
DEFINE (Bnarrow_to_region, 0175) \
DEFINE (Bwiden, 0176) \
DEFINE (Bend_of_line, 0177) \
\
DEFINE (Bconstant2, 0201) \
DEFINE (Bgoto, 0202) \
DEFINE (Bgotoifnil, 0203) \
DEFINE (Bgotoifnonnil, 0204) \
DEFINE (Bgotoifnilelsepop, 0205) \
DEFINE (Bgotoifnonnilelsepop, 0206) \
DEFINE (Breturn, 0207) \
DEFINE (Bdiscard, 0210) \
DEFINE (Bdup, 0211) \
\
DEFINE (Bsave_excursion, 0212) \
DEFINE (Bsave_window_excursion, 0213) /* Obsolete since Emacs-24.1. */ \
DEFINE (Bsave_restriction, 0214) \
DEFINE (Bcatch, 0215) \
\
DEFINE (Bunwind_protect, 0216) \
DEFINE (Bcondition_case, 0217) \
DEFINE (Btemp_output_buffer_setup, 0220) /* Obsolete since Emacs-24.1. */ \
DEFINE (Btemp_output_buffer_show, 0221) /* Obsolete since Emacs-24.1. */ \
\
DEFINE (Bunbind_all, 0222) /* Obsolete. Never used. */ \
\
DEFINE (Bset_marker, 0223) \
DEFINE (Bmatch_beginning, 0224) \
DEFINE (Bmatch_end, 0225) \
DEFINE (Bupcase, 0226) \
DEFINE (Bdowncase, 0227) \
\
DEFINE (Bstringeqlsign, 0230) \
DEFINE (Bstringlss, 0231) \
DEFINE (Bequal, 0232) \
DEFINE (Bnthcdr, 0233) \
DEFINE (Belt, 0234) \
DEFINE (Bmember, 0235) \
DEFINE (Bassq, 0236) \
DEFINE (Bnreverse, 0237) \
DEFINE (Bsetcar, 0240) \
DEFINE (Bsetcdr, 0241) \
DEFINE (Bcar_safe, 0242) \
DEFINE (Bcdr_safe, 0243) \
DEFINE (Bnconc, 0244) \
DEFINE (Bquo, 0245) \
DEFINE (Brem, 0246) \
DEFINE (Bnumberp, 0247) \
DEFINE (Bintegerp, 0250) \
\
DEFINE (BRgoto, 0252) \
DEFINE (BRgotoifnil, 0253) \
DEFINE (BRgotoifnonnil, 0254) \
DEFINE (BRgotoifnilelsepop, 0255) \
DEFINE (BRgotoifnonnilelsepop, 0256) \
\
DEFINE (BlistN, 0257) \
DEFINE (BconcatN, 0260) \
DEFINE (BinsertN, 0261) \
\
/* Bstack_ref is code 0. */ \
DEFINE (Bstack_set, 0262) \
DEFINE (Bstack_set2, 0263) \
DEFINE (BdiscardN, 0266) \
\
DEFINE (Bswitch, 0267) \
\
DEFINE (Bconstant, 0300)
enum byte_code_op
{
#define DEFINE(name, value) name = value,
BYTE_CODES
#undef DEFINE
#if BYTE_CODE_SAFE
Bscan_buffer = 0153, /* No longer generated as of v18. */
Bset_mark = 0163, /* this loser is no longer generated as of v18 */
#endif
};
#endif /* EMACS_BYTECODE_H */

View file

@ -866,8 +866,8 @@ function with `&rest' args, or `unevalled' for a special form. */)
{
short minargs, maxargs;
CHECK_SUBR (subr);
minargs = XSUBR (subr)->min_args;
maxargs = XSUBR (subr)->max_args;
minargs = XSUBR (subr)->function.min_args;
maxargs = XSUBR (subr)->function.max_args;
return Fcons (make_fixnum (minargs),
maxargs == MANY ? Qmany
: maxargs == UNEVALLED ? Qunevalled
@ -1571,7 +1571,8 @@ notify_variable_watchers (Lisp_Object symbol,
if (SUBRP (watcher))
{
Lisp_Object args[] = { symbol, newval, operation, where };
funcall_subr (XSUBR (watcher), ARRAYELTS (args), args);
funcall_subr (watcher, &XSUBR (watcher)->function,
ARRAYELTS (args), args);
}
else
CALLN (Ffuncall, watcher, symbol, newval, operation, where);

View file

@ -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);
@ -1643,6 +1649,10 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
syms_of_json ();
#endif
#ifdef HAVE_LIBJIT
syms_of_jit ();
#endif
keys_of_casefiddle ();
keys_of_cmds ();
keys_of_buffer ();

View file

@ -30,6 +30,10 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "dispextern.h"
#include "buffer.h"
#ifdef HAVE_LIBJIT
#include <jit/jit.h>
#endif
/* CACHEABLE is ordinarily nothing, except it is 'volatile' if
necessary to cajole GCC into not warning incorrectly that a
variable should be volatile. */
@ -2230,14 +2234,14 @@ eval_sub (Lisp_Object form)
check_cons_list ();
if (XFIXNUM (numargs) < XSUBR (fun)->min_args
|| (XSUBR (fun)->max_args >= 0
&& XSUBR (fun)->max_args < XFIXNUM (numargs)))
if (XFIXNUM (numargs) < XSUBR (fun)->function.min_args
|| (XSUBR (fun)->function.max_args >= 0
&& XSUBR (fun)->function.max_args < XFIXNUM (numargs)))
xsignal2 (Qwrong_number_of_arguments, original_fun, numargs);
else if (XSUBR (fun)->max_args == UNEVALLED)
val = (XSUBR (fun)->function.aUNEVALLED) (args_left);
else if (XSUBR (fun)->max_args == MANY)
else if (XSUBR (fun)->function.max_args == UNEVALLED)
val = (XSUBR (fun)->function.function.aUNEVALLED) (args_left);
else if (XSUBR (fun)->function.max_args == MANY)
{
/* Pass a vector of evaluated arguments. */
Lisp_Object *vals;
@ -2255,7 +2259,7 @@ eval_sub (Lisp_Object form)
set_backtrace_args (specpdl + count, vals, argnum);
val = XSUBR (fun)->function.aMANY (argnum, vals);
val = XSUBR (fun)->function.function.aMANY (argnum, vals);
check_cons_list ();
lisp_eval_depth--;
@ -2268,7 +2272,7 @@ eval_sub (Lisp_Object form)
}
else
{
int i, maxargs = XSUBR (fun)->max_args;
int i, maxargs = XSUBR (fun)->function.max_args;
for (i = 0; i < maxargs; i++)
{
@ -2281,40 +2285,40 @@ eval_sub (Lisp_Object form)
switch (i)
{
case 0:
val = (XSUBR (fun)->function.a0 ());
val = (XSUBR (fun)->function.function.a0 ());
break;
case 1:
val = (XSUBR (fun)->function.a1 (argvals[0]));
val = (XSUBR (fun)->function.function.a1 (argvals[0]));
break;
case 2:
val = (XSUBR (fun)->function.a2 (argvals[0], argvals[1]));
val = (XSUBR (fun)->function.function.a2 (argvals[0], argvals[1]));
break;
case 3:
val = (XSUBR (fun)->function.a3
val = (XSUBR (fun)->function.function.a3
(argvals[0], argvals[1], argvals[2]));
break;
case 4:
val = (XSUBR (fun)->function.a4
val = (XSUBR (fun)->function.function.a4
(argvals[0], argvals[1], argvals[2], argvals[3]));
break;
case 5:
val = (XSUBR (fun)->function.a5
val = (XSUBR (fun)->function.function.a5
(argvals[0], argvals[1], argvals[2], argvals[3],
argvals[4]));
break;
case 6:
val = (XSUBR (fun)->function.a6
val = (XSUBR (fun)->function.function.a6
(argvals[0], argvals[1], argvals[2], argvals[3],
argvals[4], argvals[5]));
break;
case 7:
val = (XSUBR (fun)->function.a7
val = (XSUBR (fun)->function.function.a7
(argvals[0], argvals[1], argvals[2], argvals[3],
argvals[4], argvals[5], argvals[6]));
break;
case 8:
val = (XSUBR (fun)->function.a8
val = (XSUBR (fun)->function.function.a8
(argvals[0], argvals[1], argvals[2], argvals[3],
argvals[4], argvals[5], argvals[6], argvals[7]));
break;
@ -2411,16 +2415,16 @@ usage: (apply FUNCTION &rest ARGUMENTS) */)
fun = args[0];
}
if (SUBRP (fun) && XSUBR (fun)->max_args > numargs
if (SUBRP (fun) && XSUBR (fun)->function.max_args > numargs
/* Don't hide an error by adding missing arguments. */
&& numargs >= XSUBR (fun)->min_args)
&& numargs >= XSUBR (fun)->function.min_args)
{
/* Avoid making funcall cons up a yet another new vector of arguments
by explicitly supplying nil's for optional values. */
SAFE_ALLOCA_LISP (funcall_args, 1 + XSUBR (fun)->max_args);
SAFE_ALLOCA_LISP (funcall_args, 1 + XSUBR (fun)->function.max_args);
memclear (funcall_args + numargs + 1,
(XSUBR (fun)->max_args - numargs) * word_size);
funcall_nargs = 1 + XSUBR (fun)->max_args;
(XSUBR (fun)->function.max_args - numargs) * word_size);
funcall_nargs = 1 + XSUBR (fun)->function.max_args;
}
else
{ /* We add 1 to numargs because funcall_args includes the
@ -2764,7 +2768,7 @@ FUNCTIONP (Lisp_Object object)
}
if (SUBRP (object))
return XSUBR (object)->max_args != UNEVALLED;
return XSUBR (object)->function.max_args != UNEVALLED;
else if (COMPILEDP (object) || MODULE_FUNCTIONP (object))
return true;
else if (CONSP (object))
@ -2819,7 +2823,12 @@ usage: (funcall FUNCTION &rest ARGUMENTS) */)
fun = indirect_function (fun);
if (SUBRP (fun))
val = funcall_subr (XSUBR (fun), numargs, args + 1);
val = funcall_subr (fun, &XSUBR (fun)->function, numargs, args + 1);
else if (COMPILEDP (fun)
&& XLP (XVECTOR (fun)->contents[COMPILED_JIT_CODE]) != NULL)
val = funcall_subr (fun,
(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);
else
@ -2856,28 +2865,19 @@ usage: (funcall FUNCTION &rest ARGUMENTS) */)
and return the result of evaluation. */
Lisp_Object
funcall_subr (struct Lisp_Subr *subr, ptrdiff_t numargs, Lisp_Object *args)
funcall_subr (Lisp_Object error_obj, struct subr_function *subr,
ptrdiff_t numargs, Lisp_Object *args)
{
if (numargs < subr->min_args
|| (subr->max_args >= 0 && subr->max_args < numargs))
{
Lisp_Object fun;
XSETSUBR (fun, subr);
xsignal2 (Qwrong_number_of_arguments, fun, make_fixnum (numargs));
}
xsignal2 (Qwrong_number_of_arguments, error_obj, make_fixnum (numargs));
else if (subr->max_args == UNEVALLED)
{
Lisp_Object fun;
XSETSUBR (fun, subr);
xsignal1 (Qinvalid_function, fun);
}
xsignal1 (Qinvalid_function, error_obj);
else if (subr->max_args == MANY)
return (subr->function.aMANY) (numargs, args);
else
{
Lisp_Object internal_argbuf[8];
Lisp_Object internal_argbuf[SUBR_MAX_ARGS];
Lisp_Object *internal_args;
if (subr->max_args > numargs)
{
@ -3020,6 +3020,22 @@ funcall_lambda (Lisp_Object fun, ptrdiff_t nargs,
and constants vector yet, fetch them from the file. */
if (CONSP (AREF (fun, COMPILED_BYTECODE)))
Ffetch_bytecode (fun);
#ifdef HAVE_LIBJIT
if (initialized)
{
struct Lisp_Vector *vec = XVECTOR (fun);
if (XLP (vec->contents[COMPILED_JIT_CODE]) == NULL)
emacs_jit_compile (fun);
if (XLP (vec->contents[COMPILED_JIT_CODE]) != NULL)
return funcall_subr (fun,
(struct subr_function *) XLP (vec->contents[COMPILED_JIT_CODE]),
nargs, arg_vector);
}
#endif /* HAVE_LIBJIT */
return exec_byte_code (AREF (fun, COMPILED_BYTECODE),
AREF (fun, COMPILED_CONSTANTS),
AREF (fun, COMPILED_STACK_DEPTH),

2766
src/jit.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -1891,13 +1891,12 @@ CHAR_TABLE_SET (Lisp_Object ct, int idx, Lisp_Object val)
char_table_set (ct, idx, val);
}
/* This structure describes a built-in function.
It is generated by the DEFUN macro only.
defsubr makes it into a Lisp object. */
/* The inner part of a Lisp_Subr, used when calling the function.
This is separate so it can be reused by the JIT compiler without
requiring an entire Lisp_Subr to be created there. */
struct Lisp_Subr
struct subr_function
{
union vectorlike_header header;
union {
Lisp_Object (*a0) (void);
Lisp_Object (*a1) (Lisp_Object);
@ -1912,6 +1911,18 @@ struct Lisp_Subr
Lisp_Object (*aMANY) (ptrdiff_t, Lisp_Object *);
} function;
short min_args, max_args;
};
#define SUBR_MAX_ARGS 9
/* This structure describes a built-in function.
It is generated by the DEFUN macro only.
defsubr makes it into a Lisp object. */
struct Lisp_Subr
{
union vectorlike_header header;
struct subr_function function;
const char *symbol_name;
const char *intspec;
EMACS_INT doc;
@ -2634,7 +2645,8 @@ enum Lisp_Compiled
COMPILED_CONSTANTS = 2,
COMPILED_STACK_DEPTH = 3,
COMPILED_DOC_STRING = 4,
COMPILED_INTERACTIVE = 5
COMPILED_INTERACTIVE = 5,
COMPILED_JIT_CODE = 6
};
/* Flag bits in a character. These also get used in termhooks.h.
@ -2916,8 +2928,8 @@ CHECK_FIXNUM_CDR (Lisp_Object x)
#define DEFUN(lname, fnname, sname, minargs, maxargs, intspec, doc) \
static struct Lisp_Subr sname = \
{ { PVEC_SUBR << PSEUDOVECTOR_AREA_BITS }, \
{ .a ## maxargs = fnname }, \
minargs, maxargs, lname, intspec, 0}; \
{ { .a ## maxargs = fnname }, \
minargs, maxargs }, lname, intspec, 0}; \
Lisp_Object fnname
/* defsubr (Sname);
@ -3649,7 +3661,6 @@ build_string (const char *str)
}
extern Lisp_Object pure_cons (Lisp_Object, Lisp_Object);
extern void make_byte_code (struct Lisp_Vector *);
extern struct Lisp_Vector *allocate_vector (EMACS_INT);
/* Make an uninitialized vector for SIZE objects. NOTE: you must
@ -3848,7 +3859,9 @@ extern _Noreturn void xsignal3 (Lisp_Object, Lisp_Object, Lisp_Object,
Lisp_Object);
extern _Noreturn void signal_error (const char *, Lisp_Object);
extern bool FUNCTIONP (Lisp_Object);
extern Lisp_Object funcall_subr (struct Lisp_Subr *subr, ptrdiff_t numargs, Lisp_Object *arg_vector);
extern Lisp_Object funcall_subr (Lisp_Object error_obj,
struct subr_function *subr,
ptrdiff_t numargs, Lisp_Object *arg_vector);
extern Lisp_Object eval_sub (Lisp_Object form);
extern Lisp_Object apply1 (Lisp_Object, Lisp_Object);
extern Lisp_Object call0 (Lisp_Object);
@ -4437,6 +4450,10 @@ extern bool profiler_memory_running;
extern void malloc_probe (size_t);
extern void syms_of_profiler (void);
/* Defined in jit.c. */
extern void syms_of_jit (void);
extern void init_jit (void);
extern void emacs_jit_compile (Lisp_Object);
#ifdef DOS_NT
/* Defined in msdos.c, w32.c. */
@ -4614,8 +4631,14 @@ 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__ || defined CYGWIN) \
&& 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 or Cygwin 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

View file

@ -2948,8 +2948,7 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list)
vec = XVECTOR (tmp);
if (vec->header.size == 0)
invalid_syntax ("Empty byte-code object");
make_byte_code (vec);
return tmp;
return Fmake_byte_code (vec->header.size, vec->contents);
}
if (c == '(')
{

View file

@ -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));

304
test/src/jit-tests.el Normal file
View file

@ -0,0 +1,304 @@
;;; jit-tests.el --- unit tests for src/jijt.c -*- lexical-binding: t; -*-
;; Copyright (C) 2018 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
;; Unit tests for src/jit.c.
;;; Code:
(require 'ert)
(defun jit-test-apply (func &rest args)
(unless (byte-code-function-p (symbol-function func))
(byte-compile func))
(apply func args))
;; Test Bconsp.
(defun jit-test-consp (x) (consp x))
(ert-deftest jit-consp ()
(should-not (jit-test-apply 'jit-test-consp 23))
(should-not (jit-test-apply 'jit-test-consp nil))
(should (jit-test-apply 'jit-test-consp '(1 . 2))))
;; Test Blistp.
(defun jit-test-listp (x) (listp x))
(ert-deftest jit-listp ()
(should-not (jit-test-apply 'jit-test-listp 23))
(should (jit-test-apply 'jit-test-listp nil))
(should (jit-test-apply 'jit-test-listp '(1 . 2))))
;; Test Bstringp.
(defun jit-test-stringp (x) (stringp x))
(ert-deftest jit-stringp ()
(should-not (jit-test-apply 'jit-test-stringp 23))
(should-not (jit-test-apply 'jit-test-stringp nil))
(should (jit-test-apply 'jit-test-stringp "hi")))
;; Test Bsymbolp.
(defun jit-test-symbolp (x) (symbolp x))
(ert-deftest jit-symbolp ()
(should-not (jit-test-apply 'jit-test-symbolp 23))
(should-not (jit-test-apply 'jit-test-symbolp "hi"))
(should (jit-test-apply 'jit-test-symbolp 'whatever)))
;; Test Bintegerp.
(defun jit-test-integerp (x) (integerp x))
(ert-deftest jit-integerp ()
(should (jit-test-apply 'jit-test-integerp 23))
(should-not (jit-test-apply 'jit-test-integerp 57.5))
(should-not (jit-test-apply 'jit-test-integerp "hi"))
(should-not (jit-test-apply 'jit-test-integerp 'whatever)))
;; Test Bnumberp.
(defun jit-test-numberp (x) (numberp x))
(ert-deftest jit-numberp ()
(should (jit-test-apply 'jit-test-numberp 23))
(should (jit-test-apply 'jit-test-numberp 57.5))
(should-not (jit-test-apply 'jit-test-numberp "hi"))
(should-not (jit-test-apply 'jit-test-numberp 'whatever)))
;; Test Badd1.
(defun jit-test-add1 (x) (1+ x))
(ert-deftest jit-add1 ()
(should (eq (jit-test-apply 'jit-test-add1 23) 24))
(should (eq (jit-test-apply 'jit-test-add1 -17) -16))
(should (eql (jit-test-apply 'jit-test-add1 1.0) 2.0))
(should-error (jit-test-apply 'jit-test-add1 nil)
:type 'wrong-type-argument))
;; Test Bsub1.
(defun jit-test-sub1 (x) (1- x))
(ert-deftest jit-sub1 ()
(should (eq (jit-test-apply 'jit-test-sub1 23) 22))
(should (eq (jit-test-apply 'jit-test-sub1 -17) -18))
(should (eql (jit-test-apply 'jit-test-sub1 1.0) 0.0))
(should-error (jit-test-apply 'jit-test-sub1 nil)
:type 'wrong-type-argument))
;; Test Bneg.
(defun jit-test-negate (x) (- x))
(ert-deftest jit-negate ()
(should (eq (jit-test-apply 'jit-test-negate 23) -23))
(should (eq (jit-test-apply 'jit-test-negate -17) 17))
(should (eql (jit-test-apply 'jit-test-negate 1.0) -1.0))
(should-error (jit-test-apply 'jit-test-negate nil)
:type 'wrong-type-argument))
;; Test Bnot.
(defun jit-test-not (x) (not x))
(ert-deftest jit-not ()
(should (eq (jit-test-apply 'jit-test-not 23) nil))
(should (eq (jit-test-apply 'jit-test-not nil) t))
(should (eq (jit-test-apply 'jit-test-not t) nil)))
;; Test Bbobp, Beobp, Bpoint, Bpoint_min, Bpoint_max.
(defun jit-test-bobp () (bobp))
(defun jit-test-eobp () (eobp))
(defun jit-test-point () (point))
(defun jit-test-point-min () (point-min))
(defun jit-test-point-max () (point-max))
(ert-deftest jit-bobp-and-eobp ()
(with-temp-buffer
(should (jit-test-apply 'jit-test-bobp))
(should (jit-test-apply 'jit-test-eobp))
(insert "hi")
(goto-char (point-min))
(should (eq (jit-test-apply 'jit-test-point-min) (point-min)))
(should (eq (jit-test-apply 'jit-test-point) (point-min)))
(should (jit-test-apply 'jit-test-bobp))
(should-not (jit-test-apply 'jit-test-eobp))
(goto-char (point-max))
(should (eq (jit-test-apply 'jit-test-point-max) (point-max)))
(should (eq (jit-test-apply 'jit-test-point) (point-max)))
(should-not (jit-test-apply 'jit-test-bobp))
(should (jit-test-apply 'jit-test-eobp))))
;; Test Bcar and Bcdr.
(defun jit-test-car (x) (car x))
(defun jit-test-cdr (x) (cdr x))
(ert-deftest jit-car-cdr ()
(let ((pair '(1 . b)))
(should (eq (jit-test-apply 'jit-test-car pair) 1))
(should (eq (jit-test-apply 'jit-test-car nil) nil))
(should-error (jit-test-apply 'jit-test-car 23)
:type 'wrong-type-argument)
(should (eq (jit-test-apply 'jit-test-cdr pair) 'b))
(should (eq (jit-test-apply 'jit-test-cdr nil) nil))
(should-error (jit-test-apply 'jit-test-cdr 23)
:type 'wrong-type-argument)))
;; Test Bcar_safe and Bcdr_safe.
(defun jit-test-car-safe (x) (car-safe x))
(defun jit-test-cdr-safe (x) (cdr-safe x))
(ert-deftest jit-car-cdr-safe ()
(let ((pair '(1 . b)))
(should (eq (jit-test-apply 'jit-test-car-safe pair) 1))
(should (eq (jit-test-apply 'jit-test-car-safe nil) nil))
(should (eq (jit-test-apply 'jit-test-car-safe 23) nil))
(should (eq (jit-test-apply 'jit-test-cdr-safe pair) 'b))
(should (eq (jit-test-apply 'jit-test-cdr-safe nil) nil))
(should (eq (jit-test-apply 'jit-test-cdr-safe 23) nil))))
;; Test Beq.
(defun jit-test-eq (x y) (eq x y))
(ert-deftest jit-eq ()
(should (jit-test-apply 'jit-test-eq 'a 'a))
(should (jit-test-apply 'jit-test-eq 5 5))
(should-not (jit-test-apply 'jit-test-eq 'a 'b))
(should-not (jit-test-apply 'jit-test-eq "x" "x")))
;; Test Bgotoifnil.
(defun jit-test-if (x y) (if x x y))
(ert-deftest jit-if ()
(should (eq (jit-test-apply 'jit-test-if 'a 'b) 'a))
(should (eq (jit-test-apply 'jit-test-if 0 23) 0))
(should (eq (jit-test-apply 'jit-test-if nil 'b) 'b)))
;; Test Bgotoifnilelsepop.
(defun jit-test-and (x y) (and x y))
(ert-deftest jit-and ()
(should (eq (jit-test-apply 'jit-test-and 'a 'b) 'b))
(should (eq (jit-test-apply 'jit-test-and 0 23) 23))
(should (eq (jit-test-apply 'jit-test-and nil 'b) nil)))
;; Test Bgotoifnonnilelsepop.
(defun jit-test-or (x y) (or x y))
(ert-deftest jit-or ()
(should (eq (jit-test-apply 'jit-test-or 'a 'b) 'a))
(should (eq (jit-test-apply 'jit-test-or 0 23) 0))
(should (eq (jit-test-apply 'jit-test-or nil 'b) 'b)))
;; Test Bsave_excursion.
(defun jit-test-save-excursion ()
(save-excursion
(insert "XYZ")))
;; Test Bcurrent_buffer.
(defun jit-test-current-buffer () (current-buffer))
(ert-deftest jit-save-excursion ()
(with-temp-buffer
(jit-test-apply 'jit-test-save-excursion)
(should (eq (point) (point-min)))
(should (eq (jit-test-apply 'jit-test-current-buffer) (current-buffer)))))
;; Test Bgtr.
(defun jit-test-> (a b)
(> a b))
(ert-deftest jit-> ()
(should (eq (jit-test-apply 'jit-test-> 0 23) nil))
(should (eq (jit-test-apply 'jit-test-> 23 0) t)))
;; Test Bpushcatch.
(defun jit-test-catch (&rest l)
(catch 'done
(dolist (v l)
(when (> v 23)
(throw 'done v)))))
(ert-deftest jit-catch ()
(should (eq (jit-test-apply 'jit-test-catch 0 1 2 3 4) nil))
(should (eq (jit-test-apply 'jit-test-catch 20 21 22 23 24 25 26 27 28) 24)))
;; Test Bmemq.
(defun jit-test-memq (val list)
(memq val list))
(ert-deftest jit-memq ()
(should (equal (jit-test-apply 'jit-test-memq 0 '(5 4 3 2 1 0)) '(0)))
(should (eq (jit-test-apply 'jit-test-memq 72 '(5 4 3 2 1 0)) nil)))
;; Test BlistN.
(defun jit-test-listN (x)
(list x x x x x x x x x x x x x x x x))
(ert-deftest jit-listN ()
(should (equal (jit-test-apply 'jit-test-listN 57)
'(57 57 57 57 57 57 57 57 57 57 57 57 57 57 57 57))))
;; Test BconcatN.
(defun jit-test-concatN (x)
(concat x x x x x x))
(ert-deftest jit-concatN ()
(should (equal (jit-test-apply 'jit-test-concatN "x") "xxxxxx")))
;; Test optional and rest arguments.
(defun jit-test-opt-rest (a &optional b &rest c)
(list a b c))
(ert-deftest jit-opt-rest ()
(should (equal (jit-test-apply 'jit-test-opt-rest 1) '(1 nil nil)))
(should (equal (jit-test-apply 'jit-test-opt-rest 1 2) '(1 2 nil)))
(should (equal (jit-test-apply 'jit-test-opt-rest 1 2 3) '(1 2 (3))))
(should (equal (jit-test-apply 'jit-test-opt-rest 1 2 56 57 58)
'(1 2 (56 57 58)))))
;; Test for too many arguments.
(defun jit-test-opt (a &optional b)
(cons a b))
(ert-deftest jit-opt ()
(should (equal (jit-test-apply 'jit-test-opt 23) '(23)))
(should (equal (jit-test-apply 'jit-test-opt 23 24) '(23 . 24)))
(should-error (jit-test-apply 'jit-test-opt)
:type 'wrong-number-of-arguments)
(should-error (jit-test-apply 'jit-test-opt nil 24 97)
:type 'wrong-number-of-arguments))
;; Test for unwind-protect.
(defvar jit-test-up-val nil)
(defun jit-test-unwind-protect (fun)
(setq jit-test-up-val nil)
(unwind-protect
(progn
(setq jit-test-up-val 23)
(funcall fun)
(setq jit-test-up-val 24))
(setq jit-test-up-val 999)))
(ert-deftest jit-unwind-protect ()
(jit-test-unwind-protect 'ignore)
(should (eq jit-test-up-val 999))
(condition-case nil
(jit-test-unwind-protect (lambda () (error "HI")))
(error
nil))
(should (eq jit-test-up-val 999)))
;;; jit-tests.el ends here