The attached patch adds a new stack type that only handles INTVALs.
These are much more efficient than generic stacks--on Win32 they shave a
few ten-thousandths of a second off each run of the rx_popindex op, and
take a full hundredth of a second off the benchmark.  It also shows
performance improvements on BSD.  They also take up less memory.  All
tests pass on both platforms; one warning is removed (as a side effect
of the modified interface for regex stacks) and no new ones are
introduced.

--Brent Dax
[EMAIL PROTECTED]
Parrot Configure pumpking and regex hacker

<obra> mmmm. hawt sysadmin chx0rs
<lathos> This is sad. I know of *a* hawt sysamin chx0r.
<obra> I know more than a few.
<lathos> obra: There are two? Are you sure it's not the same one?
diff -ruN -x CVS parrot-cvs/parrot/MANIFEST parrot/parrot/MANIFEST
--- parrot-cvs/parrot/MANIFEST  Wed Jan 16 01:14:26 2002
+++ parrot/parrot/MANIFEST      Tue Jan 15 18:03:52 2002
@@ -114,6 +114,8 @@
 include/parrot/resources.h
 include/parrot/runops_cores.h
 include/parrot/rx.h
+include/parrot/rxstacks.h
+include/parrot/runops_cores.h
 include/parrot/stacks.h
 include/parrot/string.h
 include/parrot/trace.h
@@ -193,6 +195,7 @@
 runops_cores.c
 rx.c
 rx.ops
+rxstacks.c
 stacks.c
 string.c
 t/harness
diff -ruN -x CVS parrot-cvs/parrot/Makefile.in parrot/parrot/Makefile.in
--- parrot-cvs/parrot/Makefile.in       Wed Jan 16 01:14:26 2002
+++ parrot/parrot/Makefile.in   Tue Jan 15 18:02:56 2002
@@ -63,7 +63,7 @@
 $(INC)/global_setup.h $(INC)/vtable.h $(INC)/oplib/core_ops.h 
$(INC)/oplib/core_ops_prederef.h \
 $(INC)/runops_cores.h $(INC)/trace.h \
 $(INC)/pmc.h $(INC)/key.h $(INC)/resources.h $(INC)/platform.h \
-$(INC)/interp_guts.h ${jit_h} ${jit_struct_h} $(INC)/rx.h
+$(INC)/interp_guts.h ${jit_h} ${jit_struct_h} $(INC)/rx.h $(INC)/rxstacks.h
 
 CLASS_O_FILES = classes/default$(O) classes/perlint$(O) classes/perlstring$(O) \
 classes/perlnum$(O) classes/perlarray$(O) classes/perlundef$(O) \
@@ -79,7 +79,7 @@
 INTERP_O_FILES = exceptions$(O) global_setup$(O) interpreter$(O) parrot$(O) 
register$(O) \
 core_ops$(O) core_ops_prederef$(O) memory$(O) packfile$(O) stacks$(O) \
 string$(O) encoding$(O) chartype$(O) runops_cores$(O) trace$(O) pmc$(O) key$(O) \
-platform$(O) ${jit_o} resources$(O) rx$(O)
+platform$(O) ${jit_o} resources$(O) rx$(O) rxstacks$(O)
 
 O_FILES = $(INTERP_O_FILES) $(IO_O_FILES) $(CLASS_O_FILES) $(ENCODING_O_FILES) 
$(CHARTYPE_O_FILES)
 
@@ -303,6 +303,8 @@
 register$(O): $(H_FILES)
 
 rx$(O): $(H_FILES)
+
+rxstacks$(O): $(H_FILES)
 
 stacks$(O): $(H_FILES)
 
