From c1111e944784f68593964e528a9bd0dd6a6314fb Mon Sep 17 00:00:00 2001 From: Mattias Engdegård Date: Thu, 17 Feb 2022 14:39:42 +0100 Subject: Fix or remove outdated comments * src/eval.c (funcall_lambda): Rewrite obsolete comment. * src/bytecode.c (exec_byte_code): Remove lying comment and unneeded #define. * lisp/emacs-lisp/byte-opt.el: Remove car. Keep pig. (byte-compile-log-lap-1): Remove obsolete and irrelevant comment. --- src/bytecode.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'src/bytecode.c') diff --git a/src/bytecode.c b/src/bytecode.c index bda9a39b7f3..96f1f905812 100644 --- a/src/bytecode.c +++ b/src/bytecode.c @@ -458,17 +458,13 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth, #ifdef BYTE_CODE_THREADED - /* A convenience define that saves us a lot of typing and makes - the table clearer. */ -#define LABEL(OP) [OP] = &&insn_ ## OP - /* This is the dispatch table for the threaded interpreter. */ static const void *const targets[256] = { [0 ... (Bconstant - 1)] = &&insn_default, [Bconstant ... 255] = &&insn_Bconstant, -#define DEFINE(name, value) LABEL (name) , +#define DEFINE(name, value) [name] = &&insn_ ## name, BYTE_CODES #undef DEFINE }; -- cgit v1.2.1 From 2fb98486e18f8a3275adc56d2740901ef5cb6e8b Mon Sep 17 00:00:00 2001 From: Mattias Engdegård Date: Thu, 3 Mar 2022 13:57:26 +0100 Subject: Faster bytecode immediate argument fetching * src/bytecode.c (FETCH2): Use `|` instead of `+` to combine the bytes forming a 16-bit immediate argument so that GCC (prior to version 12) recognises the idiom and generates a 16-bit load. This applies for little-endian machines with cheap unaligned accesses such as x86[-64], arm64 and power64le. This 1-character change results in a measurable speed gain on many kinds of Lisp code, as 16-bit immediates are used by all jump instructions. Clang performs this optimisation for both `+` and `|` from version 10. --- src/bytecode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/bytecode.c') diff --git a/src/bytecode.c b/src/bytecode.c index 96f1f905812..c5cc6590121 100644 --- a/src/bytecode.c +++ b/src/bytecode.c @@ -291,7 +291,7 @@ enum byte_code_op /* Fetch two bytes from the bytecode stream and make a 16-bit number out of them. */ -#define FETCH2 (op = FETCH, op + (FETCH << 8)) +#define FETCH2 (op = FETCH, op | (FETCH << 8)) /* Push X onto the execution stack. The expression X should not contain TOP, to avoid competing side effects. */ -- cgit v1.2.1 From 88889212c7d74fb189131dcae4abaabd05eb1870 Mon Sep 17 00:00:00 2001 From: Mattias Engdegård Date: Thu, 3 Mar 2022 19:46:13 +0100 Subject: Remove debug code for opcodes long gone * src/bytecode.c (BYTE_CODES, enum byte_code_op, exec_byte_code): Don't display custom messages in debug mode for Bscan_buffer and Bset_mark which were removed long ago. --- src/bytecode.c | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) (limited to 'src/bytecode.c') diff --git a/src/bytecode.c b/src/bytecode.c index c5cc6590121..8d3817e64c6 100644 --- a/src/bytecode.c +++ b/src/bytecode.c @@ -186,6 +186,7 @@ DEFINE (Bfollowing_char, 0147) \ DEFINE (Bpreceding_char, 0150) \ DEFINE (Bcurrent_column, 0151) \ DEFINE (Bindent_to, 0152) \ +/* 0153 was Bscan_buffer in v17. */ \ DEFINE (Beolp, 0154) \ DEFINE (Beobp, 0155) \ DEFINE (Bbolp, 0156) \ @@ -193,6 +194,7 @@ DEFINE (Bbobp, 0157) \ DEFINE (Bcurrent_buffer, 0160) \ DEFINE (Bset_buffer, 0161) \ DEFINE (Bsave_current_buffer_1, 0162) /* Replacing Bsave_current_buffer. */ \ +/* 0163 was Bset_mark in v17. */ \ DEFINE (Binteractive_p, 0164) /* Obsolete since Emacs-24.1. */ \ \ DEFINE (Bforward_char, 0165) \ @@ -277,11 +279,6 @@ 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. */ @@ -1467,19 +1464,6 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth, TOP = INTEGERP (TOP) ? Qt : Qnil; NEXT; -#if BYTE_CODE_SAFE - /* These are intentionally written using 'case' syntax, - because they are incompatible with the threaded - interpreter. */ - - case Bset_mark: - error ("set-mark is an obsolete bytecode"); - break; - case Bscan_buffer: - error ("scan-buffer is an obsolete bytecode"); - break; -#endif - CASE_ABORT: /* Actually this is Bstack_ref with offset 0, but we use Bdup for that instead. */ -- cgit v1.2.1 From 2c54e9a1dd6b4ea561be10567a7363012e70fa28 Mon Sep 17 00:00:00 2001 From: Mattias Engdegård Date: Thu, 3 Mar 2022 19:50:46 +0100 Subject: Remove never-used relative jump opcodes * src/bytecode.c (BYTE_CODES, exec_byte_code): Remove relative jump opcodes that seem to have been a short-lived experiment, never used in a release. --- src/bytecode.c | 37 +------------------------------------ 1 file changed, 1 insertion(+), 36 deletions(-) (limited to 'src/bytecode.c') diff --git a/src/bytecode.c b/src/bytecode.c index 8d3817e64c6..286a8d675d4 100644 --- a/src/bytecode.c +++ b/src/bytecode.c @@ -255,11 +255,7 @@ DEFINE (Brem, 0246) \ DEFINE (Bnumberp, 0247) \ DEFINE (Bintegerp, 0250) \ \ -DEFINE (BRgoto, 0252) \ -DEFINE (BRgotoifnil, 0253) \ -DEFINE (BRgotoifnonnil, 0254) \ -DEFINE (BRgotoifnilelsepop, 0255) \ -DEFINE (BRgotoifnonnilelsepop, 0256) \ +/* 0252-0256 were relative jumps, apparently never used. */ \ \ DEFINE (BlistN, 0257) \ DEFINE (BconcatN, 0260) \ @@ -702,7 +698,6 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth, op = FETCH2; op_branch: op -= pc - bytestr_data; - op_relative_branch: if (BYTE_CODE_SAFE && ! (bytestr_data - pc <= op && op < bytestr_data + bytestr_length - pc)) @@ -737,36 +732,6 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth, DISCARD (1); NEXT; - CASE (BRgoto): - op = FETCH - 128; - goto op_relative_branch; - - CASE (BRgotoifnil): - op = FETCH - 128; - if (NILP (POP)) - goto op_relative_branch; - NEXT; - - CASE (BRgotoifnonnil): - op = FETCH - 128; - if (!NILP (POP)) - goto op_relative_branch; - NEXT; - - CASE (BRgotoifnilelsepop): - op = FETCH - 128; - if (NILP (TOP)) - goto op_relative_branch; - DISCARD (1); - NEXT; - - CASE (BRgotoifnonnilelsepop): - op = FETCH - 128; - if (!NILP (TOP)) - goto op_relative_branch; - DISCARD (1); - NEXT; - CASE (Breturn): goto exit; -- cgit v1.2.1 From 267f41c7ce1e02f392b57aa338d387e7627df184 Mon Sep 17 00:00:00 2001 From: Mattias Engdegård Date: Tue, 18 Jan 2022 13:10:05 +0100 Subject: Simplify exec_byte_code arguments Pass the function object and encoded arity, not the other components. This speeds up several call paths and is necessary for improvements to come. * src/bytecode.c (Fbyte_code): Make a new byte code object for execution. This is slower but performance isn't critical here. (exec_byte_code): Retrieve components from the passed function. * src/eval.c (fetch_and_exec_byte_code): * src/lisp.h (exec_byte_code): Update signature. --- src/bytecode.c | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) (limited to 'src/bytecode.c') diff --git a/src/bytecode.c b/src/bytecode.c index 286a8d675d4..7c390c0d40e 100644 --- a/src/bytecode.c +++ b/src/bytecode.c @@ -324,9 +324,8 @@ If the third argument is incorrect, Emacs may crash. */) the original unibyte form. */ bytestr = Fstring_as_unibyte (bytestr); } - pin_string (bytestr); // Bytecode must be immovable. - - return exec_byte_code (bytestr, vector, maxdepth, 0, 0, NULL); + Lisp_Object args[] = {0, bytestr, vector, maxdepth}; + return exec_byte_code (Fmake_byte_code (4, args), 0, 0, NULL); } static void @@ -335,24 +334,26 @@ bcall0 (Lisp_Object f) Ffuncall (1, &f); } -/* Execute the byte-code in BYTESTR. VECTOR is the constant vector, and - MAXDEPTH is the maximum stack depth used (if MAXDEPTH is incorrect, - emacs may crash!). ARGS_TEMPLATE is the function arity encoded as an - integer, and ARGS, of size NARGS, should be a vector of the actual - arguments. The arguments in ARGS are pushed on the stack according - to ARGS_TEMPLATE before executing BYTESTR. */ +/* Execute the byte-code in FUN. ARGS_TEMPLATE is the function arity + encoded as an integer (the one in FUN is ignored), and ARGS, of + size NARGS, should be a vector of the actual arguments. The + arguments in ARGS are pushed on the stack according to + ARGS_TEMPLATE before executing FUN. */ Lisp_Object -exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth, - ptrdiff_t args_template, ptrdiff_t nargs, Lisp_Object *args) +exec_byte_code (Lisp_Object fun, ptrdiff_t args_template, + ptrdiff_t nargs, Lisp_Object *args) { #ifdef BYTE_CODE_METER int volatile this_op = 0; #endif + Lisp_Object bytestr = AREF (fun, COMPILED_BYTECODE); + eassert (!STRING_MULTIBYTE (bytestr)); eassert (string_immovable_p (bytestr)); - + Lisp_Object vector = AREF (fun, COMPILED_CONSTANTS); + Lisp_Object maxdepth = AREF (fun, COMPILED_STACK_DEPTH); ptrdiff_t const_length = ASIZE (vector); ptrdiff_t bytestr_length = SCHARS (bytestr); Lisp_Object *vectorp = XVECTOR (vector)->contents; @@ -657,10 +658,7 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth, // No autoloads. && (bytecode = AREF (fun, COMPILED_BYTECODE), !CONSP (bytecode))) - val = exec_byte_code (bytecode, - AREF (fun, COMPILED_CONSTANTS), - AREF (fun, COMPILED_STACK_DEPTH), - XFIXNUM (template), numargs, args); + val = exec_byte_code (fun, XFIXNUM (template), numargs, args); else if (SUBRP (fun) && !SUBR_NATIVE_COMPILED_DYNP (fun)) val = funcall_subr (XSUBR (fun), numargs, args); else -- cgit v1.2.1 From 3ed79cdbf21039fa209c421f746c0b49ec33f4da Mon Sep 17 00:00:00 2001 From: Mattias Engdegård Date: Sun, 13 Mar 2022 17:26:05 +0100 Subject: Separate bytecode stack Use a dedicated stack for bytecode, instead of using the C stack. Stack frames are managed explicitly and we stay in the same exec_byte_code activation throughout bytecode function calls and returns. In other words, exec_byte_code no longer uses recursion for calling bytecode functions. This results in better performance, and bytecode recursion is no longer limited by the size of the C stack. The bytecode stack is currently of fixed size but overflow is handled gracefully by signalling a Lisp error instead of the hard crash that we get now. In addition, GC marking of the stack is now faster and more precise. Full precision could be attained if desired. * src/alloc.c (ATTRIBUTE_NO_SANITIZE_ADDRESS): Make non-static. * src/bytecode.c (enum stack_frame_index, BC_STACK_SIZE) (sf_get_ptr, sf_set_ptr, sf_get_lisp_ptr, sf_set_lisp_ptr) (sf_get_saved_pc, sf_set_saved_pc, init_bc_thread, free_bc_thread) (mark_bytecode, Finternal_stack_stats, valid_sp): New. (exec_byte_code): Adapt to use the new bytecode stack. (syms_of_bytecode): Add defsubr. * src/eval.c (unwind_to_catch): Restore saved stack frame. (push_handler_nosignal): Save stack frame. * src/lisp.h (struct handler): Add act_rec member. (get_act_rec, set_act_rec): New. * src/thread.c (mark_one_thread): Call mark_bytecode. (finalize_one_thread): Free bytecode thread state. (Fmake_thread, init_threads): Set up bytecode thread state. * src/thread.h (struct bc_thread_state): New. (struct thread_state): Add bytecode thread state. --- src/bytecode.c | 318 ++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 268 insertions(+), 50 deletions(-) (limited to 'src/bytecode.c') diff --git a/src/bytecode.c b/src/bytecode.c index 7c390c0d40e..9356ebeb6cb 100644 --- a/src/bytecode.c +++ b/src/bytecode.c @@ -334,6 +334,166 @@ bcall0 (Lisp_Object f) Ffuncall (1, &f); } +/* Layout of the stack frame header. */ +enum stack_frame_index { + SFI_SAVED_FP, /* previous frame pointer */ + + /* In a frame called directly from C, the following two members are NULL. */ + SFI_SAVED_TOP, /* previous stack pointer */ + SFI_SAVED_PC, /* previous program counter */ + + SFI_FUN, /* current function object */ + + SF_SIZE /* number of words in the header */ +}; + +/* The bytecode stack size in Lisp words. + This is a fairly generous amount, but: + - if users need more, we could allocate more, or just reserve the address + space and allocate on demand + - if threads are used more, then it might be a good idea to reduce the + per-thread overhead in time and space + - for maximum flexibility but a small runtime penalty, we could allocate + the stack in smaller chunks as needed +*/ +#define BC_STACK_SIZE (512 * 1024) + +/* Bytecode interpreter stack: + + |--------------| -- + |fun | | ^ stack growth + |saved_pc | | | direction + |saved_top ------- | + fp--->|saved_fp ---- | | current frame + |--------------| | | | (called from bytecode in this example) + | (free) | | | | + top-->| ...stack... | | | | + : ... : | | | + |incoming args | | | | + |--------------| | | -- + |fun | | | | + |saved_pc | | | | + |saved_top | | | | + |saved_fp |<- | | previous frame + |--------------| | | + | (free) | | | + | ...stack... |<---- | + : ... : | + |incoming args | | + |--------------| -- + : : +*/ + +INLINE void * +sf_get_ptr (Lisp_Object *fp, enum stack_frame_index index) +{ + return XLP (fp[index]); +} + +INLINE void +sf_set_ptr (Lisp_Object *fp, enum stack_frame_index index, void *value) +{ + fp[index] = XIL ((EMACS_INT)value); +} + +INLINE Lisp_Object * +sf_get_lisp_ptr (Lisp_Object *fp, enum stack_frame_index index) +{ + return sf_get_ptr (fp, index); +} + +INLINE void +sf_set_lisp_ptr (Lisp_Object *fp, enum stack_frame_index index, + Lisp_Object *value) +{ + sf_set_ptr (fp, index, value); +} + +INLINE const unsigned char * +sf_get_saved_pc (Lisp_Object *fp) +{ + return sf_get_ptr (fp, SFI_SAVED_PC); +} + +INLINE void +sf_set_saved_pc (Lisp_Object *fp, const unsigned char *value) +{ + sf_set_ptr (fp, SFI_SAVED_PC, (unsigned char *)value); +} + +void +init_bc_thread (struct bc_thread_state *bc) +{ + bc->stack = xmalloc (BC_STACK_SIZE * sizeof *bc->stack); + bc->stack_end = bc->stack + BC_STACK_SIZE; + /* Put a dummy header at the bottom to indicate the first free location. */ + bc->fp = bc->stack; + memset (bc->fp, 0, SF_SIZE * sizeof *bc->stack); +} + +void +free_bc_thread (struct bc_thread_state *bc) +{ + xfree (bc->stack); +} + +void +mark_bytecode (struct bc_thread_state *bc) +{ + Lisp_Object *fp = bc->fp; + Lisp_Object *top = NULL; /* stack pointer of topmost frame not known */ + for (;;) + { + Lisp_Object *next_fp = sf_get_lisp_ptr (fp, SFI_SAVED_FP); + /* Only the dummy frame at the bottom has saved_fp = NULL. */ + if (!next_fp) + break; + mark_object (fp[SFI_FUN]); + Lisp_Object *frame_base = next_fp + SF_SIZE; + if (top) + { + /* The stack pointer of a frame is known: mark the part of the stack + above it conservatively. This includes any outgoing arguments. */ + mark_memory (top + 1, fp); + /* Mark the rest of the stack precisely. */ + mark_objects (frame_base, top + 1 - frame_base); + } + else + { + /* The stack pointer is unknown -- mark everything conservatively. */ + mark_memory (frame_base, fp); + } + top = sf_get_lisp_ptr (fp, SFI_SAVED_TOP); + fp = next_fp; + } +} + +DEFUN ("internal-stack-stats", Finternal_stack_stats, Sinternal_stack_stats, + 0, 0, 0, + doc: /* internal */) + (void) +{ + struct bc_thread_state *bc = ¤t_thread->bc; + int nframes = 0; + int nruns = 0; + for (Lisp_Object *fp = bc->fp; fp; fp = sf_get_lisp_ptr (fp, SFI_SAVED_FP)) + { + nframes++; + if (sf_get_lisp_ptr (fp, SFI_SAVED_TOP) == NULL) + nruns++; + } + fprintf (stderr, "%d stack frames, %d runs\n", nframes, nruns); + return Qnil; +} + +/* Whether a stack pointer is valid in the current frame. */ +INLINE bool +valid_sp (struct bc_thread_state *bc, Lisp_Object *sp) +{ + Lisp_Object *fp = bc->fp; + return sp < fp && sp + 1 >= sf_get_lisp_ptr (fp, SFI_SAVED_FP) + SF_SIZE; +} + /* Execute the byte-code in FUN. ARGS_TEMPLATE is the function arity encoded as an integer (the one in FUN is ignored), and ARGS, of size NARGS, should be a vector of the actual arguments. The @@ -347,37 +507,49 @@ exec_byte_code (Lisp_Object fun, ptrdiff_t args_template, #ifdef BYTE_CODE_METER int volatile this_op = 0; #endif + unsigned char quitcounter = 1; + struct bc_thread_state *bc = ¤t_thread->bc; + + /* Values used for the first stack record when called from C. */ + Lisp_Object *top = NULL; + unsigned char const *pc = NULL; Lisp_Object bytestr = AREF (fun, COMPILED_BYTECODE); + setup_frame: ; eassert (!STRING_MULTIBYTE (bytestr)); eassert (string_immovable_p (bytestr)); + /* FIXME: in debug mode (!NDEBUG, BYTE_CODE_SAFE or enabled checking), + save the specpdl index on function entry and check that it is the same + when returning, to detect unwind imbalances. This would require adding + a field to the frame header. */ + Lisp_Object vector = AREF (fun, COMPILED_CONSTANTS); Lisp_Object maxdepth = AREF (fun, COMPILED_STACK_DEPTH); ptrdiff_t const_length = ASIZE (vector); ptrdiff_t bytestr_length = SCHARS (bytestr); Lisp_Object *vectorp = XVECTOR (vector)->contents; - unsigned char quitcounter = 1; - /* Allocate two more slots than required, because... */ - EMACS_INT stack_items = XFIXNAT (maxdepth) + 2; - USE_SAFE_ALLOCA; - void *alloc; - SAFE_ALLOCA_LISP (alloc, stack_items); - Lisp_Object *stack_base = alloc; - /* ... we plonk BYTESTR and VECTOR there to ensure that they survive - GC (bug#33014), since these variables aren't used directly beyond - the interpreter prologue and wouldn't be found in the stack frame - otherwise. */ - stack_base[0] = bytestr; - stack_base[1] = vector; - Lisp_Object *top = stack_base + 1; - Lisp_Object *stack_lim = top + stack_items; + EMACS_INT max_stack = XFIXNAT (maxdepth); + Lisp_Object *frame_base = bc->fp + SF_SIZE; + Lisp_Object *fp = frame_base + max_stack; + + if (fp + SF_SIZE > bc->stack_end) + error ("Bytecode stack overflow"); + + /* Save the function object so that the bytecode and vector are + held from removal by the GC. */ + fp[SFI_FUN] = fun; + /* Save previous stack pointer and pc in the new frame. If we came + directly from outside, these will be NULL. */ + sf_set_lisp_ptr (fp, SFI_SAVED_TOP, top); + sf_set_saved_pc (fp, pc); + sf_set_lisp_ptr (fp, SFI_SAVED_FP, bc->fp); + bc->fp = fp; + + top = frame_base - 1; unsigned char const *bytestr_data = SDATA (bytestr); - unsigned char const *pc = bytestr_data; -#if BYTE_CODE_SAFE || !defined NDEBUG - specpdl_ref count = SPECPDL_INDEX (); -#endif + pc = bytestr_data; /* ARGS_TEMPLATE is composed of bit fields: bits 0..6 minimum number of arguments @@ -404,7 +576,7 @@ exec_byte_code (Lisp_Object fun, ptrdiff_t args_template, int op; enum handlertype type; - if (BYTE_CODE_SAFE && ! (stack_base <= top && top < stack_lim)) + if (BYTE_CODE_SAFE && !valid_sp (bc, top)) emacs_abort (); #ifdef BYTE_CODE_METER @@ -636,36 +808,45 @@ exec_byte_code (Lisp_Object fun, ptrdiff_t args_template, error ("Lisp nesting exceeds `max-lisp-eval-depth'"); } - ptrdiff_t numargs = op; - Lisp_Object fun = TOP; - Lisp_Object *args = &TOP + 1; + ptrdiff_t call_nargs = op; + Lisp_Object call_fun = TOP; + Lisp_Object *call_args = &TOP + 1; - specpdl_ref count1 = record_in_backtrace (fun, args, numargs); + specpdl_ref count1 = record_in_backtrace (call_fun, + call_args, call_nargs); maybe_gc (); if (debug_on_next_call) do_debug_on_call (Qlambda, count1); - Lisp_Object original_fun = fun; - if (SYMBOLP (fun)) - fun = XSYMBOL (fun)->u.s.function; + Lisp_Object original_fun = call_fun; + if (SYMBOLP (call_fun)) + call_fun = XSYMBOL (call_fun)->u.s.function; Lisp_Object template; Lisp_Object bytecode; - Lisp_Object val; - if (COMPILEDP (fun) + if (COMPILEDP (call_fun) // Lexical binding only. - && (template = AREF (fun, COMPILED_ARGLIST), + && (template = AREF (call_fun, COMPILED_ARGLIST), FIXNUMP (template)) // No autoloads. - && (bytecode = AREF (fun, COMPILED_BYTECODE), + && (bytecode = AREF (call_fun, COMPILED_BYTECODE), !CONSP (bytecode))) - val = exec_byte_code (fun, XFIXNUM (template), numargs, args); - else if (SUBRP (fun) && !SUBR_NATIVE_COMPILED_DYNP (fun)) - val = funcall_subr (XSUBR (fun), numargs, args); + { + fun = call_fun; + bytestr = bytecode; + args_template = XFIXNUM (template); + nargs = call_nargs; + args = call_args; + goto setup_frame; + } + + Lisp_Object val; + if (SUBRP (call_fun) && !SUBR_NATIVE_COMPILED_DYNP (call_fun)) + val = funcall_subr (XSUBR (call_fun), call_nargs, call_args); else - val = funcall_general (original_fun, numargs, args); + val = funcall_general (original_fun, call_nargs, call_args); lisp_eval_depth--; - if (backtrace_debug_on_exit (specpdl_ref_to_ptr (count1))) + if (backtrace_debug_on_exit (specpdl_ptr - 1)) val = call_debugger (list2 (Qexit, val)); specpdl_ptr--; @@ -731,7 +912,40 @@ exec_byte_code (Lisp_Object fun, ptrdiff_t args_template, NEXT; CASE (Breturn): - goto exit; + { + Lisp_Object *saved_top = sf_get_lisp_ptr (bc->fp, SFI_SAVED_TOP); + if (saved_top) + { + Lisp_Object val = TOP; + + lisp_eval_depth--; + if (backtrace_debug_on_exit (specpdl_ptr - 1)) + val = call_debugger (list2 (Qexit, val)); + specpdl_ptr--; + + top = saved_top; + pc = sf_get_saved_pc (bc->fp); + Lisp_Object *fp = sf_get_lisp_ptr (bc->fp, SFI_SAVED_FP); + bc->fp = fp; + + Lisp_Object fun = fp[SFI_FUN]; + Lisp_Object bytestr = AREF (fun, COMPILED_BYTECODE); + Lisp_Object vector = AREF (fun, COMPILED_CONSTANTS); + bytestr_data = SDATA (bytestr); + vectorp = XVECTOR (vector)->contents; + if (BYTE_CODE_SAFE) + { + /* Only required for checking, not for execution. */ + const_length = ASIZE (vector); + bytestr_length = SCHARS (bytestr); + } + + TOP = val; + NEXT; + } + else + goto exit; + } CASE (Bdiscard): DISCARD (1); @@ -786,9 +1000,23 @@ exec_byte_code (Lisp_Object fun, ptrdiff_t args_template, if (sys_setjmp (c->jmp)) { struct handler *c = handlerlist; + handlerlist = c->next; top = c->bytecode_top; op = c->bytecode_dest; - handlerlist = c->next; + Lisp_Object *fp = bc->fp; + + Lisp_Object fun = fp[SFI_FUN]; + Lisp_Object bytestr = AREF (fun, COMPILED_BYTECODE); + Lisp_Object vector = AREF (fun, COMPILED_CONSTANTS); + bytestr_data = SDATA (bytestr); + vectorp = XVECTOR (vector)->contents; + if (BYTE_CODE_SAFE) + { + /* Only required for checking, not for execution. */ + const_length = ASIZE (vector); + bytestr_length = SCHARS (bytestr); + } + pc = bytestr_data; PUSH (c->val); goto op_branch; } @@ -1527,20 +1755,9 @@ exec_byte_code (Lisp_Object fun, ptrdiff_t args_template, exit: -#if BYTE_CODE_SAFE || !defined NDEBUG - if (!specpdl_ref_eq (SPECPDL_INDEX (), count)) - { - /* Binds and unbinds are supposed to be compiled balanced. */ - if (specpdl_ref_lt (count, SPECPDL_INDEX ())) - unbind_to (count, Qnil); - error ("binding stack not balanced (serious byte compiler bug)"); - } -#endif - /* The byte code should have been properly pinned. */ - eassert (SDATA (bytestr) == bytestr_data); + bc->fp = sf_get_lisp_ptr (bc->fp, SFI_SAVED_FP); Lisp_Object result = TOP; - SAFE_FREE (); return result; } @@ -1562,6 +1779,7 @@ void syms_of_bytecode (void) { defsubr (&Sbyte_code); + defsubr (&Sinternal_stack_stats); #ifdef BYTE_CODE_METER -- cgit v1.2.1 From edb8481ce15404d9157e104958aef22b05b606a7 Mon Sep 17 00:00:00 2001 From: Mattias Engdegård Date: Sun, 13 Mar 2022 19:35:50 +0100 Subject: * src/bytecode.c (sf_set_ptr): Cast pointer to type of right size. --- src/bytecode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/bytecode.c') diff --git a/src/bytecode.c b/src/bytecode.c index 9356ebeb6cb..b26146c27f3 100644 --- a/src/bytecode.c +++ b/src/bytecode.c @@ -393,7 +393,7 @@ sf_get_ptr (Lisp_Object *fp, enum stack_frame_index index) INLINE void sf_set_ptr (Lisp_Object *fp, enum stack_frame_index index, void *value) { - fp[index] = XIL ((EMACS_INT)value); + fp[index] = XIL ((uintptr_t)value); } INLINE Lisp_Object * -- cgit v1.2.1 From 485a8fcbf4974466022798c0159e954af9482cf1 Mon Sep 17 00:00:00 2001 From: Glenn Morris Date: Sun, 13 Mar 2022 18:03:11 -0700 Subject: * src/bytecode.c: Include sysstdio.h, for fprint, stderr. ; Ref https://hydra.nixos.org/build/169207408 --- src/bytecode.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src/bytecode.c') diff --git a/src/bytecode.c b/src/bytecode.c index b26146c27f3..8704e6069dd 100644 --- a/src/bytecode.c +++ b/src/bytecode.c @@ -21,6 +21,7 @@ along with GNU Emacs. If not, see . */ #include "lisp.h" #include "blockinput.h" +#include "sysstdio.h" #include "character.h" #include "buffer.h" #include "keyboard.h" -- cgit v1.2.1 From 0d0703e9c4fb5ebcd4a87e5ebe78e5f53496621e Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Mon, 14 Mar 2022 08:55:46 -0700 Subject: Prefer CALLN * src/bytecode.c (Fbyte_code): * src/composite.c (Fclear_composition_cache): Prefer CALLN to doing it by hand. * src/fns.c (ccall2): Remove. All uses replaced by CALLN. --- src/bytecode.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/bytecode.c') diff --git a/src/bytecode.c b/src/bytecode.c index 8704e6069dd..65c3ad4da70 100644 --- a/src/bytecode.c +++ b/src/bytecode.c @@ -325,8 +325,8 @@ If the third argument is incorrect, Emacs may crash. */) the original unibyte form. */ bytestr = Fstring_as_unibyte (bytestr); } - Lisp_Object args[] = {0, bytestr, vector, maxdepth}; - return exec_byte_code (Fmake_byte_code (4, args), 0, 0, NULL); + Lisp_Object fun = CALLN (Fmake_byte_code, 0, bytestr, vector, maxdepth); + return exec_byte_code (fun, 0, 0, NULL); } static void -- cgit v1.2.1 From 751c8f88c4faddb2b4f5d5ba3f051e8cd2c0153c Mon Sep 17 00:00:00 2001 From: Mattias Engdegård Date: Mon, 14 Mar 2022 12:57:29 +0100 Subject: Put bytecode stack frame metadata in a struct Using a plain C struct instead of type-punning Lisp_Object stack slots makes the bytecode interpreter code more type-safe and potentially faster (from better alias analysis), and the special-purpose accessors are no longer needed. It also reduces the stack requirements when using 64-bit Lisp_Object on 32-bit platforms. * src/bytecode.c (enum stack_frame_index) (sf_get_ptr, sf_set_ptr, sf_get_lisp_ptr, sf_set_lisp_ptr, sf_get_saved_pc, sf_set_saved_pc): Remove. (BC_STACK_SIZE): Now in bytes, not Lisp words. (struct bc_frame): New. (init_bc_thread, mark_bytecode, Finternal_stack_stats, valid_sp) (exec_byte_code): * src/lisp.h (struct handler, get_act_rec, set_act_rec): Adapt to new struct bc_frame. --- src/bytecode.c | 112 ++++++++++++++++++++------------------------------------- 1 file changed, 38 insertions(+), 74 deletions(-) (limited to 'src/bytecode.c') diff --git a/src/bytecode.c b/src/bytecode.c index 65c3ad4da70..ed1f6ca4a85 100644 --- a/src/bytecode.c +++ b/src/bytecode.c @@ -335,20 +335,7 @@ bcall0 (Lisp_Object f) Ffuncall (1, &f); } -/* Layout of the stack frame header. */ -enum stack_frame_index { - SFI_SAVED_FP, /* previous frame pointer */ - - /* In a frame called directly from C, the following two members are NULL. */ - SFI_SAVED_TOP, /* previous stack pointer */ - SFI_SAVED_PC, /* previous program counter */ - - SFI_FUN, /* current function object */ - - SF_SIZE /* number of words in the header */ -}; - -/* The bytecode stack size in Lisp words. +/* The bytecode stack size in bytes. This is a fairly generous amount, but: - if users need more, we could allocate more, or just reserve the address space and allocate on demand @@ -357,7 +344,7 @@ enum stack_frame_index { - for maximum flexibility but a small runtime penalty, we could allocate the stack in smaller chunks as needed */ -#define BC_STACK_SIZE (512 * 1024) +#define BC_STACK_SIZE (512 * 1024 * sizeof (Lisp_Object)) /* Bytecode interpreter stack: @@ -385,51 +372,28 @@ enum stack_frame_index { : : */ -INLINE void * -sf_get_ptr (Lisp_Object *fp, enum stack_frame_index index) -{ - return XLP (fp[index]); -} - -INLINE void -sf_set_ptr (Lisp_Object *fp, enum stack_frame_index index, void *value) -{ - fp[index] = XIL ((uintptr_t)value); -} - -INLINE Lisp_Object * -sf_get_lisp_ptr (Lisp_Object *fp, enum stack_frame_index index) -{ - return sf_get_ptr (fp, index); -} +/* bytecode stack frame header (footer, actually) */ +struct bc_frame { + struct bc_frame *saved_fp; /* previous frame pointer, + NULL if bottommost frame */ -INLINE void -sf_set_lisp_ptr (Lisp_Object *fp, enum stack_frame_index index, - Lisp_Object *value) -{ - sf_set_ptr (fp, index, value); -} + /* In a frame called directly from C, the following two members are NULL. */ + Lisp_Object *saved_top; /* previous stack pointer */ + const unsigned char *saved_pc; /* previous program counter */ -INLINE const unsigned char * -sf_get_saved_pc (Lisp_Object *fp) -{ - return sf_get_ptr (fp, SFI_SAVED_PC); -} + Lisp_Object fun; /* current function object */ -INLINE void -sf_set_saved_pc (Lisp_Object *fp, const unsigned char *value) -{ - sf_set_ptr (fp, SFI_SAVED_PC, (unsigned char *)value); -} + Lisp_Object next_stack[]; /* data stack of next frame */ +}; void init_bc_thread (struct bc_thread_state *bc) { - bc->stack = xmalloc (BC_STACK_SIZE * sizeof *bc->stack); + bc->stack = xmalloc (BC_STACK_SIZE); bc->stack_end = bc->stack + BC_STACK_SIZE; /* Put a dummy header at the bottom to indicate the first free location. */ - bc->fp = bc->stack; - memset (bc->fp, 0, SF_SIZE * sizeof *bc->stack); + bc->fp = (struct bc_frame *)bc->stack; + memset (bc->fp, 0, sizeof *bc->fp); } void @@ -441,16 +405,16 @@ free_bc_thread (struct bc_thread_state *bc) void mark_bytecode (struct bc_thread_state *bc) { - Lisp_Object *fp = bc->fp; + struct bc_frame *fp = bc->fp; Lisp_Object *top = NULL; /* stack pointer of topmost frame not known */ for (;;) { - Lisp_Object *next_fp = sf_get_lisp_ptr (fp, SFI_SAVED_FP); + struct bc_frame *next_fp = fp->saved_fp; /* Only the dummy frame at the bottom has saved_fp = NULL. */ if (!next_fp) break; - mark_object (fp[SFI_FUN]); - Lisp_Object *frame_base = next_fp + SF_SIZE; + mark_object (fp->fun); + Lisp_Object *frame_base = next_fp->next_stack; if (top) { /* The stack pointer of a frame is known: mark the part of the stack @@ -464,7 +428,7 @@ mark_bytecode (struct bc_thread_state *bc) /* The stack pointer is unknown -- mark everything conservatively. */ mark_memory (frame_base, fp); } - top = sf_get_lisp_ptr (fp, SFI_SAVED_TOP); + top = fp->saved_top; fp = next_fp; } } @@ -477,10 +441,10 @@ DEFUN ("internal-stack-stats", Finternal_stack_stats, Sinternal_stack_stats, struct bc_thread_state *bc = ¤t_thread->bc; int nframes = 0; int nruns = 0; - for (Lisp_Object *fp = bc->fp; fp; fp = sf_get_lisp_ptr (fp, SFI_SAVED_FP)) + for (struct bc_frame *fp = bc->fp; fp; fp = fp->saved_fp) { nframes++; - if (sf_get_lisp_ptr (fp, SFI_SAVED_TOP) == NULL) + if (fp->saved_top == NULL) nruns++; } fprintf (stderr, "%d stack frames, %d runs\n", nframes, nruns); @@ -491,8 +455,8 @@ DEFUN ("internal-stack-stats", Finternal_stack_stats, Sinternal_stack_stats, INLINE bool valid_sp (struct bc_thread_state *bc, Lisp_Object *sp) { - Lisp_Object *fp = bc->fp; - return sp < fp && sp + 1 >= sf_get_lisp_ptr (fp, SFI_SAVED_FP) + SF_SIZE; + struct bc_frame *fp = bc->fp; + return sp < (Lisp_Object *)fp && sp + 1 >= fp->saved_fp->next_stack; } /* Execute the byte-code in FUN. ARGS_TEMPLATE is the function arity @@ -532,20 +496,20 @@ exec_byte_code (Lisp_Object fun, ptrdiff_t args_template, Lisp_Object *vectorp = XVECTOR (vector)->contents; EMACS_INT max_stack = XFIXNAT (maxdepth); - Lisp_Object *frame_base = bc->fp + SF_SIZE; - Lisp_Object *fp = frame_base + max_stack; + Lisp_Object *frame_base = bc->fp->next_stack; + struct bc_frame *fp = (struct bc_frame *)(frame_base + max_stack); - if (fp + SF_SIZE > bc->stack_end) + if ((char *)fp->next_stack > bc->stack_end) error ("Bytecode stack overflow"); /* Save the function object so that the bytecode and vector are held from removal by the GC. */ - fp[SFI_FUN] = fun; + fp->fun = fun; /* Save previous stack pointer and pc in the new frame. If we came directly from outside, these will be NULL. */ - sf_set_lisp_ptr (fp, SFI_SAVED_TOP, top); - sf_set_saved_pc (fp, pc); - sf_set_lisp_ptr (fp, SFI_SAVED_FP, bc->fp); + fp->saved_top = top; + fp->saved_pc = pc; + fp->saved_fp = bc->fp; bc->fp = fp; top = frame_base - 1; @@ -914,7 +878,7 @@ exec_byte_code (Lisp_Object fun, ptrdiff_t args_template, CASE (Breturn): { - Lisp_Object *saved_top = sf_get_lisp_ptr (bc->fp, SFI_SAVED_TOP); + Lisp_Object *saved_top = bc->fp->saved_top; if (saved_top) { Lisp_Object val = TOP; @@ -925,11 +889,11 @@ exec_byte_code (Lisp_Object fun, ptrdiff_t args_template, specpdl_ptr--; top = saved_top; - pc = sf_get_saved_pc (bc->fp); - Lisp_Object *fp = sf_get_lisp_ptr (bc->fp, SFI_SAVED_FP); + pc = bc->fp->saved_pc; + struct bc_frame *fp = bc->fp->saved_fp; bc->fp = fp; - Lisp_Object fun = fp[SFI_FUN]; + Lisp_Object fun = fp->fun; Lisp_Object bytestr = AREF (fun, COMPILED_BYTECODE); Lisp_Object vector = AREF (fun, COMPILED_CONSTANTS); bytestr_data = SDATA (bytestr); @@ -1004,9 +968,9 @@ exec_byte_code (Lisp_Object fun, ptrdiff_t args_template, handlerlist = c->next; top = c->bytecode_top; op = c->bytecode_dest; - Lisp_Object *fp = bc->fp; + struct bc_frame *fp = bc->fp; - Lisp_Object fun = fp[SFI_FUN]; + Lisp_Object fun = fp->fun; Lisp_Object bytestr = AREF (fun, COMPILED_BYTECODE); Lisp_Object vector = AREF (fun, COMPILED_CONSTANTS); bytestr_data = SDATA (bytestr); @@ -1756,7 +1720,7 @@ exec_byte_code (Lisp_Object fun, ptrdiff_t args_template, exit: - bc->fp = sf_get_lisp_ptr (bc->fp, SFI_SAVED_FP); + bc->fp = bc->fp->saved_fp; Lisp_Object result = TOP; return result; -- cgit v1.2.1 From c11b4758b7bd971fcbb824638a06f52c7768d268 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Sat, 19 Mar 2022 12:35:04 -0700 Subject: valid_sp inline fix * src/bytecode.c (valid_sp): static, not INLINE, as INLINE should be used only in headers and between INLINE_HEADER_BEGIN and INLINE_HEADER_END. No need for ‘inline’ here. --- src/bytecode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/bytecode.c') diff --git a/src/bytecode.c b/src/bytecode.c index ed1f6ca4a85..62464986160 100644 --- a/src/bytecode.c +++ b/src/bytecode.c @@ -452,7 +452,7 @@ DEFUN ("internal-stack-stats", Finternal_stack_stats, Sinternal_stack_stats, } /* Whether a stack pointer is valid in the current frame. */ -INLINE bool +static bool valid_sp (struct bc_thread_state *bc, Lisp_Object *sp) { struct bc_frame *fp = bc->fp; -- cgit v1.2.1 From 71005decb4fb447635d7b2367104dd18bdfa64ac Mon Sep 17 00:00:00 2001 From: Stefan Monnier Date: Tue, 19 Apr 2022 08:25:19 -0400 Subject: Fix GCC warnings when CHECK_LISP_OBJECT_TYPE * src/lisp.h (lisp_h_Qni): New macro. (DEFUN): Use it. * src/alloc.c (syms_of_alloc): Use it. * src/bytecode.c (Fbyte_code): Fix Lisp_Object/int mixup. --- src/bytecode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/bytecode.c') diff --git a/src/bytecode.c b/src/bytecode.c index 62464986160..74b7d16affd 100644 --- a/src/bytecode.c +++ b/src/bytecode.c @@ -325,7 +325,7 @@ If the third argument is incorrect, Emacs may crash. */) the original unibyte form. */ bytestr = Fstring_as_unibyte (bytestr); } - Lisp_Object fun = CALLN (Fmake_byte_code, 0, bytestr, vector, maxdepth); + Lisp_Object fun = CALLN (Fmake_byte_code, Qnil, bytestr, vector, maxdepth); return exec_byte_code (fun, 0, 0, NULL); } -- cgit v1.2.1 From 0e5623b491cb4158d8055b9c2ee7963fee8c75de Mon Sep 17 00:00:00 2001 From: Stefan Kangas Date: Thu, 12 May 2022 09:32:10 +0200 Subject: ; * src/bytecode.c (exec_byte_code): Fix white space. --- src/bytecode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/bytecode.c') diff --git a/src/bytecode.c b/src/bytecode.c index 74b7d16affd..a0bcbb48481 100644 --- a/src/bytecode.c +++ b/src/bytecode.c @@ -1209,7 +1209,7 @@ exec_byte_code (Lisp_Object fun, ptrdiff_t args_template, Lisp_Object v2 = POP; Lisp_Object v1 = TOP; if (FIXNUMP (v1) && FIXNUMP (v2)) - TOP = BASE_EQ(v1, v2) ? Qt : Qnil; + TOP = BASE_EQ (v1, v2) ? Qt : Qnil; else TOP = arithcompare (v1, v2, ARITH_EQUAL); NEXT; -- cgit v1.2.1 From bab1d412801eead715f1465131aa3734558f35ab Mon Sep 17 00:00:00 2001 From: Mattias Engdegård Date: Sun, 12 Jun 2022 12:05:03 +0200 Subject: Use BASE_EQ when comparing with Qunbound Qunbound is uninterned and can therefore never be EQ to any symbol with position. * src/buffer.c (Fbuffer_local_value, buffer_lisp_local_variables) (buffer_local_variables_1): * src/bytecode.c (exec_byte_code): * src/comp.c (compile_function, Fcomp__compile_ctxt_to_file): * src/composite.c (composition_gstring_cache_clear_font): * src/data.c (Fboundp, Fsymbol_value, set_internal) (Fdefault_boundp, Fdefault_value, Fmake_variable_buffer_local): * src/emacs-module.c (module_global_reference_p): * src/eval.c (Fdefault_toplevel_value, defvar) (run_hook_with_args): * src/fns.c (hash_put, Fmaphash): * src/font.c (font_put_extra): * src/frame.c (gui_set_frame_parameters) (gui_frame_get_and_record_arg, gui_default_parameter) (gui_figure_window_size): * src/haikufns.c (get_geometry_from_preferences) (haiku_create_frame, haiku_create_tip_frame): * src/haikuterm.c (haiku_draw_text_decoration) (haiku_default_font_parameter): * src/json.c (lisp_to_json_nonscalar_1): * src/keymap.c (access_keymap_1, access_keymap, current_minor_maps): * src/lread.c (readevalloop, define_symbol): * src/minibuf.c (read_minibuf, Ftry_completion): (Fall_completions, Ftest_completion): * src/pgtkfns.c (pgtk_default_font_parameter, Fx_create_frame) (x_create_tip_frame): * src/pgtkselect.c (Fpgtk_own_selection_internal): * src/print.c (print): * src/profiler.c (evict_lower_half, record_backtrace): * src/terminal.c (create_terminal): * src/textprop.c (set_properties): * src/w32fns.c (my_create_window, w32_icon) (w32_default_font_parameter, Fx_create_frame) (w32_create_tip_frame): * src/w32term.c (w32_draw_glyph_string): * src/xdisp.c (handle_single_display_spec) (cursor_row_fully_visible_p, calc_pixel_width_or_height): * src/xfns.c (x_default_scroll_bar_color_parameter, x_icon_verify) (x_icon, x_default_font_parameter, Fx_create_frame) (x_create_tip_frame): * src/xselect.c (x_handle_selection_request): * src/xterm.c (x_draw_glyph_string, x_term_init): Use BASE_EQ instead of EQ when comparing with Qunbound. --- src/bytecode.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/bytecode.c') diff --git a/src/bytecode.c b/src/bytecode.c index a0bcbb48481..fa068e1ec6b 100644 --- a/src/bytecode.c +++ b/src/bytecode.c @@ -627,7 +627,7 @@ exec_byte_code (Lisp_Object fun, ptrdiff_t args_template, Lisp_Object v1 = vectorp[op], v2; if (!SYMBOLP (v1) || XSYMBOL (v1)->u.s.redirect != SYMBOL_PLAINVAL - || (v2 = SYMBOL_VAL (XSYMBOL (v1)), EQ (v2, Qunbound))) + || (v2 = SYMBOL_VAL (XSYMBOL (v1)), BASE_EQ (v2, Qunbound))) v2 = Fsymbol_value (v1); PUSH (v2); NEXT; @@ -694,7 +694,7 @@ exec_byte_code (Lisp_Object fun, ptrdiff_t args_template, /* Inline the most common case. */ if (SYMBOLP (sym) - && !EQ (val, Qunbound) + && !BASE_EQ (val, Qunbound) && XSYMBOL (sym)->u.s.redirect == SYMBOL_PLAINVAL && !SYMBOL_TRAPPED_WRITE_P (sym)) SET_SYMBOL_VAL (XSYMBOL (sym), val); -- cgit v1.2.1 From 253a4a2c689d757cb798cfb9f51b2110283d7146 Mon Sep 17 00:00:00 2001 From: Mattias Engdegård Date: Fri, 24 Jun 2022 11:48:42 +0200 Subject: Bytecode opcode comments update This is a cosmetic change only; there is no change in behaviour. * lisp/emacs-lisp/bytecomp.el: * src/bytecode.c (BYTE_CODES, exec_byte_code): Update and/or remove incorrect, outdated or useless comments. Clarify. Reorder where appropriate. Rename Bsave_current_buffer to Bsave_current_buffer_OBSOLETE and Bsave_current_buffer_1 to Bsave_current_buffer, reflecting the state since 1996. --- src/bytecode.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'src/bytecode.c') diff --git a/src/bytecode.c b/src/bytecode.c index fa068e1ec6b..d75767bb0c5 100644 --- a/src/bytecode.c +++ b/src/bytecode.c @@ -176,8 +176,8 @@ DEFINE (Bmin, 0136) \ DEFINE (Bmult, 0137) \ \ DEFINE (Bpoint, 0140) \ -/* Was Bmark in v17. */ \ -DEFINE (Bsave_current_buffer, 0141) /* Obsolete. */ \ +/* 0141 was Bmark in v17, Bsave_current_buffer in 18-19. */ \ +DEFINE (Bsave_current_buffer_OBSOLETE, 0141) /* Obsolete since 20. */ \ DEFINE (Bgoto_char, 0142) \ DEFINE (Binsert, 0143) \ DEFINE (Bpoint_max, 0144) \ @@ -194,7 +194,7 @@ 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 (Bsave_current_buffer, 0162) \ /* 0163 was Bset_mark in v17. */ \ DEFINE (Binteractive_p, 0164) /* Obsolete since Emacs-24.1. */ \ \ @@ -924,8 +924,8 @@ exec_byte_code (Lisp_Object fun, ptrdiff_t args_template, record_unwind_protect_excursion (); NEXT; - CASE (Bsave_current_buffer): /* Obsolete since ??. */ - CASE (Bsave_current_buffer_1): + CASE (Bsave_current_buffer_OBSOLETE): /* Obsolete since 20. */ + CASE (Bsave_current_buffer): record_unwind_current_buffer (); NEXT; @@ -1678,6 +1678,12 @@ exec_byte_code (Lisp_Object fun, ptrdiff_t args_template, /* TODO: Perhaps introduce another byte-code for switch when the number of cases is less, which uses a simple vector for linear search as the jump table. */ + + /* TODO: Instead of pushing the table in a separate + Bconstant op, use an immediate argument (maybe separate + switch opcodes for 1-byte and 2-byte constant indices). + This would also get rid of some hacks that assume each + Bswitch to be preceded by a Bconstant. */ Lisp_Object jmp_table = POP; if (BYTE_CODE_SAFE && !HASH_TABLE_P (jmp_table)) emacs_abort (); -- cgit v1.2.1 From d3c4833d1350e26a2ae35e00eaf2d6bef1724679 Mon Sep 17 00:00:00 2001 From: Gregory Heytings Date: Thu, 28 Jul 2022 20:37:49 +0000 Subject: Add an optional 'lock' parameter to 'narrow-to-region' * src/editfns.c (Fnarrow_to_region): Add the parameter to the function, and handle it. Update docstring. (unwind_locked_begv, unwind_locked_zv): New functions. (Fwiden): Do nothing when restrictions are locked. Update docstring. (syms_of_editfns): Replace the 'inhibit-widen' symbol and variable with a 'restrictions-locked' symbol and variable. Update docstring. * src/xdisp.c (handle_fontified_prop): Use Fnarrow_to_region with the new parameter. (unwind_narrowed_zv): Remove function. * src/process.c (Finternal_default_process_filter): Add a third argument to Fnarrow_to_region. * src/lread.c (readevalloop): Add a third argument to Fnarrow_to_region. * src/bytecode.c (exec_byte_code): Add a third argument to Fnarrow_to_region. * etc/NEWS (like): Mention the new parameter of 'narrow-to-region'. * doc/lispref/positions.texi (Narrowing): Document it. --- src/bytecode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/bytecode.c') diff --git a/src/bytecode.c b/src/bytecode.c index d75767bb0c5..241cbaf04f6 100644 --- a/src/bytecode.c +++ b/src/bytecode.c @@ -1481,7 +1481,7 @@ exec_byte_code (Lisp_Object fun, ptrdiff_t args_template, CASE (Bnarrow_to_region): { Lisp_Object v1 = POP; - TOP = Fnarrow_to_region (TOP, v1); + TOP = Fnarrow_to_region (TOP, v1, Qnil); NEXT; } -- cgit v1.2.1 From a5adcbdf28eb8ad376a1004f4a6c9eda1f1447fb Mon Sep 17 00:00:00 2001 From: Gregory Heytings Date: Sat, 30 Jul 2022 12:02:28 +0000 Subject: Handle the optional argument of 'narrow-to-region' in byte-compiled code. * lisp/emacs-lisp/bytecomp.el: Adapt the specifications. * src/bytecode.c (exec_byte_code): Get the optional argument. --- src/bytecode.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/bytecode.c') diff --git a/src/bytecode.c b/src/bytecode.c index 241cbaf04f6..2b1eccdc518 100644 --- a/src/bytecode.c +++ b/src/bytecode.c @@ -1480,8 +1480,8 @@ exec_byte_code (Lisp_Object fun, ptrdiff_t args_template, CASE (Bnarrow_to_region): { - Lisp_Object v1 = POP; - TOP = Fnarrow_to_region (TOP, v1, Qnil); + Lisp_Object v2 = POP, v1 = POP; + TOP = Fnarrow_to_region (TOP, v1, v2); NEXT; } -- cgit v1.2.1