(Fbyte_code): Add a bunch of BEFORE_POTENTIAL_GC/
[bpt/emacs.git] / src / bytecode.c
index 57639d9..ff9a36e 100644 (file)
@@ -276,29 +276,51 @@ mark_byte_stack ()
        abort ();
       
       for (obj = stack->bottom; obj <= stack->top; ++obj)
-       mark_object (obj);
+       if (!XMARKBIT (*obj))
+         {
+           mark_object (obj);
+           XMARK (*obj);
+         }
+
+      if (!XMARKBIT (stack->byte_string))
+       {
+          mark_object (&stack->byte_string);
+         XMARK (stack->byte_string);
+       }
 
-      mark_object (&stack->byte_string);
-      mark_object (&stack->constants);
+      if (!XMARKBIT (stack->constants))
+       {
+         mark_object (&stack->constants);
+         XMARK (stack->constants);
+       }
     }
 }
 
 
-/* Relocate program counters in the stacks on byte_stack_list.  Called
-   when GC has completed.  */
+/* Unmark objects in the stacks on byte_stack_list.  Relocate program
+   counters.  Called when GC has completed.  */
 
 void 
-relocate_byte_pcs ()
+unmark_byte_stack ()
 {
   struct byte_stack *stack;
+  Lisp_Object *obj;
 
   for (stack = byte_stack_list; stack; stack = stack->next)
-    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;
-      }
+    {
+      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;
+       }
+    }
 }
 
 \f
@@ -411,12 +433,10 @@ If the third argument is incorrect, Emacs may crash.")
   while (1)
     {
 #ifdef BYTE_CODE_SAFE
-      if (top > stacks)
-       error ("Byte code stack overflow (byte compiler bug), pc %d, depth %d",
-              stack.pc - stack.byte_string_start, stacke - top);
+      if (top > stacke)
+       abort ();
       else if (top < stack.bottom - 1)
-       error ("Byte code stack underflow (byte compiler bug), pc %d",
-              stack.pc - stack.byte_string_start);
+       abort ();
 #endif
 
 #ifdef BYTE_CODE_METER
@@ -455,10 +475,18 @@ If the third argument is incorrect, Emacs may crash.")
              {
                v2 = XSYMBOL (v1)->value;
                if (MISCP (v2) || EQ (v2, Qunbound))
-                 v2 = Fsymbol_value (v1);
+                 {
+                   BEFORE_POTENTIAL_GC ();
+                   v2 = Fsymbol_value (v1);
+                   AFTER_POTENTIAL_GC ();
+                 }
              }
            else
-             v2 = Fsymbol_value (v1);
+             {
+               BEFORE_POTENTIAL_GC ();
+               v2 = Fsymbol_value (v1);
+               AFTER_POTENTIAL_GC ();
+             }
            PUSH (v2);
            break;
          }
@@ -478,9 +506,16 @@ If the third argument is incorrect, Emacs may crash.")
          {
            Lisp_Object v1;
            v1 = TOP;
-           if (CONSP (v1)) TOP = XCAR (v1);
-           else if (NILP (v1)) TOP = Qnil;
-           else Fcar (wrong_type_argument (Qlistp, v1));
+           if (CONSP (v1))
+             TOP = XCAR (v1);
+           else if (NILP (v1))
+             TOP = Qnil;
+           else
+             {
+               BEFORE_POTENTIAL_GC ();
+               Fcar (wrong_type_argument (Qlistp, v1));
+               AFTER_POTENTIAL_GC ();
+             }
            break;
          }
 
@@ -495,8 +530,10 @@ If the third argument is incorrect, Emacs may crash.")
        case Bmemq:
          {
            Lisp_Object v1;
+           BEFORE_POTENTIAL_GC ();
            v1 = POP;
            TOP = Fmemq (TOP, v1);
+           AFTER_POTENTIAL_GC ();
            break;
          }
 
