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 "