Merge from trunk
[bpt/emacs.git] / src / bytecode.c
CommitLineData
36f7ba0a 1/* Execution of byte code produced by bytecomp.el.
73b0cd50 2 Copyright (C) 1985-1988, 1993, 2000-2011 Free Software Foundation, Inc.
36f7ba0a
JB
3
4This file is part of GNU Emacs.
5
9ec0b715 6GNU Emacs is free software: you can redistribute it and/or modify
36f7ba0a 7it under the terms of the GNU General Public License as published by
9ec0b715
GM
8the Free Software Foundation, either version 3 of the License, or
9(at your option) any later version.
36f7ba0a
JB
10
11GNU Emacs is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
9ec0b715 17along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
36f7ba0a 18
9ec0b715 19/*
63639d44 20hacked on by jwz@lucid.com 17-jun-91
36f7ba0a
JB
21 o added a compile-time switch to turn on simple sanity checking;
22 o put back the obsolete byte-codes for error-detection;
8e11578b 23 o added a new instruction, unbind_all, which I will use for
36f7ba0a 24 tail-recursion elimination;
63639d44 25 o made temp_output_buffer_show be called with the right number
36f7ba0a
JB
26 of args;
27 o made the new bytecodes be called with args in the right order;
28 o added metering support.
29
30by Hallvard:
3ffbe76b 31 o added relative jump instructions;
36f7ba0a
JB
32 o all conditionals now only do QUIT if they jump.
33 */
34
18160b98 35#include <config.h>
d7306fe6 36#include <setjmp.h>
36f7ba0a
JB
37#include "lisp.h"
38#include "buffer.h"
83be827a 39#include "character.h"
36f7ba0a 40#include "syntax.h"
3f6abfd7 41#include "window.h"
36f7ba0a 42
ad7de7d7
GM
43#ifdef CHECK_FRAME_FONT
44#include "frame.h"
45#include "xterm.h"
46#endif
47
63639d44 48/*
8e11578b 49 * define BYTE_CODE_SAFE to enable some minor sanity checking (useful for
63639d44
JB
50 * debugging the byte compiler...)
51 *
8e11578b 52 * define BYTE_CODE_METER to enable generation of a byte-op usage histogram.
36f7ba0a 53 */
63639d44
JB
54/* #define BYTE_CODE_SAFE */
55/* #define BYTE_CODE_METER */
36f7ba0a
JB
56
57\f
58#ifdef BYTE_CODE_METER
59
29208e82 60Lisp_Object Qbyte_code_meter;
63639d44 61#define METER_2(code1, code2) \
36f7ba0a
JB
62 XFASTINT (XVECTOR (XVECTOR (Vbyte_code_meter)->contents[(code1)]) \
63 ->contents[(code2)])
64
63639d44
JB
65#define METER_1(code) METER_2 (0, (code))
66
2e3bf02a
GM
67#define METER_CODE(last_code, this_code) \
68{ \
69 if (byte_metering_on) \
70 { \
71 if (METER_1 (this_code) < MOST_POSITIVE_FIXNUM) \
72 METER_1 (this_code)++; \
73 if (last_code \
74 && METER_2 (last_code, this_code) < MOST_POSITIVE_FIXNUM) \
75 METER_2 (last_code, this_code)++; \
76 } \
63639d44 77}
36f7ba0a 78
63639d44 79#else /* no BYTE_CODE_METER */
36f7ba0a 80
63639d44 81#define METER_CODE(last_code, this_code)
044512ed 82
63639d44 83#endif /* no BYTE_CODE_METER */
36f7ba0a
JB
84\f
85
86Lisp_Object Qbytecode;
b9598260 87extern Lisp_Object Qand_optional, Qand_rest;
36f7ba0a
JB
88
89/* Byte codes: */
90
b9598260 91#define Bstack_ref 0
36f7ba0a
JB
92#define Bvarref 010
93#define Bvarset 020
94#define Bvarbind 030
95#define Bcall 040
96#define Bunbind 050
97
98#define Bnth 070
99#define Bsymbolp 071
100#define Bconsp 072
101#define Bstringp 073
102#define Blistp 074
103#define Beq 075
104#define Bmemq 076
105#define Bnot 077
106#define Bcar 0100
107#define Bcdr 0101
108#define Bcons 0102
109#define Blist1 0103
110#define Blist2 0104
111#define Blist3 0105
112#define Blist4 0106
113#define Blength 0107
114#define Baref 0110
115#define Baset 0111
116#define Bsymbol_value 0112
63639d44 117#define Bsymbol_function 0113
36f7ba0a 118#define Bset 0114
63639d44 119#define Bfset 0115
36f7ba0a
JB
120#define Bget 0116
121#define Bsubstring 0117
122#define Bconcat2 0120
123#define Bconcat3 0121
124#define Bconcat4 0122
125#define Bsub1 0123
126#define Badd1 0124
127#define Beqlsign 0125
128#define Bgtr 0126
129#define Blss 0127
130#define Bleq 0130
131#define Bgeq 0131
132#define Bdiff 0132
133#define Bnegate 0133
134#define Bplus 0134
135#define Bmax 0135
136#define Bmin 0136
137#define Bmult 0137
138
139#define Bpoint 0140
3b841abc
RS
140/* Was Bmark in v17. */
141#define Bsave_current_buffer 0141
36f7ba0a
JB
142#define Bgoto_char 0142
143#define Binsert 0143
144#define Bpoint_max 0144
145#define Bpoint_min 0145
146#define Bchar_after 0146
147#define Bfollowing_char 0147
148#define Bpreceding_char 0150
149#define Bcurrent_column 0151
150#define Bindent_to 0152
151#define Bscan_buffer 0153 /* No longer generated as of v18 */
152#define Beolp 0154
153#define Beobp 0155
154#define Bbolp 0156
155#define Bbobp 0157
156#define Bcurrent_buffer 0160
157#define Bset_buffer 0161
80402f25 158#define Bsave_current_buffer_1 0162 /* Replacing Bsave_current_buffer. */
63639d44 159#define Bread_char 0162 /* No longer generated as of v19 */
36f7ba0a
JB
160#define Bset_mark 0163 /* this loser is no longer generated as of v18 */
161#define Binteractive_p 0164 /* Needed since interactive-p takes unevalled args */
162
163#define Bforward_char 0165
164#define Bforward_word 0166
165#define Bskip_chars_forward 0167
166#define Bskip_chars_backward 0170
167#define Bforward_line 0171
168#define Bchar_syntax 0172
169#define Bbuffer_substring 0173
170#define Bdelete_region 0174
171#define Bnarrow_to_region 0175
172#define Bwiden 0176
63639d44 173#define Bend_of_line 0177
36f7ba0a
JB
174
175#define Bconstant2 0201
176#define Bgoto 0202
177#define Bgotoifnil 0203
178#define Bgotoifnonnil 0204
179#define Bgotoifnilelsepop 0205
180#define Bgotoifnonnilelsepop 0206
181#define Breturn 0207
182#define Bdiscard 0210
183#define Bdup 0211
184
185#define Bsave_excursion 0212
186#define Bsave_window_excursion 0213
187#define Bsave_restriction 0214
188#define Bcatch 0215
189
190#define Bunwind_protect 0216
191#define Bcondition_case 0217
192#define Btemp_output_buffer_setup 0220
193#define Btemp_output_buffer_show 0221
194
195#define Bunbind_all 0222
196
63639d44
JB
197#define Bset_marker 0223
198#define Bmatch_beginning 0224
199#define Bmatch_end 0225
200#define Bupcase 0226
201#define Bdowncase 0227
202
36f7ba0a
JB
203#define Bstringeqlsign 0230
204#define Bstringlss 0231
205#define Bequal 0232
206#define Bnthcdr 0233
207#define Belt 0234
208#define Bmember 0235
209#define Bassq 0236
210#define Bnreverse 0237
211#define Bsetcar 0240
212#define Bsetcdr 0241
213#define Bcar_safe 0242
214#define Bcdr_safe 0243
215#define Bnconc 0244
216#define Bquo 0245
217#define Brem 0246
218#define Bnumberp 0247
219#define Bintegerp 0250
220
63639d44
JB
221#define BRgoto 0252
222#define BRgotoifnil 0253
223#define BRgotoifnonnil 0254
224#define BRgotoifnilelsepop 0255
225#define BRgotoifnonnilelsepop 0256
226
227#define BlistN 0257
228#define BconcatN 0260
229#define BinsertN 0261
230
b9598260
SM
231/* Bstack_ref is code 0. */
232#define Bstack_set 0262
233#define Bstack_set2 0263
234#define Bvec_ref 0264
235#define Bvec_set 0265
236#define BdiscardN 0266
237
36f7ba0a
JB
238#define Bconstant 0300
239#define CONSTANTLIM 0100
7ca1e8b7 240
4015b3c0 241\f
7ca1e8b7
GM
242/* Structure describing a value stack used during byte-code execution
243 in Fbyte_code. */
244
245struct byte_stack
246{
247 /* Program counter. This points into the byte_string below
248 and is relocated when that string is relocated. */
33b6c007 249 const unsigned char *pc;
7ca1e8b7
GM
250
251 /* Top and bottom of stack. The bottom points to an area of memory
252 allocated with alloca in Fbyte_code. */
253 Lisp_Object *top, *bottom;
254
255 /* The string containing the byte-code, and its current address.
256 Storing this here protects it from GC because mark_byte_stack
257 marks it. */
258 Lisp_Object byte_string;
33b6c007 259 const unsigned char *byte_string_start;
7ca1e8b7
GM
260
261 /* The vector of constants used during byte-code execution. Storing
262 this here protects it from GC because mark_byte_stack marks it. */
263 Lisp_Object constants;
264
265 /* Next entry in byte_stack_list. */
266 struct byte_stack *next;
267};
268
269/* A list of currently active byte-code execution value stacks.
270 Fbyte_code adds an entry to the head of this list before it starts
271 processing byte-code, and it removed the entry again when it is
272 done. Signalling an error truncates the list analoguous to
273 gcprolist. */
274
275struct byte_stack *byte_stack_list;
276
4015b3c0 277\f
7ca1e8b7
GM
278/* Mark objects on byte_stack_list. Called during GC. */
279
280void
971de7fb 281mark_byte_stack (void)
7ca1e8b7
GM
282{
283 struct byte_stack *stack;
284 Lisp_Object *obj;
285
286 for (stack = byte_stack_list; stack; stack = stack->next)
287 {
dff13d03
GM
288 /* If STACK->top is null here, this means there's an opcode in
289 Fbyte_code that wasn't expected to GC, but did. To find out
290 which opcode this is, record the value of `stack', and walk
291 up the stack in a debugger, stopping in frames of Fbyte_code.
292 The culprit is found in the frame of Fbyte_code where the
293 address of its local variable `stack' is equal to the
294 recorded value of `stack' here. */
6b61353c 295 eassert (stack->top);
8e11578b 296
7ca1e8b7 297 for (obj = stack->bottom; obj <= stack->top; ++obj)
6b61353c 298 mark_object (*obj);
a719d13e 299
6b61353c
KH
300 mark_object (stack->byte_string);
301 mark_object (stack->constants);
7ca1e8b7
GM
302 }
303}
304
305
a719d13e
GM
306/* Unmark objects in the stacks on byte_stack_list. Relocate program
307 counters. Called when GC has completed. */
7ca1e8b7 308
8e11578b 309void
971de7fb 310unmark_byte_stack (void)
7ca1e8b7
GM
311{
312 struct byte_stack *stack;
313
314 for (stack = byte_stack_list; stack; stack = stack->next)
a719d13e 315 {
d5db4077 316 if (stack->byte_string_start != SDATA (stack->byte_string))
a719d13e
GM
317 {
318 int offset = stack->pc - stack->byte_string_start;
d5db4077 319 stack->byte_string_start = SDATA (stack->byte_string);
a719d13e
GM
320 stack->pc = stack->byte_string_start + offset;
321 }
322 }
7ca1e8b7
GM
323}
324
36f7ba0a
JB
325\f
326/* Fetch the next byte from the bytecode stream */
327
7ca1e8b7 328#define FETCH *stack.pc++
36f7ba0a 329
4015b3c0
GM
330/* Fetch two bytes from the bytecode stream and make a 16-bit number
331 out of them */
36f7ba0a
JB
332
333#define FETCH2 (op = FETCH, op + (FETCH << 8))
334
4015b3c0
GM
335/* Push x onto the execution stack. This used to be #define PUSH(x)
336 (*++stackp = (x)) This oddity is necessary because Alliant can't be
337 bothered to compile the preincrement operator properly, as of 4/91.
338 -JimB */
7ca1e8b7
GM
339
340#define PUSH(x) (top++, *top = (x))
36f7ba0a
JB
341
342/* Pop a value off the execution stack. */
343
7ca1e8b7 344#define POP (*top--)
36f7ba0a
JB
345
346/* Discard n values from the execution stack. */
347
7ca1e8b7
GM
348#define DISCARD(n) (top -= (n))
349
350/* Get the value which is at the top of the execution stack, but don't
351 pop it. */
352
353#define TOP (*top)
36f7ba0a 354
4015b3c0 355/* Actions that must be performed before and after calling a function
7ca1e8b7 356 that might GC. */
36f7ba0a 357
7ca1e8b7
GM
358#define BEFORE_POTENTIAL_GC() stack.top = top
359#define AFTER_POTENTIAL_GC() stack.top = NULL
36f7ba0a 360
14726871
RS
361/* Garbage collect if we have consed enough since the last time.
362 We do this at every branch, to avoid loops that never GC. */
363
3414f2d8
RS
364#define MAYBE_GC() \
365 if (consing_since_gc > gc_cons_threshold \
366 && consing_since_gc > gc_relative_threshold) \
367 { \
368 BEFORE_POTENTIAL_GC (); \
369 Fgarbage_collect (); \
370 AFTER_POTENTIAL_GC (); \
371 } \
5e7ed093
RS
372 else
373
3d5fc37b 374/* Check for jumping out of range. */
7ca1e8b7
GM
375
376#ifdef BYTE_CODE_SAFE
377
4015b3c0 378#define CHECK_RANGE(ARG) \
3d5fc37b
RS
379 if (ARG >= bytestr_length) abort ()
380
4015b3c0 381#else /* not BYTE_CODE_SAFE */
7ca1e8b7
GM
382
383#define CHECK_RANGE(ARG)
384
4015b3c0 385#endif /* not BYTE_CODE_SAFE */
7ca1e8b7 386
e12ea64e
GM
387/* A version of the QUIT macro which makes sure that the stack top is
388 set before signaling `quit'. */
389
390#define BYTE_CODE_QUIT \
391 do { \
392 if (!NILP (Vquit_flag) && NILP (Vinhibit_quit)) \
393 { \
731475e7 394 Lisp_Object flag = Vquit_flag; \
e12ea64e
GM
395 Vquit_flag = Qnil; \
396 BEFORE_POTENTIAL_GC (); \
731475e7 397 if (EQ (Vthrow_on_input, flag)) \
a8f0f551 398 Fthrow (Vthrow_on_input, Qt); \
e12ea64e 399 Fsignal (Qquit, Qnil); \
892a8eb5 400 AFTER_POTENTIAL_GC (); \
e12ea64e 401 } \
c0335e02 402 ELSE_PENDING_SIGNALS \
e12ea64e
GM
403 } while (0)
404
7ca1e8b7 405
b9598260 406DEFUN ("byte-code", Fbyte_code, Sbyte_code, 3, MANY, 0,
39f624fa
PJ
407 doc: /* Function used internally in byte-compiled code.
408The first argument, BYTESTR, is a string of byte code;
409the second, VECTOR, a vector of constants;
410the third, MAXDEPTH, the maximum stack depth used in this function.
b9598260
SM
411If the third argument is incorrect, Emacs may crash.
412
413If ARGS-TEMPLATE is specified, it is an argument list specification,
414according to which any remaining arguments are pushed on the stack
415before executing BYTESTR.
416
417usage: (byte-code BYTESTR VECTOR MAXDEP &optional ARGS-TEMPLATE &rest ARGS) */)
0ee81a0c 418 (int nargs, Lisp_Object *args)
b9598260
SM
419{
420 Lisp_Object args_tmpl = nargs >= 4 ? args[3] : Qnil;
421 int pnargs = nargs >= 4 ? nargs - 4 : 0;
422 Lisp_Object *pargs = nargs >= 4 ? args + 4 : 0;
423 return exec_byte_code (args[0], args[1], args[2], args_tmpl, pnargs, pargs);
424}
425
426/* Execute the byte-code in BYTESTR. VECTOR is the constant vector, and
427 MAXDEPTH is the maximum stack depth used (if MAXDEPTH is incorrect,
428 emacs may crash!). If ARGS_TEMPLATE is non-nil, it should be a lisp
429 argument list (including &rest, &optional, etc.), and ARGS, of size
430 NARGS, should be a vector of the actual arguments. The arguments in
431 ARGS are pushed on the stack according to ARGS_TEMPLATE before
432 executing BYTESTR. */
433
434Lisp_Object
0ee81a0c
SM
435exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
436 Lisp_Object args_template, int nargs, Lisp_Object *args)
36f7ba0a 437{
aed13378 438 int count = SPECPDL_INDEX ();
36f7ba0a
JB
439#ifdef BYTE_CODE_METER
440 int this_op = 0;
441 int prev_op;
442#endif
7ca1e8b7 443 int op;
4015b3c0 444 /* Lisp_Object v1, v2; */
089b985f 445 Lisp_Object *vectorp;
36f7ba0a 446#ifdef BYTE_CODE_SAFE
7ca1e8b7
GM
447 int const_length = XVECTOR (vector)->size;
448 Lisp_Object *stacke;
36f7ba0a 449#endif
089b985f 450 int bytestr_length;
7ca1e8b7
GM
451 struct byte_stack stack;
452 Lisp_Object *top;
4015b3c0 453 Lisp_Object result;
36f7ba0a 454
603a0937 455#if 0 /* CHECK_FRAME_FONT */
ad7de7d7
GM
456 {
457 struct frame *f = SELECTED_FRAME ();
458 if (FRAME_X_P (f)
459 && FRAME_FONT (f)->direction != 0
460 && FRAME_FONT (f)->direction != 1)
461 abort ();
462 }
463#endif
464
b7826503 465 CHECK_STRING (bytestr);
c616acb8 466 CHECK_VECTOR (vector);
b7826503 467 CHECK_NUMBER (maxdepth);
36f7ba0a 468
089b985f
KH
469 if (STRING_MULTIBYTE (bytestr))
470 /* BYTESTR must have been produced by Emacs 20.2 or the earlier
471 because they produced a raw 8-bit string for byte-code and now
472 such a byte-code string is loaded as multibyte while raw 8-bit
473 characters converted to multibyte form. Thus, now we must
fbd98f82 474 convert them back to the originally intended unibyte form. */
5274126b 475 bytestr = Fstring_as_unibyte (bytestr);
089b985f 476
d5db4077 477 bytestr_length = SBYTES (bytestr);
089b985f
KH
478 vectorp = XVECTOR (vector)->contents;
479
7ca1e8b7 480 stack.byte_string = bytestr;
d5db4077 481 stack.pc = stack.byte_string_start = SDATA (bytestr);
7ca1e8b7 482 stack.constants = vector;
8e11578b 483 stack.bottom = (Lisp_Object *) alloca (XFASTINT (maxdepth)
7ca1e8b7
GM
484 * sizeof (Lisp_Object));
485 top = stack.bottom - 1;
486 stack.top = NULL;
487 stack.next = byte_stack_list;
488 byte_stack_list = &stack;
36f7ba0a 489
7ca1e8b7
GM
490#ifdef BYTE_CODE_SAFE
491 stacke = stack.bottom - 1 + XFASTINT (maxdepth);
492#endif
8e11578b 493
b9598260
SM
494 if (! NILP (args_template))
495 /* We should push some arguments on the stack. */
496 {
497 Lisp_Object at;
498 int pushed = 0, optional = 0;
499
500 for (at = args_template; CONSP (at); at = XCDR (at))
501 if (EQ (XCAR (at), Qand_optional))
502 optional = 1;
503 else if (EQ (XCAR (at), Qand_rest))
504 {
505 PUSH (Flist (nargs, args));
506 pushed = nargs;
507 at = Qnil;
508 break;
509 }
510 else if (pushed < nargs)
511 {
512 PUSH (*args++);
513 pushed++;
514 }
515 else if (optional)
516 PUSH (Qnil);
517 else
518 break;
519
520 if (pushed != nargs || !NILP (at))
521 Fsignal (Qwrong_number_of_arguments,
522 Fcons (args_template, Fcons (make_number (nargs), Qnil)));
523 }
524
36f7ba0a
JB
525 while (1)
526 {
527#ifdef BYTE_CODE_SAFE
9e49c990 528 if (top > stacke)
cc94f3b2 529 abort ();
7ca1e8b7 530 else if (top < stack.bottom - 1)
cc94f3b2 531 abort ();
36f7ba0a
JB
532#endif
533
36f7ba0a
JB
534#ifdef BYTE_CODE_METER
535 prev_op = this_op;
536 this_op = op = FETCH;
537 METER_CODE (prev_op, op);
36f7ba0a 538#else
4015b3c0 539 op = FETCH;
36f7ba0a 540#endif
36f7ba0a 541
4015b3c0
GM
542 switch (op)
543 {
544 case Bvarref + 7:
36f7ba0a
JB
545 op = FETCH2;
546 goto varref;
547
8e11578b
TTN
548 case Bvarref:
549 case Bvarref + 1:
550 case Bvarref + 2:
4015b3c0 551 case Bvarref + 3:
8e11578b 552 case Bvarref + 4:
4015b3c0 553 case Bvarref + 5:
36f7ba0a 554 op = op - Bvarref;
4015b3c0
GM
555 goto varref;
556
557 /* This seems to be the most frequently executed byte-code
558 among the Bvarref's, so avoid a goto here. */
559 case Bvarref+6:
560 op = FETCH;
36f7ba0a 561 varref:
4015b3c0
GM
562 {
563 Lisp_Object v1, v2;
564
565 v1 = vectorp[op];
566 if (SYMBOLP (v1))
567 {
ce5b453a
SM
568 if (XSYMBOL (v1)->redirect != SYMBOL_PLAINVAL
569 || (v2 = SYMBOL_VAL (XSYMBOL (v1)),
570 EQ (v2, Qunbound)))
bf1de43e
GM
571 {
572 BEFORE_POTENTIAL_GC ();
573 v2 = Fsymbol_value (v1);
574 AFTER_POTENTIAL_GC ();
575 }
4015b3c0
GM
576 }
577 else
bf1de43e
GM
578 {
579 BEFORE_POTENTIAL_GC ();
580 v2 = Fsymbol_value (v1);
581 AFTER_POTENTIAL_GC ();
582 }
4015b3c0
GM
583 PUSH (v2);
584 break;
585 }
586
587 case Bgotoifnil:
21ed6de3
KR
588 {
589 Lisp_Object v1;
590 MAYBE_GC ();
591 op = FETCH2;
592 v1 = POP;
593 if (NILP (v1))
594 {
595 BYTE_CODE_QUIT;
596 CHECK_RANGE (op);
597 stack.pc = stack.byte_string_start + op;
598 }
599 break;
600 }
36f7ba0a 601
4015b3c0
GM
602 case Bcar:
603 {
604 Lisp_Object v1;
605 v1 = TOP;
14c5155a 606 TOP = CAR (v1);
4015b3c0
GM
607 break;
608 }
609
610 case Beq:
611 {
612 Lisp_Object v1;
613 v1 = POP;
614 TOP = EQ (v1, TOP) ? Qt : Qnil;
615 break;
616 }
617
618 case Bmemq:
619 {
620 Lisp_Object v1;
bf1de43e 621 BEFORE_POTENTIAL_GC ();
4015b3c0
GM
622 v1 = POP;
623 TOP = Fmemq (TOP, v1);
bf1de43e 624 AFTER_POTENTIAL_GC ();
4015b3c0
GM
625 break;
626 }
627
628 case Bcdr:
629 {
630 Lisp_Object v1;
631 v1 = TOP;
14c5155a 632 TOP = CDR (v1);
4015b3c0
GM
633 break;
634 }
36f7ba0a 635
620cc5fa
GM
636 case Bvarset:
637 case Bvarset+1:
638 case Bvarset+2:
639 case Bvarset+3:
640 case Bvarset+4:
641 case Bvarset+5:
642 op -= Bvarset;
36f7ba0a
JB
643 goto varset;
644
620cc5fa
GM
645 case Bvarset+7:
646 op = FETCH2;
4015b3c0
GM
647 goto varset;
648
649 case Bvarset+6:
650 op = FETCH;
36f7ba0a 651 varset:
620cc5fa
GM
652 {
653 Lisp_Object sym, val;
8e11578b 654
620cc5fa 655 sym = vectorp[op];
bf1de43e 656 val = TOP;
620cc5fa
GM
657
658 /* Inline the most common case. */
659 if (SYMBOLP (sym)
660 && !EQ (val, Qunbound)
ce5b453a
SM
661 && !XSYMBOL (sym)->redirect
662 && !SYMBOL_CONSTANT_P (sym))
663 XSYMBOL (sym)->val.value = val;
620cc5fa 664 else
bf1de43e
GM
665 {
666 BEFORE_POTENTIAL_GC ();
94b612ad 667 set_internal (sym, val, Qnil, 0);
bf1de43e
GM
668 AFTER_POTENTIAL_GC ();
669 }
620cc5fa 670 }
3789dcdf 671 (void) POP;
36f7ba0a
JB
672 break;
673
4015b3c0
GM
674 case Bdup:
675 {
676 Lisp_Object v1;
677 v1 = TOP;
678 PUSH (v1);
679 break;
680 }
681
682 /* ------------------ */
683
36f7ba0a
JB
684 case Bvarbind+6:
685 op = FETCH;
686 goto varbind;
687
688 case Bvarbind+7:
689 op = FETCH2;
690 goto varbind;
691
fa9aabf6
GM
692 case Bvarbind:
693 case Bvarbind+1:
694 case Bvarbind+2:
695 case Bvarbind+3:
696 case Bvarbind+4:
697 case Bvarbind+5:
36f7ba0a
JB
698 op -= Bvarbind;
699 varbind:
56b8eef5
GM
700 /* Specbind can signal and thus GC. */
701 BEFORE_POTENTIAL_GC ();
36f7ba0a 702 specbind (vectorp[op], POP);
56b8eef5 703 AFTER_POTENTIAL_GC ();
36f7ba0a
JB
704 break;
705
706 case Bcall+6:
707 op = FETCH;
708 goto docall;
709
710 case Bcall+7:
711 op = FETCH2;
712 goto docall;
713
fa9aabf6
GM
714 case Bcall:
715 case Bcall+1:
716 case Bcall+2:
717 case Bcall+3:
718 case Bcall+4:
719 case Bcall+5:
36f7ba0a
JB
720 op -= Bcall;
721 docall:
4015b3c0 722 {
fa9aabf6 723 BEFORE_POTENTIAL_GC ();
4015b3c0 724 DISCARD (op);
63639d44 725#ifdef BYTE_CODE_METER
4015b3c0
GM
726 if (byte_metering_on && SYMBOLP (TOP))
727 {
728 Lisp_Object v1, v2;
729
730 v1 = TOP;
731 v2 = Fget (v1, Qbyte_code_meter);
732 if (INTEGERP (v2)
f28e6371 733 && XINT (v2) < MOST_POSITIVE_FIXNUM)
4015b3c0
GM
734 {
735 XSETINT (v2, XINT (v2) + 1);
736 Fput (v1, Qbyte_code_meter, v2);
737 }
738 }
63639d44 739#endif
4015b3c0
GM
740 TOP = Ffuncall (op + 1, &TOP);
741 AFTER_POTENTIAL_GC ();
742 break;
743 }
36f7ba0a
JB
744
745 case Bunbind+6:
746 op = FETCH;
747 goto dounbind;
748
749 case Bunbind+7:
750 op = FETCH2;
751 goto dounbind;
752
fa9aabf6
GM
753 case Bunbind:
754 case Bunbind+1:
755 case Bunbind+2:
756 case Bunbind+3:
757 case Bunbind+4:
758 case Bunbind+5:
36f7ba0a
JB
759 op -= Bunbind;
760 dounbind:
7ca1e8b7 761 BEFORE_POTENTIAL_GC ();
aed13378 762 unbind_to (SPECPDL_INDEX () - op, Qnil);
7ca1e8b7 763 AFTER_POTENTIAL_GC ();
36f7ba0a
JB
764 break;
765
766 case Bunbind_all:
767 /* To unbind back to the beginning of this frame. Not used yet,
63639d44 768 but will be needed for tail-recursion elimination. */
7ca1e8b7 769 BEFORE_POTENTIAL_GC ();
36f7ba0a 770 unbind_to (count, Qnil);
7ca1e8b7 771 AFTER_POTENTIAL_GC ();
36f7ba0a
JB
772 break;
773
774 case Bgoto:
14726871 775 MAYBE_GC ();
e12ea64e 776 BYTE_CODE_QUIT;
36f7ba0a 777 op = FETCH2; /* pc = FETCH2 loses since FETCH2 contains pc++ */
3d5fc37b 778 CHECK_RANGE (op);
7ca1e8b7 779 stack.pc = stack.byte_string_start + op;
36f7ba0a
JB
780 break;
781
36f7ba0a 782 case Bgotoifnonnil:
21ed6de3
KR
783 {
784 Lisp_Object v1;
785 MAYBE_GC ();
786 op = FETCH2;
787 v1 = POP;
788 if (!NILP (v1))
789 {
790 BYTE_CODE_QUIT;
791 CHECK_RANGE (op);
792 stack.pc = stack.byte_string_start + op;
793 }
794 break;
795 }
36f7ba0a
JB
796
797 case Bgotoifnilelsepop:
14726871 798 MAYBE_GC ();
36f7ba0a 799 op = FETCH2;
921a8935 800 if (NILP (TOP))
36f7ba0a 801 {
e12ea64e 802 BYTE_CODE_QUIT;
3d5fc37b 803 CHECK_RANGE (op);
7ca1e8b7 804 stack.pc = stack.byte_string_start + op;
36f7ba0a 805 }
63639d44 806 else DISCARD (1);
36f7ba0a
JB
807 break;
808
809 case Bgotoifnonnilelsepop:
14726871 810 MAYBE_GC ();
36f7ba0a 811 op = FETCH2;
921a8935 812 if (!NILP (TOP))
36f7ba0a 813 {
e12ea64e 814 BYTE_CODE_QUIT;
3d5fc37b 815 CHECK_RANGE (op);
7ca1e8b7 816 stack.pc = stack.byte_string_start + op;
36f7ba0a 817 }
63639d44
JB
818 else DISCARD (1);
819 break;
820
821 case BRgoto:
14726871 822 MAYBE_GC ();
e12ea64e 823 BYTE_CODE_QUIT;
7ca1e8b7 824 stack.pc += (int) *stack.pc - 127;
63639d44
JB
825 break;
826
827 case BRgotoifnil:
21ed6de3
KR
828 {
829 Lisp_Object v1;
830 MAYBE_GC ();
831 v1 = POP;
832 if (NILP (v1))
833 {
834 BYTE_CODE_QUIT;
835 stack.pc += (int) *stack.pc - 128;
836 }
837 stack.pc++;
838 break;
839 }
63639d44
JB
840
841 case BRgotoifnonnil:
21ed6de3
KR
842 {
843 Lisp_Object v1;
844 MAYBE_GC ();
845 v1 = POP;
846 if (!NILP (v1))
847 {
848 BYTE_CODE_QUIT;
849 stack.pc += (int) *stack.pc - 128;
850 }
851 stack.pc++;
852 break;
853 }
63639d44
JB
854
855 case BRgotoifnilelsepop:
14726871 856 MAYBE_GC ();
7ca1e8b7 857 op = *stack.pc++;
63639d44
JB
858 if (NILP (TOP))
859 {
e12ea64e 860 BYTE_CODE_QUIT;
7ca1e8b7 861 stack.pc += op - 128;
63639d44
JB
862 }
863 else DISCARD (1);
864 break;
865
866 case BRgotoifnonnilelsepop:
14726871 867 MAYBE_GC ();
7ca1e8b7 868 op = *stack.pc++;
63639d44
JB
869 if (!NILP (TOP))
870 {
e12ea64e 871 BYTE_CODE_QUIT;
7ca1e8b7 872 stack.pc += op - 128;
63639d44
JB
873 }
874 else DISCARD (1);
98bf0c8d
JB
875 break;
876
36f7ba0a 877 case Breturn:
4015b3c0 878 result = POP;
36f7ba0a
JB
879 goto exit;
880
881 case Bdiscard:
63639d44 882 DISCARD (1);
36f7ba0a
JB
883 break;
884
36f7ba0a
JB
885 case Bconstant2:
886 PUSH (vectorp[FETCH2]);
887 break;
888
889 case Bsave_excursion:
fa9aabf6
GM
890 record_unwind_protect (save_excursion_restore,
891 save_excursion_save ());
36f7ba0a
JB
892 break;
893
3b841abc 894 case Bsave_current_buffer:
80402f25 895 case Bsave_current_buffer_1:
de404585 896 record_unwind_protect (set_buffer_if_live, Fcurrent_buffer ());
3b841abc
RS
897 break;
898
36f7ba0a 899 case Bsave_window_excursion:
4015b3c0 900 BEFORE_POTENTIAL_GC ();
defb1411 901 TOP = Fsave_window_excursion (TOP); /* FIXME: lexbind */
4015b3c0 902 AFTER_POTENTIAL_GC ();
36f7ba0a
JB
903 break;
904
905 case Bsave_restriction:
fa9aabf6
GM
906 record_unwind_protect (save_restriction_restore,
907 save_restriction_save ());
36f7ba0a
JB
908 break;
909
910 case Bcatch:
4015b3c0
GM
911 {
912 Lisp_Object v1;
4015b3c0 913 BEFORE_POTENTIAL_GC ();
bf1de43e 914 v1 = POP;
a0ee6f27 915 TOP = internal_catch (TOP, eval_sub, v1); /* FIXME: lexbind */
4015b3c0
GM
916 AFTER_POTENTIAL_GC ();
917 break;
918 }
36f7ba0a
JB
919
920 case Bunwind_protect:
defb1411 921 record_unwind_protect (Fprogn, POP); /* FIXME: lexbind */
36f7ba0a
JB
922 break;
923
924 case Bcondition_case:
4015b3c0 925 {
5c125a13
RS
926 Lisp_Object handlers, body;
927 handlers = POP;
928 body = POP;
4015b3c0 929 BEFORE_POTENTIAL_GC ();
defb1411 930 TOP = internal_lisp_condition_case (TOP, body, handlers); /* FIXME: lexbind */
4015b3c0
GM
931 AFTER_POTENTIAL_GC ();
932 break;
933 }
36f7ba0a
JB
934
935 case Btemp_output_buffer_setup:
4015b3c0 936 BEFORE_POTENTIAL_GC ();
b7826503 937 CHECK_STRING (TOP);
42a5b22f 938 temp_output_buffer_setup (SSDATA (TOP));
4015b3c0 939 AFTER_POTENTIAL_GC ();
36f7ba0a
JB
940 TOP = Vstandard_output;
941 break;
942
943 case Btemp_output_buffer_show:
4015b3c0
GM
944 {
945 Lisp_Object v1;
4015b3c0 946 BEFORE_POTENTIAL_GC ();
bf1de43e 947 v1 = POP;
4015b3c0
GM
948 temp_output_buffer_show (TOP);
949 TOP = v1;
950 /* pop binding of standard-output */
aed13378 951 unbind_to (SPECPDL_INDEX () - 1, Qnil);
4015b3c0
GM
952 AFTER_POTENTIAL_GC ();
953 break;
954 }
36f7ba0a
JB
955
956 case Bnth:
4015b3c0
GM
957 {
958 Lisp_Object v1, v2;
bf1de43e 959 BEFORE_POTENTIAL_GC ();
4015b3c0
GM
960 v1 = POP;
961 v2 = TOP;
b7826503 962 CHECK_NUMBER (v2);
f5941bf8 963 AFTER_POTENTIAL_GC ();
4015b3c0
GM
964 op = XINT (v2);
965 immediate_quit = 1;
14c5155a
KS
966 while (--op >= 0 && CONSP (v1))
967 v1 = XCDR (v1);
4015b3c0 968 immediate_quit = 0;
14c5155a 969 TOP = CAR (v1);
4015b3c0
GM
970 break;
971 }
36f7ba0a
JB
972
973 case Bsymbolp:
617bd3f6 974 TOP = SYMBOLP (TOP) ? Qt : Qnil;
36f7ba0a
JB
975 break;
976
977 case Bconsp:
978 TOP = CONSP (TOP) ? Qt : Qnil;
979 break;
980
981 case Bstringp:
617bd3f6 982 TOP = STRINGP (TOP) ? Qt : Qnil;
36f7ba0a
JB
983 break;
984
985 case Blistp:
921a8935 986 TOP = CONSP (TOP) || NILP (TOP) ? Qt : Qnil;
36f7ba0a
JB
987 break;
988
36f7ba0a 989 case Bnot:
921a8935 990 TOP = NILP (TOP) ? Qt : Qnil;
36f7ba0a
JB
991 break;
992
36f7ba0a 993 case Bcons:
4015b3c0
GM
994 {
995 Lisp_Object v1;
996 v1 = POP;
997 TOP = Fcons (TOP, v1);
998 break;
999 }
36f7ba0a
JB
1000
1001 case Blist1:
1002 TOP = Fcons (TOP, Qnil);
1003 break;
1004
1005 case Blist2:
4015b3c0
GM
1006 {
1007 Lisp_Object v1;
1008 v1 = POP;
1009 TOP = Fcons (TOP, Fcons (v1, Qnil));
1010 break;
1011 }
36f7ba0a
JB
1012
1013 case Blist3:
63639d44 1014 DISCARD (2);
36f7ba0a
JB
1015 TOP = Flist (3, &TOP);
1016 break;
1017
1018 case Blist4:
63639d44 1019 DISCARD (3);
36f7ba0a
JB
1020 TOP = Flist (4, &TOP);
1021 break;
1022
63639d44
JB
1023 case BlistN:
1024 op = FETCH;
1025 DISCARD (op - 1);
1026 TOP = Flist (op, &TOP);
1027 break;
1028
36f7ba0a 1029 case Blength:
bf1de43e 1030 BEFORE_POTENTIAL_GC ();
36f7ba0a 1031 TOP = Flength (TOP);
bf1de43e 1032 AFTER_POTENTIAL_GC ();
36f7ba0a
JB
1033 break;
1034
1035 case Baref:
4015b3c0
GM
1036 {
1037 Lisp_Object v1;
bf1de43e 1038 BEFORE_POTENTIAL_GC ();
4015b3c0
GM
1039 v1 = POP;
1040 TOP = Faref (TOP, v1);
bf1de43e 1041 AFTER_POTENTIAL_GC ();
4015b3c0
GM
1042 break;
1043 }
36f7ba0a
JB
1044
1045 case Baset:
4015b3c0
GM
1046 {
1047 Lisp_Object v1, v2;
bf1de43e 1048 BEFORE_POTENTIAL_GC ();
4015b3c0
GM
1049 v2 = POP; v1 = POP;
1050 TOP = Faset (TOP, v1, v2);
bf1de43e 1051 AFTER_POTENTIAL_GC ();
4015b3c0
GM
1052 break;
1053 }
36f7ba0a
JB
1054
1055 case Bsymbol_value:
bf1de43e 1056 BEFORE_POTENTIAL_GC ();
36f7ba0a 1057 TOP = Fsymbol_value (TOP);
bf1de43e 1058 AFTER_POTENTIAL_GC ();
36f7ba0a
JB
1059 break;
1060
1061 case Bsymbol_function:
bf1de43e 1062 BEFORE_POTENTIAL_GC ();
36f7ba0a 1063 TOP = Fsymbol_function (TOP);
bf1de43e 1064 AFTER_POTENTIAL_GC ();
36f7ba0a
JB
1065 break;
1066
1067 case Bset:
4015b3c0
GM
1068 {
1069 Lisp_Object v1;
bf1de43e 1070 BEFORE_POTENTIAL_GC ();
4015b3c0
GM
1071 v1 = POP;
1072 TOP = Fset (TOP, v1);
bf1de43e 1073 AFTER_POTENTIAL_GC ();
4015b3c0
GM
1074 break;
1075 }
36f7ba0a
JB
1076
1077 case Bfset:
4015b3c0
GM
1078 {
1079 Lisp_Object v1;
bf1de43e 1080 BEFORE_POTENTIAL_GC ();
4015b3c0
GM
1081 v1 = POP;
1082 TOP = Ffset (TOP, v1);
bf1de43e 1083 AFTER_POTENTIAL_GC ();
4015b3c0
GM
1084 break;
1085 }
36f7ba0a
JB
1086
1087 case Bget:
4015b3c0
GM
1088 {
1089 Lisp_Object v1;
bf1de43e 1090 BEFORE_POTENTIAL_GC ();
4015b3c0
GM
1091 v1 = POP;
1092 TOP = Fget (TOP, v1);
bf1de43e 1093 AFTER_POTENTIAL_GC ();
4015b3c0
GM
1094 break;
1095 }
36f7ba0a
JB
1096
1097 case Bsubstring:
4015b3c0
GM
1098 {
1099 Lisp_Object v1, v2;
fa9aabf6 1100 BEFORE_POTENTIAL_GC ();
bf1de43e 1101 v2 = POP; v1 = POP;
4015b3c0 1102 TOP = Fsubstring (TOP, v1, v2);
fa9aabf6 1103 AFTER_POTENTIAL_GC ();
4015b3c0
GM
1104 break;
1105 }
36f7ba0a
JB
1106
1107 case Bconcat2:
bf1de43e 1108 BEFORE_POTENTIAL_GC ();
63639d44 1109 DISCARD (1);
36f7ba0a 1110 TOP = Fconcat (2, &TOP);
bf1de43e 1111 AFTER_POTENTIAL_GC ();
36f7ba0a
JB
1112 break;
1113
1114 case Bconcat3:
bf1de43e 1115 BEFORE_POTENTIAL_GC ();
63639d44 1116 DISCARD (2);
36f7ba0a 1117 TOP = Fconcat (3, &TOP);
bf1de43e 1118 AFTER_POTENTIAL_GC ();
36f7ba0a
JB
1119 break;
1120
1121 case Bconcat4:
bf1de43e 1122 BEFORE_POTENTIAL_GC ();
63639d44 1123 DISCARD (3);
36f7ba0a 1124 TOP = Fconcat (4, &TOP);
bf1de43e 1125 AFTER_POTENTIAL_GC ();
36f7ba0a
JB
1126 break;
1127
63639d44
JB
1128 case BconcatN:
1129 op = FETCH;
bf1de43e 1130 BEFORE_POTENTIAL_GC ();
63639d44
JB
1131 DISCARD (op - 1);
1132 TOP = Fconcat (op, &TOP);
bf1de43e 1133 AFTER_POTENTIAL_GC ();
63639d44
JB
1134 break;
1135
36f7ba0a 1136 case Bsub1:
4015b3c0
GM
1137 {
1138 Lisp_Object v1;
1139 v1 = TOP;
1140 if (INTEGERP (v1))
1141 {
1142 XSETINT (v1, XINT (v1) - 1);
1143 TOP = v1;
1144 }
1145 else
e494eee5
MB
1146 {
1147 BEFORE_POTENTIAL_GC ();
1148 TOP = Fsub1 (v1);
1149 AFTER_POTENTIAL_GC ();
1150 }
4015b3c0
GM
1151 break;
1152 }
36f7ba0a
JB
1153
1154 case Badd1:
4015b3c0
GM
1155 {
1156 Lisp_Object v1;
1157 v1 = TOP;
1158 if (INTEGERP (v1))
1159 {
1160 XSETINT (v1, XINT (v1) + 1);
1161 TOP = v1;
1162 }
1163 else
bf1de43e
GM
1164 {
1165 BEFORE_POTENTIAL_GC ();
1166 TOP = Fadd1 (v1);
1167 AFTER_POTENTIAL_GC ();
1168 }
4015b3c0
GM
1169 break;
1170 }
36f7ba0a
JB
1171
1172 case Beqlsign:
4015b3c0
GM
1173 {
1174 Lisp_Object v1, v2;
f5941bf8 1175 BEFORE_POTENTIAL_GC ();
bf1de43e 1176 v2 = POP; v1 = TOP;
b7826503
PJ
1177 CHECK_NUMBER_OR_FLOAT_COERCE_MARKER (v1);
1178 CHECK_NUMBER_OR_FLOAT_COERCE_MARKER (v2);
f5941bf8 1179 AFTER_POTENTIAL_GC ();
4015b3c0
GM
1180 if (FLOATP (v1) || FLOATP (v2))
1181 {
1182 double f1, f2;
1183
1184 f1 = (FLOATP (v1) ? XFLOAT_DATA (v1) : XINT (v1));
1185 f2 = (FLOATP (v2) ? XFLOAT_DATA (v2) : XINT (v2));
1186 TOP = (f1 == f2 ? Qt : Qnil);
1187 }
1188 else
4015b3c0
GM
1189 TOP = (XINT (v1) == XINT (v2) ? Qt : Qnil);
1190 break;
1191 }
36f7ba0a
JB
1192
1193 case Bgtr:
4015b3c0
GM
1194 {
1195 Lisp_Object v1;
bf1de43e 1196 BEFORE_POTENTIAL_GC ();
4015b3c0
GM
1197 v1 = POP;
1198 TOP = Fgtr (TOP, v1);
bf1de43e 1199 AFTER_POTENTIAL_GC ();
4015b3c0
GM
1200 break;
1201 }
36f7ba0a
JB
1202
1203 case Blss:
4015b3c0
GM
1204 {
1205 Lisp_Object v1;
bf1de43e 1206 BEFORE_POTENTIAL_GC ();
4015b3c0
GM
1207 v1 = POP;
1208 TOP = Flss (TOP, v1);
bf1de43e 1209 AFTER_POTENTIAL_GC ();
4015b3c0
GM
1210 break;
1211 }
36f7ba0a
JB
1212
1213 case Bleq:
4015b3c0
GM
1214 {
1215 Lisp_Object v1;
bf1de43e 1216 BEFORE_POTENTIAL_GC ();
4015b3c0
GM
1217 v1 = POP;
1218 TOP = Fleq (TOP, v1);
bf1de43e 1219 AFTER_POTENTIAL_GC ();
4015b3c0
GM
1220 break;
1221 }
36f7ba0a
JB
1222
1223 case Bgeq:
4015b3c0
GM
1224 {
1225 Lisp_Object v1;
d9c1f6f9 1226 BEFORE_POTENTIAL_GC ();
4015b3c0
GM
1227 v1 = POP;
1228 TOP = Fgeq (TOP, v1);
d9c1f6f9 1229 AFTER_POTENTIAL_GC ();
4015b3c0
GM
1230 break;
1231 }
36f7ba0a
JB
1232
1233 case Bdiff:
bf1de43e 1234 BEFORE_POTENTIAL_GC ();
63639d44 1235 DISCARD (1);
36f7ba0a 1236 TOP = Fminus (2, &TOP);
bf1de43e 1237 AFTER_POTENTIAL_GC ();
36f7ba0a
JB
1238 break;
1239
1240 case Bnegate:
4015b3c0
GM
1241 {
1242 Lisp_Object v1;
1243 v1 = TOP;
1244 if (INTEGERP (v1))
1245 {
1246 XSETINT (v1, - XINT (v1));
1247 TOP = v1;
1248 }
1249 else
bf1de43e
GM
1250 {
1251 BEFORE_POTENTIAL_GC ();
1252 TOP = Fminus (1, &TOP);
1253 AFTER_POTENTIAL_GC ();
1254 }
4015b3c0
GM
1255 break;
1256 }
36f7ba0a
JB
1257
1258 case Bplus:
bf1de43e 1259 BEFORE_POTENTIAL_GC ();
63639d44 1260 DISCARD (1);
36f7ba0a 1261 TOP = Fplus (2, &TOP);
bf1de43e 1262 AFTER_POTENTIAL_GC ();
36f7ba0a
JB
1263 break;
1264
1265 case Bmax:
bf1de43e 1266 BEFORE_POTENTIAL_GC ();
63639d44 1267 DISCARD (1);
36f7ba0a 1268 TOP = Fmax (2, &TOP);
bf1de43e 1269 AFTER_POTENTIAL_GC ();
36f7ba0a
JB
1270 break;
1271
1272 case Bmin:
bf1de43e 1273 BEFORE_POTENTIAL_GC ();
63639d44 1274 DISCARD (1);
36f7ba0a 1275 TOP = Fmin (2, &TOP);
bf1de43e 1276 AFTER_POTENTIAL_GC ();
36f7ba0a
JB
1277 break;
1278
1279 case Bmult:
bf1de43e 1280 BEFORE_POTENTIAL_GC ();
63639d44 1281 DISCARD (1);
36f7ba0a 1282 TOP = Ftimes (2, &TOP);
bf1de43e 1283 AFTER_POTENTIAL_GC ();
36f7ba0a
JB
1284 break;
1285
1286 case Bquo:
bf1de43e 1287 BEFORE_POTENTIAL_GC ();
63639d44 1288 DISCARD (1);
36f7ba0a 1289 TOP = Fquo (2, &TOP);
bf1de43e 1290 AFTER_POTENTIAL_GC ();
36f7ba0a
JB
1291 break;
1292
1293 case Brem:
4015b3c0
GM
1294 {
1295 Lisp_Object v1;
bf1de43e 1296 BEFORE_POTENTIAL_GC ();
4015b3c0
GM
1297 v1 = POP;
1298 TOP = Frem (TOP, v1);
bf1de43e 1299 AFTER_POTENTIAL_GC ();
4015b3c0
GM
1300 break;
1301 }
36f7ba0a
JB
1302
1303 case Bpoint:
4015b3c0
GM
1304 {
1305 Lisp_Object v1;
1306 XSETFASTINT (v1, PT);
1307 PUSH (v1);
1308 break;
1309 }
36f7ba0a
JB
1310
1311 case Bgoto_char:
4015b3c0 1312 BEFORE_POTENTIAL_GC ();
36f7ba0a 1313 TOP = Fgoto_char (TOP);
4015b3c0 1314 AFTER_POTENTIAL_GC ();
36f7ba0a
JB
1315 break;
1316
1317 case Binsert:
4015b3c0 1318 BEFORE_POTENTIAL_GC ();
36f7ba0a 1319 TOP = Finsert (1, &TOP);
4015b3c0 1320 AFTER_POTENTIAL_GC ();
36f7ba0a
JB
1321 break;
1322
63639d44
JB
1323 case BinsertN:
1324 op = FETCH;
4015b3c0 1325 BEFORE_POTENTIAL_GC ();
fa9aabf6 1326 DISCARD (op - 1);
63639d44 1327 TOP = Finsert (op, &TOP);
4015b3c0 1328 AFTER_POTENTIAL_GC ();
63639d44
JB
1329 break;
1330
36f7ba0a 1331 case Bpoint_max:
4015b3c0
GM
1332 {
1333 Lisp_Object v1;
1334 XSETFASTINT (v1, ZV);
1335 PUSH (v1);
1336 break;
1337 }
36f7ba0a
JB
1338
1339 case Bpoint_min:
4015b3c0
GM
1340 {
1341 Lisp_Object v1;
1342 XSETFASTINT (v1, BEGV);
1343 PUSH (v1);
1344 break;
1345 }
36f7ba0a
JB
1346
1347 case Bchar_after:
bf1de43e 1348 BEFORE_POTENTIAL_GC ();
36f7ba0a 1349 TOP = Fchar_after (TOP);
bf1de43e 1350 AFTER_POTENTIAL_GC ();
36f7ba0a
JB
1351 break;
1352
1353 case Bfollowing_char:
4015b3c0
GM
1354 {
1355 Lisp_Object v1;
bf1de43e 1356 BEFORE_POTENTIAL_GC ();
4015b3c0 1357 v1 = Ffollowing_char ();
bf1de43e 1358 AFTER_POTENTIAL_GC ();
4015b3c0
GM
1359 PUSH (v1);
1360 break;
1361 }
36f7ba0a
JB
1362
1363 case Bpreceding_char:
4015b3c0
GM
1364 {
1365 Lisp_Object v1;
bf1de43e 1366 BEFORE_POTENTIAL_GC ();
4015b3c0 1367 v1 = Fprevious_char ();
bf1de43e 1368 AFTER_POTENTIAL_GC ();
4015b3c0
GM
1369 PUSH (v1);
1370 break;
1371 }
36f7ba0a
JB
1372
1373 case Bcurrent_column:
4015b3c0
GM
1374 {
1375 Lisp_Object v1;
96111f48 1376 BEFORE_POTENTIAL_GC ();
8e11578b 1377 XSETFASTINT (v1, (int) current_column ()); /* iftc */
96111f48 1378 AFTER_POTENTIAL_GC ();
4015b3c0
GM
1379 PUSH (v1);
1380 break;
1381 }
36f7ba0a
JB
1382
1383 case Bindent_to:
4015b3c0 1384 BEFORE_POTENTIAL_GC ();
36f7ba0a 1385 TOP = Findent_to (TOP, Qnil);
4015b3c0 1386 AFTER_POTENTIAL_GC ();
36f7ba0a
JB
1387 break;
1388
1389 case Beolp:
1390 PUSH (Feolp ());
1391 break;
1392
1393 case Beobp:
1394 PUSH (Feobp ());
1395 break;
1396
1397 case Bbolp:
1398 PUSH (Fbolp ());
1399 break;
1400
1401 case Bbobp:
1402 PUSH (Fbobp ());
1403 break;
1404
1405 case Bcurrent_buffer:
1406 PUSH (Fcurrent_buffer ());
1407 break;
1408
1409 case Bset_buffer:
4015b3c0 1410 BEFORE_POTENTIAL_GC ();
36f7ba0a 1411 TOP = Fset_buffer (TOP);
4015b3c0 1412 AFTER_POTENTIAL_GC ();
36f7ba0a
JB
1413 break;
1414
36f7ba0a
JB
1415 case Binteractive_p:
1416 PUSH (Finteractive_p ());
1417 break;
1418
1419 case Bforward_char:
4015b3c0 1420 BEFORE_POTENTIAL_GC ();
36f7ba0a 1421 TOP = Fforward_char (TOP);
4015b3c0 1422 AFTER_POTENTIAL_GC ();
36f7ba0a
JB
1423 break;
1424
1425 case Bforward_word:
4015b3c0 1426 BEFORE_POTENTIAL_GC ();
36f7ba0a 1427 TOP = Fforward_word (TOP);
4015b3c0 1428 AFTER_POTENTIAL_GC ();
36f7ba0a
JB
1429 break;
1430
1431 case Bskip_chars_forward:
4015b3c0
GM
1432 {
1433 Lisp_Object v1;
4015b3c0 1434 BEFORE_POTENTIAL_GC ();
bf1de43e 1435 v1 = POP;
4015b3c0
GM
1436 TOP = Fskip_chars_forward (TOP, v1);
1437 AFTER_POTENTIAL_GC ();
1438 break;
1439 }
36f7ba0a
JB
1440
1441 case Bskip_chars_backward:
4015b3c0
GM
1442 {
1443 Lisp_Object v1;
4015b3c0 1444 BEFORE_POTENTIAL_GC ();
bf1de43e 1445 v1 = POP;
4015b3c0
GM
1446 TOP = Fskip_chars_backward (TOP, v1);
1447 AFTER_POTENTIAL_GC ();
1448 break;
1449 }
36f7ba0a
JB
1450
1451 case Bforward_line:
4015b3c0 1452 BEFORE_POTENTIAL_GC ();
36f7ba0a 1453 TOP = Fforward_line (TOP);
4015b3c0 1454 AFTER_POTENTIAL_GC ();
36f7ba0a
JB
1455 break;
1456
1457 case Bchar_syntax:
9281d077
KH
1458 {
1459 int c;
1460
1461 BEFORE_POTENTIAL_GC ();
1462 CHECK_CHARACTER (TOP);
1463 AFTER_POTENTIAL_GC ();
1464 c = XFASTINT (TOP);
1465 if (NILP (current_buffer->enable_multibyte_characters))
1466 MAKE_CHAR_MULTIBYTE (c);
1467 XSETFASTINT (TOP, syntax_code_spec[(int) SYNTAX (c)]);
8f924df7 1468 }
36f7ba0a
JB
1469 break;
1470
1471 case Bbuffer_substring:
4015b3c0
GM
1472 {
1473 Lisp_Object v1;
4015b3c0 1474 BEFORE_POTENTIAL_GC ();
bf1de43e 1475 v1 = POP;
4015b3c0
GM
1476 TOP = Fbuffer_substring (TOP, v1);
1477 AFTER_POTENTIAL_GC ();
1478 break;
1479 }
36f7ba0a
JB
1480
1481 case Bdelete_region:
4015b3c0
GM
1482 {
1483 Lisp_Object v1;
4015b3c0 1484 BEFORE_POTENTIAL_GC ();
bf1de43e 1485 v1 = POP;
4015b3c0
GM
1486 TOP = Fdelete_region (TOP, v1);
1487 AFTER_POTENTIAL_GC ();
1488 break;
1489 }
36f7ba0a
JB
1490
1491 case Bnarrow_to_region:
4015b3c0
GM
1492 {
1493 Lisp_Object v1;
4015b3c0 1494 BEFORE_POTENTIAL_GC ();
bf1de43e 1495 v1 = POP;
4015b3c0
GM
1496 TOP = Fnarrow_to_region (TOP, v1);
1497 AFTER_POTENTIAL_GC ();
1498 break;
1499 }
36f7ba0a
JB
1500
1501 case Bwiden:
4015b3c0 1502 BEFORE_POTENTIAL_GC ();
36f7ba0a 1503 PUSH (Fwiden ());
4015b3c0 1504 AFTER_POTENTIAL_GC ();
36f7ba0a
JB
1505 break;
1506
63639d44 1507 case Bend_of_line:
4015b3c0 1508 BEFORE_POTENTIAL_GC ();
63639d44 1509 TOP = Fend_of_line (TOP);
4015b3c0 1510 AFTER_POTENTIAL_GC ();
63639d44
JB
1511 break;
1512
1513 case Bset_marker:
4015b3c0
GM
1514 {
1515 Lisp_Object v1, v2;
bf1de43e 1516 BEFORE_POTENTIAL_GC ();
4015b3c0
GM
1517 v1 = POP;
1518 v2 = POP;
1519 TOP = Fset_marker (TOP, v2, v1);
bf1de43e 1520 AFTER_POTENTIAL_GC ();
4015b3c0
GM
1521 break;
1522 }
63639d44
JB
1523
1524 case Bmatch_beginning:
bf1de43e 1525 BEFORE_POTENTIAL_GC ();
63639d44 1526 TOP = Fmatch_beginning (TOP);
bf1de43e 1527 AFTER_POTENTIAL_GC ();
63639d44
JB
1528 break;
1529
1530 case Bmatch_end:
bf1de43e 1531 BEFORE_POTENTIAL_GC ();
63639d44 1532 TOP = Fmatch_end (TOP);
bf1de43e 1533 AFTER_POTENTIAL_GC ();
63639d44
JB
1534 break;
1535
1536 case Bupcase:
bf1de43e 1537 BEFORE_POTENTIAL_GC ();
63639d44 1538 TOP = Fupcase (TOP);
bf1de43e 1539 AFTER_POTENTIAL_GC ();
63639d44
JB
1540 break;
1541
1542 case Bdowncase:
bf1de43e 1543 BEFORE_POTENTIAL_GC ();
63639d44 1544 TOP = Fdowncase (TOP);
bf1de43e 1545 AFTER_POTENTIAL_GC ();
63639d44
JB
1546 break;
1547
36f7ba0a 1548 case Bstringeqlsign:
4015b3c0
GM
1549 {
1550 Lisp_Object v1;
bf1de43e 1551 BEFORE_POTENTIAL_GC ();
4015b3c0
GM
1552 v1 = POP;
1553 TOP = Fstring_equal (TOP, v1);
bf1de43e 1554 AFTER_POTENTIAL_GC ();
4015b3c0
GM
1555 break;
1556 }
36f7ba0a
JB
1557
1558 case Bstringlss:
4015b3c0
GM
1559 {
1560 Lisp_Object v1;
bf1de43e 1561 BEFORE_POTENTIAL_GC ();
4015b3c0
GM
1562 v1 = POP;
1563 TOP = Fstring_lessp (TOP, v1);
bf1de43e 1564 AFTER_POTENTIAL_GC ();
4015b3c0
GM
1565 break;
1566 }
36f7ba0a
JB
1567
1568 case Bequal:
4015b3c0
GM
1569 {
1570 Lisp_Object v1;
1571 v1 = POP;
1572 TOP = Fequal (TOP, v1);
1573 break;
1574 }
36f7ba0a
JB
1575
1576 case Bnthcdr:
4015b3c0
GM
1577 {
1578 Lisp_Object v1;
bf1de43e 1579 BEFORE_POTENTIAL_GC ();
4015b3c0
GM
1580 v1 = POP;
1581 TOP = Fnthcdr (TOP, v1);
bf1de43e 1582 AFTER_POTENTIAL_GC ();
4015b3c0
GM
1583 break;
1584 }
36f7ba0a
JB
1585
1586 case Belt:
4015b3c0
GM
1587 {
1588 Lisp_Object v1, v2;
1589 if (CONSP (TOP))
1590 {
1591 /* Exchange args and then do nth. */
bf1de43e 1592 BEFORE_POTENTIAL_GC ();
4015b3c0
GM
1593 v2 = POP;
1594 v1 = TOP;
b7826503 1595 CHECK_NUMBER (v2);
f5941bf8 1596 AFTER_POTENTIAL_GC ();
4015b3c0
GM
1597 op = XINT (v2);
1598 immediate_quit = 1;
14c5155a
KS
1599 while (--op >= 0 && CONSP (v1))
1600 v1 = XCDR (v1);
4015b3c0 1601 immediate_quit = 0;
14c5155a 1602 TOP = CAR (v1);
4015b3c0
GM
1603 }
1604 else
1605 {
bf1de43e 1606 BEFORE_POTENTIAL_GC ();
4015b3c0
GM
1607 v1 = POP;
1608 TOP = Felt (TOP, v1);
bf1de43e 1609 AFTER_POTENTIAL_GC ();
4015b3c0
GM
1610 }
1611 break;
1612 }
36f7ba0a
JB
1613
1614 case Bmember:
4015b3c0
GM
1615 {
1616 Lisp_Object v1;
bf1de43e 1617 BEFORE_POTENTIAL_GC ();
4015b3c0
GM
1618 v1 = POP;
1619 TOP = Fmember (TOP, v1);
bf1de43e 1620 AFTER_POTENTIAL_GC ();
4015b3c0
GM
1621 break;
1622 }
36f7ba0a
JB
1623
1624 case Bassq:
4015b3c0
GM
1625 {
1626 Lisp_Object v1;
bf1de43e 1627 BEFORE_POTENTIAL_GC ();
4015b3c0
GM
1628 v1 = POP;
1629 TOP = Fassq (TOP, v1);
bf1de43e 1630 AFTER_POTENTIAL_GC ();
4015b3c0
GM
1631 break;
1632 }
36f7ba0a
JB
1633
1634 case Bnreverse:
bf1de43e 1635 BEFORE_POTENTIAL_GC ();
36f7ba0a 1636 TOP = Fnreverse (TOP);
bf1de43e 1637 AFTER_POTENTIAL_GC ();
36f7ba0a
JB
1638 break;
1639
1640 case Bsetcar:
4015b3c0
GM
1641 {
1642 Lisp_Object v1;
bf1de43e 1643 BEFORE_POTENTIAL_GC ();
4015b3c0
GM
1644 v1 = POP;
1645 TOP = Fsetcar (TOP, v1);
bf1de43e 1646 AFTER_POTENTIAL_GC ();
4015b3c0
GM
1647 break;
1648 }
36f7ba0a
JB
1649
1650 case Bsetcdr:
4015b3c0
GM
1651 {
1652 Lisp_Object v1;
bf1de43e 1653 BEFORE_POTENTIAL_GC ();
4015b3c0
GM
1654 v1 = POP;
1655 TOP = Fsetcdr (TOP, v1);
bf1de43e 1656 AFTER_POTENTIAL_GC ();
4015b3c0
GM
1657 break;
1658 }
36f7ba0a
JB
1659
1660 case Bcar_safe:
4015b3c0
GM
1661 {
1662 Lisp_Object v1;
1663 v1 = TOP;
14c5155a 1664 TOP = CAR_SAFE (v1);
4015b3c0
GM
1665 break;
1666 }
36f7ba0a
JB
1667
1668 case Bcdr_safe:
4015b3c0
GM
1669 {
1670 Lisp_Object v1;
1671 v1 = TOP;
14c5155a 1672 TOP = CDR_SAFE (v1);
4015b3c0
GM
1673 break;
1674 }
36f7ba0a
JB
1675
1676 case Bnconc:
bf1de43e 1677 BEFORE_POTENTIAL_GC ();
63639d44 1678 DISCARD (1);
36f7ba0a 1679 TOP = Fnconc (2, &TOP);
bf1de43e 1680 AFTER_POTENTIAL_GC ();
36f7ba0a
JB
1681 break;
1682
1683 case Bnumberp:
63639d44 1684 TOP = (NUMBERP (TOP) ? Qt : Qnil);
36f7ba0a
JB
1685 break;
1686
1687 case Bintegerp:
617bd3f6 1688 TOP = INTEGERP (TOP) ? Qt : Qnil;
36f7ba0a
JB
1689 break;
1690
1691#ifdef BYTE_CODE_SAFE
1692 case Bset_mark:
f5941bf8 1693 BEFORE_POTENTIAL_GC ();
36f7ba0a 1694 error ("set-mark is an obsolete bytecode");
f5941bf8 1695 AFTER_POTENTIAL_GC ();
36f7ba0a
JB
1696 break;
1697 case Bscan_buffer:
f5941bf8 1698 BEFORE_POTENTIAL_GC ();
36f7ba0a 1699 error ("scan-buffer is an obsolete bytecode");
f5941bf8 1700 AFTER_POTENTIAL_GC ();
36f7ba0a 1701 break;
36f7ba0a
JB
1702#endif
1703
b9598260
SM
1704 /* Handy byte-codes for lexical binding. */
1705 case Bstack_ref:
1706 case Bstack_ref+1:
1707 case Bstack_ref+2:
1708 case Bstack_ref+3:
1709 case Bstack_ref+4:
1710 case Bstack_ref+5:
1711 PUSH (stack.bottom[op - Bstack_ref]);
1712 break;
1713 case Bstack_ref+6:
1714 PUSH (stack.bottom[FETCH]);
1715 break;
1716 case Bstack_ref+7:
1717 PUSH (stack.bottom[FETCH2]);
1718 break;
1719 case Bstack_set:
1720 stack.bottom[FETCH] = POP;
1721 break;
1722 case Bstack_set2:
1723 stack.bottom[FETCH2] = POP;
1724 break;
1725 case Bvec_ref:
1726 case Bvec_set:
1727 /* These byte-codes used mostly for variable references to
1728 lexically bound variables that are in an environment vector
1729 instead of on the byte-interpreter stack (generally those
1730 variables which might be shared with a closure). */
1731 {
1732 int index = FETCH;
1733 Lisp_Object vec = POP;
1734
1735 if (! VECTORP (vec))
1736 wrong_type_argument (Qvectorp, vec);
1737 else if (index < 0 || index >= XVECTOR (vec)->size)
3c3ddb98 1738 args_out_of_range (vec, make_number (index));
b9598260
SM
1739
1740 if (op == Bvec_ref)
1741 PUSH (XVECTOR (vec)->contents[index]);
1742 else
1743 XVECTOR (vec)->contents[index] = POP;
1744 }
1745 break;
1746 case BdiscardN:
1747 op = FETCH;
1748 if (op & 0x80)
1749 {
1750 op &= 0x7F;
1751 top[-op] = TOP;
1752 }
1753 DISCARD (op);
1754 break;
c96d71f7
RS
1755
1756 case 255:
36f7ba0a
JB
1757 default:
1758#ifdef BYTE_CODE_SAFE
1759 if (op < Bconstant)
f5941bf8 1760 {
cc94f3b2 1761 abort ();
f5941bf8 1762 }
36f7ba0a 1763 if ((op -= Bconstant) >= const_length)
f5941bf8 1764 {
cc94f3b2 1765 abort ();
f5941bf8 1766 }
36f7ba0a
JB
1767 PUSH (vectorp[op]);
1768#else
1769 PUSH (vectorp[op - Bconstant]);
1770#endif
1771 }
1772 }
1773
1774 exit:
7ca1e8b7
GM
1775
1776 byte_stack_list = byte_stack_list->next;
1777
36f7ba0a 1778 /* Binds and unbinds are supposed to be compiled balanced. */
aed13378 1779 if (SPECPDL_INDEX () != count)
36f7ba0a
JB
1780#ifdef BYTE_CODE_SAFE
1781 error ("binding stack not balanced (serious byte compiler bug)");
1782#else
1783 abort ();
1784#endif
8e11578b 1785
4015b3c0 1786 return result;
36f7ba0a
JB
1787}
1788
dfcf069d 1789void
971de7fb 1790syms_of_bytecode (void)
36f7ba0a 1791{
d67b4f80 1792 Qbytecode = intern_c_string ("byte-code");
36f7ba0a
JB
1793 staticpro (&Qbytecode);
1794
1795 defsubr (&Sbyte_code);
1796
1797#ifdef BYTE_CODE_METER
1798
29208e82 1799 DEFVAR_LISP ("byte-code-meter", Vbyte_code_meter,
39f624fa
PJ
1800 doc: /* A vector of vectors which holds a histogram of byte-code usage.
1801\(aref (aref byte-code-meter 0) CODE) indicates how many times the byte
1802opcode CODE has been executed.
1803\(aref (aref byte-code-meter CODE1) CODE2), where CODE1 is not 0,
1804indicates how many times the byte opcodes CODE1 and CODE2 have been
1805executed in succession. */);
8e11578b 1806
29208e82 1807 DEFVAR_BOOL ("byte-metering-on", byte_metering_on,
39f624fa
PJ
1808 doc: /* If non-nil, keep profiling information on byte code usage.
1809The variable byte-code-meter indicates how often each byte opcode is used.
1810If a symbol has a property named `byte-code-meter' whose value is an
1811integer, it is incremented each time that symbol's function is called. */);
36f7ba0a
JB
1812
1813 byte_metering_on = 0;
63639d44 1814 Vbyte_code_meter = Fmake_vector (make_number (256), make_number (0));
d67b4f80 1815 Qbyte_code_meter = intern_c_string ("byte-code-meter");
63639d44 1816 staticpro (&Qbyte_code_meter);
36f7ba0a
JB
1817 {
1818 int i = 256;
1819 while (i--)
63639d44
JB
1820 XVECTOR (Vbyte_code_meter)->contents[i] =
1821 Fmake_vector (make_number (256), make_number (0));
36f7ba0a
JB
1822 }
1823#endif
1824}