1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-05-20 03:30:27 +02:00

Remove MVRA from VM frames

* libguile/_scm.h (SCM_OBJCODE_MINOR_VERSION): Bump for frame layout
  change.

* libguile/frames.c: Update some static checks.
  (scm_frame_num_locals, scm_frame_local_ref, scm_frame_local_set_x):
  Update to not skip over uninitialized frames, as that's not a thing
  any more.

* libguile/frames.h: Update to remove MVRA.  Woo!

* libguile/vm-engine.c (ALLOC_FRAME, RETURN_ONE_VALUE):
  (rtl_vm_engine): Update for 3 words per frame instead of 4.

* libguile/vm.c (vm_return_to_continuation): Likewise.

* module/language/cps/slot-allocation.scm (allocate-slots): 3 words per
  frame, not 4.

* module/system/vm/assembler.scm (*bytecode-minor-version*): Bump.  Also
  remove a couple of tc7's that aren't around any more.
This commit is contained in:
Andy Wingo 2013-11-15 17:13:10 +01:00
parent 840ec33422
commit f8085163d6
7 changed files with 45 additions and 100 deletions

View file

@ -270,7 +270,7 @@ void scm_ia64_longjmp (scm_i_jmp_buf *, int);
/* Major and minor versions must be single characters. */
#define SCM_OBJCODE_MAJOR_VERSION 3
#define SCM_OBJCODE_MINOR_VERSION 2
#define SCM_OBJCODE_MINOR_VERSION 3
#define SCM_OBJCODE_MAJOR_VERSION_STRING \
SCM_CPP_STRINGIFY(SCM_OBJCODE_MAJOR_VERSION)
#define SCM_OBJCODE_MINOR_VERSION_STRING \

View file