diff -ruN -x CVS parrot-cvs/parrot/include/parrot/rx.h 
parrot/parrot/include/parrot/rx.h
--- parrot-cvs/parrot/include/parrot/rx.h       Wed Jan 16 01:14:26 2002
+++ parrot/parrot/include/parrot/rx.h   Tue Jan 15 14:26:50 2002
@@ -1,7 +1,7 @@
 /* rx.h
  *  Copyright: (When this is determined...it will go here)
  *  CVS Info
- *     $Id: rx.h,v 1.8 2002/01/15 22:13:39 brentdax Exp $
+ *     $Id: rx.h,v 1.7 2002/01/15 16:54:35 brentdax Exp $
  *  Overview:
  *     Supporting file for the regular expression engine
  *  Data Structure and Algorithms:
@@ -16,6 +16,7 @@
 #define PARROT_RX_H_GUARD
 
 #include "parrot/parrot.h"
+#include "parrot/rxstacks.h"
 
 typedef struct bitmap_t {
        char *bmp;
@@ -57,7 +58,7 @@
 
        opcode_t *substfunc;
 
-        struct Stack_chunk_t* stack;
+        rxStack stack;
 } rxinfo;
 
 #if __cplusplus
diff -ruN -x CVS parrot-cvs/parrot/include/parrot/rxstacks.h 
parrot/parrot/include/parrot/rxstacks.h
--- parrot-cvs/parrot/include/parrot/rxstacks.h Wed Dec 31 16:00:00 1969
+++ parrot/parrot/include/parrot/rxstacks.h     Tue Jan 15 14:30:16 2002
@@ -0,0 +1,55 @@
+/* stacks.h
+ *  Copyright: (When this is determined...it will go here)
+ *  CVS Info
+ *     $Id$
+ *  Overview:
+ *     Regex stack handling routines for Parrot
+ *  Data Structure and Algorithms:
+ *  History:
+ *  Notes:
+ *  References:
+ */
+
+#if !defined(PARROT_RXSTACKS_H_GUARD)
+#define PARROT_RXSTACKS_H_GUARD
+
+#include "parrot/parrot.h"
+
+#define STACK_CHUNK_DEPTH 256
+
+typedef struct rxStack_entry_t {
+    INTVAL value;
+}* rxStack_Entry;
+
+typedef struct rxStack_chunk_t {
+  INTVAL used;
+  struct rxStack_chunk_t *next;
+  struct rxStack_chunk_t *prev;
+  struct rxStack_entry_t entry[STACK_CHUNK_DEPTH];
+}* rxStack_Chunk;
+
+typedef rxStack_Chunk rxStack;
+
+rxStack
+rxstack_new(struct Parrot_Interp *);
+
+INTVAL
+rxstack_depth(struct Parrot_Interp *, rxStack);
+
+void
+rxstack_push(struct Parrot_Interp *, rxStack, INTVAL);
+
+INTVAL
+rxstack_pop(struct Parrot_Interp *, rxStack);
+
+#endif
+
+/*
+ * Local variables:
+ * c-indentation-style: bsd
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil 
+ * End:
+ *
+ * vim: expandtab shiftwidth=4:
+*/
diff -ruN -x CVS parrot-cvs/parrot/rx.c parrot/parrot/rx.c
--- parrot-cvs/parrot/rx.c      Wed Jan 16 01:14:26 2002
+++ parrot/parrot/rx.c  Tue Jan 15 17:57:12 2002
@@ -37,7 +37,7 @@
        rx->groupstart=pmc_new(interpreter, enum_class_PerlArray);
        rx->groupend=pmc_new(interpreter, enum_class_PerlArray);
 
-       rx->stack = new_stack(interpreter);
+       rx->stack = rxstack_new(interpreter);
        
        string_transcode(interpreter, rx->string, encoding_lookup("utf32"), 
rx->string->type, &rx->string);
 
@@ -75,18 +75,6 @@
        return bitmap_match(bmp, ch);
 }
 
