# New Ticket Created by  Leopold Toetsch 
# Please include the string:  [perl #22745]
# in the subject line of all future correspondence about this issue. 
# <URL: http://rt.perl.org/rt2/Ticket/Display.html?id=22745 >


Attached is a first try to unify the various sub types, structures and 
classes.

- sub, continuation and coroutine have the same structure now
- Contination and Coroutine are subclasses of Sub
- stack_destroy() is new

The major change in the functionality of subroutine calls now is:
- on creating a Sub it gets its own pad_stack with the current lex_pad 
pushed on it (if any)
- on invoke, this pad_stack is placed as the interpreter's pad_stack
This is the same behavior as a coroutined did and does.

I'm not totally sure, if we should create a new pad_stack. OTOH, on very 
deeply nested subroutine calls, the return continuation would have COW 
copies of this stack. When there is a new_pad opcode, the stack of the 
subroutine would be copied then, which would be more expensive for 
deeper sub call depths.
We might also reduce the STACK_CHUNK_DEPTH, which currently is 256.

Still remaining questions are:
- do we want a Sub class that supports the old invoke/ret scheme?
   (and how should the class be named?)
- do we want a new Sublite class (as proposed by Jonathan), that doesn't 
   have its own pad_stack for non closures
(and how should the class be named?)

- can we toss CSub and related functions in method_utils?

Comments welcome,
leo


-- attachment  1 ------------------------------------------------------
url: http://rt.perl.org/rt2/attach/59625/44168/975abe/parrot-subs.patch

--- parrot/classes/continuation.pmc     Fri Jun  6 17:15:39 2003
+++ parrot-leo/classes/continuation.pmc Fri Jun 20 10:55:12 2003
@@ -14,7 +14,7 @@
 #include "parrot/parrot.h"
 #include "parrot/method_util.h"
 
