Subject: Re: bug#4470: Acknowledgement (23.1; threaded interpreter)

From: Tom Tromey <[email-masked]>
Date: Fri, 18 Sep 2009 13:00:28 -0600

Andreas> You can use [0 ... 255] = &&insn_default, [Bconstant ... 255] =
Andreas> &&insn_Bconstant to statically initialize the array, avoiding the
Andreas> runtime initialisation.

Why, so you can.  For some reason I thought that would be an error.

New patch appended.

Tom

diff --git a/src/bytecode.c b/src/bytecode.c
index 43d972e..5031472 100644
--- a/src/bytecode.c
+++ b/src/bytecode.c
@@ -54,6 +54,13 @@ by Hallvard:
 /* #define BYTE_CODE_SAFE */
 /* #define BYTE_CODE_METER */
 
+/* If BYTE_CODE_THREADED is defined, then the interpreter will be
+   indirect threaded, using GCC's computed goto extension.  This is
+   incompatible with BYTE_CODE_SAFE and BYTE_CODE_METER.  */
+#if defined (__GNUC__) && !defined (BYTE_CODE_SAFE) && !defined (BYTE_CODE_METER)
+#define BYTE_CODE_THREADED
+#endif
+
 
 #ifdef BYTE_CODE_METER
 
@@ -90,10 +97,45 @@ Lisp_Object Qbytecode;
 /*  Byte codes: */
 
 #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 Bnth 070
 #define Bsymbolp 071
@@ -463,27 +505,241 @@ If the third argument is incorrect, Emacs may crash.  */)
       this_op = op = FETCH;
       METER_CODE (prev_op, op);
 #else
+#ifndef BYTE_CODE_THREADED
       op = FETCH;
 #endif
+#endif
+
+      /* The interpreter can be compiled one of two ways: as an
+	 ordinary switch-based interpreter, or as a threaded
+	 interpreter.  The threaded interpreter relies on GCC's
+	 computed goto extension, so it is not available everywhere.
+	 Threading provides a performance boost.  These macros are how
+	 we allow the code to be compiled both ways.  */
+#ifdef BYTE_CODE_THREADED
+      /* The CASE macro introduces an instruction's body.  It is
+	 either a label or a case label.  */
+#define CASE(OP) insn_ ## OP
+      /* NEXT is invoked at the end of an instruction to go to the
+	 next instruction.  It is either a computed goto, or a
+	 plain break.  */
+#define NEXT goto *(targets[op = FETCH])
+      /* FIRST is like NEXT, but is only used at the start of the
+	 interpreter body.  In the switch-based interpreter it is the
+	 switch, so the threaded definition must include a semicolon.  */
+#define FIRST NEXT;
+      /* Most cases are labeled with the CASE macro, above.
+	 CASE_DEFAULT is one exception; it is used if the interpreter
+	 being built requires a default case.  The threaded
+	 interpreter does not, because the dispatch table is
+	 completely filled.  */
+#define CASE_DEFAULT
+      /* This introduces an instruction that is known to call abort.  */
+#define CASE_ABORT CASE (default)
+#else
+      /* See above for the meaning of the various defines.  */
+#define CASE(OP) case OP
+#define NEXT break
+#define FIRST switch (op)
+#define CASE_DEFAULT case 255: default:
+#define CASE_ABORT case 0
+#endif
+
+#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,
+
+	  LABEL (Bvarref),
+	  LABEL (Bvarref1),
+	  LABEL (Bvarref2),
+	  LABEL (Bvarref3),
+	  LABEL (Bvarref4),
+	  LABEL (Bvarref5),
+	  LABEL (Bvarref6),
+	  LABEL (Bvarref7),
+	  LABEL (Bvarset),
+	  LABEL (Bvarset1),
+	  LABEL (Bvarset2),
+	  LABEL (Bvarset3),
+	  LABEL (Bvarset4),
+	  LABEL (Bvarset5),
+	  LABEL (Bvarset6),
+	  LABEL (Bvarset7),
+	  LABEL (Bvarbind),
+	  LABEL (Bvarbind1),
+	  LABEL (Bvarbind2),
+	  LABEL (Bvarbind3),
+	  LABEL (Bvarbind4),
+	  LABEL (Bvarbind5),
+	  LABEL (Bvarbind6),
+	  LABEL (Bvarbind7),
+	  LABEL (Bcall),
+	  LABEL (Bcall1),
+	  LABEL (Bcall2),
+	  LABEL (Bcall3),
+	  LABEL (Bcall4),
+	  LABEL (Bcall5),
+	  LABEL (Bcall6),
+	  LABEL (Bcall7),
+	  LABEL (Bunbind),
+	  LABEL (Bunbind1),
+	  LABEL (Bunbind2),
+	  LABEL (Bunbind3),
+	  LABEL (Bunbind4),
+	  LABEL (Bunbind5),
+	  LABEL (Bunbind6),
+	  LABEL (Bunbind7),
+	  LABEL (Bnth),
+	  LABEL (Bsymbolp),
+	  LABEL (Bconsp),
+	  LABEL (Bstringp),
+	  LABEL (Blistp),
+	  LABEL (Beq),
+	  LABEL (Bmemq),
+	  LABEL (Bnot),
+	  LABEL (Bcar),
+	  LABEL (Bcdr),
+	  LABEL (Bcons),
+	  LABEL (Blist1),
+	  LABEL (Blist2),
+	  LABEL (Blist3),
+	  LABEL (Blist4),
+	  LABEL (Blength),
+	  LABEL (Baref),
+	  LABEL (Baset),
+	  LABEL (Bsymbol_value),
+	  LABEL (Bsymbol_function),
+	  LABEL (Bset),
+	  LABEL (Bfset),
+	  LABEL (Bget),
+	  LABEL (Bsubstring),
+	  LABEL (Bconcat2),
+	  LABEL (Bconcat3),
+	  LABEL (Bconcat4),
+	  LABEL (Bsub1),
+	  LABEL (Badd1),
+	  LABEL (Beqlsign),
+	  LABEL (Bgtr),
+	  LABEL (Blss),
+	  LABEL (Bleq),
+	  LABEL (Bgeq),
+	  LABEL (Bdiff),
+	  LABEL (Bnegate),
+	  LABEL (Bplus),
+	  LABEL (Bmax),
+	  LABEL (Bmin),
+	  LABEL (Bmult),
+	  LABEL (Bpoint),
+	  LABEL (Bsave_current_buffer),
+	  LABEL (Bgoto_char),
+	  LABEL (Binsert),
+	  LABEL (Bpoint_max),
+	  LABEL (Bpoint_min),
+	  LABEL (Bchar_after),
+	  LABEL (Bfollowing_char),
+	  LABEL (Bpreceding_char),
+	  LABEL (Bcurrent_column),
+	  LABEL (Bindent_to),
+	  LABEL (Bscan_buffer),
+	  LABEL (Beolp),
+	  LABEL (Beobp),
+	  LABEL (Bbolp),
+	  LABEL (Bbobp),
+	  LABEL (Bcurrent_buffer),
+	  LABEL (Bset_buffer),
+	  LABEL (Bsave_current_buffer_1),
+	  LABEL (Bset_mark),
+	  LABEL (Binteractive_p),
+	  LABEL (Bforward_char),
+	  LABEL (Bforward_word),
+	  LABEL (Bskip_chars_forward),
+	  LABEL (Bskip_chars_backward),
+	  LABEL (Bforward_line),
+	  LABEL (Bchar_syntax),
+	  LABEL (Bbuffer_substring),
+	  LABEL (Bdelete_region),
+	  LABEL (Bnarrow_to_region),
+	  LABEL (Bwiden),
+	  LABEL (Bend_of_line),
+	  LABEL (Bconstant2),
+	  LABEL (Bgoto),
+	  LABEL (Bgotoifnil),
+	  LABEL (Bgotoifnonnil),
+	  LABEL (Bgotoifnilelsepop),
+	  LABEL (Bgotoifnonnilelsepop),
+	  LABEL (Breturn),
+	  LABEL (Bdiscard),
+	  LABEL (Bdup),
+	  LABEL (Bsave_excursion),
+	  LABEL (Bsave_window_excursion),
+	  LABEL (Bsave_restriction),
+	  LABEL (Bcatch),
+	  LABEL (Bunwind_protect),
+	  LABEL (Bcondition_case),
+	  LABEL (Btemp_output_buffer_setup),
+	  LABEL (Btemp_output_buffer_show),
+	  LABEL (Bunbind_all),
+	  LABEL (Bset_marker),
+	  LABEL (Bmatch_beginning),
+	  LABEL (Bmatch_end),
+	  LABEL (Bupcase),
+	  LABEL (Bdowncase),
+	  LABEL (Bstringeqlsign),
+	  LABEL (Bstringlss),
+	  LABEL (Bequal),
+	  LABEL (Bnthcdr),
+	  LABEL (Belt),
+	  LABEL (Bmember),
+	  LABEL (Bassq),
+	  LABEL (Bnreverse),
+	  LABEL (Bsetcar),
+	  LABEL (Bsetcdr),
+	  LABEL (Bcar_safe),
+	  LABEL (Bcdr_safe),
+	  LABEL (Bnconc),
+	  LABEL (Bquo),
+	  LABEL (Brem),
+	  LABEL (Bnumberp),
+	  LABEL (Bintegerp),
+	  LABEL (BRgoto),
+	  LABEL (BRgotoifnil),
+	  LABEL (BRgotoifnonnil),
+	  LABEL (BRgotoifnilelsepop),
+	  LABEL (BRgotoifnonnilelsepop),
+	  LABEL (BlistN),
+	  LABEL (BconcatN),
+	  LABEL (BinsertN),
+	  LABEL (Bconstant)
+	};
+#endif
+
 