-STRING *rxP_get_substr(struct Parrot_Interp *interpreter, STRING * source, INTVAL 
startindex, INTVAL length) {
-       STRING *ret;
-       
-       /*printf("rxP_get_substr(%p, %p(%d), %d, %d)", interpreter, source, -1, 
startindex, length);*/
-
-       ret=string_make(interpreter, NULL, 0, NULL, 0, NULL);
-
-       string_substr(interpreter, source, startindex, length, &ret);
-
-       return ret;
-}
-
 Bitmap bitmap_make(struct Parrot_Interp *interpreter, STRING* str) {
        UINTVAL i, ch;
        Bitmap bmp=mem_sys_allocate(sizeof(struct bitmap_t));
@@ -98,7 +86,7 @@
        }
        
        for(i=0; i < string_length(str); i++) {
-               ch=string_ord(str, i);
+               ch=string_ord(str, (INTVAL)i);
 
                if(ch > 255) {
                        bmp->bigchars=string_concat(interpreter, bmp->bigchars, 
string_make(interpreter, (void*)&ch, 1, 0, 0, 0), 0);
@@ -145,7 +133,7 @@
                UINTVAL i;
                
                for(i=0; i < string_length(bmp->bigchars); i++) {
-                       if(string_ord(bmp->bigchars, i) == ch) {
+                       if(string_ord(bmp->bigchars, (INTVAL)i) == ch) {
                                return 1;
                        }
                }
diff -ruN -x CVS parrot-cvs/parrot/rx.ops parrot/parrot/rx.ops
--- parrot-cvs/parrot/rx.ops    Wed Jan 16 01:14:26 2002
+++ parrot/parrot/rx.ops        Tue Jan 15 14:23:56 2002
@@ -225,8 +225,8 @@
        rx->minlength=0;
        rx->whichway=enum_rxdirection_forwards;
        
-       while(stack_depth(interpreter, rx->stack)) {
-               stack_pop(interpreter, rx->stack, NULL, STACK_ENTRY_INT);
+       while(rxstack_depth(interpreter, rx->stack)) {
+               rxstack_pop(interpreter, rx->stack);
        }
        
        rx->string=$2;
@@ -271,10 +271,10 @@
        rxinfo *rx2;
        RX_dUNPACK($1);
        
-       rx2=rx_allocate_info(interpreter, rx->string);
+       rx2=mem_sys_allocate(sizeof(rxinfo));
        *rx2=*rx;
        
-       rx2->stack=new_stack(interpreter);
+       rx2->stack=rxstack_new(interpreter);
 
        $1=pmc_new(interpreter, enum_class_ParrotPointer);
        $1->data=rx2;
@@ -401,7 +401,7 @@
 op rx_pushindex(in pmc) {
        RX_dUNPACK($1);
 
-       stack_push(interpreter, rx->stack, &rx->index, STACK_ENTRY_INT, NULL);
+       rxstack_push(interpreter, rx->stack, rx->index);
        
        goto NEXT();
 }
@@ -418,7 +418,7 @@
 op rx_pushmark(in pmc) {
        RX_dUNPACK($1);
 
-       stack_push(interpreter, rx->stack, (void *)&RX_MARK, STACK_ENTRY_INT, NULL);
+       rxstack_push(interpreter, rx->stack, RX_MARK);
        
        goto NEXT();
 }
@@ -436,7 +436,7 @@
        RX_dUNPACK($1);
        INTVAL i;
        
-       stack_pop(interpreter, rx->stack, &i, STACK_ENTRY_INT);
+       i=rxstack_pop(interpreter, rx->stack);
 
        if(i==RX_MARK) {
                goto OFFSET($2);
@@ -527,8 +527,8 @@
 
        rx->index=rx->startindex;
        
-       while(stack_depth(interpreter, rx->stack)) {
-               stack_pop(interpreter, rx->stack, NULL, STACK_ENTRY_INT);
+       while(rxstack_depth(interpreter, rx->stack)) {
+               rxstack_pop(interpreter, rx->stack);
        }
        
        goto NEXT();
diff -ruN -x CVS parrot-cvs/parrot/rxstacks.c parrot/parrot/rxstacks.c
--- parrot-cvs/parrot/rxstacks.c        Wed Dec 31 16:00:00 1969
+++ parrot/parrot/rxstacks.c    Tue Jan 15 14:31:20 2002
@@ -0,0 +1,102 @@
+/* rxstacks.c
+ *  Copyright: (When this is determined...it will go here)
+ *  CVS Info
+ *     $Id$
+ *  Overview:
+ *     Regex stack handling routines for Parrot
+ *  Data Structure and Algorithms:
+ *     Same as regular stacks, except they store only INTVALs and don't have
+ *     cleanup routines.
+ *  History:
+ *  Notes:
+ * References: */
+
+#include <assert.h>
+#include "parrot/parrot.h"
+#include "parrot/rxstacks.h"
+
+#define STACK_CHUNK_BASE(x) (void *)(MASK_STACK_CHUNK_LOW_BITS & (ptrcast_t)x)
+
+rxStack
+rxstack_new(struct Parrot_Interp *interpreter)
+{
+    rxStack stack=mem_allocate_aligned(sizeof(struct rxStack_chunk_t));
+    stack->used=0;
+    stack->next=stack;
+    stack->prev=stack;
+    return stack;
+}
+
+INTVAL
+rxstack_depth(struct Parrot_Interp *interpreter, rxStack stack)
+{
+    rxStack_Chunk chunk;
+    INTVAL depth = stack->used;
+
+    for (chunk = stack->next; chunk != stack; chunk = chunk->next)
+        depth += chunk->used;
+
+    return depth;
+}
+
+void
+rxstack_push(struct Parrot_Interp *interpreter, rxStack stack, INTVAL data)
+{
+    rxStack_Chunk chunk = stack->prev;
+    rxStack_Entry entry = &chunk->entry[chunk->used];
+
+    entry->value = data;
+
+    /* Register the new entry */
+    if (++chunk->used == STACK_CHUNK_DEPTH) {
+        /* Need to add a new chunk */
+        rxStack_Chunk new_chunk = mem_allocate_aligned(sizeof(*new_chunk));
+        new_chunk->used = 0;
+        new_chunk->next = stack;
+        new_chunk->prev = chunk;
+        chunk->next = new_chunk;
+        stack->prev = new_chunk;
+    }
+}
+
+INTVAL
+rxstack_pop(struct Parrot_Interp *interpreter, rxStack stack)
+{
+    rxStack_Chunk chunk = stack->prev;
+    rxStack_Entry entry;
+
+    /* We may have an empty chunk at the end of the list */
+    if (chunk->used == 0 && chunk != stack) {
+        /* That chunk != stack check is just to allow the empty stack case
+         * to fall through to the following exception throwing code. */
+
+        /* Need to pop off the last entry */
+        stack->prev = chunk->prev;
+        stack->prev->next = stack;
+        /* Relying on GC feels dirty... */
+        chunk = stack->prev;
+    }
+    
+    /* Quick sanity check */
+    if (chunk->used == 0) {
+        INTERNAL_EXCEPTION(ERROR_STACK_EMPTY, "No entries on stack!\n");
+    }
+
+    entry = &chunk->entry[chunk->used - 1];
+
+    /* Now decrement the SP */
+    chunk->used--;
+
+    /* Snag the value */
+    return entry->value;
+}
+
+/*
+ * Local variables:
+ * c-indentation-style: bsd
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil 
+ * End:
+ *
+ * vim: expandtab shiftwidth=4:
+*/

Reply via email to