+
+\f
+/* Structure describing a value stack used during byte-code execution
+ in Fbyte_code. */
+
+struct byte_stack
+{
+ /* Program counter. This points into the byte_string below
+ and is relocated when that string is relocated. */
+ unsigned char *pc;
+
+ /* Top and bottom of stack. The bottom points to an area of memory
+ allocated with alloca in Fbyte_code. */
+ Lisp_Object *top, *bottom;
+
+ /* The string containing the byte-code, and its current address.
+ Storing this here protects it from GC because mark_byte_stack
+ marks it. */
+ Lisp_Object byte_string;
+ unsigned char *byte_string_start;
+
+ /* The vector of constants used during byte-code execution. Storing
+ this here protects it from GC because mark_byte_stack marks it. */
+ Lisp_Object constants;
+
+ /* 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 removed the entry again when it is
+ done. Signalling an error truncates the list analoguous to
+ gcprolist. */
+
+struct byte_stack *byte_stack_list;
+
+\f
+/* Mark objects on byte_stack_list. Called during GC. */
+
+void
+mark_byte_stack ()
+{
+ struct byte_stack *stack;
+ Lisp_Object *obj;
+
+ for (stack = byte_stack_list; stack; stack = stack->next)
+ {
+ if (!stack->top)
+ abort ();
+
+ for (obj = stack->bottom; obj <= stack->top; ++obj)
+ if (!XMARKBIT (*obj))
+ {
+ mark_object (obj);
+ XMARK (*obj);
+ }
+
+ if (!XMARKBIT (stack->byte_string))
+ {
+ mark_object (&stack->byte_string);
+ XMARK (stack->byte_string);
+ }
+
+ if (!XMARKBIT (stack->constants))
+ {
+ mark_object (&stack->constants);
+ XMARK (stack->constants);
+ }
+ }
+}
+
+
+/* Unmark objects in the stacks on byte_stack_list. Relocate program
+ counters. Called when GC has completed. */
+
+void
+unmark_byte_stack ()
+{
+ struct byte_stack *stack;
+ Lisp_Object *obj;
+
+ for (stack = byte_stack_list; stack; stack = stack->next)
+ {
+ for (obj = stack->bottom; obj <= stack->top; ++obj)
+ XUNMARK (*obj);
+
+ XUNMARK (stack->byte_string);
+ XUNMARK (stack->constants);
+
+ if (stack->byte_string_start != XSTRING (stack->byte_string)->data)
+ {
+ int offset = stack->pc - stack->byte_string_start;
+ stack->byte_string_start = XSTRING (stack->byte_string)->data;
+ stack->pc = stack->byte_string_start + offset;
+ }
+ }
+}
+