aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGerd Moellmann1999-11-05 21:26:15 +0000
committerGerd Moellmann1999-11-05 21:26:15 +0000
commit7ca1e8b752b9844676922fd2515efdfd4be6a08d (patch)
treee19eeea619dec7d4d80f4b1ecf96d79adf478ad9 /src
parent4d59c34cd8864ef9f39689a75b0c19c78c280707 (diff)
downloademacs-7ca1e8b752b9844676922fd2515efdfd4be6a08d.tar.gz
emacs-7ca1e8b752b9844676922fd2515efdfd4be6a08d.zip
(struct byte_stack): New.
(byte_stack_list, mark_byte_stack, relocate_byte_pcs): New (BEFORE_POTENTIAL_GC, AFTER_POTENTIAL_GC): New. (FETCH, PUSH, POP, DISCARD, TOP, MAYBE_GC): Rewritten. (HANDLE_RELOCATION): Removed. (Fbyte_code): Use byte_stack structures.
Diffstat (limited to 'src')
-rw-r--r--src/bytecode.c225
1 files changed, 158 insertions, 67 deletions
diff --git a/src/bytecode.c b/src/bytecode.c
index e69ae722248..0093e692b2f 100644
--- a/src/bytecode.c
+++ b/src/bytecode.c
@@ -224,10 +224,86 @@ Lisp_Object Qbytecode;
224 224
225#define Bconstant 0300 225#define Bconstant 0300
226#define CONSTANTLIM 0100 226#define CONSTANTLIM 0100
227
228/* Structure describing a value stack used during byte-code execution
229 in Fbyte_code. */
230
231struct byte_stack
232{
233 /* Program counter. This points into the byte_string below
234 and is relocated when that string is relocated. */
235 unsigned char *pc;
236
237 /* Top and bottom of stack. The bottom points to an area of memory
238 allocated with alloca in Fbyte_code. */
239 Lisp_Object *top, *bottom;
240
241 /* The string containing the byte-code, and its current address.
242 Storing this here protects it from GC because mark_byte_stack
243 marks it. */
244 Lisp_Object byte_string;
245 unsigned char *byte_string_start;
246
247 /* The vector of constants used during byte-code execution. Storing
248 this here protects it from GC because mark_byte_stack marks it. */
249 Lisp_Object constants;
250
251 /* Next entry in byte_stack_list. */
252 struct byte_stack *next;
253};
254
255/* A list of currently active byte-code execution value stacks.
256 Fbyte_code adds an entry to the head of this list before it starts
257 processing byte-code, and it removed the entry again when it is
258 done. Signalling an error truncates the list analoguous to
259 gcprolist. */
260
261struct byte_stack *byte_stack_list;
262
263/* Mark objects on byte_stack_list. Called during GC. */
264
265void
266mark_byte_stack ()
267{
268 struct byte_stack *stack;
269 Lisp_Object *obj;
270
271 for (stack = byte_stack_list; stack; stack = stack->next)
272 {
273 if (!stack->top)
274 abort ();
275
276 for (obj = stack->bottom; obj <= stack->top; ++obj)
277 mark_object (obj);
278
279 mark_object (&stack->byte_string);
280 mark_object (&stack->constants);
281 }
282}
283
284
285/* Relocate program counters in the stacks on byte_stack_list. Called
286 when GC has completed. */
287
288void
289relocate_byte_pcs ()
290{
291 struct byte_stack *stack;
292
293 for (stack = byte_stack_list; stack; stack = stack->next)
294 if (stack->byte_string_start != XSTRING (stack->byte_string)->data)
295 {
296 int offset = stack->pc - stack->byte_string_start;
297 stack->byte_string_start = XSTRING (stack->byte_string)->data;
298 stack->pc = stack->byte_string_start + offset;
299 }
300}
301
302
227 303
228/* Fetch the next byte from the bytecode stream */ 304/* Fetch the next byte from the bytecode stream */
229 305
230#define FETCH *pc++ 306#define FETCH *stack.pc++
231 307
232/* Fetch two bytes from the bytecode stream 308/* Fetch two bytes from the bytecode stream
233 and make a 16-bit number out of them */ 309 and make a 16-bit number out of them */
@@ -236,22 +312,30 @@ Lisp_Object Qbytecode;
236 312
237/* Push x onto the execution stack. */ 313/* Push x onto the execution stack. */
238 314
239/* This used to be #define PUSH(x) (*++stackp = (x)) 315/* This used to be #define PUSH(x) (*++stackp = (x)) This oddity is
240 This oddity is necessary because Alliant can't be bothered to 316 necessary because Alliant can't be bothered to compile the
241 compile the preincrement operator properly, as of 4/91. -JimB */ 317 preincrement operator properly, as of 4/91. -JimB */
242#define PUSH(x) (stackp++, *stackp = (x)) 318
319#define PUSH(x) (top++, *top = (x))
243 320
244/* Pop a value off the execution stack. */ 321/* Pop a value off the execution stack. */
245 322
246#define POP (*stackp--) 323#define POP (*top--)
247 324
248/* Discard n values from the execution stack. */ 325/* Discard n values from the execution stack. */
249 326
250#define DISCARD(n) (stackp -= (n)) 327#define DISCARD(n) (top -= (n))
328
329/* Get the value which is at the top of the execution stack, but don't
330 pop it. */
331
332#define TOP (*top)
251 333
252/* Get the value which is at the top of the execution stack, but don't pop it. */ 334/* Actions that must performed before and after calling a function
335 that might GC. */
253 336
254#define TOP (*stackp) 337#define BEFORE_POTENTIAL_GC() stack.top = top
338#define AFTER_POTENTIAL_GC() stack.top = NULL
255 339
256/* Garbage collect if we have consed enough since the last time. 340/* Garbage collect if we have consed enough since the last time.
257 We do this at every branch, to avoid loops that never GC. */ 341 We do this at every branch, to avoid loops that never GC. */
@@ -259,24 +343,26 @@ Lisp_Object Qbytecode;
259#define MAYBE_GC() \ 343#define MAYBE_GC() \
260 if (consing_since_gc > gc_cons_threshold) \ 344 if (consing_since_gc > gc_cons_threshold) \
261 { \ 345 { \
346 BEFORE_POTENTIAL_GC (); \
262 Fgarbage_collect (); \ 347 Fgarbage_collect (); \
263 HANDLE_RELOCATION (); \ 348 AFTER_POTENTIAL_GC (); \
264 } \ 349 } \
265 else 350 else
266 351
267/* Relocate BYTESTR if there has been a GC recently. */
268#define HANDLE_RELOCATION() \
269 if (! EQ (string_saved, bytestr)) \
270 { \
271 pc = pc - XSTRING (string_saved)->data + XSTRING (bytestr)->data; \
272 string_saved = bytestr; \
273 } \
274 else
275
276/* Check for jumping out of range. */ 352/* Check for jumping out of range. */
353
354#ifdef BYTE_CODE_SAFE
355
277#define CHECK_RANGE(ARG) \ 356#define CHECK_RANGE(ARG) \
278 if (ARG >= bytestr_length) abort () 357 if (ARG >= bytestr_length) abort ()
279 358
359#else
360
361#define CHECK_RANGE(ARG)
362
363#endif
364
365
280DEFUN ("byte-code", Fbyte_code, Sbyte_code, 3, 3, 0, 366DEFUN ("byte-code", Fbyte_code, Sbyte_code, 3, 3, 0,
281 "Function used internally in byte-compiled code.\n\ 367 "Function used internally in byte-compiled code.\n\
282The first argument, BYTESTR, is a string of byte code;\n\ 368The first argument, BYTESTR, is a string of byte code;\n\
@@ -286,61 +372,53 @@ If the third argument is incorrect, Emacs may crash.")
286 (bytestr, vector, maxdepth) 372 (bytestr, vector, maxdepth)
287 Lisp_Object bytestr, vector, maxdepth; 373 Lisp_Object bytestr, vector, maxdepth;
288{ 374{
289 struct gcpro gcpro1, gcpro2, gcpro3;
290 int count = specpdl_ptr - specpdl; 375 int count = specpdl_ptr - specpdl;
291#ifdef BYTE_CODE_METER 376#ifdef BYTE_CODE_METER
292 int this_op = 0; 377 int this_op = 0;
293 int prev_op; 378 int prev_op;
294#endif 379#endif
295 register int op; 380 int op;
296 unsigned char *pc; 381 Lisp_Object v1, v2;
297 Lisp_Object *stack; 382 Lisp_Object *stackp;
298 register Lisp_Object *stackp; 383 Lisp_Object *vectorp = XVECTOR (vector)->contents;
299 Lisp_Object *stacke;
300 register Lisp_Object v1, v2;
301 register Lisp_Object *vectorp = XVECTOR (vector)->contents;
302#ifdef BYTE_CODE_SAFE 384#ifdef BYTE_CODE_SAFE
303 register int const_length = XVECTOR (vector)->size; 385 int const_length = XVECTOR (vector)->size;
386 Lisp_Object *stacke;
304#endif 387#endif
305 /* Copy of BYTESTR, saved so we can tell if BYTESTR was relocated. */
306 Lisp_Object string_saved;
307 /* Cached address of beginning of string,
308 valid if BYTESTR equals STRING_SAVED. */
309 register unsigned char *strbeg;
310 int bytestr_length = STRING_BYTES (XSTRING (bytestr)); 388 int bytestr_length = STRING_BYTES (XSTRING (bytestr));
389 struct byte_stack stack;
390 Lisp_Object *top;
311 391
312 CHECK_STRING (bytestr, 0); 392 CHECK_STRING (bytestr, 0);
313 if (!VECTORP (vector)) 393 if (!VECTORP (vector))
314 vector = wrong_type_argument (Qvectorp, vector); 394 vector = wrong_type_argument (Qvectorp, vector);
315 CHECK_NUMBER (maxdepth, 2); 395 CHECK_NUMBER (maxdepth, 2);
316 396
317 stackp = (Lisp_Object *) alloca (XFASTINT (maxdepth) * sizeof (Lisp_Object)); 397 stack.byte_string = bytestr;
318 bzero (stackp, XFASTINT (maxdepth) * sizeof (Lisp_Object)); 398 stack.pc = stack.byte_string_start = XSTRING (bytestr)->data;
319 GCPRO3 (bytestr, vector, *stackp); 399 stack.constants = vector;
320 gcpro3.nvars = XFASTINT (maxdepth); 400 stack.bottom = (Lisp_Object *) alloca (XFASTINT (maxdepth)
321 401 * sizeof (Lisp_Object));
322 --stackp; 402 top = stack.bottom - 1;
323 stack = stackp; 403 stack.top = NULL;
324 stacke = stackp + XFASTINT (maxdepth); 404 stack.next = byte_stack_list;
325 405 byte_stack_list = &stack;
326 /* Initialize the saved pc-pointer for fetching from the string. */
327 string_saved = bytestr;
328 pc = XSTRING (string_saved)->data;
329 406
407#ifdef BYTE_CODE_SAFE
408 stacke = stack.bottom - 1 + XFASTINT (maxdepth);
409#endif
410
330 while (1) 411 while (1)
331 { 412 {
332#ifdef BYTE_CODE_SAFE 413#ifdef BYTE_CODE_SAFE
333 if (stackp > stacke) 414 if (top > stacks)
334 error ("Byte code stack overflow (byte compiler bug), pc %d, depth %d", 415 error ("Byte code stack overflow (byte compiler bug), pc %d, depth %d",
335 pc - XSTRING (string_saved)->data, stacke - stackp); 416 stack.pc - stack.byte_string_start, stacke - top);
336 if (stackp < stack) 417 else if (top < stack.bottom - 1)
337 error ("Byte code stack underflow (byte compiler bug), pc %d", 418 error ("Byte code stack underflow (byte compiler bug), pc %d",
338 pc - XSTRING (string_saved)->data); 419 stack.pc - stack.byte_string_start);
339#endif 420#endif
340 421
341 /* Update BYTESTR if we had a garbage collection. */
342 HANDLE_RELOCATION ();
343
344#ifdef BYTE_CODE_METER 422#ifdef BYTE_CODE_METER
345 prev_op = this_op; 423 prev_op = this_op;
346 this_op = op = FETCH; 424 this_op = op = FETCH;
@@ -430,7 +508,9 @@ If the third argument is incorrect, Emacs may crash.")
430 } 508 }
431 } 509 }
432#endif 510#endif
511 BEFORE_POTENTIAL_GC ();
433 TOP = Ffuncall (op + 1, &TOP); 512 TOP = Ffuncall (op + 1, &TOP);
513 AFTER_POTENTIAL_GC ();
434 break; 514 break;
435 515
436 case Bunbind+6: 516 case Bunbind+6:
@@ -445,13 +525,17 @@ If the third argument is incorrect, Emacs may crash.")
445 case Bunbind+4: case Bunbind+5: 525 case Bunbind+4: case Bunbind+5:
446 op -= Bunbind; 526 op -= Bunbind;
447 dounbind: 527 dounbind:
528 BEFORE_POTENTIAL_GC ();
448 unbind_to (specpdl_ptr - specpdl - op, Qnil); 529 unbind_to (specpdl_ptr - specpdl - op, Qnil);
530 AFTER_POTENTIAL_GC ();
449 break; 531 break;
450 532
451 case Bunbind_all: 533 case Bunbind_all:
452 /* To unbind back to the beginning of this frame. Not used yet, 534 /* To unbind back to the beginning of this frame. Not used yet,
453 but will be needed for tail-recursion elimination. */ 535 but will be needed for tail-recursion elimination. */
536 BEFORE_POTENTIAL_GC ();
454 unbind_to (count, Qnil); 537 unbind_to (count, Qnil);
538 AFTER_POTENTIAL_GC ();
455 break; 539 break;
456 540
457 case Bgoto: 541 case Bgoto:
@@ -459,7 +543,7 @@ If the third argument is incorrect, Emacs may crash.")
459 QUIT; 543 QUIT;
460 op = FETCH2; /* pc = FETCH2 loses since FETCH2 contains pc++ */ 544 op = FETCH2; /* pc = FETCH2 loses since FETCH2 contains pc++ */
461 CHECK_RANGE (op); 545 CHECK_RANGE (op);
462 pc = XSTRING (string_saved)->data + op; 546 stack.pc = stack.byte_string_start + op;
463 break; 547 break;
464 548
465 case Bgotoifnil: 549 case Bgotoifnil:
@@ -469,7 +553,7 @@ If the third argument is incorrect, Emacs may crash.")
469 { 553 {
470 QUIT; 554 QUIT;
471 CHECK_RANGE (op); 555 CHECK_RANGE (op);
472 pc = XSTRING (string_saved)->data + op; 556 stack.pc = stack.byte_string_start + op;
473 } 557 }
474 break; 558 break;
475 559
@@ -480,7 +564,7 @@ If the third argument is incorrect, Emacs may crash.")
480 { 564 {
481 QUIT; 565 QUIT;
482 CHECK_RANGE (op); 566 CHECK_RANGE (op);
483 pc = XSTRING (string_saved)->data + op; 567 stack.pc = stack.byte_string_start + op;
484 } 568 }
485 break; 569 break;
486 570
@@ -491,7 +575,7 @@ If the third argument is incorrect, Emacs may crash.")
491 { 575 {
492 QUIT; 576 QUIT;
493 CHECK_RANGE (op); 577 CHECK_RANGE (op);
494 pc = XSTRING (string_saved)->data + op; 578 stack.pc = stack.byte_string_start + op;
495 } 579 }
496 else DISCARD (1); 580 else DISCARD (1);
497 break; 581 break;
@@ -503,7 +587,7 @@ If the third argument is incorrect, Emacs may crash.")
503 { 587 {
504 QUIT; 588 QUIT;
505 CHECK_RANGE (op); 589 CHECK_RANGE (op);
506 pc = XSTRING (string_saved)->data + op; 590 stack.pc = stack.byte_string_start + op;
507 } 591 }
508 else DISCARD (1); 592 else DISCARD (1);
509 break; 593 break;
@@ -511,7 +595,7 @@ If the third argument is incorrect, Emacs may crash.")
511 case BRgoto: 595 case BRgoto:
512 MAYBE_GC (); 596 MAYBE_GC ();
513 QUIT; 597 QUIT;
514 pc += (int) *pc - 127; 598 stack.pc += (int) *stack.pc - 127;
515 break; 599 break;
516 600
517 case BRgotoifnil: 601 case BRgotoifnil:
@@ -519,9 +603,9 @@ If the third argument is incorrect, Emacs may crash.")
519 if (NILP (POP)) 603 if (NILP (POP))
520 { 604 {
521 QUIT; 605 QUIT;
522 pc += (int) *pc - 128; 606 stack.pc += (int) *stack.pc - 128;
523 } 607 }
524 pc++; 608 stack.pc++;
525 break; 609 break;
526 610
527 case BRgotoifnonnil: 611 case BRgotoifnonnil:
@@ -529,29 +613,29 @@ If the third argument is incorrect, Emacs may crash.")
529 if (!NILP (POP)) 613 if (!NILP (POP))
530 { 614 {
531 QUIT; 615 QUIT;
532 pc += (int) *pc - 128; 616 stack.pc += (int) *stack.pc - 128;
533 } 617 }
534 pc++; 618 stack.pc++;
535 break; 619 break;
536 620
537 case BRgotoifnilelsepop: 621 case BRgotoifnilelsepop:
538 MAYBE_GC (); 622 MAYBE_GC ();
539 op = *pc++; 623 op = *stack.pc++;
540 if (NILP (TOP)) 624 if (NILP (TOP))
541 { 625 {
542 QUIT; 626 QUIT;
543 pc += op - 128; 627 stack.pc += op - 128;
544 } 628 }
545 else DISCARD (1); 629 else DISCARD (1);
546 break; 630 break;
547 631
548 case BRgotoifnonnilelsepop: 632 case BRgotoifnonnilelsepop:
549 MAYBE_GC (); 633 MAYBE_GC ();
550 op = *pc++; 634 op = *stack.pc++;
551 if (!NILP (TOP)) 635 if (!NILP (TOP))
552 { 636 {
553 QUIT; 637 QUIT;
554 pc += op - 128; 638 stack.pc += op - 128;
555 } 639 }
556 else DISCARD (1); 640 else DISCARD (1);
557 break; 641 break;
@@ -603,7 +687,9 @@ If the third argument is incorrect, Emacs may crash.")
603 case Bcondition_case: 687 case Bcondition_case:
604 v1 = POP; 688 v1 = POP;
605 v1 = Fcons (POP, v1); 689 v1 = Fcons (POP, v1);
690 BEFORE_POTENTIAL_GC ();
606 TOP = Fcondition_case (Fcons (TOP, v1)); 691 TOP = Fcondition_case (Fcons (TOP, v1));
692 AFTER_POTENTIAL_GC ();
607 break; 693 break;
608 694
609 case Btemp_output_buffer_setup: 695 case Btemp_output_buffer_setup:
@@ -616,7 +702,9 @@ If the third argument is incorrect, Emacs may crash.")
616 temp_output_buffer_show (TOP); 702 temp_output_buffer_show (TOP);
617 TOP = v1; 703 TOP = v1;
618 /* pop binding of standard-output */ 704 /* pop binding of standard-output */
705 BEFORE_POTENTIAL_GC ();
619 unbind_to (specpdl_ptr - specpdl - 1, Qnil); 706 unbind_to (specpdl_ptr - specpdl - 1, Qnil);
707 AFTER_POTENTIAL_GC ();
620 break; 708 break;
621 709
622 case Bnth: 710 case Bnth:
@@ -1146,7 +1234,9 @@ If the third argument is incorrect, Emacs may crash.")
1146 } 1234 }
1147 1235
1148 exit: 1236 exit:
1149 UNGCPRO; 1237
1238 byte_stack_list = byte_stack_list->next;
1239
1150 /* Binds and unbinds are supposed to be compiled balanced. */ 1240 /* Binds and unbinds are supposed to be compiled balanced. */
1151 if (specpdl_ptr - specpdl != count) 1241 if (specpdl_ptr - specpdl != count)
1152#ifdef BYTE_CODE_SAFE 1242#ifdef BYTE_CODE_SAFE
@@ -1154,6 +1244,7 @@ If the third argument is incorrect, Emacs may crash.")
1154#else 1244#else
1155 abort (); 1245 abort ();
1156#endif 1246#endif
1247
1157 return v1; 1248 return v1;
1158} 1249}
1159 1250