@@ -504,26 +541,63 @@ If the third argument is incorrect, Emacs may crash.")
          {
            Lisp_Object v1;
            v1 = TOP;
-           if (CONSP (v1)) TOP = XCDR (v1);
-           else if (NILP (v1)) TOP = Qnil;
-           else Fcdr (wrong_type_argument (Qlistp, v1));
+           if (CONSP (v1))
+             TOP = XCDR (v1);
+           else if (NILP (v1))
+             TOP = Qnil;
+           else
+             {
+               BEFORE_POTENTIAL_GC ();
+               Fcdr (wrong_type_argument (Qlistp, v1));
+               AFTER_POTENTIAL_GC ();
+             }
            break;
          }
 
-       case Bvarset+7:
-         op = FETCH2;
+       case Bvarset:
+       case Bvarset+1:
+       case Bvarset+2:
+       case Bvarset+3:
+       case Bvarset+4:
+       case Bvarset+5:
+         op -= Bvarset;
          goto varset;
 
-       case Bvarset: case Bvarset+1: case Bvarset+2: case Bvarset+3:
-       case Bvarset+4: case Bvarset+5:
-         op -= Bvarset;
+       case Bvarset+7:
+         op = FETCH2;
          goto varset;
 
        case Bvarset+6:
          op = FETCH;
        varset:
-         set_internal (vectorp[op], POP, 0);
-         /* Fset (vectorp[op], POP); */
+         {
+           Lisp_Object sym, val;
+             
+           sym = vectorp[op];
+           val = TOP;
+
+           /* Inline the most common case.  */
+           if (SYMBOLP (sym)
+               && !EQ (val, Qunbound)
+               && !MISCP (XSYMBOL (sym)->value)
+               /* I think this should either be checked in the byte
+                  compiler, or there should be a flag indicating that
+                  a symbol might be constant in Lisp_Symbol, instead
+                  of checking this here over and over again. --gerd.  */
+               && !EQ (sym, Qnil)
+               && !EQ (sym, Qt)
+               && !(XSYMBOL (sym)->name->data[0] == ':'
+                    && EQ (XSYMBOL (sym)->obarray, initial_obarray)
+                    && !EQ (val, sym)))
+             XSYMBOL (sym)->value = val;
+           else
+             {
+               BEFORE_POTENTIAL_GC ();
+               set_internal (sym, val, current_buffer, 0);
+               AFTER_POTENTIAL_GC ();
+             }
+         }
+         POP;
          break;
 
        case Bdup:
@@ -544,8 +618,12 @@ If the third argument is incorrect, Emacs may crash.")
          op = FETCH2;
          goto varbind;
 
-       case Bvarbind: case Bvarbind+1: case Bvarbind+2: case Bvarbind+3:
-       case Bvarbind+4: case Bvarbind+5:
+       case Bvarbind:
+       case Bvarbind+1:
+       case Bvarbind+2:
+       case Bvarbind+3:
+       case Bvarbind+4:
+       case Bvarbind+5:
          op -= Bvarbind;
        varbind:
          specbind (vectorp[op], POP);
@@ -559,11 +637,16 @@ If the third argument is incorrect, Emacs may crash.")
          op = FETCH2;
          goto docall;
 
-       case Bcall: case Bcall+1: case Bcall+2: case Bcall+3:
-       case Bcall+4: case Bcall+5:
+       case Bcall:
+       case Bcall+1:
+       case Bcall+2:
+       case Bcall+3:
+       case Bcall+4:
+       case Bcall+5:
          op -= Bcall;
        docall:
          {
+           BEFORE_POTENTIAL_GC ();
            DISCARD (op);
 #ifdef BYTE_CODE_METER
            if (byte_metering_on && SYMBOLP (TOP))
@@ -580,7 +663,6 @@ If the third argument is incorrect, Emacs may crash.")
                  }
              }
 #endif
-           BEFORE_POTENTIAL_GC ();
            TOP = Ffuncall (op + 1, &TOP);
            AFTER_POTENTIAL_GC ();
            break;
@@ -594,8 +676,12 @@ If the third argument is incorrect, Emacs may crash.")
          op = FETCH2;
          goto dounbind;
 
