[Quipu-dev] quipu/quipu: Implement continuations by stack switching

Back to archive index

scmno****@osdn***** scmno****@osdn*****
Tue Jun 19 12:57:44 JST 2018


changeset e43e6126839f in quipu/quipu
details: http://hg.osdn.jp/view/quipu/quipu?cmd=changeset;node=e43e6126839f
user: Agustina Arzille <avarz****@riseu*****>
date: Tue Jun 19 03:57:33 2018 +0000
description: Implement continuations by stack switching

diffstat:

 builtins.cpp     |   15 ------
 compiler.cpp     |   11 ++--
 continuation.cpp |  120 ++++++++++++++++++++++++------------------------------
 continuation.h   |    8 +--
 initop.cpp       |    5 +-
 5 files changed, 63 insertions(+), 96 deletions(-)

diffs (257 lines):

diff -r 06a738bc166f -r e43e6126839f builtins.cpp
--- a/builtins.cpp	Mon Jun 18 18:36:06 2018 -0300
+++ b/builtins.cpp	Tue Jun 19 03:57:33 2018 +0000
@@ -1250,21 +1250,6 @@
   qp_return (as_continuation(cn)->value);
 }
 
-DEFBUILTIN (iter_next)
-{
-  if (argc != 1)
-    interp->raise_nargs ("iter-next", 1, 1, argc);
-
-  object cn = *argv;
-  if (!continuation_p (cn))
-    interp->raise2 ("arg-error", "iter-next: argument must be a generator");
-
-  uint32_t sp = interp->stkdiff ();
-  object ret = call_continuation (interp, cn);
-  interp->stkend = interp->stack + sp;
-  qp_return (continuation_p (ret) ? ret : NIL);
-}
-
 DEFBUILTIN (symname_fct)
 {
   if (argc != 1)
diff -r 06a738bc166f -r e43e6126839f compiler.cpp
--- a/compiler.cpp	Mon Jun 18 18:36:06 2018 -0300
+++ b/compiler.cpp	Tue Jun 19 03:57:33 2018 +0000
@@ -2196,7 +2196,7 @@
 
   if (cdp != 0)
     { // Restored from a caught exception.
-      top_frame = cdp->topf;
+      top_frame = cont != UNBOUND ? 0 : cdp->topf;
       nargs = as_int (stack[interp->cur_frame - 3]);
       bp = interp->cur_frame - interpreter::frame_size - nargs;
       fn = stack[bp - 1];
@@ -2206,12 +2206,11 @@
   else if (cont != UNBOUND)
     { // Continuation-passing style.
       continuation *cnp = as_continuation (cont);
-      cnp->push (interp);
-      fn = stack[interp->cur_frame - interpreter::frame_size -
-        as_int (stack[interp->cur_frame - 3]) - 1];
-      set_lastf (interp, fn, lastf);
-      bp = lastf - interpreter::frame_size - as_int (stack[lastf - 3]);
+      lastf = cnp->sframes[0], top_frame = 0;
+      nargs = as_int (stack[lastf - 3]);
+      bp = 1, fn = stack[bp - 1];
       ip = as_bvector(fct_bcode (fn))->data + cnp->ip_offset;
+      *stkend++ = cnp->value;
     }
   else
     { // Regular function call.
diff -r 06a738bc166f -r e43e6126839f continuation.cpp
--- a/continuation.cpp	Mon Jun 18 18:36:06 2018 -0300
+++ b/continuation.cpp	Tue Jun 19 03:57:33 2018 +0000
@@ -10,89 +10,75 @@
 QP_DECLS_BEGIN
 
 static object
-make_argv (interpreter *interp, uint32_t ilastf, int& nframes)
+make_argv (interpreter *interp, uint32_t ilastf, continuation *outp)
 {
   uint32_t start = ilastf - as_int (interp->stack[ilastf - 3]) -
     interpreter::frame_size - 1;
-
-  uint32_t lastf = as_int (interp->stack[ilastf - 4]), nf = 0;
   uint32_t sp = interp->stkdiff ();
 
-  for (uint32_t cf = interp->cur_frame; cf > lastf;
-      cf = as_int (interp->stack[cf - 4]), ++nf) ;
+  outp->sframes[1] = interp->cur_frame - ilastf;
+  uint32_t max_sp = as_fct(interp->stack[start])->max_sp;
 
-  array *ap = as_array (alloc_array (interp, sp - start + nf));
-  copy_objs (ap->data + nf, interp->stack + start, sp - start);
+  array *ap =  as_array (alloc_array (interp,
+    max (sp - start, max_sp), UNBOUND));
+  copy_objs (ap->data, interp->stack + start, sp - start);
 
-  object *offp = ap->data + nf;
-  for (uint32_t cf = interp->cur_frame; cf > lastf;
-      cf = as_int (interp->stack[cf - 4]))
-    *--offp = interp->stack[cf - 3];
+  for (uint32_t cf = interp->cur_frame ; ; )
+    {
+      if (cf == ilastf)
+        {
+          outp->sframes[0] = cf - start;
+          ap->data[cf - start - 4] = intobj (0);
+          break;
+        }
 
-  nframes = (int)nf;
+      uint32_t ipos = cf - start;
+      uint32_t prev = as_int (interp->stack[cf - 4]);
+      ap->data[ipos - 4] = intobj (prev - start);
+      cf = prev;
+    }
+
+  outp->sframes[1] += outp->sframes[0];
   return (ap->as_obj ());
 }
 
-static object
-mark_argv (interpreter *interp, uint32_t ilastf, int *xfp)
+class cont_state
 {
-  uint32_t start = ilastf - as_int (interp->stack[ilastf - 3]) -
-    interpreter::frame_size - 1;
-  uint32_t nf = 0, sp = interp->stkdiff ();
+public:
+  interpreter *interp;
+  object stkobj;
+  uint32_t cf;
+  uint32_t sp;
 
-  ilastf = as_int (interp->stack[ilastf - 4]);
+  cont_state (interpreter *ip) : interp (ip),
+      stkobj (ip->stkobj), cf (ip->cur_frame), sp (ip->stkdiff ()) {}
 
-  for (uint32_t cf = interp->cur_frame; cf > ilastf;
-      cf = as_int (interp->stack[cf - 4]), ++nf) ;
+  ~cont_state ()
+    {
+      this->interp->stkobj = this->stkobj;
+      this->interp->stack = &xaref(this->stkobj, 0);
+      this->interp->stkend = this->interp->stack + this->sp;
+      this->interp->cur_frame = this->cf;
+    }
+};
 
-  array *ap =  as_array (alloc_array (interp, sp - start));
-  copy_objs (ap->data, interp->stack + start, sp - start);
+object iter_next (interpreter *interp, object *argv, int argc)
+{
+  if (argc != 1)
+    interp->raise_nargs ("iter-next", 1, 1, argc);
 
-  QP_TMARK (interp);
-  uint32_t *offp = (uint32_t *)QP_TALLOC (interp, (nf + 1) * sizeof (*offp));
-  offp[nf] = 0;
+  object cn = *argv;
+  if (!continuation_p (cn))
+    interp->raise2 ("arg-error", "iter-next: argument must be a generator");
 
-  for (uint32_t cf = interp->cur_frame; cf > ilastf; --nf)
-    {
-      uint32_t prev = as_int (interp->stack[cf - 4]);
-      offp[nf - 1] = cf - prev;
-      cf = prev;
-    }
-
-  start = 0;
-
-  do
-    {
-      ap->data[*offp++] = start;
-      start += *offp;
-    }
-  while (!*offp);
-
-  *xfp = (int)start;
-  return (ap->as_obj ());
-}
-
-
-void continuation::push (interpreter *interp)
-{
-  array *ap = as_array (this->argv);
-
-  interp->growstk (ap->len - this->nframes +
-    as_fct (ap->data[this->nframes])->max_sp);
-  copy_objs (interp->stkend, ap->data +
-    this->nframes, ap->len - this->nframes);
-
-  uint32_t nsp = interp->stkdiff ();
-  for (int i = 0; i < this->nframes; ++i)
-    {
-      nsp += as_int (ap->data[i]) + interpreter::frame_size + 1;
-      interp->stack[nsp - 4] = intobj (interp->cur_frame);
-      interp->cur_frame = nsp;
-    }
-
-  interp->stkend = interp->stack + nsp + this->sp_diff;
-  interp->stkend += this->sp_diff;
-  interp->push (this->value);
+  cont_state state (interp);
+  continuation *cnp = as_continuation (cn);
+  interp->stkobj = cnp->argv;
+  interp->stack = &xaref(interp->stkobj, 0);
+  interp->cur_frame = cnp->sframes[1];
+  interp->stkend = interp->stack + interp->cur_frame + cnp->sp_diff;
+  object ret = call_continuation (interp, cn);
+  qp_return (continuation_p (ret) ? ret : NIL);
 }
 
 continuation* continuation::alloc_raw ()
@@ -118,7 +104,7 @@
   continuation *ret = alloc_raw ();
   ret->value = UNBOUND;
 
-  ret->argv = make_argv (interp, lastf, ret->nframes);
+  ret->argv = make_argv (interp, lastf, ret);
   interp->alval = ret->as_obj ();
   gcregister (interp, ret);
   return (interp->alval);
diff -r 06a738bc166f -r e43e6126839f continuation.h
--- a/continuation.h	Mon Jun 18 18:36:06 2018 -0300
+++ b/continuation.h	Tue Jun 19 03:57:33 2018 +0000
@@ -9,17 +9,13 @@
 {
 public:
   static continuation* alloc_raw ();
-
   static object make (interpreter *__interp, uint32_t __lastf);
 
-  void push (interpreter *__interp);
-
   object value;
   object argv;
   int ip_offset;
-  int nframes;
   int sp_diff;
-  int xframe;
+  uint32_t sframes[2];
 };
 
 inline bool continuation_p (object __obj)
@@ -36,6 +32,8 @@
 
 QP_EXPORT object call_continuation (interpreter *__interp, object __cont);
 
+QP_EXPORT object iter_next (interpreter *__interp, object *__argv, int __argc);
+
 class stream;
 class io_info;
 
diff -r 06a738bc166f -r e43e6126839f initop.cpp
--- a/initop.cpp	Mon Jun 18 18:36:06 2018 -0300
+++ b/initop.cpp	Tue Jun 19 03:57:33 2018 +0000
@@ -38,12 +38,11 @@
 
 bool init_op_list::call (interpreter *interp)
 {
-  int ret = init_op::result_ok;
-
   for (int i = 0; i < this->nops; ++i)
     {
       init_op *op = this->ops[i];
-      ret = op->call (interp);
+      int ret = op->call (interp);
+
       if (ret == init_op::result_circular)
         {
           fprintf (stderr, "Circular dependency detected "




More information about the Quipu-dev mailing list
Back to archive index