At 4:44 PM +0200 9/27/02, Leopold Toetsch wrote:
>Tom Hughes wrote:
>
>>In message <[EMAIL PROTECTED]>
>>         Leopold Toetsch <[EMAIL PROTECTED]> wrote:
>
>
>>I applied this to my checkout (with _intlist_new renamed to
>>allocate_chunk because names starting with _ are reserved).
>
>
>Ah, didn't know that - ok changed too.
>
>>Unfortunately it doesn't test clean afterwards:
>>
>>dunsmere [~/src/parrot] % perl t/harness t/pmc/intlist.t
>>t/pmc/intlist....NOK 3#     Failed test (t/pmc/intlist.t at line 149)       
>>#          got: ''
>
>
>Ah, dumps core, aha GC, ahaaha junk_list moved. I ran the tests with 
>my Lea allocator in place, which doesn't suffer from this problem ;-)
>
>Anyway here is an update, tested with CVS GC.
>
>Additionally indexed access is simplified by a view lines.
>
>Thanks for testing and sorry,
>leo
>
>
>--- parrot/intlist.c   Thu Sep 26 18:30:29 2002
>+++ parrot-leo/intlist.c       Fri Sep 27 16:32:26 2002
>@@ -70,6 +70,24 @@
>   *     shift: read element, discard chunk and advance if necessary
>   *     unshift: unshift a chunk if necessary, write element
>   *
>+ *     Direct aka indexed access of intlist data:
>+ *
>+ *     The classic method would be to walk the intlist->next pointers
>+ *     (or optimized, the ->prev pointers if an index near the end is
>+ *     requested) and locate the chunk, that holds the wanted list
>+ *     item.
>+ *     To speed things up, especially for bigger lists, there are
>+ *     additional fields in the 'list' (the head chunk):
>+ *     chunk_list  ... holds pointers to individual chunks
>+ *     collect_runs ... collect_runs counter, when chunk_list was
>+ *                     rebuilt last.
>+ *     n_chunks ... used length in chunk_list
>+ *
>+ *     If on any indexed access interpreter's collect_runs is
>+ *     different, the chunks might have been moved, so the chunk_list
>+ *     has to be rebuilt.
>+ *
>+ *
>   *  History:
>   *  Notes:
>   * References: */
>@@ -78,9 +96,29 @@
>  #include "parrot/intlist.h"
>
>  static size_t rebuild_chunk_list(Interp *interpreter, IntList *list);
>+static IntList* allocate_chunk(Interp *interpreter, int initial);
>+static size_t rebuild_chunk_list(Interp *interpreter, IntList *list);
>
>  IntList*
>-intlist_new(Interp *interpreter, int initial)
>+intlist_new(Interp *interpreter) {
>+    return allocate_chunk(interpreter, 1);
>+}
>+
>+/* growth increment of chunk_list, must be a power of 2 */
>+#define CL_SIZE 16
>+
>+/* Buffers store the used len in bytes in buflen
>+ * so, the len in entries is: */
>+
>+#define chunk_list_size(list) \
>+                (list->chunk_list.buflen / sizeof(IntList_Chunk *))
>+
>+/* hide the ugly cast somehow: */
>+#define chunk_list_ptr(list, idx) \
>+        ((IntList_Chunk**)list->chunk_list.bufstart)[idx]
>+
>+static IntList*
>+allocate_chunk(Interp *interpreter, int initial)
>  {
>      IntList* list;
>
>@@ -96,11 +134,8 @@
>      Parrot_allocate(interpreter, (Buffer*) list,
>                      INTLIST_CHUNK_SIZE * sizeof(INTVAL));
>      if (initial) {
>-        /* XXX managed memory or custom destroy? */
>-        list->chunk_list = mem_sys_allocate(sizeof(IntList_Chunk *));
>-        list->n_chunks = 1;
>-        list->collect_runs = interpreter->dod_runs;
>-        list->chunk_list[0] = (IntList_Chunk*) list;
>+        /* we have a cleared list, so no need to zero chunk_list */
>+        rebuild_chunk_list(interpreter, list);
>      }
>      interpreter->DOD_block_level--;
>      interpreter->GC_block_level--;
>@@ -115,10 +150,11 @@
>          buffer_lives((Buffer *) chunk);
>          chunk = chunk->next;
>      } while (chunk != (IntList_Chunk*) list);
>-
>+    buffer_lives(&list->chunk_list);
>      return last;
>  }
>
>+#ifdef INTLIST_DEBUG
>  void
>  intlist_dump(FILE* fp, IntList* list, int verbose)
>  {
>@@ -144,6 +180,7 @@
>
>      fprintf(fp, "\n");
>  }
>+#endif
>
>  static size_t
>  rebuild_chunk_list(Interp *interpreter, IntList *list)
>@@ -151,16 +188,25 @@
>      IntList_Chunk* chunk = (IntList_Chunk*) list;
>      IntList_Chunk* lastChunk = list->prev;
>      size_t len = 0;
>+    /* allocate a new chunk_list buffer, old one my have moved
>+     * firsr, count chunks */
>      while (1) {
>-        if (len >= list->n_chunks)
>-            list->chunk_list = mem_sys_realloc(list->chunk_list,
>-                    (len + 1)* sizeof(IntList_Chunk *));
>-        list->chunk_list[len] = chunk;
>          len++;
>          if (chunk == lastChunk) break;
>          chunk = chunk->next;
>      }
>-    list->collect_runs = interpreter->dod_runs;
>+    Parrot_allocate(interpreter, &list->chunk_list,
>+                    (len+1) * sizeof(IntList_Chunk *));
>+    len = 0;
>+    chunk = list;
>+    /* then fill list */
>+    while (1) {
>+        chunk_list_ptr(list, len) = (IntList_Chunk*) chunk;
>+        len++;
>+        if (chunk == lastChunk) break;
>+        chunk = chunk->next;
>+    }
>+    list->collect_runs = interpreter->collect_runs;
>      list->n_chunks = len;
>      return len;
>  }
>@@ -172,7 +218,7 @@
>
>      if (chunk->next == list) {
>          /* Need to add a new chunk */
>-        IntList_Chunk* new_chunk = intlist_new(interpreter, 0);
>+        IntList_Chunk* new_chunk = allocate_chunk(interpreter, 0);
>          new_chunk->next = list;
>          new_chunk->prev = chunk;
>          chunk->next = new_chunk;
>@@ -190,7 +236,17 @@
>      add_chunk(interpreter, list);
>      list->prev->start = 0;
>      list->prev->end = 0;
>+    /* optimization, add new chunk directly, if still space
>+     * but only, if no collections was done in between
>+     */
>+    if (list->n_chunks >= chunk_list_size(list) ||
>+            list->collect_runs != interpreter->collect_runs)
>      rebuild_chunk_list(interpreter, list);
>+    else {
>+        /* add the appended = last chunk = list->prev to chunk_list */
>+        chunk_list_ptr(list, list->n_chunks) = list->prev;
>+        list->n_chunks++;
>+    }
>  }
>
>  static void
>@@ -223,15 +279,15 @@
>      INTVAL length = chunk->length + 1;
>      INTVAL offset;
>      IntList_Chunk * o = chunk;
>-    size_t n = chunk->n_chunks;
>
>      /* Add on a new chunk if necessary */
>      if (chunk->start == 0) {
>          unshift_chunk(interpreter, *list);
>          chunk = chunk->prev;
>          *list = chunk;
>+        /* move chunk_list to new list head */
>          (*list)->chunk_list = o->chunk_list;
>-        (*list)->n_chunks = n;
>+        /* and rebuild it from scratch */
>          rebuild_chunk_list(interpreter, *list);
>      }
>
>@@ -247,7 +303,6 @@
>      INTVAL length = chunk->length - 1;
>      INTVAL value;
>      IntList_Chunk * o = chunk;
>-    size_t n = chunk->n_chunks;
>
>      if (chunk->start >= chunk->end) {
>          internal_exception(OUT_OF_BOUNDS, "No entries on list!\n");
>@@ -262,8 +317,8 @@
>          chunk->next->prev = chunk->prev;
>          chunk->prev->next = chunk;
>          *list = chunk->next;
>+        /* like above */
>          (*list)->chunk_list = o->chunk_list;
>-        (*list)->n_chunks = n;
>          rebuild_chunk_list(interpreter, *list);
>      }
>
>@@ -285,6 +340,7 @@
>          chunk->next = list;
>          list->prev = chunk->prev;
>          chunk = chunk->prev;
>+        /* chunk_list hold one less valid entry now */
>          list->n_chunks--;
>      }
>
>@@ -306,23 +362,9 @@
>      IntList_Chunk* chunk = list;
>      UNUSED(interpreter);
>
>-#if 1
>-    if (list->collect_runs != interpreter->dod_runs)
>+    if (list->collect_runs != interpreter->collect_runs)
>          rebuild_chunk_list(interpreter, list);
>-    idx +=  chunk->start;
>-
>-    return list->chunk_list[idx / INTLIST_CHUNK_SIZE];
>-#else
>-    /* Possible optimization: start from the closer end of the chunk list */
>-
>-    /* Find the chunk containing the requested element */
>-    while (idx >= chunk->end - chunk->start) {
>-        idx -= chunk->end - chunk->start;
>-        chunk = chunk->next;
>-    }
>-
>-    return chunk;
>-#endif
>+    return chunk_list_ptr(list, idx / INTLIST_CHUNK_SIZE);
>  }
>
>  INTVAL
>@@ -339,13 +381,13 @@
>      }
>
>      if (idx < 0) idx += length;
>+    idx +=  list->start;
>
>      chunk = find_chunk(interpreter, list, idx);
>
>-    if (idx >= list->end - list->start) idx -= list->end - list->start;
>      idx = idx % INTLIST_CHUNK_SIZE;
>
>-    return ((INTVAL*)chunk->buffer.bufstart)[idx + chunk->start];
>+    return ((INTVAL*)chunk->buffer.bufstart)[idx];
>  }
>
>  static void
>@@ -394,11 +436,11 @@
>          intlist_extend(interpreter, list, idx + 1);
>      }
>
>+    idx +=  list->start;
>      chunk = find_chunk(interpreter, list, idx);
>
>-    if (idx >= list->end - list->start) idx -= list->end - list->start;
>      idx = idx % INTLIST_CHUNK_SIZE;
>-    ((INTVAL*)chunk->buffer.bufstart)[idx + chunk->start] = val;
>+    ((INTVAL*)chunk->buffer.bufstart)[idx] = val;
>  }
>
>  /*
>--- parrot/include/parrot/intlist.h    Thu Sep 26 18:30:30 2002
>+++ parrot-leo/include/parrot/intlist.h        Fri Sep 27 12:10:47 2002
>@@ -24,10 +24,12 @@
>
>  struct IntList_chunk_t {
>      Buffer buffer; /* This struct is a Buffer header subclass! */
>-    INTVAL length; /* Only valid for the "head" chunk (1) */
>-    size_t  collect_runs;       /* when chunklist was built (1) */
>-    IntList_Chunk ** chunk_list; /* list of chunks for fast access (1) */
>-    size_t n_chunks;            /* number of chunks in chunk_list */
>+    INTVAL length;              /* number of items in list (1) */
>+    size_t  collect_runs;       /* counter, when chunklist was built (1) */
>+    Buffer chunk_list;          /* holding list of chunks for fast 
>access (1) */
>+    size_t n_chunks;            /* number of used chunks in chunk_list (1) */
>+    /* all above items, marked (1) are only valid in the head junk
>+     * s. intlist.c for a detailled description */
>      INTVAL start;
>      INTVAL end;
>      IntList_Chunk* next;
>@@ -38,7 +40,7 @@
>
>  PMC* intlist_mark(Interp*, IntList*, PMC* last);
>
>-IntList *intlist_new(Interp*, int initial);
>+IntList *intlist_new(Interp*);
>
>  static INTVAL intlist_length(Interp* interpreter, IntList* list)
>  {
>--- parrot/classes/intlist.pmc Thu Sep 26 18:30:30 2002
>+++ parrot-leo/classes/intlist.pmc     Fri Sep 27 11:55:15 2002
>@@ -30,7 +30,7 @@
>      }
>
>      void init () {
>-        SELF->data = intlist_new(INTERP, 1);
>+        SELF->data = intlist_new(INTERP);
>          SELF->cache.int_val = 0;
>          SELF->flags |= PMC_custom_mark_FLAG;
>      }
>--- parrot/t/src/intlist.t     Thu Sep 26 18:30:36 2002
>+++ parrot-leo/t/src/intlist.t Fri Sep 27 15:42:25 2002
>@@ -15,7 +15,7 @@
>              if (interpreter == NULL) return 1;
>              Parrot_init(interpreter, (void*) &interpreter);
>
>-            list = intlist_new(interpreter, 1);
>+            list = intlist_new(interpreter);
>              if (list == NULL) return 1;
>
>              intlist_push(interpreter, list, 42);
>@@ -44,7 +44,7 @@
>              if (interpreter == NULL) return "create interpreter";
>              Parrot_init(interpreter, (void*) &interpreter);
>
>-            list = intlist_new(interpreter, 1);
>+            list = intlist_new(interpreter);
>              if (list == NULL) return "create list";
>
>              /* Push 3, then pop 2. Repeat N times. */
>@@ -177,7 +177,7 @@
>              if (interpreter == NULL) return 1;
>              Parrot_init(interpreter, (void*) &interpreter);
>
>-            list = intlist_new(interpreter, 1);
>+            list = intlist_new(interpreter);
>              if (list == NULL) return 1;
>
>              printf("Step 1: 0\n");
>@@ -282,7 +282,7 @@
>              if (interpreter == NULL) return 1;
>              Parrot_init(interpreter, (void*) &interpreter);
>
>-            list = intlist_new(interpreter, 1);
>+            list = intlist_new(interpreter);
>              if (list == NULL) return 1;
>
>              for (i = 0; i < INTLIST_CHUNK_SIZE * 2.5; i++) {


-- 
                                         Dan

--------------------------------------"it's like this"-------------------
Dan Sugalski                          even samurai
[EMAIL PROTECTED]                         have teddy bears and even
                                       teddy bears get drunk

Reply via email to