As a more concrete demonstration of what I'm talking about, here's an
implementiation of the easy part: the pinning and releasing macros.
(UNPIN would probably be better than RELEASE, huh?) It's a naive
implementation with a low fixed limit on the max number of pinned
objects (10), but at least it's fairly fast. Pinned PMCs could
probably be better done as a prebuilt prefix to the next_for_GC list.
Index: dod.c
===================================================================
RCS file: /cvs/public/parrot/dod.c,v
retrieving revision 1.38
diff -u -r1.38 dod.c
--- dod.c       12 Dec 2002 08:07:08 -0000      1.38
+++ dod.c       18 Dec 2002 07:48:49 -0000
@@ -94,6 +94,23 @@
  * the root set, and used by the PMC GC handling routines to tag their
  * individual pieces if they have private ones */
 
+static PMC*
+trace_pinned_pmcs(struct Parrot_Interp *interpreter, PMC* last)
+{
+    int i;
+    for (i = 0; i < interpreter->ctx.num_pinned_pmcs; i++)
+        last = mark_used(interpreter->ctx.pinned_pmcs[i], last);
+    return last;
+}
+
+static void
+trace_pinned_pobjs(struct Parrot_Interp *interpreter)
+{
+    int i;
+    for (i = 0; i < interpreter->ctx.num_pinned_pobjs; i++)
+        buffer_lives(interpreter, (Buffer *)interpreter->ctx.pinned_pobjs[i]);
+}
+
 /* Do a full trace run and mark all the PMCs as active if they are */
 static void
 trace_active_PMCs(struct Parrot_Interp *interpreter)
@@ -125,6 +142,10 @@
     /* Parrot_base_classname_hash */
     last = mark_used(Parrot_base_classname_hash, last);
 
+#if ! PARROT_REGISTER_SCAN
+    last = trace_pinned_pmcs(interpreter, last);
+#endif
+
     /* Find important stuff on the system stack */
 #if ! DISABLE_GC_DEBUG
     CONSERVATIVE_POINTER_CHASING = 1;
@@ -336,6 +357,11 @@
 
         cur_stack = cur_stack->prev;
     }
+
+    /* Don't forget the pinned pointers */
+#if ! PARROT_REGISTER_SCAN
+    trace_pinned_pobjs(interpreter);
+#endif
 }
 
 /* Free up any PMCs that aren't in use */
Index: include/parrot/interpreter.h
===================================================================
RCS file: /cvs/public/parrot/include/parrot/interpreter.h,v
retrieving revision 1.58
diff -u -r1.58 interpreter.h
--- include/parrot/interpreter.h        11 Dec 2002 14:50:46 -0000      1.58
+++ include/parrot/interpreter.h        18 Dec 2002 07:48:49 -0000
@@ -13,6 +13,8 @@
 #if !defined(PARROT_INTERPRETER_H_GUARD)
 #define PARROT_INTERPRETER_H_GUARD
 
+#include <assert.h>
+
 /* These should be visible to embedders. */
 
 /* General flags */
@@ -67,6 +69,19 @@
     FLOATVAL time;
 } ProfData;
 
+#if PARROT_REGISTER_SCAN
+#  define PIN_POBJ(interp,p)
+#  define RELEASE_POBJ(interp,p)
+#  define PIN_PMC(interp,p)
+#  define RELEASE_PMC(interp,p)
+#else
+#  define MAX_PINNED 10
+#  define PIN_POBJ(interp,p) (interp)->ctx.pinned[(interp)->num_pinned_pobjs++]=(p)
+#  define RELEASE_POBJ(interp,p) Parrot_release_pobj((interp),(p))
+#  define PIN_PMC(interp,p) (interp)->ctx.pinned_pmcs[(interp)->num_pinned_pmcs++]=(p)
+#  define RELEASE_PMC(interp,p) Parrot_release_pmc((interp),(p))
+#endif
+
 typedef struct Parrot_Context {
     struct IReg int_reg;
     struct NReg num_reg;
@@ -87,7 +102,12 @@
     struct Stack_Chunk *user_stack;     /* Base of the scratch stack */
     struct Stack_Chunk *control_stack;  /* Base of the flow control stack */
     IntStack intstack;                  /* Base of the regex stack */
-
+#if ! PARROT_REGISTER_SCAN
+    PObj* pinned_pobjs[MAX_PINNED];
+    int num_pinned_pobjs;
+    PMC* pinned_pmcs[MAX_PINNED];
+    int num_pinned_pmcs;
+#endif
 } parrot_context_t;
 
 /*
@@ -172,6 +192,35 @@
     PDB_t *pdb;                 /* Debug system */
     void *lo_var_ptr;           /* Pointer to memory on runops system stack */
 } Interp;
+
+#if PARROT_REGISTER_SCAN
+static inline void
+Parrot_release(Parrot_Interp* interp, void **pinned, int *num_pinned, void *p)
+{
+    int i;
+    for (i = 0; i < *num_pinned; i++) {
+        if (pinned[i] == p) {
+            memmove(&pinned[i], &pinned[i+1],
+                    (*num_pinned - i - 1) * sizeof(p));
+            break;
+        }
+    }
+    assert(i < *num_pinned); /* found the object */
+    *num_pinned--;
+}
+static inline void
+Parrot_release_pmc(Parrot_Interp* interp, PMC* p)
+{
+    Parrot_release(interp,
+                   interp->ctx.pinned_pmcs, &interp->ctx.num_pinned_pmcs, p);
+}
+static inline void
+Parrot_release_pobj(Parrot_Interp* interp, PObj* p)
+{
+    Parrot_release(interp,
+                   interp->ctx.pinned_pobjs, &interp->ctx.num_pinned_pobjs, p);
+}
+#endif
 
 #define PCONST(i) PF_CONST(interpreter->code, (i))
 #define PNCONST   PF_NCONST(interpreter->code)


Reply via email to