Bset_mark = 0163, /* this loser is no longer generated as of v18 */
#endif
};
-
-/* Whether to maintain a `top' and `bottom' field in the stack frame. */
-#define BYTE_MAINTAIN_TOP (BYTE_CODE_SAFE || BYTE_MARK_STACK)
\f
/* Structure describing a value stack used during byte-code execution
in Fbyte_code. */
and is relocated when that string is relocated. */
const unsigned char *pc;
- /* Top and bottom of stack. The bottom points to an area of memory
- allocated with alloca in Fbyte_code. */
-#if BYTE_MAINTAIN_TOP
- Lisp_Object *top, *bottom;
-#endif
-
/* The string containing the byte-code, and its current address.
Storing this here protects it from GC because mark_byte_stack
marks it. */
this here protects it from GC because mark_byte_stack marks it. */
Lisp_Object constants;
#endif
-
- /* Next entry in byte_stack_list. */
- struct byte_stack *next;
};
-
-/* A list of currently active byte-code execution value stacks.
- Fbyte_code adds an entry to the head of this list before it starts
- processing byte-code, and it removes the entry again when it is
- done. Signaling an error truncates the list analogous to
- gcprolist. */
-
-struct byte_stack *byte_stack_list;
-
-\f
-/* Mark objects on byte_stack_list. Called during GC. */
-
-#if BYTE_MARK_STACK
-void
-mark_byte_stack (void)
-{
- struct byte_stack *stack;
- Lisp_Object *obj;
-
- for (stack = byte_stack_list; stack; stack = stack->next)
- {
- /* If STACK->top is null here, this means there's an opcode in
- Fbyte_code that wasn't expected to GC, but did. To find out
- which opcode this is, record the value of `stack', and walk
- up the stack in a debugger, stopping in frames of Fbyte_code.
- The culprit is found in the frame of Fbyte_code where the
- address of its local variable `stack' is equal to the
- recorded value of `stack' here. */
- eassert (stack->top);
-
- for (obj = stack->bottom; obj <= stack->top; ++obj)
- mark_object (*obj);
-
- mark_object (stack->byte_string);
- mark_object (stack->constants);
- }
-}
-#endif
-
-/* Unmark objects in the stacks on byte_stack_list. Relocate program
- counters. Called when GC has completed. */
-
-void
-unmark_byte_stack (void)
-{
- struct byte_stack *stack;
-
- for (stack = byte_stack_list; stack; stack = stack->next)
- {
- if (stack->byte_string_start != SDATA (stack->byte_string))
- {
- ptrdiff_t offset = stack->pc - stack->byte_string_start;
- stack->byte_string_start = SDATA (stack->byte_string);
- stack->pc = stack->byte_string_start + offset;
- }
- }
-}
-
\f
/* Fetch the next byte from the bytecode stream. */
/* Actions that must be performed before and after calling a function
that might GC. */
-#if !BYTE_MAINTAIN_TOP
#define BEFORE_POTENTIAL_GC() ((void)0)
#define AFTER_POTENTIAL_GC() ((void)0)
-#else
-#define BEFORE_POTENTIAL_GC() stack.top = top
-#define AFTER_POTENTIAL_GC() stack.top = NULL
-#endif
/* Garbage collect if we have consed enough since the last time.
We do this at every branch, to avoid loops that never GC. */
ARGS are pushed on the stack according to ARGS_TEMPLATE before
executing BYTESTR. */
+/* {{coccinelle:skip_start}} */
Lisp_Object
exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
Lisp_Object args_template, ptrdiff_t nargs, Lisp_Object *args)
if (MAX_ALLOCA / word_size <= XFASTINT (maxdepth))
memory_full (SIZE_MAX);
top = alloca ((XFASTINT (maxdepth) + 1) * sizeof *top);
-#if BYTE_MAINTAIN_TOP
- stack.bottom = top + 1;
- stack.top = NULL;
-#endif
- stack.next = byte_stack_list;
- byte_stack_list = &stack;
#ifdef BYTE_CODE_SAFE
stacke = stack.bottom - 1 + XFASTINT (maxdepth);
varbind:
/* Specbind can signal and thus GC. */
BEFORE_POTENTIAL_GC ();
+ dynwind_begin ();
specbind (vectorp[op], POP);
AFTER_POTENTIAL_GC ();
NEXT;
op -= Bunbind;
dounbind:
BEFORE_POTENTIAL_GC ();
- unbind_to (SPECPDL_INDEX () - op, Qnil);
+ for (int i = 0; i < op; i++)
+ dynwind_end ();
AFTER_POTENTIAL_GC ();
NEXT;
CASE (Bunbind_all): /* Obsolete. Never used. */
- /* To unbind back to the beginning of this frame. Not used yet,
- but will be needed for tail-recursion elimination. */
- BEFORE_POTENTIAL_GC ();
- unbind_to (count, Qnil);
- AFTER_POTENTIAL_GC ();
+ emacs_abort ();
NEXT;
CASE (Bgoto):
NEXT;
CASE (Bsave_excursion):
+ dynwind_begin ();
record_unwind_protect (save_excursion_restore,
save_excursion_save ());
NEXT;
CASE (Bsave_current_buffer): /* Obsolete since ??. */
CASE (Bsave_current_buffer_1):
+ dynwind_begin ();
record_unwind_current_buffer ();
NEXT;
CASE (Bsave_window_excursion): /* Obsolete since 24.1. */
{
- ptrdiff_t count1 = SPECPDL_INDEX ();
+ dynwind_begin ();
record_unwind_protect (restore_window_configuration,
Fcurrent_window_configuration (Qnil));
BEFORE_POTENTIAL_GC ();
TOP = Fprogn (TOP);
- unbind_to (count1, TOP);
+ dynwind_end ();
AFTER_POTENTIAL_GC ();
NEXT;
}
CASE (Bsave_restriction):
+ dynwind_begin ();
record_unwind_protect (save_restriction_restore,
save_restriction_save ());
NEXT;
}
CASE (Bpushcatch): /* New in 24.4. */
- type = CATCHER;
- goto pushhandler;
- CASE (Bpushconditioncase): /* New in 24.4. */
- {
- extern EMACS_INT lisp_eval_depth;
- extern int poll_suppress_count;
- extern int interrupt_input_blocked;
- struct handler *c;
- Lisp_Object tag;
- int dest;
-
- type = CONDITION_CASE;
- pushhandler:
- tag = POP;
- dest = FETCH2;
+ emacs_abort ();
+ NEXT;
- PUSH_HANDLER (c, tag, type);
- c->bytecode_dest = dest;
- c->bytecode_top = top;
-
- if (sys_setjmp (c->jmp))
- {
- struct handler *c = handlerlist;
- int dest;
- top = c->bytecode_top;
- dest = c->bytecode_dest;
- handlerlist = c->next;
- PUSH (c->val);
- CHECK_RANGE (dest);
- /* Might have been re-set by longjmp! */
- stack.byte_string_start = SDATA (stack.byte_string);
- stack.pc = stack.byte_string_start + dest;
- }
-
- NEXT;
- }
+ CASE (Bpushconditioncase): /* New in 24.4. */
+ emacs_abort ();
+ NEXT;
CASE (Bpophandler): /* New in 24.4. */
- {
- handlerlist = handlerlist->next;
- NEXT;
- }
+ emacs_abort ();
+ NEXT;
CASE (Bunwind_protect): /* FIXME: avoid closure for lexbind. */
{
Lisp_Object handler = POP;
+ dynwind_begin ();
/* Support for a function here is new in 24.4. */
record_unwind_protect (NILP (Ffunctionp (handler))
? unwind_body : bcall0,
CASE (Btemp_output_buffer_setup): /* Obsolete since 24.1. */
BEFORE_POTENTIAL_GC ();
CHECK_STRING (TOP);
+ dynwind_begin ();
temp_output_buffer_setup (SSDATA (TOP));
AFTER_POTENTIAL_GC ();
TOP = Vstandard_output;
temp_output_buffer_show (TOP);
TOP = v1;
/* pop binding of standard-output */
- unbind_to (SPECPDL_INDEX () - 1, Qnil);
+ dynwind_end ();
AFTER_POTENTIAL_GC ();
NEXT;
}
exit:
- byte_stack_list = byte_stack_list->next;
-
/* Binds and unbinds are supposed to be compiled balanced. */
if (SPECPDL_INDEX () != count)
{
return result;
}
+/* {{coccinelle:skip_end}} */
void
syms_of_bytecode (void)
{
- defsubr (&Sbyte_code);
+#include "bytecode.x"
#ifdef BYTE_CODE_METER