-      switch (op)
+      FIRST
 	{
-	case Bvarref + 7:
+	CASE (Bvarref7):
 	  op = FETCH2;
 	  goto varref;
 
-	case Bvarref:
-	case Bvarref + 1:
-	case Bvarref + 2:
-	case Bvarref + 3:
-	case Bvarref + 4:
-	case Bvarref + 5:
+	CASE (Bvarref):
+	CASE (Bvarref1):
+	CASE (Bvarref2):
+	CASE (Bvarref3):
+	CASE (Bvarref4):
+	CASE (Bvarref5):
 	  op = op - Bvarref;
 	  goto varref;
 
 	/* This seems to be the most frequently executed byte-code
 	   among the Bvarref's, so avoid a goto here.  */
-	case Bvarref+6:
+	CASE (Bvarref6):
 	  op = FETCH;
 	varref:
 	  {
@@ -507,10 +763,10 @@ If the third argument is incorrect, Emacs may crash.  */)
 		AFTER_POTENTIAL_GC ();
 	      }
 	    PUSH (v2);
-	    break;
+	    NEXT;
 	  }
 
-	case Bgotoifnil:
+	CASE (Bgotoifnil):
 	  {
 	    Lisp_Object v1;
 	    MAYBE_GC ();
@@ -522,57 +778,57 @@ If the third argument is incorrect, Emacs may crash.  */)
 		CHECK_RANGE (op);
 		stack.pc = stack.byte_string_start + op;
 	      }
-	    break;
+	    NEXT;
 	  }
 
-	case Bcar:
+	CASE (Bcar):
 	  {
 	    Lisp_Object v1;
 	    v1 = TOP;
 	    TOP = CAR (v1);
-	    break;
+	    NEXT;
 	  }
 
-	case Beq:
+	CASE (Beq):
 	  {
 	    Lisp_Object v1;
 	    v1 = POP;
 	    TOP = EQ (v1, TOP) ? Qt : Qnil;
-	    break;
+	    NEXT;
 	  }
 
-	case Bmemq:
+	CASE (Bmemq):
 	  {
 	    Lisp_Object v1;
 	    BEFORE_POTENTIAL_GC ();
 	    v1 = POP;
 	    TOP = Fmemq (TOP, v1);
 	    AFTER_POTENTIAL_GC ();
-	    break;
+	    NEXT;
 	  }
 
-	case Bcdr:
+	CASE (Bcdr):
 	  {
 	    Lisp_Object v1;
 	    v1 = TOP;
 	    TOP = CDR (v1);
-	    break;
+	    NEXT;
 	  }
 