@ -28,7 +28,7 @@
/* Make sure assumptions on the layout of `struct scm_vm_frame' hold. */
verify (sizeof (SCM) == sizeof (SCM *));
verify (sizeof (struct scm_vm_frame) == 5 * sizeof (SCM));
verify (sizeof (struct scm_vm_frame) == 4 * sizeof (SCM));
verify (offsetof (struct scm_vm_frame, dynamic_link) == 0);
@ -110,39 +110,28 @@ SCM_DEFINE (scm_frame_source, "frame-source", 1, 0, 0,
}
#undef FUNC_NAME
/* The number of locals would be a simple thing to compute, if it weren't for
the presence of not-yet-active frames on the stack. So we have a cheap
heuristic to detect not-yet-active frames, and skip over them. Perhaps we
should represent them more usefully.
*/
SCM_DEFINE (scm_frame_num_locals, "frame-num-locals", 1, 0, 0,
(SCM frame),
"")
#define FUNC_NAME s_scm_frame_num_locals
{
SCM *sp, *p;
unsigned int n = 0;
SCM_VALIDATE_VM_FRAME (1, frame);
sp = SCM_VM_FRAME_SP (frame);
p = SCM_FRAME_STACK_ADDRESS (SCM_VM_FRAME_FP (frame));
/* The frame size of an RTL program is fixed, except in the case of
passing a wrong number of arguments to the program. So we do
need to use an SP for determining the number of locals. */
return scm_from_ptrdiff_t (sp + 1 - p);
}
#undef FUNC_NAME
/* Need same not-yet-active frame logic here as in frame-num-locals */
SCM_DEFINE (scm_frame_local_ref, "frame-local-ref", 2, 0, 0,
(SCM frame, SCM index),
"")
#define FUNC_NAME s_scm_frame_local_ref
{
SCM *sp, *p;
unsigned int n = 0;
unsigned int i;
SCM_VALIDATE_VM_FRAME (1, frame);
@ -150,19 +139,10 @@ SCM_DEFINE (scm_frame_local_ref, "frame-local-ref", 2, 0, 0,
sp = SCM_VM_FRAME_SP (frame);
p = SCM_FRAME_STACK_ADDRESS (SCM_VM_FRAME_FP (frame));
while (p <= sp)
{
if (SCM_UNPACK (p[0]) == 0)
/* skip over not-yet-active frame */
p += 3;
else if (n == i)
return *p;
else
{
p++;
n++;
}
}
if (p + i <= sp)
return SCM_FRAME_VARIABLE (SCM_VM_FRAME_FP (frame), i);
SCM_OUT_OF_RANGE (SCM_ARG2, index);
}
#undef FUNC_NAME
@ -174,7 +154,6 @@ SCM_DEFINE (scm_frame_local_set_x, "frame-local-set!", 3, 0, 0,
#define FUNC_NAME s_scm_frame_local_set_x
{
SCM *sp, *p;
unsigned int n = 0;
unsigned int i;
SCM_VALIDATE_VM_FRAME (1, frame);
@ -182,22 +161,13 @@ SCM_DEFINE (scm_frame_local_set_x, "frame-local-set!", 3, 0, 0,
sp = SCM_VM_FRAME_SP (frame);
p = SCM_FRAME_STACK_ADDRESS (SCM_VM_FRAME_FP (frame));
while (p <= sp)
if (p + i <= sp)
{
if (SCM_UNPACK (p[0]) == 0)
/* skip over not-yet-active frame */
p += 3;
else if (n == i)
{
*p = val;
return SCM_UNSPECIFIED;
}
else
{
p++;
n++;
}
SCM_FRAME_VARIABLE (SCM_VM_FRAME_FP (frame), i) = val;
return SCM_UNSPECIFIED;
}
SCM_OUT_OF_RANGE (SCM_ARG2, index);
}
#undef FUNC_NAME

View file

@ -50,21 +50,26 @@
| Program | <- fp - 1
+==================+
| Return address | <- SCM_FRAME_UPPER_ADDRESS (fp)
| MV return address|
| Dynamic link | <- fp - 4 = SCM_FRAME_DATA_ADDRESS (fp) = SCM_FRAME_LOWER_ADDRESS (fp)
| Dynamic link | <- fp - 3 = SCM_FRAME_DATA_ADDRESS (fp) = SCM_FRAME_LOWER_ADDRESS (fp)
+==================+
| |
As can be inferred from this drawing, it is assumed that
`sizeof (SCM *) == sizeof (SCM)', since pointers (the `link' parts) are
assumed to be as long as SCM objects. */
assumed to be as long as SCM objects.
When a program returns multiple values, it will shuffle them down to
start contiguously from slot 1, as for a tail call. This means that
when the caller goes to access them, there are 2 or 3 empty words
between the top of the caller stack and the bottom of the values,
corresponding to the frame that was just popped.
*/
/* This structure maps to the contents of a VM stack frame. It can
alias a frame directly. */
struct scm_vm_frame
{
SCM *dynamic_link;
scm_t_uint8 *mv_return_address;
scm_t_uint8 *return_address;
SCM program;
SCM stack[1]; /* Variable-length */
@ -73,7 +78,7 @@ struct scm_vm_frame
#define SCM_FRAME_STRUCT(fp) \
((struct scm_vm_frame *) SCM_FRAME_DATA_ADDRESS (fp))
#define SCM_FRAME_DATA_ADDRESS(fp) (((SCM *) (fp)) - 4)
#define SCM_FRAME_DATA_ADDRESS(fp) (((SCM *) (fp)) - 3)
#define SCM_FRAME_STACK_ADDRESS(fp) (SCM_FRAME_STRUCT (fp)->stack)
#define SCM_FRAME_UPPER_ADDRESS(fp) ((SCM*)&SCM_FRAME_STRUCT (fp)->return_address)
#define SCM_FRAME_LOWER_ADDRESS(fp) ((SCM*)SCM_FRAME_STRUCT (fp))
@ -85,8 +90,6 @@ struct scm_vm_frame
(SCM_FRAME_STRUCT (fp)->return_address)
#define SCM_FRAME_SET_RETURN_ADDRESS(fp, ra) \
SCM_FRAME_STRUCT (fp)->return_address = (ra)
#define SCM_FRAME_SET_MV_RETURN_ADDRESS(fp, mvra) \
SCM_FRAME_STRUCT (fp)->mv_return_address = (mvra)
#define SCM_FRAME_DYNAMIC_LINK(fp) \
(SCM_FRAME_STRUCT (fp)->dynamic_link)
#define SCM_FRAME_SET_DYNAMIC_LINK(fp, dl) \
@ -97,34 +100,13 @@ struct scm_vm_frame
(SCM_FRAME_STRUCT (fp)->program)
/*
* RTL frames
*/
/* The frame format for the new RTL programs is almost like that for the
stack-vm programs. They differ in their handling of MV returns,
however. For RTL, every call is an MV call: every call has an MVRA.
Unlike the stack-vm programs, the MVRA for RTL programs is computable
from the RA -- it's always one word (4 bytes) before the RA.
Until we completely migrate to the RTL VM, we will also write the
MVRA to the stack.
When an RTL program returns multiple values, it will shuffle them
down to start contiguously from slot 0, as for a tail call. This
means that when the caller goes to access them, there are 2 or 3
empty words between the top of the caller stack and the bottom of the
values, corresponding to the frame that was just popped.
*/
/* FIXME: Replace SCM_FRAME_RETURN_ADDRESS with these. */
#define SCM_FRAME_RTL_RETURN_ADDRESS(fp) \
((scm_t_uint32 *) SCM_FRAME_RETURN_ADDRESS (fp))
#define SCM_FRAME_SET_RTL_RETURN_ADDRESS(fp, ip) \
SCM_FRAME_SET_RETURN_ADDRESS (fp, (scm_t_uint8 *) (ip))
#define SCM_FRAME_SET_RTL_MV_RETURN_ADDRESS(fp, ip) \
SCM_FRAME_SET_MV_RETURN_ADDRESS (fp, (scm_t_uint8 *) (ip))
/*
* Heap frames

View file

@ -142,12 +142,12 @@
/* Reserve stack space for a frame. Will check that there is sufficient
stack space for N locals, including the procedure, in addition to
3 words to set up the next frame. Invoke after preparing the new
2 words to set up the next frame. Invoke after preparing the new
frame and setting the fp and ip. */
#define ALLOC_FRAME(n) \
do { \
SCM *new_sp = vp->sp = fp - 1 + n - 1; \
CHECK_OVERFLOW (new_sp + 4); \
CHECK_OVERFLOW (new_sp + 3); \
} while (0)
/* Reset the current frame to hold N locals. Used when we know that no
@ -229,10 +229,9 @@
/* Clear frame. */ \
sp[0] = SCM_BOOL_F; \
sp[1] = SCM_BOOL_F; \
sp[2] = SCM_BOOL_F; \
/* Leave proc. */ \
sp[4] = val; \
vp->sp = sp + 4; \
sp[3] = val; \
vp->sp = sp + 3; \
POP_CONTINUATION_HOOK (sp, 1); \
NEXT (0); \
} while (0)
@ -446,11 +445,11 @@ RTL_VM_NAME (SCM vm, SCM program, SCM *argv, size_t nargs_)
{
SCM *base;
/* Check that we have enough space: 4 words for the boot
continuation, 4 + nargs for the procedure application, and 4 for
/* Check that we have enough space: 3 words for the boot
continuation, 3 + nargs for the procedure application, and 3 for
setting up a new frame. */
base = vp->sp + 1;
CHECK_OVERFLOW (vp->sp + 4 + 4 + nargs_ + 4);
CHECK_OVERFLOW (vp->sp + 3 + 3 + nargs_ + 3);
/* Since it's possible to receive the arguments on the stack itself,
and indeed the regular VM invokes us that way, shuffle up the
@ -458,24 +457,22 @@ RTL_VM_NAME (SCM vm, SCM program, SCM *argv, size_t nargs_)
{
int i;
for (i = nargs_ - 1; i >= 0; i--)
base[8 + i] = argv[i];
base[6 + i] = argv[i];
}
/* Initial frame, saving previous fp and ip, with the boot
continuation. */
base[0] = SCM_PACK (fp); /* dynamic link */
base[1] = SCM_PACK (0); /* the boot continuation does not return to scheme */
base[2] = SCM_PACK (ip); /* ra */
base[3] = rtl_boot_continuation;
fp = &base[4];
base[1] = SCM_PACK (ip); /* ra */
base[2] = rtl_boot_continuation;
fp = &base[3];
ip = (scm_t_uint32 *) rtl_boot_continuation_code;
/* MV-call frame, function & arguments */
base[4] = SCM_PACK (fp); /* dynamic link */
base[5] = SCM_PACK (ip); /* in RTL programs, MVRA same as RA */
base[6] = SCM_PACK (ip); /* ra */
base[7] = program;
fp = vp->fp = &base[8];
base[3] = SCM_PACK (fp); /* dynamic link */
base[4] = SCM_PACK (ip); /* ra */
base[5] = program;
fp = vp->fp = &base[6];
RESET_FRAME (nargs_ + 1);
}
@ -525,20 +522,20 @@ RTL_VM_NAME (SCM vm, SCM program, SCM *argv, size_t nargs_)
*/
VM_DEFINE_OP (0, halt, "halt", OP1 (U8_X24))
{
scm_t_uint32 nvals = FRAME_LOCALS_COUNT() - 5;
scm_t_uint32 nvals = FRAME_LOCALS_COUNT() - 4;
SCM ret;
/* Boot closure in r0, empty frame in r1/r2/r3, proc in r4, values from r5. */
/* Boot closure in r0, empty frame in r1/r2, proc in r3, values from r4. */
if (nvals == 1)
ret = LOCAL_REF (5);
ret = LOCAL_REF (4);
else
{
scm_t_uint32 n;
ret = SCM_EOL;
SYNC_BEFORE_GC();
for (n = nvals; n > 0; n--)
ret = scm_cons (LOCAL_REF (5 + n - 1), ret);
ret = scm_cons (LOCAL_REF (4 + n - 1), ret);
ret = scm_values (ret);
}
@ -574,7 +571,6 @@ RTL_VM_NAME (SCM vm, SCM program, SCM *argv, size_t nargs_)
fp = vp->fp = old_fp + proc;
SCM_FRAME_SET_DYNAMIC_LINK (fp, old_fp);
SCM_FRAME_SET_RTL_MV_RETURN_ADDRESS (fp, 0);
SCM_FRAME_SET_RTL_RETURN_ADDRESS (fp, ip + 2);
RESET_FRAME (nlocals);
@ -717,7 +713,6 @@ RTL_VM_NAME (SCM vm, SCM program, SCM *argv, size_t nargs_)
/* Clear stack frame. */
base[-2] = SCM_BOOL_F;
base[-3] = SCM_BOOL_F;
base[-4] = SCM_BOOL_F;
POP_CONTINUATION_HOOK (base, nvalues);

View file

@ -144,7 +144,7 @@ vm_return_to_continuation (SCM vm, SCM cont, size_t n, SCM *argv)
vp = SCM_VM_DATA (vm);
cp = SCM_VM_CONT_DATA (cont);
if (vp->stack_size < cp->stack_size + n + 4)
if (vp->stack_size < cp->stack_size + n + 3)
scm_misc_error ("vm-engine", "not enough space to reinstate continuation",
scm_list_2 (vm, cont));
@ -165,7 +165,7 @@ vm_return_to_continuation (SCM vm, SCM cont, size_t n, SCM *argv)
size_t i;
/* Push on an empty frame, as the continuation expects. */
for (i = 0; i < 4; i++)
for (i = 0; i < 3; i++)
{
vp->sp++;
*vp->sp = SCM_BOOL_F;

View file

@ -258,7 +258,7 @@ are comparable with eqv?. A tmp slot may be used."
(find-first-zero live-slots)))
(define (compute-call-proc-slot live-slots)
(+ 3 (find-first-trailing-zero live-slots)))
(+ 2 (find-first-trailing-zero live-slots)))
(define (compute-prompt-handler-proc-slot live-slots)
(1- (find-first-trailing-zero live-slots)))

View file

@ -701,11 +701,9 @@ returned instead."
;(define-tc7-macro-assembler br-if-fluid 37)
;(define-tc7-macro-assembler br-if-dynamic-state 45)
;(define-tc7-macro-assembler br-if-frame 47)
;(define-tc7-macro-assembler br-if-objcode 53)
;(define-tc7-macro-assembler br-if-vm 55)
;(define-tc7-macro-assembler br-if-vm-cont 71)
;(define-tc7-macro-assembler br-if-rtl-program 69)
;(define-tc7-macro-assembler br-if-program 79)
;(define-tc7-macro-assembler br-if-weak-set 85)
;(define-tc7-macro-assembler br-if-weak-table 87)
;(define-tc7-macro-assembler br-if-array 93)
@ -1202,7 +1200,7 @@ needed."
;; FIXME: Define these somewhere central, shared with C.
(define *bytecode-major-version* #x0202)
(define *bytecode-minor-version* 2)
(define *bytecode-minor-version* 3)
(define (link-dynamic-section asm text rw rw-init)
"Link the dynamic section for an ELF image with RTL text, given the