-       case Bunbind: case Bunbind+1: case Bunbind+2: case Bunbind+3:
-       case Bunbind+4: case Bunbind+5:
+       case Bunbind:
+       case Bunbind+1:
+       case Bunbind+2:
+       case Bunbind+3:
+       case Bunbind+4:
+       case Bunbind+5:
          op -= Bunbind;
        dounbind:
          BEFORE_POTENTIAL_GC ();
@@ -715,7 +801,8 @@ If the third argument is incorrect, Emacs may crash.")
          break;
 
        case Bsave_excursion:
-         record_unwind_protect (save_excursion_restore, save_excursion_save ());
+         record_unwind_protect (save_excursion_restore,
+                                save_excursion_save ());
          break;
 
        case Bsave_current_buffer:
@@ -730,15 +817,15 @@ If the third argument is incorrect, Emacs may crash.")
          break;
 
        case Bsave_restriction:
-         record_unwind_protect (save_restriction_restore, save_restriction_save ());
+         record_unwind_protect (save_restriction_restore,
+                                save_restriction_save ());
          break;
 
        case Bcatch:
          {
            Lisp_Object v1;
-
-           v1 = POP;
            BEFORE_POTENTIAL_GC ();
+           v1 = POP;
            TOP = internal_catch (TOP, Feval, v1);
            AFTER_POTENTIAL_GC ();
            break;
@@ -770,8 +857,8 @@ If the third argument is incorrect, Emacs may crash.")
        case Btemp_output_buffer_show:
          {
            Lisp_Object v1;
-           v1 = POP;
            BEFORE_POTENTIAL_GC ();
+           v1 = POP;
            temp_output_buffer_show (TOP);
            TOP = v1;
            /* pop binding of standard-output */
@@ -783,9 +870,11 @@ If the third argument is incorrect, Emacs may crash.")
        case Bnth:
          {
            Lisp_Object v1, v2;
+           BEFORE_POTENTIAL_GC ();
            v1 = POP;
            v2 = TOP;
            CHECK_NUMBER (v2, 0);
+           AFTER_POTENTIAL_GC ();
            op = XINT (v2);
            immediate_quit = 1;
            while (--op >= 0)
@@ -795,15 +884,24 @@ If the third argument is incorrect, Emacs may crash.")
                else if (!NILP (v1))
                  {
                    immediate_quit = 0;
+                   BEFORE_POTENTIAL_GC ();
                    v1 = wrong_type_argument (Qlistp, v1);
+                   AFTER_POTENTIAL_GC ();
                    immediate_quit = 1;
                    op++;
                  }
              }
            immediate_quit = 0;
-           if (CONSP (v1)) TOP = XCAR (v1);
-           else if (NILP (v1)) TOP = Qnil;
-           else Fcar (wrong_type_argument (Qlistp, v1));
+           if (CONSP (v1))
+             TOP = XCAR (v1);
+           else if (NILP (v1))
+             TOP = Qnil;
+           else
+             {
+               BEFORE_POTENTIAL_GC ();
+               Fcar (wrong_type_argument (Qlistp, v1));
+               AFTER_POTENTIAL_GC ();
+             }
            break;
          }
 
@@ -864,84 +962,110 @@ If the third argument is incorrect, Emacs may crash.")
          break;
 
        case Blength:
+         BEFORE_POTENTIAL_GC ();
          TOP = Flength (TOP);
+         AFTER_POTENTIAL_GC ();
          break;
 
        case Baref:
          {
            Lisp_Object v1;
+           BEFORE_POTENTIAL_GC ();
            v1 = POP;
            TOP = Faref (TOP, v1);
+           AFTER_POTENTIAL_GC ();
            break;
          }
 
        case Baset:
          {
            Lisp_Object v1, v2;
+           BEFORE_POTENTIAL_GC ();
            v2 = POP; v1 = POP;
            TOP = Faset (TOP, v1, v2);
+           AFTER_POTENTIAL_GC ();
            break;
          }
 
        case Bsymbol_value:
+         BEFORE_POTENTIAL_GC ();
          TOP = Fsymbol_value (TOP);
+         AFTER_POTENTIAL_GC ();
          break;
 
        case Bsymbol_function:
+         BEFORE_POTENTIAL_GC ();
          TOP = Fsymbol_function (TOP);
+         AFTER_POTENTIAL_GC ();
          break;
 
        case Bset:
          {
            Lisp_Object v1;
+           BEFORE_POTENTIAL_GC ();
            v1 = POP;
            TOP = Fset (TOP, v1);
+           AFTER_POTENTIAL_GC ();
            break;
          }
 
        case Bfset:
          {
            Lisp_Object v1;
+           BEFORE_POTENTIAL_GC ();
            v1 = POP;
            TOP = Ffset (TOP, v1);
+           AFTER_POTENTIAL_GC ();
            break;
          }
 
        case Bget:
          {
            Lisp_Object v1;
+           BEFORE_POTENTIAL_GC ();
            v1 = POP;
            TOP = Fget (TOP, v1);
+           AFTER_POTENTIAL_GC ();
            break;
          }
 
        case Bsubstring:
          {
            Lisp_Object v1, v2;
+           BEFORE_POTENTIAL_GC ();
            v2 = POP; v1 = POP;
            TOP = Fsubstring (TOP, v1, v2);
+           AFTER_POTENTIAL_GC ();
            break;
          }
 
        case Bconcat2:
+         BEFORE_POTENTIAL_GC ();
          DISCARD (1);
          TOP = Fconcat (2, &TOP);
+         AFTER_POTENTIAL_GC ();
          break;
 
        case Bconcat3:
+         BEFORE_POTENTIAL_GC ();
          DISCARD (2);
          TOP = Fconcat (3, &TOP);
+         AFTER_POTENTIAL_GC ();
          break;
 
        case Bconcat4:
+         BEFORE_POTENTIAL_GC ();
          DISCARD (3);
          TOP = Fconcat (4, &TOP);
+         AFTER_POTENTIAL_GC ();
          break;
 
        case BconcatN:
          op = FETCH;
+         BEFORE_POTENTIAL_GC ();
          DISCARD (op - 1);
          TOP = Fconcat (op, &TOP);
+         AFTER_POTENTIAL_GC ();
          break;
 
        case Bsub1:
@@ -968,17 +1092,22 @@ If the third argument is incorrect, Emacs may crash.")
                TOP = v1;
              }
            else