-	case Bvarset:
-	case Bvarset+1:
-	case Bvarset+2:
-	case Bvarset+3:
-	case Bvarset+4:
-	case Bvarset+5:
+	CASE (Bvarset):
+	CASE (Bvarset1):
+	CASE (Bvarset2):
+	CASE (Bvarset3):
+	CASE (Bvarset4):
+	CASE (Bvarset5):
 	  op -= Bvarset;
 	  goto varset;
 
-	case Bvarset+7:
+	CASE (Bvarset7):
 	  op = FETCH2;
 	  goto varset;
 
-	case Bvarset+6:
+	CASE (Bvarset6):
 	  op = FETCH;
 	varset:
 	  {
@@ -596,54 +852,54 @@ If the third argument is incorrect, Emacs may crash.  */)
 	      }
 	  }
 	  (void) POP;
-	  break;
+	  NEXT;
 
-	case Bdup:
+	CASE (Bdup):
 	  {
 	    Lisp_Object v1;
 	    v1 = TOP;
 	    PUSH (v1);
-	    break;
+	    NEXT;
 	  }
 
 	/* ------------------ */
 
-	case Bvarbind+6:
+	CASE (Bvarbind6):
 	  op = FETCH;
 	  goto varbind;
 
-	case Bvarbind+7:
+	CASE (Bvarbind7):
 	  op = FETCH2;
 	  goto varbind;
 
-	case Bvarbind:
-	case Bvarbind+1:
-	case Bvarbind+2:
-	case Bvarbind+3:
-	case Bvarbind+4:
-	case Bvarbind+5:
+	CASE (Bvarbind):
+	CASE (Bvarbind1):
+	CASE (Bvarbind2):
+	CASE (Bvarbind3):
+	CASE (Bvarbind4):
+	CASE (Bvarbind5):
 	  op -= Bvarbind;
 	varbind:
 	  /* Specbind can signal and thus GC.  */
 	  BEFORE_POTENTIAL_GC ();
 	  specbind (vectorp[op], POP);
 	  AFTER_POTENTIAL_GC ();
-	  break;
+	  NEXT;
 
-	case Bcall+6:
+	CASE (Bcall6):
 	  op = FETCH;
 	  goto docall;
 
-	case Bcall+7:
+	CASE (Bcall7):
 	  op = FETCH2;
 	  goto docall;
 
-	case Bcall:
-	case Bcall+1:
-	case Bcall+2:
-	case Bcall+3:
-	case Bcall+4:
-	case Bcall+5:
+	CASE (Bcall):
+	CASE (Bcall1):
+	CASE (Bcall2):
+	CASE (Bcall3):
+	CASE (Bcall4):
+	CASE (Bcall5):
 	  op -= Bcall;
 	docall:
 	  {
@@ -666,47 +922,47 @@ If the third argument is incorrect, Emacs may crash.  */)
 #endif
 	    TOP = Ffuncall (op + 1, &TOP);
 	    AFTER_POTENTIAL_GC ();
-	    break;
+	    NEXT;
 	  }
 
-	case Bunbind+6:
+	CASE (Bunbind6):
 	  op = FETCH;
 	  goto dounbind;
 
-	case Bunbind+7:
+	CASE (Bunbind7):
 	  op = FETCH2;
 	  goto dounbind;
 
-	case Bunbind:
-	case Bunbind+1:
-	case Bunbind+2:
-	case Bunbind+3:
-	case Bunbind+4:
-	case Bunbind+5:
+	CASE (Bunbind):
+	CASE (Bunbind1):
+	CASE (Bunbind2):
+	CASE (Bunbind3):
+	CASE (Bunbind4):
+	CASE (Bunbind5):
 	  op -= Bunbind;
 	dounbind:
 	  BEFORE_POTENTIAL_GC ();
 	  unbind_to (SPECPDL_INDEX () - op, Qnil);
 	  AFTER_POTENTIAL_GC ();
-	  break;
+	  NEXT;
 
-	case Bunbind_all:
+	CASE (Bunbind_all):
 	  /* 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 ();
-	  break;
+	  NEXT;
 
-	case Bgoto:
+	CASE (Bgoto):
 	  MAYBE_GC ();
 	  BYTE_CODE_QUIT;
 	  op = FETCH2;    /* pc = FETCH2 loses since FETCH2 contains pc++ */
 	  CHECK_RANGE (op);
 	  stack.pc = stack.byte_string_start + op;
-	  break;
+	  NEXT;
 
-	case Bgotoifnonnil:
+	CASE (Bgotoifnonnil):
 	  {
 	    Lisp_Object v1;
 	    MAYBE_GC ();
@@ -718,10 +974,10 @@ If the third argument is incorrect, Emacs may crash.  */)
 		CHECK_RANGE (op);
 		stack.pc = stack.byte_string_start + op;
 	      }
-	    break;
+	    NEXT;
 	  }
 
-	case Bgotoifnilelsepop:
+	CASE (Bgotoifnilelsepop):
 	  MAYBE_GC ();
 	  op = FETCH2;
 	  if (NILP (TOP))
@@ -731,9 +987,9 @@ If the third argument is incorrect, Emacs may crash.  */)
 	      stack.pc = stack.byte_string_start + op;
 	    }
 	  else DISCARD (1);
-	  break;
+	  NEXT;
 
-	case Bgotoifnonnilelsepop:
+	CASE (Bgotoifnonnilelsepop):
 	  MAYBE_GC ();
 	  op = FETCH2;
 	  if (!NILP (TOP))
@@ -743,15 +999,15 @@ If the third argument is incorrect, Emacs may crash.  */)
 	      stack.pc = stack.byte_string_start + op;
 	    }
 	  else DISCARD (1);
-	  break;
+	  NEXT;
 
-	case BRgoto:
+	CASE (BRgoto):
 	  MAYBE_GC ();
 	  BYTE_CODE_QUIT;
 	  stack.pc += (int) *stack.pc - 127;
-	  break;
+	  NEXT;
 
-	case BRgotoifnil:
+	CASE (BRgotoifnil):
 	  {
 	    Lisp_Object v1;
 	    MAYBE_GC ();
@@ -762,10 +1018,10 @@ If the third argument is incorrect, Emacs may crash.  */)
 		stack.pc += (int) *stack.pc - 128;
 	      }
 	    stack.pc++;
-	    break;
+	    NEXT;
 	  }
 
