[svn:parrot] r40592 - in branches/context_pmc2: include/parrot src src/gc src/pmc

whiteknight at svn.parrot.org whiteknight at svn.parrot.org
Sun Aug 16 12:50:26 UTC 2009


Author: whiteknight
Date: Sun Aug 16 12:50:24 2009
New Revision: 40592
URL: https://trac.parrot.org/parrot/changeset/40592

Log:
[pmc_context2] create a skeleton PMC type for Context that is only a simple wrapper around the Parrot_Context* structure

Added:
   branches/context_pmc2/src/pmc/context.pmc
Modified:
   branches/context_pmc2/include/parrot/interpreter.h
   branches/context_pmc2/src/gc/alloc_register.c
   branches/context_pmc2/src/pmc/continuation.pmc
   branches/context_pmc2/src/pmc/sub.pmc
   branches/context_pmc2/src/sub.c

Modified: branches/context_pmc2/include/parrot/interpreter.h
==============================================================================
--- branches/context_pmc2/include/parrot/interpreter.h	Sun Aug 16 12:02:49 2009	(r40591)
+++ branches/context_pmc2/include/parrot/interpreter.h	Sun Aug 16 12:50:24 2009	(r40592)
@@ -195,14 +195,14 @@
 
 struct Parrot_Context {
     /* common header with Interp_Context */
-    struct Parrot_Context *caller_ctx;      /* caller context */
+    PMC                   *caller_ctx;      /* caller context */
     Regs_ni                bp;              /* pointers to FLOATVAL & INTVAL */
     Regs_ps                bp_ps;           /* pointers to PMC & STR */
 
     /* end common header */
     INTVAL                n_regs_used[4];   /* INSP in PBC points to Sub */
-    PMC                   *lex_pad;         /* LexPad PMC */
-    struct Parrot_Context *outer_ctx;       /* outer context, if a closure */
+    PMC                  *lex_pad;          /* LexPad PMC */
+    PMC                  *outer_ctx;        /* outer context, if a closure */
 
     /* new call scheme and introspective variables */
     PMC      *current_sub;           /* the Sub we are executing */
@@ -221,8 +221,6 @@
 
     INTVAL                 current_HLL;     /* see also src/hll.c */
     size_t                 regs_mem_size;   /* memory occupied by registers */
-    int                    ref_count;       /* how often refered to */
-    int                    gc_mark;         /* marked in gc run */
 
     UINTVAL                warns;           /* Keeps track of what warnings
                                              * have been activated */
@@ -250,21 +248,7 @@
     size_t n_allocated;                 /* allocated size of it */
 } Prederef;
 
-
-/*
- * This is an 'inlined' copy of the first 3 Context items for
- * faster access of registers mainly
- * During a context switch a 3 pointers are set
- */
-typedef struct Interp_Context {
-    /* common header */
-    struct Parrot_Context *state;       /* context  */
-    Regs_ni                bp;          /* pointers to FLOATVAL & INTVAL */
-    Regs_ps                bp_ps;       /* pointers to PMC & STR */
-    /* end common header */
-} Interp_Context;
-
-#define CONTEXT(interp) ((interp)->ctx.state)
+#define CONTEXT(interp) (Parrot_ctx_get_context_struct((interp)->ctx))
 
 #define CHUNKED_CTX_MEM 0           /* no longer works, but will be reinstated
                                      * some day; see src/register.c for details.
