1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-05-20 19:50:24 +02:00

Reserve frame word for machine return address

* libguile/frames.h: Add machine return address to diagram.
  (SCM_FRAME_MACHINE_RETURN_ADDRESS):
  (SCM_FRAME_SET_MACHINE_RETURN_ADDRESS): New macros.
  (SCM_FRAME_PREVIOUS_SP):
  (SCM_FRAME_DYNAMIC_LINK):
  (SCM_FRAME_SET_DYNAMIC_LINK): Adapt for new frame size.
* libguile/vm-engine.c (halt): Set frame size to 3.
  (call, call-label): Set mRA to 0.
* libguile/vm.c (push_interrupt_frame, reinstate_continuation_x):
  (scm_call_n): Set frame size to 3.  In push_interrupt_frame, init the
  mRA of the frame.
  (vm_builtin_call_with_values_code, vm_handle_interrupt_code): Allocate
  larger frames.
* module/language/cps/slot-allocation.scm (allocate-slots): Frame size
  is 3.
* module/system/vm/disassembler.scm (define-clobber-parser): Bump frame
  size.
This commit is contained in:
Andy Wingo 2018-07-16 15:42:05 +02:00
parent b1705bd0f0
commit 043432fd57
5 changed files with 33 additions and 24 deletions

View file

@ -44,6 +44,8 @@
| Dynamic link | | Dynamic link |
+------------------------------+ +------------------------------+
| Virtual return address (vRA) | | Virtual return address (vRA) |
+------------------------------+
| Machine return address (mRA) |
+==============================+ <- fp +==============================+ <- fp
| Local 0 | | Local 0 |
+------------------------------+ +------------------------------+
@ -57,12 +59,12 @@
The stack grows down. The stack grows down.
The calling convention is that a caller prepares a stack frame The calling convention is that a caller prepares a stack frame
consisting of the saved FP and the saved virtual return address, consisting of the saved FP, the saved virtual return addres, and the
followed by the procedure and then the arguments to the call, in saved machine return address of the calling function, followed by the
order. Thus in the beginning of a call, the procedure being called procedure and then the arguments to the call, in order. Thus in the
is in slot 0, the first argument is in slot 1, and the SP points to beginning of a call, the procedure being called is in slot 0, the
the last argument. The number of arguments, including the procedure, first argument is in slot 1, and the SP points to the last argument.
is thus FP - SP. The number of arguments, including the procedure, is thus FP - SP.
After ensuring that the correct number of arguments have been passed, After ensuring that the correct number of arguments have been passed,
a function will set the stack pointer to point to the last local a function will set the stack pointer to point to the last local
@ -103,11 +105,13 @@ union scm_vm_stack_element
scm_t_bits as_bits; scm_t_bits as_bits;
}; };
#define SCM_FRAME_PREVIOUS_SP(fp) ((fp) + 2) #define SCM_FRAME_PREVIOUS_SP(fp) ((fp) + 3)
#define SCM_FRAME_VIRTUAL_RETURN_ADDRESS(fp) ((fp)[0].as_vcode) #define SCM_FRAME_MACHINE_RETURN_ADDRESS(fp) ((fp)[0].as_mcode)
#define SCM_FRAME_SET_VIRTUAL_RETURN_ADDRESS(fp, ra) ((fp)[0].as_vcode = (ra)) #define SCM_FRAME_SET_MACHINE_RETURN_ADDRESS(fp, ra) ((fp)[0].as_mcode = (ra))
#define SCM_FRAME_DYNAMIC_LINK(fp) ((fp) + (fp)[1].as_uint) #define SCM_FRAME_VIRTUAL_RETURN_ADDRESS(fp) ((fp)[1].as_vcode)
#define SCM_FRAME_SET_DYNAMIC_LINK(fp, dl) ((fp)[1].as_uint = ((dl) - (fp))) #define SCM_FRAME_SET_VIRTUAL_RETURN_ADDRESS(fp, ra) ((fp)[1].as_vcode = (ra))
#define SCM_FRAME_DYNAMIC_LINK(fp) ((fp) + (fp)[2].as_uint)
#define SCM_FRAME_SET_DYNAMIC_LINK(fp, dl) ((fp)[2].as_uint = ((dl) - (fp)))
#define SCM_FRAME_SLOT(fp,i) ((fp) - (i) - 1) #define SCM_FRAME_SLOT(fp,i) ((fp) - (i) - 1)
#define SCM_FRAME_LOCAL(fp,i) (SCM_FRAME_SLOT (fp, i)->as_scm) #define SCM_FRAME_LOCAL(fp,i) (SCM_FRAME_SLOT (fp, i)->as_scm)
#define SCM_FRAME_NUM_LOCALS(fp, sp) ((fp) - (sp)) #define SCM_FRAME_NUM_LOCALS(fp, sp) ((fp) - (sp))

View file