-	case BRgotoifnonnil:
+	CASE (BRgotoifnonnil):
 	  {
 	    Lisp_Object v1;
 	    MAYBE_GC ();
@@ -776,10 +1032,10 @@ If the third argument is incorrect, Emacs may crash.  */)
 		stack.pc += (int) *stack.pc - 128;
 	      }
 	    stack.pc++;
-	    break;
+	    NEXT;
 	  }
 
-	case BRgotoifnilelsepop:
+	CASE (BRgotoifnilelsepop):
 	  MAYBE_GC ();
 	  op = *stack.pc++;
 	  if (NILP (TOP))
@@ -788,9 +1044,9 @@ If the third argument is incorrect, Emacs may crash.  */)
 	      stack.pc += op - 128;
 	    }
 	  else DISCARD (1);
-	  break;
+	  NEXT;
 
-	case BRgotoifnonnilelsepop:
+	CASE (BRgotoifnonnilelsepop):
 	  MAYBE_GC ();
 	  op = *stack.pc++;
 	  if (!NILP (TOP))
@@ -799,56 +1055,56 @@ If the third argument is incorrect, Emacs may crash.  */)
 	      stack.pc += op - 128;
 	    }
 	  else DISCARD (1);
-	  break;
+	  NEXT;
 
-	case Breturn:
+	CASE (Breturn):
 	  result = POP;
 	  goto exit;
 
-	case Bdiscard:
+	CASE (Bdiscard):
 	  DISCARD (1);
-	  break;
+	  NEXT;
 
-	case Bconstant2:
+	CASE (Bconstant2):
 	  PUSH (vectorp[FETCH2]);
-	  break;
+	  NEXT;
 
-	case Bsave_excursion:
+	CASE (Bsave_excursion):
 	  record_unwind_protect (save_excursion_restore,
 				 save_excursion_save ());
-	  break;
+	  NEXT;
 
-	case Bsave_current_buffer:
-	case Bsave_current_buffer_1:
+	CASE (Bsave_current_buffer):
+	CASE (Bsave_current_buffer_1):
 	  record_unwind_protect (set_buffer_if_live, Fcurrent_buffer ());
-	  break;
+	  NEXT;
 
-	case Bsave_window_excursion:
+	CASE (Bsave_window_excursion):
 	  BEFORE_POTENTIAL_GC ();
 	  TOP = Fsave_window_excursion (TOP);
 	  AFTER_POTENTIAL_GC ();
-	  break;
+	  NEXT;
 
-	case Bsave_restriction:
+	CASE (Bsave_restriction):
 	  record_unwind_protect (save_restriction_restore,
 				 save_restriction_save ());
-	  break;
+	  NEXT;
 
-	case Bcatch:
+	CASE (Bcatch):
 	  {
 	    Lisp_Object v1;
 	    BEFORE_POTENTIAL_GC ();
 	    v1 = POP;
 	    TOP = internal_catch (TOP, Feval, v1);
 	    AFTER_POTENTIAL_GC ();
-	    break;
+	    NEXT;
 	  }
 
-	case Bunwind_protect:
+	CASE (Bunwind_protect):
 	  record_unwind_protect (Fprogn, POP);
-	  break;
+	  NEXT;
 
-	case Bcondition_case:
+	CASE (Bcondition_case):
 	  {
 	    Lisp_Object handlers, body;
 	    handlers = POP;
@@ -856,18 +1112,18 @@ If the third argument is incorrect, Emacs may crash.  */)
 	    BEFORE_POTENTIAL_GC ();
 	    TOP = internal_lisp_condition_case (TOP, body, handlers);
 	    AFTER_POTENTIAL_GC ();
-	    break;
+	    NEXT;
 	  }
 
-	case Btemp_output_buffer_setup:
+	CASE (Btemp_output_buffer_setup):
 	  BEFORE_POTENTIAL_GC ();
 	  CHECK_STRING (TOP);
 	  temp_output_buffer_setup (SDATA (TOP));
 	  AFTER_POTENTIAL_GC ();
 	  TOP = Vstandard_output;
-	  break;
+	  NEXT;
 
-	case Btemp_output_buffer_show:
+	CASE (Btemp_output_buffer_show):
 	  {
 	    Lisp_Object v1;
 	    BEFORE_POTENTIAL_GC ();
@@ -877,10 +1133,10 @@ If the third argument is incorrect, Emacs may crash.  */)
 	    /* pop binding of standard-output */
 	    unbind_to (SPECPDL_INDEX () - 1, Qnil);
 	    AFTER_POTENTIAL_GC ();
-	    break;
+	    NEXT;
 	  }
 
-	case Bnth:
+	CASE (Bnth):
 	  {
 	    Lisp_Object v1, v2;
 	    BEFORE_POTENTIAL_GC ();
@@ -894,173 +1150,173 @@ If the third argument is incorrect, Emacs may crash.  */)
 	      v1 = XCDR (v1);
 	    immediate_quit = 0;
 	    TOP = CAR (v1);
-	    break;
+	    NEXT;
 	  }
 
-	case Bsymbolp:
+	CASE (Bsymbolp):
 	  TOP = SYMBOLP (TOP) ? Qt : Qnil;
-	  break;
+	  NEXT;
 
-	case Bconsp:
+	CASE (Bconsp):
 	  TOP = CONSP (TOP) ? Qt : Qnil;
-	  break;
+	  NEXT;
 
-	case Bstringp:
+	CASE (Bstringp):
 	  TOP = STRINGP (TOP) ? Qt : Qnil;
-	  break;
+	  NEXT;
 
-	case Blistp:
+	CASE (Blistp):
 	  TOP = CONSP (TOP) || NILP (TOP) ? Qt : Qnil;
-	  break;
+	  NEXT;
 
-	case Bnot:
+	CASE (Bnot):
 	  TOP = NILP (TOP) ? Qt : Qnil;
-	  break;
+	  NEXT;
 
-	case Bcons:
+	CASE (Bcons):
 	  {
 	    Lisp_Object v1;
 	    v1 = POP;
 	    TOP = Fcons (TOP, v1);
-	    break;
+	    NEXT;
 	  }
 
-	case Blist1:
+	CASE (Blist1):
 	  TOP = Fcons (TOP, Qnil);
-	  break;
+	  NEXT;
 
