aboutsummaryrefslogtreecommitdiffstats
path: root/src/bytecode.c
diff options
context:
space:
mode:
authorMattias EngdegÄrd2022-03-14 12:57:29 +0100
committerMattias EngdegÄrd2022-03-17 16:38:22 +0100
commit751c8f88c4faddb2b4f5d5ba3f051e8cd2c0153c (patch)
tree73078523cc6c2343db46ff45c8189e1d75055c9a /src/bytecode.c
parentedb28bf669b890b7498cad0fd818ffa38b5e13a9 (diff)
downloademacs-751c8f88c4faddb2b4f5d5ba3f051e8cd2c0153c.tar.gz
emacs-751c8f88c4faddb2b4f5d5ba3f051e8cd2c0153c.zip
Put bytecode stack frame metadata in a struct
Using a plain C struct instead of type-punning Lisp_Object stack slots makes the bytecode interpreter code more type-safe and potentially faster (from better alias analysis), and the special-purpose accessors are no longer needed. It also reduces the stack requirements when using 64-bit Lisp_Object on 32-bit platforms. * src/bytecode.c (enum stack_frame_index) (sf_get_ptr, sf_set_ptr, sf_get_lisp_ptr, sf_set_lisp_ptr, sf_get_saved_pc, sf_set_saved_pc): Remove. (BC_STACK_SIZE): Now in bytes, not Lisp words. (struct bc_frame): New. (init_bc_thread, mark_bytecode, Finternal_stack_stats, valid_sp) (exec_byte_code): * src/lisp.h (struct handler, get_act_rec, set_act_rec): Adapt to new struct bc_frame.
Diffstat (limited to 'src/bytecode.c')
-rw-r--r--src/bytecode.c112
1 files changed, 38 insertions, 74 deletions
diff --git a/src/bytecode.c b/src/bytecode.c
index 65c3ad4da70..ed1f6ca4a85 100644
--- a/src/bytecode.c
+++ b/src/bytecode.c
@@ -335,20 +335,7 @@ bcall0 (Lisp_Object f)
335 Ffuncall (1, &f); 335 Ffuncall (1, &f);
336} 336}
337 337
338/* Layout of the stack frame header. */ 338/* The bytecode stack size in bytes.
339enum stack_frame_index {
340 SFI_SAVED_FP, /* previous frame pointer */
341
342 /* In a frame called directly from C, the following two members are NULL. */
343 SFI_SAVED_TOP, /* previous stack pointer */
344 SFI_SAVED_PC, /* previous program counter */
345
346 SFI_FUN, /* current function object */
347
348 SF_SIZE /* number of words in the header */
349};
350
351/* The bytecode stack size in Lisp words.
352 This is a fairly generous amount, but: 339 This is a fairly generous amount, but:
353 - if users need more, we could allocate more, or just reserve the address 340 - if users need more, we could allocate more, or just reserve the address
354 space and allocate on demand 341 space and allocate on demand
@@ -357,7 +344,7 @@ enum stack_frame_index {
357 - for maximum flexibility but a small runtime penalty, we could allocate 344 - for maximum flexibility but a small runtime penalty, we could allocate
358 the stack in smaller chunks as needed 345 the stack in smaller chunks as needed
359*/ 346*/
360#define BC_STACK_SIZE (512 * 1024) 347#define BC_STACK_SIZE (512 * 1024 * sizeof (Lisp_Object))
361 348
362/* Bytecode interpreter stack: 349/* Bytecode interpreter stack:
363 350
@@ -385,51 +372,28 @@ enum stack_frame_index {
385 : : 372 : :
386*/ 373*/
387 374
388INLINE void * 375/* bytecode stack frame header (footer, actually) */
389sf_get_ptr (Lisp_Object *fp, enum stack_frame_index index) 376struct bc_frame {
390{ 377 struct bc_frame *saved_fp; /* previous frame pointer,
391 return XLP (fp[index]); 378 NULL if bottommost frame */
392}
393
394INLINE void
395sf_set_ptr (Lisp_Object *fp, enum stack_frame_index index, void *value)
396{
397 fp[index] = XIL ((uintptr_t)value);
398}
399
400INLINE Lisp_Object *
401sf_get_lisp_ptr (Lisp_Object *fp, enum stack_frame_index index)
402{
403 return sf_get_ptr (fp, index);
404}
405 379
406INLINE void 380 /* In a frame called directly from C, the following two members are NULL. */
407sf_set_lisp_ptr (Lisp_Object *fp, enum stack_frame_index index, 381 Lisp_Object *saved_top; /* previous stack pointer */
408 Lisp_Object *value) 382 const unsigned char *saved_pc; /* previous program counter */
409{
410 sf_set_ptr (fp, index, value);
411}
412 383
413INLINE const unsigned char * 384 Lisp_Object fun; /* current function object */
414sf_get_saved_pc (Lisp_Object *fp)
415{
416 return sf_get_ptr (fp, SFI_SAVED_PC);
417}
418 385
419INLINE void 386 Lisp_Object next_stack[]; /* data stack of next frame */
420sf_set_saved_pc (Lisp_Object *fp, const unsigned char *value) 387};
421{
422 sf_set_ptr (fp, SFI_SAVED_PC, (unsigned char *)value);
423}
424 388
425void 389void
426init_bc_thread (struct bc_thread_state *bc) 390init_bc_thread (struct bc_thread_state *bc)
427{ 391{
428 bc->stack = xmalloc (BC_STACK_SIZE * sizeof *bc->stack); 392 bc->stack = xmalloc (BC_STACK_SIZE);
429 bc->stack_end = bc->stack + BC_STACK_SIZE; 393 bc->stack_end = bc->stack + BC_STACK_SIZE;
430 /* Put a dummy header at the bottom to indicate the first free location. */ 394 /* Put a dummy header at the bottom to indicate the first free location. */
431 bc->fp = bc->stack; 395 bc->fp = (struct bc_frame *)bc->stack;
432 memset (bc->fp, 0, SF_SIZE * sizeof *bc->stack); 396 memset (bc->fp, 0, sizeof *bc->fp);
433} 397}
434 398
435void 399void
@@ -441,16 +405,16 @@ free_bc_thread (struct bc_thread_state *bc)
441void 405void
442mark_bytecode (struct bc_thread_state *bc) 406mark_bytecode (struct bc_thread_state *bc)
443{ 407{
444 Lisp_Object *fp = bc->fp; 408 struct bc_frame *fp = bc->fp;
445 Lisp_Object *top = NULL; /* stack pointer of topmost frame not known */ 409 Lisp_Object *top = NULL; /* stack pointer of topmost frame not known */
446 for (;;) 410 for (;;)
447 { 411 {
448 Lisp_Object *next_fp = sf_get_lisp_ptr (fp, SFI_SAVED_FP); 412 struct bc_frame *next_fp = fp->saved_fp;
449 /* Only the dummy frame at the bottom has saved_fp = NULL. */ 413 /* Only the dummy frame at the bottom has saved_fp = NULL. */
450 if (!next_fp) 414 if (!next_fp)
451 break; 415 break;
452 mark_object (fp[SFI_FUN]); 416 mark_object (fp->fun);
453 Lisp_Object *frame_base = next_fp + SF_SIZE; 417 Lisp_Object *frame_base = next_fp->next_stack;
454 if (top) 418 if (top)
455 { 419 {
456 /* The stack pointer of a frame is known: mark the part of the stack 420 /* The stack pointer of a frame is known: mark the part of the stack
@@ -464,7 +428,7 @@ mark_bytecode (struct bc_thread_state *bc)
464 /* The stack pointer is unknown -- mark everything conservatively. */ 428 /* The stack pointer is unknown -- mark everything conservatively. */
465 mark_memory (frame_base, fp); 429 mark_memory (frame_base, fp);
466 } 430 }
467 top = sf_get_lisp_ptr (fp, SFI_SAVED_TOP); 431 top = fp->saved_top;
468 fp = next_fp; 432 fp = next_fp;
469 } 433 }
470} 434}
@@ -477,10 +441,10 @@ DEFUN ("internal-stack-stats", Finternal_stack_stats, Sinternal_stack_stats,
477 struct bc_thread_state *bc = &current_thread->bc; 441 struct bc_thread_state *bc = &current_thread->bc;
478 int nframes = 0; 442 int nframes = 0;
479 int nruns = 0; 443 int nruns = 0;
480 for (Lisp_Object *fp = bc->fp; fp; fp = sf_get_lisp_ptr (fp, SFI_SAVED_FP)) 444 for (struct bc_frame *fp = bc->fp; fp; fp = fp->saved_fp)
481 { 445 {
482 nframes++; 446 nframes++;
483 if (sf_get_lisp_ptr (fp, SFI_SAVED_TOP) == NULL) 447 if (fp->saved_top == NULL)
484 nruns++; 448 nruns++;
485 } 449 }
486 fprintf (stderr, "%d stack frames, %d runs\n", nframes, nruns); 450 fprintf (stderr, "%d stack frames, %d runs\n", nframes, nruns);
@@ -491,8 +455,8 @@ DEFUN ("internal-stack-stats", Finternal_stack_stats, Sinternal_stack_stats,
491INLINE bool 455INLINE bool
492valid_sp (struct bc_thread_state *bc, Lisp_Object *sp) 456valid_sp (struct bc_thread_state *bc, Lisp_Object *sp)
493{ 457{
494 Lisp_Object *fp = bc->fp; 458 struct bc_frame *fp = bc->fp;
495 return sp < fp && sp + 1 >= sf_get_lisp_ptr (fp, SFI_SAVED_FP) + SF_SIZE; 459 return sp < (Lisp_Object *)fp && sp + 1 >= fp->saved_fp->next_stack;
496} 460}
497 461
498/* Execute the byte-code in FUN. ARGS_TEMPLATE is the function arity 462/* Execute the byte-code in FUN. ARGS_TEMPLATE is the function arity
@@ -532,20 +496,20 @@ exec_byte_code (Lisp_Object fun, ptrdiff_t args_template,
532 Lisp_Object *vectorp = XVECTOR (vector)->contents; 496 Lisp_Object *vectorp = XVECTOR (vector)->contents;
533 497
534 EMACS_INT max_stack = XFIXNAT (maxdepth); 498 EMACS_INT max_stack = XFIXNAT (maxdepth);
535 Lisp_Object *frame_base = bc->fp + SF_SIZE; 499 Lisp_Object *frame_base = bc->fp->next_stack;
536 Lisp_Object *fp = frame_base + max_stack; 500 struct bc_frame *fp = (struct bc_frame *)(frame_base + max_stack);
537 501
538 if (fp + SF_SIZE > bc->stack_end) 502 if ((char *)fp->next_stack > bc->stack_end)
539 error ("Bytecode stack overflow"); 503 error ("Bytecode stack overflow");
540 504
541 /* Save the function object so that the bytecode and vector are 505 /* Save the function object so that the bytecode and vector are
542 held from removal by the GC. */ 506 held from removal by the GC. */
543 fp[SFI_FUN] = fun; 507 fp->fun = fun;
544 /* Save previous stack pointer and pc in the new frame. If we came 508 /* Save previous stack pointer and pc in the new frame. If we came
545 directly from outside, these will be NULL. */ 509 directly from outside, these will be NULL. */
546 sf_set_lisp_ptr (fp, SFI_SAVED_TOP, top); 510 fp->saved_top = top;
547 sf_set_saved_pc (fp, pc); 511 fp->saved_pc = pc;
548 sf_set_lisp_ptr (fp, SFI_SAVED_FP, bc->fp); 512 fp->saved_fp = bc->fp;
549 bc->fp = fp; 513 bc->fp = fp;
550 514
551 top = frame_base - 1; 515 top = frame_base - 1;
@@ -914,7 +878,7 @@ exec_byte_code (Lisp_Object fun, ptrdiff_t args_template,
914 878
915 CASE (Breturn): 879 CASE (Breturn):
916 { 880 {
917 Lisp_Object *saved_top = sf_get_lisp_ptr (bc->fp, SFI_SAVED_TOP); 881 Lisp_Object *saved_top = bc->fp->saved_top;
918 if (saved_top) 882 if (saved_top)
919 { 883 {
920 Lisp_Object val = TOP; 884 Lisp_Object val = TOP;
@@ -925,11 +889,11 @@ exec_byte_code (Lisp_Object fun, ptrdiff_t args_template,
925 specpdl_ptr--; 889 specpdl_ptr--;
926 890
927 top = saved_top; 891 top = saved_top;
928 pc = sf_get_saved_pc (bc->fp); 892 pc = bc->fp->saved_pc;
929 Lisp_Object *fp = sf_get_lisp_ptr (bc->fp, SFI_SAVED_FP); 893 struct bc_frame *fp = bc->fp->saved_fp;
930 bc->fp = fp; 894 bc->fp = fp;
931 895
932 Lisp_Object fun = fp[SFI_FUN]; 896 Lisp_Object fun = fp->fun;
933 Lisp_Object bytestr = AREF (fun, COMPILED_BYTECODE); 897 Lisp_Object bytestr = AREF (fun, COMPILED_BYTECODE);
934 Lisp_Object vector = AREF (fun, COMPILED_CONSTANTS); 898 Lisp_Object vector = AREF (fun, COMPILED_CONSTANTS);
935 bytestr_data = SDATA (bytestr); 899 bytestr_data = SDATA (bytestr);
@@ -1004,9 +968,9 @@ exec_byte_code (Lisp_Object fun, ptrdiff_t args_template,
1004 handlerlist = c->next; 968 handlerlist = c->next;
1005 top = c->bytecode_top; 969 top = c->bytecode_top;
1006 op = c->bytecode_dest; 970 op = c->bytecode_dest;
1007 Lisp_Object *fp = bc->fp; 971 struct bc_frame *fp = bc->fp;
1008 972
1009 Lisp_Object fun = fp[SFI_FUN]; 973 Lisp_Object fun = fp->fun;
1010 Lisp_Object bytestr = AREF (fun, COMPILED_BYTECODE); 974 Lisp_Object bytestr = AREF (fun, COMPILED_BYTECODE);
1011 Lisp_Object vector = AREF (fun, COMPILED_CONSTANTS); 975 Lisp_Object vector = AREF (fun, COMPILED_CONSTANTS);
1012 bytestr_data = SDATA (bytestr); 976 bytestr_data = SDATA (bytestr);
@@ -1756,7 +1720,7 @@ exec_byte_code (Lisp_Object fun, ptrdiff_t args_template,
1756 1720
1757 exit: 1721 exit:
1758 1722
1759 bc->fp = sf_get_lisp_ptr (bc->fp, SFI_SAVED_FP); 1723 bc->fp = bc->fp->saved_fp;
1760 1724
1761 Lisp_Object result = TOP; 1725 Lisp_Object result = TOP;
1762 return result; 1726 return result;