diff options
| author | Gerd Moellmann | 1999-11-05 21:26:15 +0000 |
|---|---|---|
| committer | Gerd Moellmann | 1999-11-05 21:26:15 +0000 |
| commit | 7ca1e8b752b9844676922fd2515efdfd4be6a08d (patch) | |
| tree | e19eeea619dec7d4d80f4b1ecf96d79adf478ad9 /src | |
| parent | 4d59c34cd8864ef9f39689a75b0c19c78c280707 (diff) | |
| download | emacs-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.c | 225 |
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 | |||
| 231 | struct 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 | |||
| 261 | struct byte_stack *byte_stack_list; | ||
| 262 | |||
| 263 | /* Mark objects on byte_stack_list. Called during GC. */ | ||
| 264 | |||
| 265 | void | ||
| 266 | mark_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 | |||
| 288 | void | ||
| 289 | relocate_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 | |||
| 280 | DEFUN ("byte-code", Fbyte_code, Sbyte_code, 3, 3, 0, | 366 | DEFUN ("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\ |
| 282 | The first argument, BYTESTR, is a string of byte code;\n\ | 368 | The 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 | ||