-	case Blist2:
+	CASE (Blist2):
 	  {
 	    Lisp_Object v1;
 	    v1 = POP;
 	    TOP = Fcons (TOP, Fcons (v1, Qnil));
-	    break;
+	    NEXT;
 	  }
 
-	case Blist3:
+	CASE (Blist3):
 	  DISCARD (2);
 	  TOP = Flist (3, &TOP);
-	  break;
+	  NEXT;
 
-	case Blist4:
+	CASE (Blist4):
 	  DISCARD (3);
 	  TOP = Flist (4, &TOP);
-	  break;
+	  NEXT;
 
-	case BlistN:
+	CASE (BlistN):
 	  op = FETCH;
 	  DISCARD (op - 1);
 	  TOP = Flist (op, &TOP);
-	  break;
+	  NEXT;
 
-	case Blength:
+	CASE (Blength):
 	  BEFORE_POTENTIAL_GC ();
 	  TOP = Flength (TOP);
 	  AFTER_POTENTIAL_GC ();
-	  break;
+	  NEXT;
 
-	case Baref:
+	CASE (Baref):
 	  {
 	    Lisp_Object v1;
 	    BEFORE_POTENTIAL_GC ();
 	    v1 = POP;
 	    TOP = Faref (TOP, v1);
 	    AFTER_POTENTIAL_GC ();
-	    break;
+	    NEXT;
 	  }
 
-	case Baset:
+	CASE (Baset):
 	  {
 	    Lisp_Object v1, v2;
 	    BEFORE_POTENTIAL_GC ();
 	    v2 = POP; v1 = POP;
 	    TOP = Faset (TOP, v1, v2);
 	    AFTER_POTENTIAL_GC ();
-	    break;
+	    NEXT;
 	  }
 
-	case Bsymbol_value:
+	CASE (Bsymbol_value):
 	  BEFORE_POTENTIAL_GC ();
 	  TOP = Fsymbol_value (TOP);
 	  AFTER_POTENTIAL_GC ();
-	  break;
+	  NEXT;
 
-	case Bsymbol_function:
+	CASE (Bsymbol_function):
 	  BEFORE_POTENTIAL_GC ();
 	  TOP = Fsymbol_function (TOP);
 	  AFTER_POTENTIAL_GC ();
-	  break;
+	  NEXT;
 
-	case Bset:
+	CASE (Bset):
 	  {
 	    Lisp_Object v1;
 	    BEFORE_POTENTIAL_GC ();
 	    v1 = POP;
 	    TOP = Fset (TOP, v1);
 	    AFTER_POTENTIAL_GC ();
-	    break;
+	    NEXT;
 	  }
 
-	case Bfset:
+	CASE (Bfset):
 	  {
 	    Lisp_Object v1;
 	    BEFORE_POTENTIAL_GC ();
 	    v1 = POP;
 	    TOP = Ffset (TOP, v1);
 	    AFTER_POTENTIAL_GC ();
-	    break;
+	    NEXT;
 	  }
 
-	case Bget:
+	CASE (Bget):
 	  {
 	    Lisp_Object v1;
 	    BEFORE_POTENTIAL_GC ();
 	    v1 = POP;
 	    TOP = Fget (TOP, v1);
 	    AFTER_POTENTIAL_GC ();
-	    break;
+	    NEXT;
 	  }
 
-	case Bsubstring:
+	CASE (Bsubstring):
 	  {
 	    Lisp_Object v1, v2;
 	    BEFORE_POTENTIAL_GC ();
 	    v2 = POP; v1 = POP;
 	    TOP = Fsubstring (TOP, v1, v2);
 	    AFTER_POTENTIAL_GC ();
-	    break;
+	    NEXT;
 	  }
 
-	case Bconcat2:
+	CASE (Bconcat2):
 	  BEFORE_POTENTIAL_GC ();
 	  DISCARD (1);
 	  TOP = Fconcat (2, &TOP);
 	  AFTER_POTENTIAL_GC ();
-	  break;
+	  NEXT;
 
-	case Bconcat3:
+	CASE (Bconcat3):
 	  BEFORE_POTENTIAL_GC ();
 	  DISCARD (2);
 	  TOP = Fconcat (3, &TOP);
 	  AFTER_POTENTIAL_GC ();
-	  break;
+	  NEXT;
 
-	case Bconcat4:
+	CASE (Bconcat4):
 	  BEFORE_POTENTIAL_GC ();
 	  DISCARD (3);
 	  TOP = Fconcat (4, &TOP);
 	  AFTER_POTENTIAL_GC ();
-	  break;
+	  NEXT;
 
-	case BconcatN:
+	CASE (BconcatN):
 	  op = FETCH;
 	  BEFORE_POTENTIAL_GC ();
 	  DISCARD (op - 1);
 	  TOP = Fconcat (op, &TOP);
 	  AFTER_POTENTIAL_GC ();
-	  break;
+	  NEXT;
 
-	case Bsub1:
+	CASE (Bsub1):
 	  {
 	    Lisp_Object v1;
 	    v1 = TOP;
@@ -1075,10 +1331,10 @@ If the third argument is incorrect, Emacs may crash.  */)
 		TOP = Fsub1 (v1);
 		AFTER_POTENTIAL_GC ();
 	      }
-	    break;
+	    NEXT;
 	  }
 
-	case Badd1:
+	CASE (Badd1):
 	  {
 	    Lisp_Object v1;
 	    v1 = TOP;
@@ -1093,10 +1349,10 @@ If the third argument is incorrect, Emacs may crash.  */)
 		TOP = Fadd1 (v1);
 		AFTER_POTENTIAL_GC ();
 	      }
-	    break;
+	    NEXT;
 	  }
 
-	case Beqlsign:
+	CASE (Beqlsign):
 	  {
 	    Lisp_Object v1, v2;
 	    BEFORE_POTENTIAL_GC ();
@@ -1114,57 +1370,57 @@ If the third argument is incorrect, Emacs may crash.  */)
 	      }
 	    else
 	      TOP = (XINT (v1) == XINT (v2) ? Qt : Qnil);
-	    break;
+	    NEXT;
 	  }
 
-	case Bgtr:
+	CASE (Bgtr):
 	  {
 	    Lisp_Object v1;
 	    BEFORE_POTENTIAL_GC ();
 	    v1 = POP;
 	    TOP = Fgtr (TOP, v1);
 	    AFTER_POTENTIAL_GC ();
-	    break;
+	    NEXT;
 	  }
 