@@ -303,7 +287,7 @@
 
 /* The actual interpreter structure */
 struct parrot_interp_t {
-    struct Interp_Context ctx;
+    PMC                  *ctx;
     context_mem           ctx_mem;            /* ctx memory managment */
 
     struct Arenas *arena_base;                /* Pointer to this interpreter's

Modified: branches/context_pmc2/src/gc/alloc_register.c
==============================================================================
--- branches/context_pmc2/src/gc/alloc_register.c	Sun Aug 16 12:02:49 2009	(r40591)
+++ branches/context_pmc2/src/gc/alloc_register.c	Sun Aug 16 12:50:24 2009	(r40592)
@@ -19,6 +19,7 @@
 
 #include "parrot/parrot.h"
 #include "parrot/register.h"
+#include "../pmc/pmc_context.h"
 #include "../pmc/pmc_sub.h"
 
 
@@ -146,6 +147,22 @@
 
 /*
 
+=item C<Parrot_Context * Parrot_ctx_get_context_struct(PARROT_INTERP, PMC * context)>
+
+=cut
+
+*/
+
+PARROT_CAN_RETURN_NULL
+Parrot_Context *
+Parrot_ctx_get_context_struct(PARROT_INTERP, ARGIN(PMC * context))
+{
+    ASSERT_ARGS(Parrot_ctx_get_context_struct)
+    return PARROT_CONTEXT(context);
+}
+
+/*
+
 =item C<void destroy_context(PARROT_INTERP)>
 
 Frees allocated context memory.
@@ -247,103 +264,6 @@
 }
 
 
-/*
-
-=item C<static void clear_regs(PARROT_INTERP, Parrot_Context *ctx)>
-
-Clears all registers in a context.  PMC and STRING registers contain PMCNULL
-and NULL, respectively.  Integer and float registers contain negative flag
-values, for debugging purposes.
-
-=cut
-
-*/
-
-static void
-clear_regs(PARROT_INTERP, ARGMOD(Parrot_Context *ctx))
-{
-    ASSERT_ARGS(clear_regs)
-    int i;
-
-    /* NULL out registers - P/S have to be NULL for GC
-     *
-     * if the architecture has 0x := NULL and 0.0 we could memset too
-     */
-
-    for (i = 0; i < ctx->n_regs_used[REGNO_PMC]; i++) {
-        CTX_REG_PMC(ctx, i) = PMCNULL;
-    }
-
-    for (i = 0; i < ctx->n_regs_used[REGNO_STR]; i++) {
-        CTX_REG_STR(ctx, i) = NULL;
-    }
-
-    if (Interp_debug_TEST(interp, PARROT_REG_DEBUG_FLAG)) {
-        /* depending on -D40 we set int and num to be identifiable garbage values */
-        for (i = 0; i < ctx->n_regs_used[REGNO_INT]; i++) {
-            CTX_REG_INT(ctx, i) = -999;
-        }
-        for (i = 0; i < ctx->n_regs_used[REGNO_NUM]; i++) {
-            CTX_REG_NUM(ctx, i) = -99.9;
-        }
-    }
-}
-
-
-/*
-
-=item C<static void init_context(PARROT_INTERP, Parrot_Context *ctx, const
-Parrot_Context *old)>
-
-Initializes a freshly allocated or recycled context.
-
-=cut
-
-*/
-
-static void
-init_context(PARROT_INTERP, ARGMOD(Parrot_Context *ctx),
-        ARGIN_NULLOK(const Parrot_Context *old))
-{
-    ASSERT_ARGS(init_context)
-    ctx->ref_count         = 0;
-    ctx->gc_mark           = 0;
-    ctx->current_results   = NULL;
-    ctx->results_signature = NULL;
-    ctx->lex_pad           = PMCNULL;
-    ctx->outer_ctx         = NULL;
-    ctx->current_cont      = NULL;
-    ctx->current_object    = NULL;
-    ctx->handlers          = PMCNULL;
-    ctx->caller_ctx        = NULL;
-
-    if (old) {
-        /* some items should better be COW copied */
-        ctx->constants         = old->constants;
-        ctx->warns             = old->warns;
-        ctx->errors            = old->errors;
-        ctx->trace_flags       = old->trace_flags;
-        ctx->pred_offset       = old->pred_offset;
-        ctx->current_HLL       = old->current_HLL;
-        ctx->current_namespace = old->current_namespace;
-        /* end COW */
-        ctx->recursion_depth   = old->recursion_depth;
-    }
-    else {
-        ctx->constants         = NULL;
-        ctx->warns             = 0;
-        ctx->errors            = 0;
-        ctx->trace_flags       = 0;
-        ctx->pred_offset       = 0;
-        ctx->current_HLL       = 0;
-        ctx->current_namespace = PMCNULL;
-        ctx->recursion_depth   = 0;
-    }
-
-    /* other stuff is set inside Sub.invoke */
-    clear_regs(interp, ctx);
-}
-
 
 /*
 
@@ -412,105 +332,6 @@
     interp->ctx.bp_ps    = old->bp_ps;
 }
 
-
-/*
-
-=item C<Parrot_Context * Parrot_alloc_context(PARROT_INTERP, const INTVAL
-*number_regs_used, Parrot_Context *old)>
-
-Allocates and returns a new context.  Does not set this new context as the
-current context. Note that the register usage C<n_regs_used> is copied.  Use
-the init flag to indicate whether you want to initialize the new context
-(setting its default values and clearing its registers).
-
-=cut
-
-*/
-
-PARROT_CANNOT_RETURN_NULL
-PARROT_WARN_UNUSED_RESULT
-Parrot_Context *
-Parrot_alloc_context(PARROT_INTERP, ARGIN(const INTVAL *number_regs_used),
-    ARGIN_NULLOK(Parrot_Context *old))
-{
-    ASSERT_ARGS(Parrot_alloc_context)
-    Parrot_Context *ctx;
-    void *p;
-
-    const size_t size_i = sizeof (INTVAL)   * number_regs_used[REGNO_INT];
-    const size_t size_n = sizeof (FLOATVAL) * number_regs_used[REGNO_NUM];
-    const size_t size_s = sizeof (STRING *) * number_regs_used[REGNO_STR];
-    const size_t size_p = sizeof (PMC *)    * number_regs_used[REGNO_PMC];
-
-    const size_t size_nip      = size_n + size_i + size_p;
-    const size_t all_regs_size = size_n + size_i + size_p + size_s;
-    const size_t reg_alloc     = ROUND_ALLOC_SIZE(all_regs_size);
-    const int    slot          = CALCULATE_SLOT_NUM(reg_alloc);
-
-    /*
-     * If slot is beyond the end of the allocated list, extend the list to
-     * allocate more slots.
-     */
-    if (slot >= interp->ctx_mem.n_free_slots) {
-        const int extend_size = slot + 1;
-        int i;
-
-        mem_realloc_n_typed(interp->ctx_mem.free_list, extend_size, void *);
-        for (i = interp->ctx_mem.n_free_slots; i < extend_size; ++i)
-            interp->ctx_mem.free_list[i] = NULL;
-        interp->ctx_mem.n_free_slots = extend_size;
-    }
-
-    /*
-     * The free_list contains a linked list of pointers for each size (slot
-     * index). Pop off an available context of the desired size from free_list.
-     * If no contexts of the desired size are available, allocate a new one.
-     */
-    ctx = (Parrot_Context *)interp->ctx_mem.free_list[slot];
-
-    if (ctx) {
-        /*
-         * Store the next pointer from the linked list for this size (slot
-         * index) in free_list. On "*(void **) ctx", C won't dereference a void
-         * * pointer (untyped), so type cast ctx to void ** (a dereference-able
-         * type) then dereference it to get a void *. Store the dereferenced
-         * value (the next pointer in the linked list) in free_list.
-         */
-        interp->ctx_mem.free_list[slot] = *(void **)ctx;
-    }
-    else {
-        const size_t to_alloc = reg_alloc + ALIGNED_CTX_SIZE;
-        ctx                   = (Parrot_Context *)mem_sys_allocate(to_alloc);
-    }
-
-    ctx->n_regs_used[REGNO_INT] = number_regs_used[REGNO_INT];
-    ctx->n_regs_used[REGNO_NUM] = number_regs_used[REGNO_NUM];
-    ctx->n_regs_used[REGNO_STR] = number_regs_used[REGNO_STR];
-    ctx->n_regs_used[REGNO_PMC] = number_regs_used[REGNO_PMC];
-
-#if CTX_LEAK_DEBUG
-    if (Interp_debug_TEST(interp, PARROT_CTX_DESTROY_DEBUG_FLAG)) {
-        fprintf(stderr, "[alloc ctx %p]\n", ctx);
-    }
-#endif
-
-    ctx->regs_mem_size = reg_alloc;
-
-    /* regs start past the context */
-    p   = (void *) ((char *)ctx + ALIGNED_CTX_SIZE);
-
-    /* ctx.bp points to I0, which has Nx on the left */
-    ctx->bp.regs_i = (INTVAL *)((char *)p + size_n);
-
-    /* ctx.bp_ps points to S0, which has Px on the left */
-    ctx->bp_ps.regs_s = (STRING **)((char *)p + size_nip);
-
-    init_context(interp, ctx, old);
-
-    return ctx;
-}
-
-
 /*
 
 =item C<Parrot_Context * Parrot_set_new_context(PARROT_INTERP, const INTVAL
@@ -540,112 +361,6 @@
 }
 
 
-/*
-
-=item C<void Parrot_free_context(PARROT_INTERP, Parrot_Context *ctx, int deref)>
-
-Frees the context if its reference count is zero.  If C<deref>
-is true, then reduce the reference count prior to determining
-if the context should be freed.
-
-=cut
-
-*/
-
-PARROT_EXPORT
-void
-Parrot_free_context(PARROT_INTERP, ARGMOD(Parrot_Context *ctx), int deref)
-{
-    ASSERT_ARGS(Parrot_free_context)
-    /*
-     * The context structure has a reference count, initially 0.
-     * This field is incremented when something outside of the normal
-     * calling chain (such as a continuation or outer scope) wants to
-     * preserve the context.  The field is decremented when
-     * Parrot_free_context is called with the C<deref> flag set true.
-     * To trace context handling and check for leaks,
-     * (a) disable NDEBUG, (b) enable CTX_LEAK_DEBUG in interpreter.h,
-     * and (c) execute "debug 0x80" in a (preferably small) test case.
-     *
-     */
-    if (deref) {
-#if CTX_LEAK_DEBUG
-        if (Interp_debug_TEST(interp, PARROT_CTX_DESTROY_DEBUG_FLAG)) {
-            fprintf(stderr, "[reference to context %p released]\n", (void*)ctx);
-        }
-#endif
-        ctx->ref_count--;
-    }
-
-    if (ctx->ref_count <= 0) {
-        void *ptr;
-        int slot;
-
-#ifndef NDEBUG
-        if (Interp_debug_TEST(interp, PARROT_CTX_DESTROY_DEBUG_FLAG)
-            && ctx->current_sub) {
-            /* can't probably Parrot_io_eprintf here */
-            Parrot_sub *doomed;
-            PMC_get_sub(interp, ctx->current_sub, doomed);
-
-            if (doomed) {
-                fprintf(stderr, "[free  ctx %p of sub '%s']\n",
-                        (void *)ctx,
-                        (doomed->name == (void*)0xdeadbeef
-                        ? "???"
-                        : (char*)doomed->name->strstart));
-            }
-            else {
-                Parrot_ex_throw_from_c_args(interp, NULL, 1,
-                        "NULL doomed sub detected in Parrot_free_context");
-            }
-        }
-#endif
-
-        if (ctx->outer_ctx)
-            Parrot_free_context(interp, ctx->outer_ctx, 1);
-
-        ctx->n_regs_used[REGNO_INT] = 0;
-        ctx->n_regs_used[REGNO_NUM] = 0;
-        ctx->n_regs_used[REGNO_STR] = 0;
-        ctx->n_regs_used[REGNO_PMC] = 0;
-
-#if CTX_LEAK_DEBUG_FULL
-        /* for debugging, poison the freed context in case anything
-         * tries to use it later. */
-        ctx->current_results   = (opcode_t *)0xbeefcafe;
-        ctx->results_signature = (PMC *)0xbeefcafe;
-        ctx->lex_pad           = (PMC *)0xbeefcafe;
-        ctx->outer_ctx         = (Parrot_Context *)0xbeefcafe;
-        ctx->current_cont      = (PMC *)0xbeefcafe;
-        ctx->current_object    = (PMC *)0xbeefcafe;
-        ctx->current_HLL       = -1;
-        ctx->handlers          = (PMC *)0xbeefcafe;
-        ctx->constants         = (struct PackFile_Constant **)0xbeefcafe;
-        ctx->current_namespace = (PMC *)0xbeefcafe;
-#endif
-
-        /* don't put the same context on the free list multiple times; we don't
-         * have the re-use versus multiple ref count semantics right yet */
-        if (ctx->ref_count < 0)
-            return;
-
-        /* force the reference count negative to indicate a dead context
-         * so mark_context (src/sub.c) can report it */
-        ctx->ref_count--;
-
-        ptr             = ctx;
-        slot            = CALCULATE_SLOT_NUM(ctx->regs_mem_size);
-
-#if CTX_LEAK_DEBUG_FULL
-        slot = 0;
-#endif
-
-        PARROT_ASSERT(slot < interp->ctx_mem.n_free_slots);
-        *(void **)ptr                   = interp->ctx_mem.free_list[slot];
-        interp->ctx_mem.free_list[slot] = ptr;
-    }
-}
 
 
 /*

Added: branches/context_pmc2/src/pmc/context.pmc
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ branches/context_pmc2/src/pmc/context.pmc	Sun Aug 16 12:50:24 2009	(r40592)
@@ -0,0 +1,331 @@
+/*
+
+=item C<static void clear_regs(PARROT_INTERP, Parrot_Context *ctx)>
+
+Clears all registers in a context.  PMC and STRING registers contain PMCNULL
+and NULL, respectively.  Integer and float registers contain negative flag
+values, for debugging purposes.
+
+=cut
+
+*/
+
+static void
+clear_regs(PARROT_INTERP, ARGMOD(Parrot_Context *ctx))
+{
+    ASSERT_ARGS(clear_regs)
+    int i;
+
+    /* NULL out registers - P/S have to be NULL for GC
+     *
+     * if the architecture has 0x := NULL and 0.0 we could memset too
+     */
+
+    for (i = 0; i < ctx->n_regs_used[REGNO_PMC]; i++) {
+        CTX_REG_PMC(ctx, i) = PMCNULL;
+    }
+
+    for (i = 0; i < ctx->n_regs_used[REGNO_STR]; i++) {
+        CTX_REG_STR(ctx, i) = NULL;
+    }
+
+    if (Interp_debug_TEST(interp, PARROT_REG_DEBUG_FLAG)) {
+        /* depending on -D40 we set int and num to be identifiable garbage values */
+        for (i = 0; i < ctx->n_regs_used[REGNO_INT]; i++) {
+            CTX_REG_INT(ctx, i) = -999;
+        }
+        for (i = 0; i < ctx->n_regs_used[REGNO_NUM]; i++) {
+            CTX_REG_NUM(ctx, i) = -99.9;
+        }
+    }
+}
+
+/*
+
+=item C<static void init_context(PARROT_INTERP, Parrot_Context *ctx, const
+Parrot_Context *old)>
+
+Initializes a freshly allocated or recycled context.
+
+=cut
+
+*/
+
+static void
+init_context(PARROT_INTERP, ARGMOD(Parrot_Context *ctx))
+{
+    ASSERT_ARGS(init_context)
+    ctx->current_results   = NULL;
+    ctx->results_signature = NULL;
+    ctx->lex_pad           = PMCNULL;
+    ctx->outer_ctx         = NULL;
+    ctx->current_cont      = NULL;
+    ctx->current_object    = NULL;
+    ctx->handlers          = PMCNULL;
+    ctx->caller_ctx        = NULL;
+    ctx->constants         = NULL;
+    ctx->warns             = 0;
+    ctx->errors            = 0;
+    ctx->trace_flags       = 0;
+    ctx->pred_offset       = 0;
+    ctx->current_HLL       = 0;
+    ctx->current_namespace = PMCNULL;
+    ctx->recursion_depth   = 0;
+
+    /* other stuff is set inside Sub.invoke */
+    clear_regs(interp, ctx);
+}
+
+/*
+
+=item C<Parrot_Context * Parrot_alloc_context(PARROT_INTERP, const INTVAL
+*number_regs_used, Parrot_Context *old)>
+
+Allocates and returns a new context.  Does not set this new context as the
+current context. Note that the register usage C<n_regs_used> is copied.  Use
+the init flag to indicate whether you want to initialize the new context
+(setting its default values and clearing its registers).
+
+=cut
+
+*/
+
+PARROT_CANNOT_RETURN_NULL
+PARROT_WARN_UNUSED_RESULT
+Parrot_Context *
+Parrot_alloc_context(PARROT_INTERP, ARGIN(const INTVAL *number_regs_used),
+    ARGIN_NULLOK(Parrot_Context *old))
+{
+    ASSERT_ARGS(Parrot_alloc_context)
+    Parrot_Context *ctx;
+    void *p;
+
+    const size_t size_i = sizeof (INTVAL)   * number_regs_used[REGNO_INT];
+    const size_t size_n = sizeof (FLOATVAL) * number_regs_used[REGNO_NUM];
+    const size_t size_s = sizeof (STRING *) * number_regs_used[REGNO_STR];
+    const size_t size_p = sizeof (PMC *)    * number_regs_used[REGNO_PMC];
+
+    const size_t size_nip      = size_n + size_i + size_p;
+    const size_t all_regs_size = size_n + size_i + size_p + size_s;
+    const size_t reg_alloc     = ROUND_ALLOC_SIZE(all_regs_size);
+    const int    slot          = CALCULATE_SLOT_NUM(reg_alloc);
+
+    /*
+     * If slot is beyond the end of the allocated list, extend the list to
+     * allocate more slots.
+     */
+    if (slot >= interp->ctx_mem.n_free_slots) {
+        const int extend_size = slot + 1;
+        int i;
+
+        mem_realloc_n_typed(interp->ctx_mem.free_list, extend_size, void *);
+        for (i = interp->ctx_mem.n_free_slots; i < extend_size; ++i)
+            interp->ctx_mem.free_list[i] = NULL;
+        interp->ctx_mem.n_free_slots = extend_size;
+    }
+
+    /*
+     * The free_list contains a linked list of pointers for each size (slot
+     * index). Pop off an available context of the desired size from free_list.
+     * If no contexts of the desired size are available, allocate a new one.
+     */
+    ctx = (Parrot_Context *)interp->ctx_mem.free_list[slot];
+
+    if (ctx) {
+        /*
+         * Store the next pointer from the linked list for this size (slot
+         * index) in free_list. On "*(void **) ctx", C won't dereference a void
+         * * pointer (untyped), so type cast ctx to void ** (a dereference-able
+         * type) then dereference it to get a void *. Store the dereferenced
+         * value (the next pointer in the linked list) in free_list.
+         */
+        interp->ctx_mem.free_list[slot] = *(void **)ctx;
+    }
+    else {
+        const size_t to_alloc = reg_alloc + ALIGNED_CTX_SIZE;
+        ctx                   = (Parrot_Context *)mem_sys_allocate(to_alloc);
+    }
+
+    ctx->n_regs_used[REGNO_INT] = number_regs_used[REGNO_INT];
+    ctx->n_regs_used[REGNO_NUM] = number_regs_used[REGNO_NUM];
+    ctx->n_regs_used[REGNO_STR] = number_regs_used[REGNO_STR];
+    ctx->n_regs_used[REGNO_PMC] = number_regs_used[REGNO_PMC];
+
+#if CTX_LEAK_DEBUG
+    if (Interp_debug_TEST(interp, PARROT_CTX_DESTROY_DEBUG_FLAG)) {
+        fprintf(stderr, "[alloc ctx %p]\n", ctx);
+    }
+#endif
+
+    ctx->regs_mem_size = reg_alloc;
+
+    /* regs start past the context */
+    p   = (void *) ((char *)ctx + ALIGNED_CTX_SIZE);
+
+    /* ctx.bp points to I0, which has Nx on the left */
+    ctx->bp.regs_i = (INTVAL *)((char *)p + size_n);
+
+    /* ctx.bp_ps points to S0, which has Px on the left */
+    ctx->bp_ps.regs_s = (STRING **)((char *)p + size_nip);
+
+    init_context(interp, ctx, old);
+
+    return ctx;
+}
+
+/*
+
+=item C<void Parrot_free_context(PARROT_INTERP, Parrot_Context *ctx, int deref)>
+
+Frees the context.
+
+=cut
+
+*/
+
+PARROT_EXPORT
+void
+Parrot_free_context(PARROT_INTERP, ARGMOD(Parrot_Context *ctx))
+{
+    ASSERT_ARGS(Parrot_free_context)
+
+    void *ptr;
+    int slot;
+
+#ifndef NDEBUG
+    if (Interp_debug_TEST(interp, PARROT_CTX_DESTROY_DEBUG_FLAG)
+        && ctx->current_sub) {
+        /* can't probably Parrot_io_eprintf here */
+        Parrot_sub *doomed;
+        PMC_get_sub(interp, ctx->current_sub, doomed);
+
+        if (doomed) {
+            fprintf(stderr, "[free  ctx %p of sub '%s']\n",
+                    (void *)ctx,
+                    (doomed->name == (void*)0xdeadbeef
+                    ? "???"
+                    : (char*)doomed->name->strstart));
+        }
+        else {
+            Parrot_ex_throw_from_c_args(interp, NULL, 1,
+                    "NULL doomed sub detected in Parrot_free_context");
+        }
+    }
+#endif
+
+    ctx->n_regs_used[REGNO_INT] = 0;
+    ctx->n_regs_used[REGNO_NUM] = 0;
+    ctx->n_regs_used[REGNO_STR] = 0;
+    ctx->n_regs_used[REGNO_PMC] = 0;
+
+#if CTX_LEAK_DEBUG_FULL
+    /* for debugging, poison the freed context in case anything
+     * tries to use it later. */
+    ctx->current_results   = (opcode_t *)0xbeefcafe;
+    ctx->results_signature = (PMC *)0xbeefcafe;
+    ctx->lex_pad           = (PMC *)0xbeefcafe;
+    ctx->outer_ctx         = (Parrot_Context *)0xbeefcafe;
+    ctx->current_cont      = (PMC *)0xbeefcafe;
+    ctx->current_object    = (PMC *)0xbeefcafe;
+    ctx->current_HLL       = -1;
+    ctx->handlers          = (PMC *)0xbeefcafe;
+    ctx->constants         = (struct PackFile_Constant **)0xbeefcafe;
+    ctx->current_namespace = (PMC *)0xbeefcafe;
+#endif
+
+    /* don't put the same context on the free list multiple times; we don't
+     * have the re-use versus multiple ref count semantics right yet */
+    if (ctx->ref_count < 0)
+        return;
+
+    /* force the reference count negative to indicate a dead context
+     * so mark_context (src/sub.c) can report it */
+    ctx->ref_count--;
+
+    ptr             = ctx;
+    slot            = CALCULATE_SLOT_NUM(ctx->regs_mem_size);
+
+#if CTX_LEAK_DEBUG_FULL
+    slot = 0;
+#endif
+
+    PARROT_ASSERT(slot < interp->ctx_mem.n_free_slots);
+    *(void **)ptr                   = interp->ctx_mem.free_list[slot];
+    interp->ctx_mem.free_list[slot] = ptr;
+}
+
+pmclass Context {
+    ATTR Parrot_Context * ctx;
+
+    VTABLE void init()
+    {
+        Parrot_Context_attributes * const attrs = mem_sys_allocate_typed(Parrot_Context_attributes);
+        Parrot_Context * const ctx = mem_sys_allocate_typed(Parrot_Context);
+        init_context(INTERP, ctx);
+        attrs->ctx = ctx;
+        PMC_DATA(SELF) = attrs;
+    }
+
+    VTABLE void mark()
+    {
+        Parrot_Context * const ctx = PARROT_CONTEXT(SELF)->ctx;
+        PObj *obj;
+        int   i;
+
+        obj = (PObj *)ctx->current_sub;
+        if (obj)
+            Parrot_gc_mark_PObj_alive(interp, obj);
+
+        obj = (PObj *)ctx->current_object;
+        if (obj)
+            Parrot_gc_mark_PObj_alive(interp, obj);
+
+        obj = (PObj *)ctx->current_cont;
+        if (obj && !PObj_live_TEST(obj))
+            Parrot_gc_mark_PObj_alive(interp, obj);
+
+        obj = (PObj *)ctx->caller_ctx;
+        if (obj)
+            Parrot_gc_mark_PObj_alive(interp, obj);
+
+        obj = (PObj *)ctx->outer_ctx;
+        if (obj)
+            Parrot_gc_mark_PObj_alive(interp, obj);
+
+        obj = (PObj *)ctx->current_namespace;
+        if (obj)
+            Parrot_gc_mark_PObj_alive(interp, obj);
+
+        obj = (PObj *)ctx->lex_pad;
+        if (obj)
+            Parrot_gc_mark_PObj_alive(interp, obj);
+
+        obj = (PObj *)ctx->handlers;
+        if (obj)
+            Parrot_gc_mark_PObj_alive(interp, obj);
+
+        if (!ctx->n_regs_used)
+            return;
+
+        for (i = 0; i < ctx->n_regs_used[REGNO_PMC]; ++i) {
+            obj = (PObj *)CTX_REG_PMC(ctx, i);
+            if (obj)
+                Parrot_gc_mark_PObj_alive(interp, obj);
+        }
+
+        for (i = 0; i < ctx->n_regs_used[REGNO_STR]; ++i) {
+            obj = (PObj *)CTX_REG_STR(ctx, i);
+            if (obj)
+                Parrot_gc_mark_PObj_alive(interp, obj);
+        }
+    }
+
+    VTABLE void destroy()
+    {
+        Parrot_Context_attributes * const attrs = PARROT_CONTEXT(SELF);
+        Parrot_Context * const ctx = attrs->ctx;
+        Parrot_free_context(INTERP, ctx);
+        mem_sys_free(ctx);
+        mem_sys_free(attrs);
+    }
+}

Modified: branches/context_pmc2/src/pmc/continuation.pmc
==============================================================================
--- branches/context_pmc2/src/pmc/continuation.pmc	Sun Aug 16 12:02:49 2009	(r40591)
+++ branches/context_pmc2/src/pmc/continuation.pmc	Sun Aug 16 12:50:24 2009	(r40592)
@@ -89,9 +89,9 @@
         Parrot_cont *cc = PMC_cont(SELF);
 
         if (cc->to_ctx)
-            mark_context(INTERP, cc->to_ctx);
+            Parrot_gc_mark_PObj_alive(INTERP, (PObj *) cc->to_ctx);
         if (cc->from_ctx)
-            mark_context(INTERP, cc->from_ctx);
+            Parrot_gc_mark_PObj_alive(INTERP, (PObj *) cc->from_ctx);
     }
 
 /*

Modified: branches/context_pmc2/src/pmc/sub.pmc
==============================================================================
--- branches/context_pmc2/src/pmc/sub.pmc	Sun Aug 16 12:02:49 2009	(r40591)
+++ branches/context_pmc2/src/pmc/sub.pmc	Sun Aug 16 12:50:24 2009	(r40592)
@@ -504,9 +504,9 @@
         if (sub->subid)
             Parrot_gc_mark_PObj_alive(INTERP, (PObj *) sub->subid);
         if (sub->ctx)
-            mark_context(interp, sub->ctx);
+            Parrot_gc_mark_PObj_alive(INTERP, (PObj *) sub->ctx);
         if (sub->outer_ctx)
-            mark_context(interp, sub->outer_ctx);
+            Parrot_gc_mark_PObj_alive(INTERP, (PObj *) sub->outer_ctx);
     }
 
 /*

Modified: branches/context_pmc2/src/sub.c
==============================================================================
--- branches/context_pmc2/src/sub.c	Sun Aug 16 12:02:49 2009	(r40591)
+++ branches/context_pmc2/src/sub.c	Sun Aug 16 12:50:24 2009	(r40592)
@@ -26,105 +26,6 @@
 
 /* HEADERIZER HFILE: include/parrot/sub.h */
 
