{ \
SYNC_IP (); \
exp; \
+ CACHE_FP (); \
} \
} while (0)
#else
RUN_HOOK0 (restore_continuation)
#define VM_HANDLE_INTERRUPTS \
- SCM_ASYNC_TICK_WITH_CODE (current_thread, SYNC_IP ())
+ SCM_ASYNC_TICK_WITH_GUARD_CODE (current_thread, SYNC_IP (), CACHE_FP ())
/* Virtual Machine
whenever we would need to know the IP of the top frame. In practice,
we need to SYNC_IP whenever we call out of the VM to a function that
would like to walk the stack, perhaps as the result of an
- exception. */
+ exception.
+
+ One more thing. We allow the stack to move, when it expands.
+ Therefore if you call out to a C procedure that could call Scheme
+ code, or otherwise push anything on the stack, you will need to
+ CACHE_FP afterwards to restore the possibly-changed FP. */
#define SYNC_IP() vp->ip = (ip)
+#define CACHE_FP() fp = (vp->fp)
+#define CACHE_REGISTER() \
+ do { \
+ ip = vp->ip; \
+ fp = vp->fp; \
+ } while (0)
+
+
/* After advancing vp->sp, but before writing any stack slots, check
that it is actually in bounds. If it is not in bounds, currently we
{ \
SYNC_IP (); \
vm_expand_stack (vp); \
- CACHE_REGISTER (); \
+ CACHE_FP (); \
} \
} while (0)
} while (0)
-#define CACHE_REGISTER() \
- do { \
- ip = vp->ip; \
- fp = vp->fp; \
- } while (0)
-
#ifdef HAVE_LABELS_AS_VALUES
# define BEGIN_DISPATCH_SWITCH /* */
# define END_DISPATCH_SWITCH /* */
#define RETURN_ONE_VALUE(ret) \
do { \
SCM val = ret; \
- SCM *old_fp = fp; \
+ SCM *old_fp; \
VM_HANDLE_INTERRUPTS; \
+ old_fp = fp; \
ip = SCM_FRAME_RETURN_ADDRESS (fp); \
fp = vp->fp = SCM_FRAME_DYNAMIC_LINK (fp); \
/* Clear frame. */ \
SCM res; \
SYNC_IP (); \
res = srel (x, y); \
+ CACHE_FP (); \
if ((ip[1] & 0x1) ? scm_is_false (res) : scm_is_true (res)) \
{ \
scm_t_int32 offset = ip[1]; \
a2 = LOCAL_REF (src2)
#define RETURN(x) \
do { LOCAL_SET (dst, x); NEXT (1); } while (0)
+#define RETURN_EXP(exp) \
+ do { SCM __x; SYNC_IP (); __x = exp; CACHE_FP (); RETURN (__x); } while (0)
/* The maximum/minimum tagged integers. */
#define INUM_MAX \
if (SCM_FIXABLE (n)) \
RETURN (SCM_I_MAKINUM (n)); \
} \
- SYNC_IP (); \
- RETURN (SFUNC (x, y)); \
+ RETURN_EXP (SFUNC (x, y)); \
}
#define VM_VALIDATE_PAIR(x, proc) \
VM_DEFINE_OP (1, call, "call", OP2 (U8_U24, X8_U24))
{
scm_t_uint32 proc, nlocals;
- SCM *old_fp = fp;
+ SCM *old_fp;
UNPACK_24 (op, proc);
UNPACK_24 (ip[1], nlocals);
VM_HANDLE_INTERRUPTS;
+ old_fp = fp;
fp = vp->fp = old_fp + proc;
SCM_FRAME_SET_DYNAMIC_LINK (fp, old_fp);
SCM_FRAME_SET_RETURN_ADDRESS (fp, ip + 2);
*/
VM_DEFINE_OP (7, return_values, "return-values", OP1 (U8_X24))
{
- SCM *old_fp = fp;
+ SCM *old_fp;
VM_HANDLE_INTERRUPTS;
+
+ old_fp = fp;
ip = SCM_FRAME_RETURN_ADDRESS (fp);
fp = vp->fp = SCM_FRAME_DYNAMIC_LINK (fp);
abort ();
}
- // NULLSTACK_FOR_NONLOCAL_EXIT ();
+ CACHE_FP ();
if (SCM_UNLIKELY (SCM_VALUESP (ret)))
/* multiple values returned to continuation */
// FIXME: separate args
ret = scm_i_foreign_call (scm_cons (cif, pointer), LOCAL_ADDRESS (1));
- // NULLSTACK_FOR_NONLOCAL_EXIT ();
+ CACHE_FP ();
if (SCM_UNLIKELY (SCM_VALUESP (ret)))
/* multiple values returned to continuation */
* If the value in A is equal? to the value in B, add OFFSET, a signed
* 24-bit number, to the current instruction pointer.
*/
- // FIXME: should sync_ip before calling out?
+ // FIXME: Should sync_ip before calling out and cache_fp before coming
+ // back! Another reason to remove this opcode!
VM_DEFINE_OP (38, br_if_equal, "br-if-equal", OP2 (U8_U12_U12, B1_X7_L24))
{
BR_BINARY (x, y,
SYNC_IP ();
var = scm_lookup (LOCAL_REF (sym));
+ CACHE_FP ();
if (ip[1] & 0x1)
VM_ASSERT (VARIABLE_BOUNDP (var),
vm_error_unbound (fp[0], LOCAL_REF (sym)));
UNPACK_12_12 (op, sym, val);
SYNC_IP ();
scm_define (LOCAL_REF (sym), LOCAL_REF (val));
+ CACHE_FP ();
NEXT (1);
}
mod = scm_the_root_module ();
var = scm_module_lookup (mod, sym);
+ CACHE_FP ();
if (ip[4] & 0x1)
VM_ASSERT (VARIABLE_BOUNDP (var), vm_error_unbound (fp[0], sym));
else
var = scm_private_lookup (SCM_CDR (modname), sym);
+ CACHE_FP ();
+
if (ip[4] & 0x1)
VM_ASSERT (VARIABLE_BOUNDP (var), vm_error_unbound (fp[0], sym));
RETURN (result);
}
- SYNC_IP ();
- RETURN (scm_sum (x, SCM_I_MAKINUM (1)));
+ RETURN_EXP (scm_sum (x, SCM_I_MAKINUM (1)));
}
/* sub dst:8 a:8 b:8
RETURN (result);
}
- SYNC_IP ();
- RETURN (scm_difference (x, SCM_I_MAKINUM (1)));
+ RETURN_EXP (scm_difference (x, SCM_I_MAKINUM (1)));
}
/* mul dst:8 a:8 b:8
VM_DEFINE_OP (83, mul, "mul", OP1 (U8_U8_U8_U8) | OP_DST)
{
ARGS2 (x, y);
- SYNC_IP ();
- RETURN (scm_product (x, y));
+ RETURN_EXP (scm_product (x, y));
}
/* div dst:8 a:8 b:8
VM_DEFINE_OP (84, div, "div", OP1 (U8_U8_U8_U8) | OP_DST)
{
ARGS2 (x, y);
- SYNC_IP ();
- RETURN (scm_divide (x, y));
+ RETURN_EXP (scm_divide (x, y));
}
/* quo dst:8 a:8 b:8
VM_DEFINE_OP (85, quo, "quo", OP1 (U8_U8_U8_U8) | OP_DST)
{
ARGS2 (x, y);
- SYNC_IP ();
- RETURN (scm_quotient (x, y));
+ RETURN_EXP (scm_quotient (x, y));
}
/* rem dst:8 a:8 b:8
VM_DEFINE_OP (86, rem, "rem", OP1 (U8_U8_U8_U8) | OP_DST)
{
ARGS2 (x, y);
- SYNC_IP ();
- RETURN (scm_remainder (x, y));
+ RETURN_EXP (scm_remainder (x, y));
}
/* mod dst:8 a:8 b:8
VM_DEFINE_OP (87, mod, "mod", OP1 (U8_U8_U8_U8) | OP_DST)
{
ARGS2 (x, y);
- SYNC_IP ();
- RETURN (scm_modulo (x, y));
+ RETURN_EXP (scm_modulo (x, y));
}
/* ash dst:8 a:8 b:8
}
/* fall through */
}
- SYNC_IP ();
- RETURN (scm_ash (x, y));
+ RETURN_EXP (scm_ash (x, y));
}
/* logand dst:8 a:8 b:8
if (SCM_I_INUMP (x) && SCM_I_INUMP (y))
/* Compute bitwise AND without untagging */
RETURN (SCM_PACK (SCM_UNPACK (x) & SCM_UNPACK (y)));
- SYNC_IP ();
- RETURN (scm_logand (x, y));
+ RETURN_EXP (scm_logand (x, y));
}
/* logior dst:8 a:8 b:8
if (SCM_I_INUMP (x) && SCM_I_INUMP (y))
/* Compute bitwise OR without untagging */
RETURN (SCM_PACK (SCM_UNPACK (x) | SCM_UNPACK (y)));
- SYNC_IP ();
- RETURN (scm_logior (x, y));
+ RETURN_EXP (scm_logior (x, y));
}
/* logxor dst:8 a:8 b:8
ARGS2 (x, y);
if (SCM_I_INUMP (x) && SCM_I_INUMP (y))
RETURN (SCM_I_MAKINUM (SCM_I_INUM (x) ^ SCM_I_INUM (y)));
- SYNC_IP ();
- RETURN (scm_logxor (x, y));
+ RETURN_EXP (scm_logxor (x, y));
}
/* make-vector/immediate dst:8 length:8 init:8