-	case Blss:
+	CASE (Blss):
 	  {
 	    Lisp_Object v1;
 	    BEFORE_POTENTIAL_GC ();
 	    v1 = POP;
 	    TOP = Flss (TOP, v1);
 	    AFTER_POTENTIAL_GC ();
-	    break;
+	    NEXT;
 	  }
 
-	case Bleq:
+	CASE (Bleq):
 	  {
 	    Lisp_Object v1;
 	    BEFORE_POTENTIAL_GC ();
 	    v1 = POP;
 	    TOP = Fleq (TOP, v1);
 	    AFTER_POTENTIAL_GC ();
-	    break;
+	    NEXT;
 	  }
 
-	case Bgeq:
+	CASE (Bgeq):
 	  {
 	    Lisp_Object v1;
 	    BEFORE_POTENTIAL_GC ();
 	    v1 = POP;
 	    TOP = Fgeq (TOP, v1);
 	    AFTER_POTENTIAL_GC ();
-	    break;
+	    NEXT;
 	  }
 
-	case Bdiff:
+	CASE (Bdiff):
 	  BEFORE_POTENTIAL_GC ();
 	  DISCARD (1);
 	  TOP = Fminus (2, &TOP);
 	  AFTER_POTENTIAL_GC ();
-	  break;
+	  NEXT;
 
-	case Bnegate:
+	CASE (Bnegate):
 	  {
 	    Lisp_Object v1;
 	    v1 = TOP;
@@ -1179,209 +1435,209 @@ If the third argument is incorrect, Emacs may crash.  */)
 		TOP = Fminus (1, &TOP);
 		AFTER_POTENTIAL_GC ();
 	      }
-	    break;
+	    NEXT;
 	  }
 
-	case Bplus:
+	CASE (Bplus):
 	  BEFORE_POTENTIAL_GC ();
 	  DISCARD (1);
 	  TOP = Fplus (2, &TOP);
 	  AFTER_POTENTIAL_GC ();
-	  break;
+	  NEXT;
 
-	case Bmax:
+	CASE (Bmax):
 	  BEFORE_POTENTIAL_GC ();
 	  DISCARD (1);
 	  TOP = Fmax (2, &TOP);
 	  AFTER_POTENTIAL_GC ();
-	  break;
+	  NEXT;
 
-	case Bmin:
+	CASE (Bmin):
 	  BEFORE_POTENTIAL_GC ();
 	  DISCARD (1);
 	  TOP = Fmin (2, &TOP);
 	  AFTER_POTENTIAL_GC ();
-	  break;
+	  NEXT;
 
-	case Bmult:
+	CASE (Bmult):
 	  BEFORE_POTENTIAL_GC ();
 	  DISCARD (1);
 	  TOP = Ftimes (2, &TOP);
 	  AFTER_POTENTIAL_GC ();
-	  break;
+	  NEXT;
 
-	case Bquo:
+	CASE (Bquo):
 	  BEFORE_POTENTIAL_GC ();
 	  DISCARD (1);
 	  TOP = Fquo (2, &TOP);
 	  AFTER_POTENTIAL_GC ();
-	  break;
+	  NEXT;
 
-	case Brem:
+	CASE (Brem):
 	  {
 	    Lisp_Object v1;
 	    BEFORE_POTENTIAL_GC ();
 	    v1 = POP;
 	    TOP = Frem (TOP, v1);
 	    AFTER_POTENTIAL_GC ();
-	    break;
+	    NEXT;
 	  }
 
-	case Bpoint:
+	CASE (Bpoint):
 	  {
 	    Lisp_Object v1;
 	    XSETFASTINT (v1, PT);
 	    PUSH (v1);
-	    break;
+	    NEXT;
 	  }
 
-	case Bgoto_char:
+	CASE (Bgoto_char):
 	  BEFORE_POTENTIAL_GC ();
 	  TOP = Fgoto_char (TOP);
 	  AFTER_POTENTIAL_GC ();
-	  break;
+	  NEXT;
 
-	case Binsert:
+	CASE (Binsert):
 	  BEFORE_POTENTIAL_GC ();
 	  TOP = Finsert (1, &TOP);
 	  AFTER_POTENTIAL_GC ();
-	  break;
+	  NEXT;
 
-	case BinsertN:
+	CASE (BinsertN):
 	  op = FETCH;
 	  BEFORE_POTENTIAL_GC ();
 	  DISCARD (op - 1);
 	  TOP = Finsert (op, &TOP);
 	  AFTER_POTENTIAL_GC ();
-	  break;
+	  NEXT;
 
-	case Bpoint_max:
+	CASE (Bpoint_max):
 	  {
 	    Lisp_Object v1;
 	    XSETFASTINT (v1, ZV);
 	    PUSH (v1);
-	    break;
+	    NEXT;
 	  }
 
-	case Bpoint_min:
+	CASE (Bpoint_min):
 	  {
 	    Lisp_Object v1;
 	    XSETFASTINT (v1, BEGV);
 	    PUSH (v1);
-	    break;
+	    NEXT;
 	  }
 
-	case Bchar_after:
+	CASE (Bchar_after):
 	  BEFORE_POTENTIAL_GC ();
 	  TOP = Fchar_after (TOP);
 	  AFTER_POTENTIAL_GC ();
-	  break;
+	  NEXT;
 
-	case Bfollowing_char:
+	CASE (Bfollowing_char):
 	  {
 	    Lisp_Object v1;
 	    BEFORE_POTENTIAL_GC ();
 	    v1 = Ffollowing_char ();
 	    AFTER_POTENTIAL_GC ();
 	    PUSH (v1);
-	    break;
+	    NEXT;
 	  }
 
-	case Bpreceding_char:
+	CASE (Bpreceding_char):
 	  {
 	    Lisp_Object v1;
 	    BEFORE_POTENTIAL_GC ();
 	    v1 = Fprevious_char ();
 	    AFTER_POTENTIAL_GC ();
 	    PUSH (v1);
-	    break;
+	    NEXT;
 	  }
 
