summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndy Wingo <wingo@pobox.com>2011-03-15 23:33:32 +0100
committerAndy Wingo <wingo@pobox.com>2011-03-15 23:45:58 +0100
commit9b709b0fe1ec5a71903e07d21006441d15e0c1ed (patch)
tree21ba9462ce57a01a57e5c7ab9a2d167a5fd299ef
parent958173e489c69b2f9e3c83752713a89e3ea3e79d (diff)
downloadguile-9b709b0fe1ec5a71903e07d21006441d15e0c1ed.tar.gz
fix frame dynamic linkage in the face of partial continuation application
* libguile/vm-i-system.c (new-frame): Though it was appealing to set the dynamic link here on the incomplete frame, we no longer do that, for the reasons mentioned in the code. (call, mv-call): Adapt to set the frame's dynamic link. * libguile/vm-engine.c (vm_engine): Don't set dynamic link here, even for boot program. * libguile/frames.c (scm_frame_num_locals, scm_frame_local_ref) (scm_frame_local_set_x): Fix up not-yet-active frame detection.
-rw-r--r--libguile/frames.c6
-rw-r--r--libguile/vm-engine.c2
-rw-r--r--libguile/vm-i-system.c49
3 files changed, 40 insertions, 17 deletions
diff --git a/libguile/frames.c b/libguile/frames.c
index bc1bb82a8..62ba23fff 100644
--- a/libguile/frames.c
+++ b/libguile/frames.c
@@ -124,7 +124,7 @@ SCM_DEFINE (scm_frame_num_locals, "frame-num-locals", 1, 0, 0,
p = SCM_FRAME_STACK_ADDRESS (SCM_VM_FRAME_FP (frame));
while (p <= sp)
{
- if (p + 1 < sp && p[1] == (SCM)0)
+ if (p[0] == (SCM)0)
/* skip over not-yet-active frame */
p += 3;
else
@@ -154,7 +154,7 @@ SCM_DEFINE (scm_frame_local_ref, "frame-local-ref", 2, 0, 0,
p = SCM_FRAME_STACK_ADDRESS (SCM_VM_FRAME_FP (frame));
while (p <= sp)
{
- if (p + 1 < sp && p[1] == (SCM)0)
+ if (p[0] == (SCM)0)
/* skip over not-yet-active frame */
p += 3;
else if (n == i)
@@ -186,7 +186,7 @@ SCM_DEFINE (scm_frame_local_set_x, "frame-local-set!", 3, 0, 0,
p = SCM_FRAME_STACK_ADDRESS (SCM_VM_FRAME_FP (frame));
while (p <= sp)
{
- if (p + 1 < sp && p[1] == (SCM)0)
+ if (p[0] == (SCM)0)
/* skip over not-yet-active frame */
p += 3;
else if (n == i)
diff --git a/libguile/vm-engine.c b/libguile/vm-engine.c
index 20d9ed2c8..4b0ca3ec3 100644
--- a/libguile/vm-engine.c
+++ b/libguile/vm-engine.c
@@ -93,7 +93,7 @@ VM_NAME (SCM vm, SCM program, SCM *argv, int nargs)
fp = sp + 1;
ip = SCM_C_OBJCODE_BASE (bp);
/* MV-call frame, function & arguments */
- PUSH ((SCM)fp); /* dynamic link */
+ PUSH (0); /* dynamic link */
PUSH (0); /* mvra */
PUSH (0); /* ra */
PUSH (prog);
diff --git a/libguile/vm-i-system.c b/libguile/vm-i-system.c
index 57712cabd..980d22afe 100644
--- a/libguile/vm-i-system.c
+++ b/libguile/vm-i-system.c
@@ -756,9 +756,14 @@ VM_DEFINE_INSTRUCTION (52, new_frame, "new-frame", 0, 0, 3)
{
/* NB: if you change this, see frames.c:vm-frame-num-locals */
/* and frames.h, vm-engine.c, etc of course */
- PUSH ((SCM)fp); /* dynamic link */
- PUSH (0); /* mvra */
- PUSH (0); /* ra */
+
+ /* We don't initialize the dynamic link here because we don't actually
+ know that this frame will point to the current fp: it could be
+ placed elsewhere on the stack if captured in a partial
+ continuation, and invoked from some other context. */
+ PUSH (0); /* dynamic link */
+ PUSH (0); /* mvra */
+ PUSH (0); /* ra */
NEXT;
}
@@ -790,11 +795,20 @@ VM_DEFINE_INSTRUCTION (53, call, "call", 1, -1, 1)
}
CACHE_PROGRAM ();
- fp = sp - nargs + 1;
- ASSERT (SCM_FRAME_RETURN_ADDRESS (fp) == 0);
- ASSERT (SCM_FRAME_MV_RETURN_ADDRESS (fp) == 0);
- SCM_FRAME_SET_RETURN_ADDRESS (fp, ip);
- SCM_FRAME_SET_MV_RETURN_ADDRESS (fp, 0);
+
+ {
+ SCM *old_fp = fp;
+
+ fp = sp - nargs + 1;
+
+ ASSERT (SCM_FRAME_DYNAMIC_LINK (fp) == 0);
+ ASSERT (SCM_FRAME_RETURN_ADDRESS (fp) == 0);
+ ASSERT (SCM_FRAME_MV_RETURN_ADDRESS (fp) == 0);
+ SCM_FRAME_SET_DYNAMIC_LINK (fp, old_fp);
+ SCM_FRAME_SET_RETURN_ADDRESS (fp, ip);
+ SCM_FRAME_SET_MV_RETURN_ADDRESS (fp, 0);
+ }
+
ip = SCM_C_OBJCODE_BASE (bp);
PUSH_CONTINUATION_HOOK ();
APPLY_HOOK ();
@@ -1091,11 +1105,20 @@ VM_DEFINE_INSTRUCTION (62, mv_call, "mv-call", 4, -1, 1)
}
CACHE_PROGRAM ();
- fp = sp - nargs + 1;
- ASSERT (SCM_FRAME_RETURN_ADDRESS (fp) == 0);
- ASSERT (SCM_FRAME_MV_RETURN_ADDRESS (fp) == 0);
- SCM_FRAME_SET_RETURN_ADDRESS (fp, ip);
- SCM_FRAME_SET_MV_RETURN_ADDRESS (fp, mvra);
+
+ {
+ SCM *old_fp = fp;
+
+ fp = sp - nargs + 1;
+
+ ASSERT (SCM_FRAME_DYNAMIC_LINK (fp) == 0);
+ ASSERT (SCM_FRAME_RETURN_ADDRESS (fp) == 0);
+ ASSERT (SCM_FRAME_MV_RETURN_ADDRESS (fp) == 0);
+ SCM_FRAME_SET_DYNAMIC_LINK (fp, old_fp);
+ SCM_FRAME_SET_RETURN_ADDRESS (fp, ip);
+ SCM_FRAME_SET_MV_RETURN_ADDRESS (fp, mvra);
+ }
+
ip = SCM_C_OBJCODE_BASE (bp);
PUSH_CONTINUATION_HOOK ();
APPLY_HOOK ();