@ -321,7 +321,7 @@ VM_NAME (scm_thread *thread)
*/ */
VM_DEFINE_OP (0, halt, "halt", OP1 (X32)) VM_DEFINE_OP (0, halt, "halt", OP1 (X32))
{ {
size_t frame_size = 2; size_t frame_size = 3;
/* Boot closure, then empty frame, then callee, then values. */ /* Boot closure, then empty frame, then callee, then values. */
size_t first_value = 1 + frame_size + 1; size_t first_value = 1 + frame_size + 1;
uint32_t nvals = FRAME_LOCALS_COUNT_FROM (first_value); uint32_t nvals = FRAME_LOCALS_COUNT_FROM (first_value);
@ -373,6 +373,7 @@ VM_NAME (scm_thread *thread)
VP->fp = SCM_FRAME_SLOT (old_fp, proc - 1); VP->fp = SCM_FRAME_SLOT (old_fp, proc - 1);
SCM_FRAME_SET_DYNAMIC_LINK (VP->fp, old_fp); SCM_FRAME_SET_DYNAMIC_LINK (VP->fp, old_fp);
SCM_FRAME_SET_VIRTUAL_RETURN_ADDRESS (VP->fp, ip + 2); SCM_FRAME_SET_VIRTUAL_RETURN_ADDRESS (VP->fp, ip + 2);
SCM_FRAME_SET_MACHINE_RETURN_ADDRESS (VP->fp, 0);
RESET_FRAME (nlocals); RESET_FRAME (nlocals);
@ -416,6 +417,7 @@ VM_NAME (scm_thread *thread)
VP->fp = SCM_FRAME_SLOT (old_fp, proc - 1); VP->fp = SCM_FRAME_SLOT (old_fp, proc - 1);
SCM_FRAME_SET_DYNAMIC_LINK (VP->fp, old_fp); SCM_FRAME_SET_DYNAMIC_LINK (VP->fp, old_fp);
SCM_FRAME_SET_VIRTUAL_RETURN_ADDRESS (VP->fp, ip + 3); SCM_FRAME_SET_VIRTUAL_RETURN_ADDRESS (VP->fp, ip + 3);
SCM_FRAME_SET_MACHINE_RETURN_ADDRESS (VP->fp, 0);
RESET_FRAME (nlocals); RESET_FRAME (nlocals);

View file

@ -351,11 +351,11 @@ static const uint32_t vm_builtin_abort_to_prompt_code[] = {
static const uint32_t vm_builtin_call_with_values_code[] = { static const uint32_t vm_builtin_call_with_values_code[] = {
SCM_PACK_OP_24 (assert_nargs_ee, 3), SCM_PACK_OP_24 (assert_nargs_ee, 3),
SCM_PACK_OP_24 (alloc_frame, 7), SCM_PACK_OP_24 (alloc_frame, 8),
SCM_PACK_OP_12_12 (mov, 0, 5), SCM_PACK_OP_12_12 (mov, 0, 6),
SCM_PACK_OP_24 (call, 6), SCM_PACK_OP_ARG_8_24 (0, 1), SCM_PACK_OP_24 (call, 7), SCM_PACK_OP_ARG_8_24 (0, 1),
SCM_PACK_OP_24 (long_fmov, 0), SCM_PACK_OP_ARG_8_24 (0, 2), SCM_PACK_OP_24 (long_fmov, 0), SCM_PACK_OP_ARG_8_24 (0, 2),
SCM_PACK_OP_24 (tail_call_shuffle, 7) SCM_PACK_OP_24 (tail_call_shuffle, 8)
}; };
static const uint32_t vm_builtin_call_with_current_continuation_code[] = { static const uint32_t vm_builtin_call_with_current_continuation_code[] = {
@ -364,9 +364,9 @@ static const uint32_t vm_builtin_call_with_current_continuation_code[] = {
}; };
static const uint32_t vm_handle_interrupt_code[] = { static const uint32_t vm_handle_interrupt_code[] = {
SCM_PACK_OP_24 (alloc_frame, 3), SCM_PACK_OP_24 (alloc_frame, 4),
SCM_PACK_OP_12_12 (mov, 0, 2), SCM_PACK_OP_12_12 (mov, 0, 3),
SCM_PACK_OP_24 (call, 2), SCM_PACK_OP_ARG_8_24 (0, 1), SCM_PACK_OP_24 (call, 3), SCM_PACK_OP_ARG_8_24 (0, 1),
SCM_PACK_OP_24 (return_from_interrupt, 0) SCM_PACK_OP_24 (return_from_interrupt, 0)
}; };
@ -1014,7 +1014,7 @@ static void
push_interrupt_frame (scm_thread *thread, uint8_t *mra) push_interrupt_frame (scm_thread *thread, uint8_t *mra)
{ {
union scm_vm_stack_element *old_fp; union scm_vm_stack_element *old_fp;
size_t frame_overhead = 2; size_t frame_overhead = 3;
size_t old_frame_size = frame_locals_count (thread); size_t old_frame_size = frame_locals_count (thread);
SCM proc = scm_i_async_pop (thread); SCM proc = scm_i_async_pop (thread);
@ -1030,6 +1030,7 @@ push_interrupt_frame (scm_thread *thread, uint8_t *mra)
/* Arrange to return to the same handle-interrupts opcode to handle /* Arrange to return to the same handle-interrupts opcode to handle
any additional interrupts. */ any additional interrupts. */
SCM_FRAME_SET_VIRTUAL_RETURN_ADDRESS (thread->vm.fp, thread->vm.ip); SCM_FRAME_SET_VIRTUAL_RETURN_ADDRESS (thread->vm.fp, thread->vm.ip);
SCM_FRAME_SET_MACHINE_RETURN_ADDRESS (thread->vm.fp, mra);
SCM_FRAME_LOCAL (thread->vm.fp, 0) = proc; SCM_FRAME_LOCAL (thread->vm.fp, 0) = proc;
} }
@ -1070,7 +1071,7 @@ reinstate_continuation_x (scm_thread *thread, SCM cont)
scm_t_contregs *continuation = scm_i_contregs (cont); scm_t_contregs *continuation = scm_i_contregs (cont);
struct scm_vm *vp = &thread->vm; struct scm_vm *vp = &thread->vm;
struct scm_vm_cont *cp; struct scm_vm_cont *cp;
size_t n, i, frame_overhead = 2; size_t n, i, frame_overhead = 3;
union scm_vm_stack_element *argv; union scm_vm_stack_element *argv;
struct return_to_continuation_data data; struct return_to_continuation_data data;
@ -1374,7 +1375,7 @@ scm_call_n (SCM proc, SCM *argv, size_t nargs)
elements and each element is at least 4 bytes, nargs will not be elements and each element is at least 4 bytes, nargs will not be
greater than INTMAX/2 and therefore we don't have to check for greater than INTMAX/2 and therefore we don't have to check for
overflow here or below. */ overflow here or below. */
size_t return_nlocals = 1, call_nlocals = nargs + 1, frame_size = 2; size_t return_nlocals = 1, call_nlocals = nargs + 1, frame_size = 3;
ptrdiff_t stack_reserve_words; ptrdiff_t stack_reserve_words;
size_t i; size_t i;
@ -1399,6 +1400,7 @@ scm_call_n (SCM proc, SCM *argv, size_t nargs)
return_fp = call_fp + frame_size + return_nlocals; return_fp = call_fp + frame_size + return_nlocals;
SCM_FRAME_SET_VIRTUAL_RETURN_ADDRESS (return_fp, vp->ip); SCM_FRAME_SET_VIRTUAL_RETURN_ADDRESS (return_fp, vp->ip);
SCM_FRAME_SET_MACHINE_RETURN_ADDRESS (return_fp, 0);
SCM_FRAME_SET_DYNAMIC_LINK (return_fp, vp->fp); SCM_FRAME_SET_DYNAMIC_LINK (return_fp, vp->fp);
SCM_FRAME_LOCAL (return_fp, 0) = vm_boot_continuation; SCM_FRAME_LOCAL (return_fp, 0) = vm_boot_continuation;
@ -1406,6 +1408,7 @@ scm_call_n (SCM proc, SCM *argv, size_t nargs)
vp->fp = call_fp; vp->fp = call_fp;
SCM_FRAME_SET_VIRTUAL_RETURN_ADDRESS (call_fp, vp->ip); SCM_FRAME_SET_VIRTUAL_RETURN_ADDRESS (call_fp, vp->ip);
SCM_FRAME_SET_MACHINE_RETURN_ADDRESS (call_fp, 0);
SCM_FRAME_SET_DYNAMIC_LINK (call_fp, return_fp); SCM_FRAME_SET_DYNAMIC_LINK (call_fp, return_fp);
SCM_FRAME_LOCAL (call_fp, 0) = proc; SCM_FRAME_LOCAL (call_fp, 0) = proc;
for (i = 0; i < nargs; i++) for (i = 0; i < nargs; i++)

View file

@ -807,7 +807,7 @@ are comparable with eqv?. A tmp slot may be used."
needs-slot) needs-slot)
empty-intset))) empty-intset)))
(define frame-size 2) (define frame-size 3)
(define (empty-live-slots) (define (empty-live-slots)
#b0) #b0)

View file

@ -615,7 +615,7 @@ address of that offset."
(lambda () (lambda ()
(disassemble-one code (/ pos 4))) (disassemble-one code (/ pos 4)))
(lambda (len elt) (lambda (len elt)
(define frame-size 2) (define frame-size 3)
(match elt (match elt
((_ proc . _) ((_ proc . _)
(let lp ((slot (- proc frame-size))) (let lp ((slot (- proc frame-size)))