-pmclass Continuation {
+pmclass Continuation extends Sub {
 
     void init () {
         struct Parrot_Continuation * cc;
@@ -27,10 +27,6 @@
         mem_sys_free(PMC_data(SELF));
     }
 
-    void set_integer_native (INTVAL value) {
-        ((struct Parrot_Continuation *)PMC_data(SELF))->continuation
-            = (opcode_t *)value;
-    }
 
     void mark () {
         mark_stack(
@@ -63,32 +59,10 @@
         stack_mark_cow(retc->ctx.control_stack);
     }
 
-    PMC* get_pmc () {
-        return SELF;
-    }
-
-    INTVAL is_same (PMC* value) {
-        return SELF == value;
-    }
-
-    void set_same (PMC* value) {
-        PMC_data(SELF) = PMC_data(value);
-    }
-
-    INTVAL is_equal (PMC* value) {
-        return (SELF->vtable == value->vtable
-                && memcmp(PMC_data(value), PMC_data(SELF),
-                          sizeof(struct Parrot_Continuation)) == 0);
-    }
-
-    INTVAL defined () {
-        return ((struct Parrot_Continuation *)PMC_data(SELF))->continuation != NULL;
-    }
-
     void* invoke (void* next) {
         struct Parrot_Continuation * cc
             = (struct Parrot_Continuation*)PMC_data(SELF);
         restore_context(interpreter, &cc->ctx);
-        return cc->continuation; /* interp will jump to this address */
+        return cc->address; /* interp will jump to this address */
     }
 }
--- parrot/classes/coroutine.pmc        Fri Jun  6 17:15:39 2003
+++ parrot-leo/classes/coroutine.pmc    Fri Jun 20 11:51:15 2003
@@ -14,11 +14,7 @@
 #include "parrot/parrot.h"
 #include "parrot/method_util.h"
 
-pmclass Coroutine {
-
-    INTVAL type () {
-        return enum_class_Coroutine;
-    }
+pmclass Coroutine extends Sub {
 
     STRING* name () {
         return whoami;
@@ -30,68 +26,29 @@
     }
 
     void destroy () {
-       /* XXX stack_destroy for deeper stacks */
-       mem_sys_free(((struct Parrot_Coroutine *)PMC_data(SELF))->ctx.user_stack);
-       mem_sys_free(((struct Parrot_Coroutine *)PMC_data(SELF))->ctx.control_stack);
+       struct Parrot_Coroutine * co =
+           (struct Parrot_Coroutine *)PMC_data(SELF);
+       stack_destroy(co->ctx.pad_stack);
+       stack_destroy(co->ctx.control_stack);
+       stack_destroy(co->ctx.user_stack);
         mem_sys_free(PMC_data(SELF));
     }
 
     void mark () {
-        struct Parrot_Coroutine * co = (struct Parrot_Coroutine *)PMC_data(SELF);
+        struct Parrot_Coroutine * co =
+           (struct Parrot_Coroutine *)PMC_data(SELF);
         mark_stack(INTERP, co->ctx.user_stack);
         mark_stack(INTERP, co->ctx.control_stack);
         mark_stack(INTERP, co->ctx.pad_stack);
     }
 
-    void set_integer (PMC * value) {
-        ((struct Parrot_Coroutine*)PMC_data(SELF))->resume
-            = (opcode_t*)VTABLE_get_integer(INTERP, value);
-    }
-
-    void set_integer_native (INTVAL value) {
-        ((struct Parrot_Coroutine*)PMC_data(SELF))->resume = (opcode_t*)value;
-    }
-
-    PMC* get_pmc () {
-        return SELF;
-    }
-
-    INTVAL is_same (PMC* value) {
-        return SELF == value;
-    }
 
-    INTVAL is_equal (PMC* value) {
-        return (SELF->vtable == value->vtable
-                && memcmp(PMC_data(value), PMC_data(SELF),
-                          sizeof(struct Parrot_Coroutine)) == 0);
-    }
-
-    INTVAL defined () {
-        return ((struct Parrot_Coroutine*)PMC_data(SELF))->resume != NULL;
-    }
 
     void* invoke (void* next) {
         struct Parrot_Coroutine* co = (struct Parrot_Coroutine*)PMC_data(SELF);
-        struct Stack_Chunk * tmp_stack = NULL;
-        void * dest = co->resume;
-        co->resume = (opcode_t *)next;
-
-       /*
-         * Swap control, user and pad stacks. Data in other parts of the
-         * context are not preserved between calls to the coroutine.
-         */
-
-        tmp_stack = INTERP->ctx.user_stack;
-        INTERP->ctx.user_stack = co->ctx.user_stack;
-        co->ctx.user_stack = tmp_stack;
-
-        tmp_stack = INTERP->ctx.control_stack;
-        INTERP->ctx.control_stack = co->ctx.control_stack;
-        co->ctx.control_stack = tmp_stack;
-
-        tmp_stack = INTERP->ctx.pad_stack;
-        INTERP->ctx.pad_stack = co->ctx.pad_stack;
-        co->ctx.pad_stack = tmp_stack;
+        void * dest = co->address;
+        co->address = (opcode_t *)next;
+       swap_context(interpreter, &co->ctx);
 
         return dest;
     }
--- parrot/classes/eval.pmc     Fri Jun  6 17:15:39 2003
+++ parrot-leo/classes/eval.pmc Fri Jun 20 11:00:08 2003
@@ -23,17 +23,9 @@
    }
 
    void* invoke (void* next) {
-       PMC * pad = ((struct Parrot_Sub *)PMC_data(SELF))->lex_pad;
        struct PackFile_ByteCode *old_cs;
        struct PackFile_ByteCode *eval_cs = (struct PackFile_ByteCode *)
-          ((struct Parrot_Sub *)PMC_data(SELF))->init;
-
-       if (pad) {
-          /* put the correct pad in place
-           * XXX leo: do we need this? */
-          stack_push(INTERP, &INTERP->ctx.pad_stack, pad,
-                  STACK_ENTRY_PMC, STACK_CLEANUP_NULL);
-       }
+          SUPER(next); /* invoke on Sub returns the address */
 
        /* return address that the interpreter should jump to */
        stack_push(INTERP, &(INTERP->ctx.control_stack), next,
@@ -49,9 +41,9 @@
           PIO_eprintf(interpreter, "*** back from %s\n",
                   eval_cs->base.name);
        }
-       if (pad)
-           stack_pop(interpreter, &interpreter->ctx.pad_stack,
-               NULL, STACK_ENTRY_PMC);
+       /* restore ctx */
+       interpreter->ctx.pad_stack =
+              ((struct Parrot_Sub*) PMC_data(SELF))->ctx.pad_stack;
        /* if code jumped to different code segment, go out of runloop
        * which then actually will switch segments */
        if (interpreter->resume_flag & 2)
--- parrot/classes/sub.pmc      Wed Jun 18 16:47:55 2003
+++ parrot-leo/classes/sub.pmc  Fri Jun 20 11:47:24 2003
@@ -12,6 +12,7 @@
  */
 
 #include "parrot/parrot.h"
+#include "parrot/method_util.h"
 
 pmclass Sub {
 
@@ -20,48 +21,57 @@
    }
 
    void init () {
-       INTVAL address = 0; /* XXX this was originally passed as a
-                            * parameter, but that's not valid.  So
-                            * this is totally broken now. */
-       PMC_data(SELF) = new_sub(INTERP, (opcode_t*)address);
+       PMC_data(SELF) = new_sub(INTERP, (opcode_t*)0);
        PObj_custom_mark_destroy_SETALL(SELF);
    }
 
    void mark () {
-       PMC * pad = ((struct Parrot_Sub *)PMC_data(SELF))->lex_pad;
-       if (pad) {
-           pobject_lives(INTERP, (PObj *)pad);
-       }
+        struct Parrot_Sub * sub = (struct Parrot_Sub *)PMC_data(SELF);
+        mark_stack(INTERP, sub->ctx.pad_stack);
    }
 
    void destroy () {
-       mem_sys_free(PMC_data(SELF));
+       struct Parrot_Sub * sub = (struct Parrot_Sub *)PMC_data(SELF);
+       stack_destroy(sub->ctx.pad_stack);
+       mem_sys_free(sub);
    }
 
    void set_integer (PMC * value) {
-       ((struct Parrot_Sub*)PMC_data(SELF))->init = 
(opcode_t*)VTABLE_get_integer(INTERP, value);
+       ((struct Parrot_Sub*)PMC_data(SELF))->address =
+              (opcode_t*)VTABLE_get_integer(INTERP, value);
    }
 
    void set_integer_native (INTVAL value) {
-       ((struct Parrot_Sub*)PMC_data(SELF))->init = (opcode_t*)value;
+       ((struct Parrot_Sub*)PMC_data(SELF))->address = (opcode_t*)value;
    }
 
-   void* invoke (void* next) {
-       PMC * pad = ((struct Parrot_Sub *)PMC_data(SELF))->lex_pad;
-
-       if (pad) {
-           /* put the correct pad in place */
-           stack_push(INTERP, &INTERP->ctx.pad_stack, pad,
-                      STACK_ENTRY_PMC, STACK_CLEANUP_NULL);
+   INTVAL defined () {
+       return ((struct Parrot_Sub*)PMC_data(SELF))->address != NULL;
        }
 
-       return ((struct Parrot_Sub*)PMC_data(SELF))->init;
+   void* invoke (void* next) {
+       struct Parrot_Sub * sub = (struct Parrot_Sub *)PMC_data(SELF);
+       INTERP->ctx.pad_stack = sub->ctx.pad_stack;
+
+       return sub->address;
    }
 
    void clone (PMC *ret) {
+       struct Parrot_Sub * sub;
         PObj_custom_mark_destroy_SETALL(ret);
-       PMC_data(ret) = mem_sys_allocate(sizeof(struct Parrot_Sub));
-       memcpy(PMC_data(ret), PMC_data(SELF), sizeof(struct Parrot_Sub));
+       sub = PMC_data(ret) = mem_sys_allocate(sizeof(struct Parrot_Sub));
+       memcpy(sub, PMC_data(SELF), sizeof(struct Parrot_Sub));
+       stack_mark_cow(sub->ctx.pad_stack);
+   }
+
+    void set_same (PMC* value) {
+        PMC_data(SELF) = PMC_data(value);
+    }
+
+    INTVAL is_equal (PMC* value) {
+        return (SELF->vtable == value->vtable
+                && memcmp(PMC_data(value), PMC_data(SELF),
+                          sizeof(struct Parrot_Sub)) == 0);
    }
 
 }
--- parrot/include/parrot/stacks.h      Fri Jun 13 23:15:48 2003
+++ parrot-leo/include/parrot/stacks.h  Fri Jun 20 11:34:51 2003
@@ -48,6 +48,7 @@
 #define STACK_CLEANUP_NULL ((Stack_cleanup_method)NULLfunc)
 
 Stack_Chunk_t * new_stack(Interp *interpreter);
+void stack_destroy(Stack_Chunk_t * top);
 
 Stack_Chunk_t * stack_copy(Interp *interpreter, Stack_Chunk_t *old_stack);
 
--- parrot/include/parrot/sub.h Wed Jun 18 16:47:55 2003
+++ parrot-leo/include/parrot/sub.h     Fri Jun 20 10:19:40 2003
@@ -22,22 +22,24 @@
     List * values;    /* lexicals go here */
     List * names;     /* names of lexicals go here */
 } * parrot_lexicals_t;
-
+/*
+ * we currently use the same structure for all 3 sub types
+ * so tath we can unify the Sub classes
+ * if one structure needs more data, pleas append them at the end
+ */
 typedef struct Parrot_Sub {
-    INTVAL              flags;
-    PMC                 *lex_pad;
-    opcode_t            *init;
+    struct Parrot_Context ctx;
+    opcode_t             *address;
 } * parrot_sub_t;
 
 typedef struct Parrot_Coroutine {
-    INTVAL               flags;
     struct Parrot_Context ctx;
-    opcode_t             *resume;
+    opcode_t             *address;
 } * parrot_coroutine_t;
 
 typedef struct Parrot_Continuation {
     struct Parrot_Context ctx;
-    opcode_t            *continuation;
+    opcode_t             *address;
 } * parrot_continuation_t;
 
 struct Parrot_Sub * new_sub(struct Parrot_Interp * interp,
@@ -52,9 +54,8 @@
 PMC * new_continuation_pmc(struct Parrot_Interp * interp,
                            opcode_t * address);
 
-void save_context(struct Parrot_Interp * interp,
-                  struct Parrot_Context * ctx);
-
+void save_context(struct Parrot_Interp * interp, struct Parrot_Context * ctx);
+void swap_context(struct Parrot_Interp * interp, struct Parrot_Context * ctx);
 void restore_context(struct Parrot_Interp * interp,
                      struct Parrot_Context * ctx);
 
--- parrot/interpreter.c        Thu Jun 19 01:44:11 2003
+++ parrot-leo/interpreter.c    Fri Jun 20 11:36:18 2003
@@ -669,23 +669,9 @@
         }
     }
 
-    /* XXX move this to stacks.c */
-    {
-        Stack_Chunk_t *chunks[3];
-        chunks[0] = interpreter->ctx.pad_stack;
-        chunks[1] = interpreter->ctx.user_stack;
-        chunks[2] = interpreter->ctx.control_stack;
-        for (i = 0; i< 3; i++) {
-            Stack_Chunk_t *top = chunks[i];
-            while (top->next)
-                top = top->next;
-            while(top) {
-                Stack_Chunk_t *next = top->prev;
-                mem_sys_free(top);
-                top = next;
-            }
-        }
-    }
+    stack_destroy(interpreter->ctx.pad_stack);
+    stack_destroy(interpreter->ctx.user_stack);
+    stack_destroy(interpreter->ctx.control_stack);
     /* intstack */
     intstack_free(interpreter, interpreter->ctx.intstack);
 
--- parrot/stacks.c     Fri Jun 13 23:15:48 2003
+++ parrot-leo/stacks.c Fri Jun 20 11:34:58 2003
@@ -47,6 +47,18 @@
 }
 
 void
+stack_destroy(Stack_Chunk_t * top)
+{
+    while (top->next)
+        top = top->next;
+    while(top) {
+        Stack_Chunk_t *next = top->prev;
+        mem_sys_free(top);
+        top = next;
+    }
+}
+
+void
 stack_mark_cow(Stack_Chunk_t *stack)
 {
     Stack_Chunk_t *chunk = stack;
--- parrot/sub.c        Wed Jun 18 16:47:54 2003
+++ parrot-leo/sub.c    Fri Jun 20 11:21:25 2003
@@ -24,6 +24,29 @@
 }
 
 void
+swap_context(struct Parrot_Interp *interp, struct Parrot_Context *ctx)
+{
+    struct Stack_Chunk * tmp_stack = NULL;
+    /*
+     * Swap control, user and pad stacks. Data in other parts of the
+     * context are not preserved between calls to the coroutine.
+     */
+
+    tmp_stack = interp->ctx.user_stack;
+    interp->ctx.user_stack = ctx->user_stack;
+    ctx->user_stack = tmp_stack;
+
+    tmp_stack = interp->ctx.control_stack;
+    interp->ctx.control_stack = ctx->control_stack;
+    ctx->control_stack = tmp_stack;
+
+    tmp_stack = interp->ctx.pad_stack;
+    interp->ctx.pad_stack = ctx->pad_stack;
+    ctx->pad_stack = tmp_stack;
+
+}
+
+void
 restore_context(struct Parrot_Interp *interp, struct Parrot_Context *ctx)
 {
     memcpy(&interp->ctx, ctx, sizeof(*ctx));
@@ -34,8 +57,14 @@
 {
     /* Using system memory until I figure out GC issues */
     struct Parrot_Sub *newsub = mem_sys_allocate(sizeof(struct Parrot_Sub));
-    newsub->init = address;
-    newsub->lex_pad = scratchpad_get_current(interp);
+    PMC * pad = scratchpad_get_current(interp);
+    newsub->address = address;
+    newsub->ctx.pad_stack = new_stack(interp);
+    if (pad) {
+        /* put the correct pad in place */
+        stack_push(interp, &newsub->ctx.pad_stack, pad,
+                STACK_ENTRY_PMC, STACK_CLEANUP_NULL);
+    }
     return newsub;
 }
 
@@ -46,7 +75,7 @@
     PMC * pad = NULL;
     struct Parrot_Coroutine *newco =
         mem_sys_allocate(sizeof(struct Parrot_Coroutine));
-    newco->resume = NULL;
+    newco->address = NULL;
     newco->ctx.user_stack = new_stack(interp);
     newco->ctx.control_stack = new_stack(interp);
     newco->ctx.pad_stack = new_stack(interp);
@@ -65,7 +94,7 @@
 {
     struct Parrot_Continuation *cc =
         mem_sys_allocate(sizeof(struct Parrot_Continuation));
-    cc->continuation = address;
+    cc->address = address;
     save_context(interp, &cc->ctx);
     return cc;
 }
@@ -75,7 +104,7 @@
 new_continuation_pmc(struct Parrot_Interp * interp, opcode_t * address)
 {
     PMC* continuation = pmc_new(interp, enum_class_Continuation);
-    ((struct Parrot_Continuation*)PMC_data(continuation))->continuation = address;
+    ((struct Parrot_Continuation*)PMC_data(continuation))->address = address;
     return continuation;
 }
 

Reply via email to