-             TOP = Fadd1 (v1);
+             {
+               BEFORE_POTENTIAL_GC ();
+               TOP = Fadd1 (v1);
+               AFTER_POTENTIAL_GC ();
+             }
            break;
          }
 
        case Beqlsign:
          {
            Lisp_Object v1, v2;
+           BEFORE_POTENTIAL_GC ();
            v2 = POP; v1 = TOP;
            CHECK_NUMBER_OR_FLOAT_COERCE_MARKER (v1, 0);
            CHECK_NUMBER_OR_FLOAT_COERCE_MARKER (v2, 0);
-#ifdef LISP_FLOAT_TYPE
+           AFTER_POTENTIAL_GC ();
            if (FLOATP (v1) || FLOATP (v2))
              {
                double f1, f2;
@@ -988,7 +1117,6 @@ If the third argument is incorrect, Emacs may crash.")
                TOP = (f1 == f2 ? Qt : Qnil);
              }
            else
-#endif
              TOP = (XINT (v1) == XINT (v2) ? Qt : Qnil);
            break;
          }
@@ -996,24 +1124,30 @@ If the third argument is incorrect, Emacs may crash.")
        case Bgtr:
          {
            Lisp_Object v1;
+           BEFORE_POTENTIAL_GC ();
            v1 = POP;
            TOP = Fgtr (TOP, v1);
+           AFTER_POTENTIAL_GC ();
            break;
          }
 
        case Blss:
          {
            Lisp_Object v1;
+           BEFORE_POTENTIAL_GC ();
            v1 = POP;
            TOP = Flss (TOP, v1);
+           AFTER_POTENTIAL_GC ();
            break;
          }
 
        case Bleq:
          {
            Lisp_Object v1;
+           BEFORE_POTENTIAL_GC ();
            v1 = POP;
            TOP = Fleq (TOP, v1);
+           AFTER_POTENTIAL_GC ();
            break;
          }
 