-	case Bcurrent_column:
+	CASE (Bcurrent_column):
 	  {
 	    Lisp_Object v1;
 	    BEFORE_POTENTIAL_GC ();
 	    XSETFASTINT (v1, (int) current_column ()); /* iftc */
 	    AFTER_POTENTIAL_GC ();
 	    PUSH (v1);
-	    break;
+	    NEXT;
 	  }
 
-	case Bindent_to:
+	CASE (Bindent_to):
 	  BEFORE_POTENTIAL_GC ();
 	  TOP = Findent_to (TOP, Qnil);
 	  AFTER_POTENTIAL_GC ();
-	  break;
+	  NEXT;
 
-	case Beolp:
+	CASE (Beolp):
 	  PUSH (Feolp ());
-	  break;
+	  NEXT;
 
-	case Beobp:
+	CASE (Beobp):
 	  PUSH (Feobp ());
-	  break;
+	  NEXT;
 
-	case Bbolp:
+	CASE (Bbolp):
 	  PUSH (Fbolp ());
-	  break;
+	  NEXT;
 
-	case Bbobp:
+	CASE (Bbobp):
 	  PUSH (Fbobp ());
-	  break;
+	  NEXT;
 
-	case Bcurrent_buffer:
+	CASE (Bcurrent_buffer):
 	  PUSH (Fcurrent_buffer ());
-	  break;
+	  NEXT;
 
-	case Bset_buffer:
+	CASE (Bset_buffer):
 	  BEFORE_POTENTIAL_GC ();
 	  TOP = Fset_buffer (TOP);
 	  AFTER_POTENTIAL_GC ();
-	  break;
+	  NEXT;
 
-	case Binteractive_p:
+	CASE (Binteractive_p):
 	  PUSH (Finteractive_p ());
-	  break;
+	  NEXT;
 
-	case Bforward_char:
+	CASE (Bforward_char):
 	  BEFORE_POTENTIAL_GC ();
 	  TOP = Fforward_char (TOP);
 	  AFTER_POTENTIAL_GC ();
-	  break;
+	  NEXT;
 
-	case Bforward_word:
+	CASE (Bforward_word):
 	  BEFORE_POTENTIAL_GC ();
 	  TOP = Fforward_word (TOP);
 	  AFTER_POTENTIAL_GC ();
-	  break;
+	  NEXT;
 
-	case Bskip_chars_forward:
+	CASE (Bskip_chars_forward):
 	  {
 	    Lisp_Object v1;
 	    BEFORE_POTENTIAL_GC ();
 	    v1 = POP;
 	    TOP = Fskip_chars_forward (TOP, v1);
 	    AFTER_POTENTIAL_GC ();
-	    break;
+	    NEXT;
 	  }
 
-	case Bskip_chars_backward:
+	CASE (Bskip_chars_backward):
 	  {
 	    Lisp_Object v1;
 	    BEFORE_POTENTIAL_GC ();
 	    v1 = POP;
 	    TOP = Fskip_chars_backward (TOP, v1);
 	    AFTER_POTENTIAL_GC ();
-	    break;
+	    NEXT;
 	  }
 
-	case Bforward_line:
+	CASE (Bforward_line):
 	  BEFORE_POTENTIAL_GC ();
 	  TOP = Fforward_line (TOP);
 	  AFTER_POTENTIAL_GC ();
-	  break;
+	  NEXT;
 
-	case Bchar_syntax:
+	CASE (Bchar_syntax):
 	  {
 	    int c;
 
@@ -1393,51 +1649,51 @@ If the third argument is incorrect, Emacs may crash.  */)
 	      MAKE_CHAR_MULTIBYTE (c);
 	    XSETFASTINT (TOP, syntax_code_spec[(int) SYNTAX (c)]);
 	  }
-	  break;
+	  NEXT;
 
-	case Bbuffer_substring:
+	CASE (Bbuffer_substring):
 	  {
 	    Lisp_Object v1;
 	    BEFORE_POTENTIAL_GC ();
 	    v1 = POP;
 	    TOP = Fbuffer_substring (TOP, v1);
 	    AFTER_POTENTIAL_GC ();
-	    break;
+	    NEXT;
 	  }
 
-	case Bdelete_region:
+	CASE (Bdelete_region):
 	  {
 	    Lisp_Object v1;
 	    BEFORE_POTENTIAL_GC ();
 	    v1 = POP;
 	    TOP = Fdelete_region (TOP, v1);
 	    AFTER_POTENTIAL_GC ();
-	    break;
+	    NEXT;
 	  }
 
-	case Bnarrow_to_region:
+	CASE (Bnarrow_to_region):
 	  {
 	    Lisp_Object v1;
 	    BEFORE_POTENTIAL_GC ();
 	    v1 = POP;
 	    TOP = Fnarrow_to_region (TOP, v1);
 	    AFTER_POTENTIAL_GC ();
-	    break;
+	    NEXT;
 	  }
 
-	case Bwiden:
+	CASE (Bwiden):
 	  BEFORE_POTENTIAL_GC ();
 	  PUSH (Fwiden ());
 	  AFTER_POTENTIAL_GC ();
-	  break;
+	  NEXT;
 
-	case Bend_of_line:
+	CASE (Bend_of_line):
 	  BEFORE_POTENTIAL_GC ();
 	  TOP = Fend_of_line (TOP);
 	  AFTER_POTENTIAL_GC ();
-	  break;
+	  NEXT;
 
-	case Bset_marker:
+	CASE (Bset_marker):
 	  {
 	    Lisp_Object v1, v2;
 	    BEFORE_POTENTIAL_GC ();
@@ -1445,72 +1701,72 @@ If the third argument is incorrect, Emacs may crash.  */)
 	    v2 = POP;
 	    TOP = Fset_marker (TOP, v2, v1);
 	    AFTER_POTENTIAL_GC ();
-	    break;
+	    NEXT;
 	  }
 
-	case Bmatch_beginning:
+	CASE (Bmatch_beginning):
 	  BEFORE_POTENTIAL_GC ();
 	  TOP = Fmatch_beginning (TOP);
 	  AFTER_POTENTIAL_GC ();
-	  break;
+	  NEXT;
 
-	case Bmatch_end:
+	CASE (Bmatch_end):
 	  BEFORE_POTENTIAL_GC ();
 	  TOP = Fmatch_end (TOP);
 	  AFTER_POTENTIAL_GC ();
-	  break;
+	  NEXT;
 