-
-/*
-
-=item C<void mark_context_start(void)>
-
-Indicate that a new round of context marking is about to take place.
-
-=cut
-
-*/
-
-static int context_gc_mark = 0;
-
-void
-mark_context_start(void)
-{
-    ASSERT_ARGS(mark_context_start)
-    if (++context_gc_mark == 0) context_gc_mark = 1;
-}
-
-
-/*
-
-=item C<void mark_context(PARROT_INTERP, Parrot_Context* ctx)>
-
-Marks the context C<*ctx>.
-
-=cut
-
-*/
-
-void
-mark_context(PARROT_INTERP, ARGMOD(Parrot_Context* ctx))
-{
-    ASSERT_ARGS(mark_context)
-    PObj *obj;
-    int   i;
-
-    if (ctx->gc_mark == context_gc_mark)
-        return;
-    ctx->gc_mark = context_gc_mark;
-
-    /* don't mark the context if it's actually dead */
-    if (ctx->ref_count < 0) {
-        /* report it, though */
-        if (Interp_debug_TEST(interp, PARROT_CTX_DESTROY_DEBUG_FLAG)) {
-            fprintf(stderr, "[attempt to mark dead context %p]\n",
-                (void *)ctx);
-        }
-        return;
-    }
-
-    obj = (PObj *)ctx->current_sub;
-    if (obj)
-        Parrot_gc_mark_PObj_alive(interp, obj);
-
-    obj = (PObj *)ctx->current_object;
-    if (obj)
-        Parrot_gc_mark_PObj_alive(interp, obj);
-
-    obj = (PObj *)ctx->current_cont;
-    if (obj && !PObj_live_TEST(obj))
-        Parrot_gc_mark_PObj_alive(interp, obj);
-
-    if (ctx->caller_ctx)
-        mark_context(interp, ctx->caller_ctx);
-
-    if (ctx->outer_ctx)
-        mark_context(interp, ctx->outer_ctx);
-
-    obj = (PObj *)ctx->current_namespace;
-    if (obj)
-        Parrot_gc_mark_PObj_alive(interp, obj);
-
-    obj = (PObj *)ctx->lex_pad;
-    if (obj)
-        Parrot_gc_mark_PObj_alive(interp, obj);
-
-    obj = (PObj *)ctx->handlers;
-    if (obj)
-        Parrot_gc_mark_PObj_alive(interp, obj);
-
-
-    if (!ctx->n_regs_used)
-        return;
-
-    for (i = 0; i < ctx->n_regs_used[REGNO_PMC]; ++i) {
-        obj = (PObj *)CTX_REG_PMC(ctx, i);
-        if (obj)
-            Parrot_gc_mark_PObj_alive(interp, obj);
-    }
-
-    for (i = 0; i < ctx->n_regs_used[REGNO_STR]; ++i) {
-        obj = (PObj *)CTX_REG_STR(ctx, i);
-        if (obj)
-            Parrot_gc_mark_PObj_alive(interp, obj);
-    }
-}
-
 /*
 
 =item C<Parrot_sub * new_sub(PARROT_INTERP)>


More information about the parrot-commits mailing list