@@ -1026,8 +1160,10 @@ If the third argument is incorrect, Emacs may crash.")
          }
 
        case Bdiff:
+         BEFORE_POTENTIAL_GC ();
          DISCARD (1);
          TOP = Fminus (2, &TOP);
+         AFTER_POTENTIAL_GC ();
          break;
 
        case Bnegate:
@@ -1040,40 +1176,56 @@ If the third argument is incorrect, Emacs may crash.")
                TOP = v1;
              }
            else
-             TOP = Fminus (1, &TOP);
+             {
+               BEFORE_POTENTIAL_GC ();
+               TOP = Fminus (1, &TOP);
+               AFTER_POTENTIAL_GC ();
+             }
            break;
          }
 
        case Bplus:
+         BEFORE_POTENTIAL_GC ();
          DISCARD (1);
          TOP = Fplus (2, &TOP);
+         AFTER_POTENTIAL_GC ();
          break;
 
        case Bmax:
+         BEFORE_POTENTIAL_GC ();
          DISCARD (1);
          TOP = Fmax (2, &TOP);
+         AFTER_POTENTIAL_GC ();
          break;
 
        case Bmin:
+         BEFORE_POTENTIAL_GC ();
          DISCARD (1);
          TOP = Fmin (2, &TOP);
+         AFTER_POTENTIAL_GC ();
          break;
 
        case Bmult:
+         BEFORE_POTENTIAL_GC ();
          DISCARD (1);
          TOP = Ftimes (2, &TOP);
+         AFTER_POTENTIAL_GC ();
          break;
 
        case Bquo:
+         BEFORE_POTENTIAL_GC ();
          DISCARD (1);
          TOP = Fquo (2, &TOP);
+         AFTER_POTENTIAL_GC ();
          break;
 
        case Brem:
          {
            Lisp_Object v1;
+           BEFORE_POTENTIAL_GC ();
            v1 = POP;
            TOP = Frem (TOP, v1);
+           AFTER_POTENTIAL_GC ();
            break;
          }
 
@@ -1099,8 +1251,8 @@ If the third argument is incorrect, Emacs may crash.")
 
        case BinsertN:
          op = FETCH;
-         DISCARD (op - 1);
          BEFORE_POTENTIAL_GC ();
+         DISCARD (op - 1);
          TOP = Finsert (op, &TOP);
          AFTER_POTENTIAL_GC ();
          break;
@@ -1122,13 +1274,17 @@ If the third argument is incorrect, Emacs may crash.")
          }
 
        case Bchar_after:
+         BEFORE_POTENTIAL_GC ();
          TOP = Fchar_after (TOP);
+         AFTER_POTENTIAL_GC ();
          break;
 
        case Bfollowing_char:
          {
            Lisp_Object v1;
+           BEFORE_POTENTIAL_GC ();
            v1 = Ffollowing_char ();
+           AFTER_POTENTIAL_GC ();
            PUSH (v1);
            break;
          }
@@ -1136,7 +1292,9 @@ If the third argument is incorrect, Emacs may crash.")
        case Bpreceding_char:
          {
            Lisp_Object v1;
+           BEFORE_POTENTIAL_GC ();
            v1 = Fprevious_char ();
+           AFTER_POTENTIAL_GC ();
            PUSH (v1);
            break;
          }