-	case Bupcase:
+	CASE (Bupcase):
 	  BEFORE_POTENTIAL_GC ();
 	  TOP = Fupcase (TOP);
 	  AFTER_POTENTIAL_GC ();
-	  break;
+	  NEXT;
 
-	case Bdowncase:
+	CASE (Bdowncase):
 	  BEFORE_POTENTIAL_GC ();
 	  TOP = Fdowncase (TOP);
 	  AFTER_POTENTIAL_GC ();
-	break;
+	NEXT;
 
-	case Bstringeqlsign:
+      CASE (Bstringeqlsign):
 	  {
 	    Lisp_Object v1;
 	    BEFORE_POTENTIAL_GC ();
 	    v1 = POP;
 	    TOP = Fstring_equal (TOP, v1);
 	    AFTER_POTENTIAL_GC ();
-	    break;
+	    NEXT;
 	  }
 
-	case Bstringlss:
+	CASE (Bstringlss):
 	  {
 	    Lisp_Object v1;
 	    BEFORE_POTENTIAL_GC ();
 	    v1 = POP;
 	    TOP = Fstring_lessp (TOP, v1);
 	    AFTER_POTENTIAL_GC ();
-	    break;
+	    NEXT;
 	  }
 
-	case Bequal:
+	CASE (Bequal):
 	  {
 	    Lisp_Object v1;
 	    v1 = POP;
 	    TOP = Fequal (TOP, v1);
-	    break;
+	    NEXT;
 	  }
 
-	case Bnthcdr:
+	CASE (Bnthcdr):
 	  {
 	    Lisp_Object v1;
 	    BEFORE_POTENTIAL_GC ();
 	    v1 = POP;
 	    TOP = Fnthcdr (TOP, v1);
 	    AFTER_POTENTIAL_GC ();
-	    break;
+	    NEXT;
 	  }
 
-	case Belt:
+	CASE (Belt):
 	  {
 	    Lisp_Object v1, v2;
 	    if (CONSP (TOP))
@@ -1535,104 +1791,105 @@ If the third argument is incorrect, Emacs may crash.  */)
 		TOP = Felt (TOP, v1);
 		AFTER_POTENTIAL_GC ();
 	      }
-	    break;
+	    NEXT;
 	  }
 
-	case Bmember:
+	CASE (Bmember):
 	  {
 	    Lisp_Object v1;
 	    BEFORE_POTENTIAL_GC ();
 	    v1 = POP;
 	    TOP = Fmember (TOP, v1);
 	    AFTER_POTENTIAL_GC ();
-	    break;
+	    NEXT;
 	  }
 
-	case Bassq:
+	CASE (Bassq):
 	  {
 	    Lisp_Object v1;
 	    BEFORE_POTENTIAL_GC ();
 	    v1 = POP;
 	    TOP = Fassq (TOP, v1);
 	    AFTER_POTENTIAL_GC ();
-	    break;
+	    NEXT;
 	  }
 
-	case Bnreverse:
+	CASE (Bnreverse):
 	  BEFORE_POTENTIAL_GC ();
 	  TOP = Fnreverse (TOP);
 	  AFTER_POTENTIAL_GC ();
-	  break;
+	  NEXT;
 
-	case Bsetcar:
+	CASE (Bsetcar):
 	  {
 	    Lisp_Object v1;
 	    BEFORE_POTENTIAL_GC ();
 	    v1 = POP;
 	    TOP = Fsetcar (TOP, v1);
 	    AFTER_POTENTIAL_GC ();
-	    break;
+	    NEXT;
 	  }
 
-	case Bsetcdr:
+	CASE (Bsetcdr):
 	  {
 	    Lisp_Object v1;
 	    BEFORE_POTENTIAL_GC ();
 	    v1 = POP;
 	    TOP = Fsetcdr (TOP, v1);
 	    AFTER_POTENTIAL_GC ();
-	    break;
+	    NEXT;
 	  }
 
-	case Bcar_safe:
+	CASE (Bcar_safe):
 	  {
 	    Lisp_Object v1;
 	    v1 = TOP;
 	    TOP = CAR_SAFE (v1);
-	    break;
+	    NEXT;
 	  }
 
-	case Bcdr_safe:
+	CASE (Bcdr_safe):
 	  {
 	    Lisp_Object v1;
 	    v1 = TOP;
 	    TOP = CDR_SAFE (v1);
-	    break;
+	    NEXT;
 	  }
 
-	case Bnconc:
+	CASE (Bnconc):
 	  BEFORE_POTENTIAL_GC ();
 	  DISCARD (1);
 	  TOP = Fnconc (2, &TOP);
 	  AFTER_POTENTIAL_GC ();
-	  break;
+	  NEXT;
 
-	case Bnumberp:
+	CASE (Bnumberp):
 	  TOP = (NUMBERP (TOP) ? Qt : Qnil);
-	  break;
+	  NEXT;
 
-	case Bintegerp:
+	CASE (Bintegerp):
 	  TOP = INTEGERP (TOP) ? Qt : Qnil;
-	  break;
+	  NEXT;
 
 #ifdef BYTE_CODE_SAFE
-	case Bset_mark:
+	CASE (Bset_mark):
 	  BEFORE_POTENTIAL_GC ();
 	  error ("set-mark is an obsolete bytecode");
 	  AFTER_POTENTIAL_GC ();
-	  break;
-	case Bscan_buffer:
+	  NEXT;
+	CASE (Bscan_buffer):
 	  BEFORE_POTENTIAL_GC ();
 	  error ("scan-buffer is an obsolete bytecode");
 	  AFTER_POTENTIAL_GC ();
-	  break;
-#endif
-
-	case 0:
+	  NEXT;
+#else
+	CASE (Bset_mark):
+	CASE (Bscan_buffer):
 	  abort ();
+#endif
 
-	case 255:
-	default:
+	CASE_DEFAULT
+	CASE (Bconstant):
 #ifdef BYTE_CODE_SAFE
 	  if (op < Bconstant)
 	    {
@@ -1646,6 +1903,10 @@ If the third argument is incorrect, Emacs may crash.  */)
 #else
 	  PUSH (vectorp[op - Bconstant]);
 #endif
+	  NEXT;
+
+	CASE_ABORT:
+	  abort ();
 	}
     }