@@ -1200,8 +1358,8 @@ If the third argument is incorrect, Emacs may crash.")
        case Bskip_chars_forward:
          {
            Lisp_Object v1;
-           v1 = POP;
            BEFORE_POTENTIAL_GC ();
+           v1 = POP;
            TOP = Fskip_chars_forward (TOP, v1);
            AFTER_POTENTIAL_GC ();
            break;
@@ -1210,8 +1368,8 @@ If the third argument is incorrect, Emacs may crash.")
        case Bskip_chars_backward:
          {
            Lisp_Object v1;
-           v1 = POP;
            BEFORE_POTENTIAL_GC ();
+           v1 = POP;
            TOP = Fskip_chars_backward (TOP, v1);
            AFTER_POTENTIAL_GC ();
            break;
@@ -1224,15 +1382,17 @@ If the third argument is incorrect, Emacs may crash.")
          break;
 
        case Bchar_syntax:
+         BEFORE_POTENTIAL_GC ();
          CHECK_NUMBER (TOP, 0);
+         AFTER_POTENTIAL_GC ();
          XSETFASTINT (TOP, syntax_code_spec[(int) SYNTAX (XINT (TOP))]);
          break;
 
        case Bbuffer_substring:
          {
            Lisp_Object v1;
-           v1 = POP;
            BEFORE_POTENTIAL_GC ();
+           v1 = POP;
            TOP = Fbuffer_substring (TOP, v1);
            AFTER_POTENTIAL_GC ();
            break;
@@ -1241,8 +1401,8 @@ If the third argument is incorrect, Emacs may crash.")
        case Bdelete_region:
          {
            Lisp_Object v1;
-           v1 = POP;
            BEFORE_POTENTIAL_GC ();
+           v1 = POP;
            TOP = Fdelete_region (TOP, v1);
            AFTER_POTENTIAL_GC ();
            break;
@@ -1251,8 +1411,8 @@ If the third argument is incorrect, Emacs may crash.")
        case Bnarrow_to_region:
          {
            Lisp_Object v1;
-           v1 = POP;
            BEFORE_POTENTIAL_GC ();
+           v1 = POP;
            TOP = Fnarrow_to_region (TOP, v1);
            AFTER_POTENTIAL_GC ();
            break;
@@ -1273,41 +1433,55 @@ If the third argument is incorrect, Emacs may crash.")
        case Bset_marker:
          {
            Lisp_Object v1, v2;
+           BEFORE_POTENTIAL_GC ();
            v1 = POP;
            v2 = POP;
            TOP = Fset_marker (TOP, v2, v1);
+           AFTER_POTENTIAL_GC ();
            break;
          }
 
        case Bmatch_beginning:
+         BEFORE_POTENTIAL_GC ();
          TOP = Fmatch_beginning (TOP);
+         AFTER_POTENTIAL_GC ();
          break;
 
        case Bmatch_end:
+         BEFORE_POTENTIAL_GC ();
          TOP = Fmatch_end (TOP);
+         AFTER_POTENTIAL_GC ();
          break;
 
        case Bupcase:
+         BEFORE_POTENTIAL_GC ();
          TOP = Fupcase (TOP);
+         AFTER_POTENTIAL_GC ();
          break;
 
        case Bdowncase:
+         BEFORE_POTENTIAL_GC ();
          TOP = Fdowncase (TOP);
+         AFTER_POTENTIAL_GC ();
        break;
 
        case Bstringeqlsign:
          {
            Lisp_Object v1;
+           BEFORE_POTENTIAL_GC ();
            v1 = POP;
            TOP = Fstring_equal (TOP, v1);
+           AFTER_POTENTIAL_GC ();
            break;
          }
 
        case Bstringlss:
          {
            Lisp_Object v1;
+           BEFORE_POTENTIAL_GC ();
            v1 = POP;
            TOP = Fstring_lessp (TOP, v1);
+           AFTER_POTENTIAL_GC ();
            break;
          }
 
@@ -1322,8 +1496,10 @@ If the third argument is incorrect, Emacs may crash.")
        case Bnthcdr:
          {
            Lisp_Object v1;
+           BEFORE_POTENTIAL_GC ();
            v1 = POP;
            TOP = Fnthcdr (TOP, v1);
+           AFTER_POTENTIAL_GC ();
            break;
          }
 
@@ -1333,9 +1509,11 @@ If the third argument is incorrect, Emacs may crash.")
            if (CONSP (TOP))
              {
                /* Exchange args and then do nth.  */
+               BEFORE_POTENTIAL_GC ();
                v2 = POP;
                v1 = TOP;
                CHECK_NUMBER (v2, 0);
+               AFTER_POTENTIAL_GC ();
                op = XINT (v2);
                immediate_quit = 1;
                while (--op >= 0)
@@ -1345,20 +1523,31 @@ If the third argument is incorrect, Emacs may crash.")
                    else if (!NILP (v1))
                      {
                        immediate_quit = 0;
+                       BEFORE_POTENTIAL_GC ();
                        v1 = wrong_type_argument (Qlistp, v1);
+                       AFTER_POTENTIAL_GC ();
                        immediate_quit = 1;
                        op++;
                      }
                  }
                immediate_quit = 0;
-               if (CONSP (v1)) TOP = XCAR (v1);
-               else if (NILP (v1)) TOP = Qnil;
-               else Fcar (wrong_type_argument (Qlistp, v1));
+               if (CONSP (v1))
+                 TOP = XCAR (v1);
+               else if (NILP (v1))
+                 TOP = Qnil;
+               else
+                 {
+                   BEFORE_POTENTIAL_GC ();
+                   Fcar (wrong_type_argument (Qlistp, v1));
+                   AFTER_POTENTIAL_GC ();
+                 }
              }
            else
              {
+               BEFORE_POTENTIAL_GC ();
                v1 = POP;
                TOP = Felt (TOP, v1);
+               AFTER_POTENTIAL_GC ();
              }
            break;
          }
@@ -1366,36 +1555,46 @@ If the third argument is incorrect, Emacs may crash.")
        case Bmember:
          {
            Lisp_Object v1;
+           BEFORE_POTENTIAL_GC ();
            v1 = POP;
            TOP = Fmember (TOP, v1);
+           AFTER_POTENTIAL_GC ();
            break;
          }
 
        case Bassq:
          {
            Lisp_Object v1;
+           BEFORE_POTENTIAL_GC ();
            v1 = POP;
            TOP = Fassq (TOP, v1);
+           AFTER_POTENTIAL_GC ();
            break;
          }
 
        case Bnreverse:
+         BEFORE_POTENTIAL_GC ();
          TOP = Fnreverse (TOP);
+         AFTER_POTENTIAL_GC ();
          break;
 
        case Bsetcar:
          {
            Lisp_Object v1;
+           BEFORE_POTENTIAL_GC ();
            v1 = POP;
            TOP = Fsetcar (TOP, v1);
+           AFTER_POTENTIAL_GC ();
            break;
          }
 
        case Bsetcdr:
          {
            Lisp_Object v1;
+           BEFORE_POTENTIAL_GC ();
            v1 = POP;
            TOP = Fsetcdr (TOP, v1);
+           AFTER_POTENTIAL_GC ();
            break;
          }
 
@@ -1422,8 +1621,10 @@ If the third argument is incorrect, Emacs may crash.")
          }
 
        case Bnconc:
+         BEFORE_POTENTIAL_GC ();
          DISCARD (1);
          TOP = Fnconc (2, &TOP);
+         AFTER_POTENTIAL_GC ();
          break;
 
        case Bnumberp:
@@ -1436,19 +1637,31 @@ If the third argument is incorrect, Emacs may crash.")
 
 #ifdef BYTE_CODE_SAFE
        case Bset_mark:
+         BEFORE_POTENTIAL_GC ();
          error ("set-mark is an obsolete bytecode");
+         AFTER_POTENTIAL_GC ();
          break;
        case Bscan_buffer:
+         BEFORE_POTENTIAL_GC ();
          error ("scan-buffer is an obsolete bytecode");
+         AFTER_POTENTIAL_GC ();
          break;
 #endif
 
+       case 0:
+         abort ();
+
+       case 255:
        default:
 #ifdef BYTE_CODE_SAFE
          if (op < Bconstant)
-           error ("unknown bytecode %d (byte compiler bug)", op);
+           {
+             abort ();
+           }
          if ((op -= Bconstant) >= const_length)
-           error ("no constant number %d (byte compiler bug)", op);
+           {
+             abort ();
+           }
          PUSH (vectorp[op]);
 #else
          PUSH (vectorp[op - Bconstant]);