summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--colm/bytecode.h17
-rw-r--r--colm/program.c39
2 files changed, 36 insertions, 20 deletions
diff --git a/colm/bytecode.h b/colm/bytecode.h
index d07dfb2e..f3661230 100644
--- a/colm/bytecode.h
+++ b/colm/bytecode.h
@@ -414,13 +414,14 @@ typedef unsigned char uchar;
#define IFR_RFR 0 /* return frame pointer */
/* Exported to modules other than bytecode.c */
-#define vm_push(i) ( ( sp == prg->sb_beg ? (sp = vm_grow(prg, sp, 1)) : 0 ), (*(--sp) = (i)) )
-#define vm_pop() ({ SW r = *sp++; if ( sp == prg->sb_end ) { sp = vm_shrink(prg); }; r; })
-#define vm_pop_ignore() ({ sp++; if ( sp == prg->sb_end ) { sp = vm_shrink(prg); }; })
-#define vm_pushn(n) ( ( (sp-(n)) < prg->sb_beg ? (sp = vm_grow(prg, sp, n)) : 0 ),(sp -= (n)) )
-#define vm_popn(n) ( ( (sp+(n)) > prg->sb_end ? (sp = vm_shrink(prg)) : 0 ), (sp += (n)) )
+#define vm_push(i) ( ( sp == prg->sb_beg ? (sp = vm_bs_add(prg, sp, 1)) : 0 ), (*(--sp) = (i)) )
+#define vm_pushn(n) ( ( (sp-(n)) < prg->sb_beg ? (sp = vm_bs_add(prg, sp, n)) : 0 ), (sp -= (n)) )
-#define vm_contiguous(n) ( ( (sp-(n)) < prg->sb_beg ? (sp = vm_grow(prg, sp, n)) : 0 ) )
+#define vm_pop() ({ SW r = *sp; (sp+1) >= prg->sb_end ? (sp = vm_bs_pop(prg, sp, 1)) : (sp += 1); r; })
+#define vm_pop_ignore() ({ (sp+1) >= prg->sb_end ? (sp = vm_bs_pop(prg, sp, 1)) : (sp += 1); })
+#define vm_popn(n) ({ (sp+(n)) >= prg->sb_end ? (sp = vm_bs_pop(prg, sp, n)) : (sp += (n)); })
+
+#define vm_contiguous(n) ( ( (sp-(n)) < prg->sb_beg ? (sp = vm_bs_add(prg, sp, n)) : 0 ) )
#define vm_top() (*sp)
#define vm_ptop() (sp)
@@ -433,8 +434,8 @@ typedef unsigned char uchar;
#define vm_plocal_iframe(o) (&exec->iframePtr[o])
void vm_init( struct ColmProgram * );
-Tree** vm_grow( struct ColmProgram *, Tree **, int );
-Tree** vm_shrink( struct ColmProgram * );
+Tree** vm_bs_add( struct ColmProgram *, Tree **, int );
+Tree** vm_bs_pop( struct ColmProgram *, Tree **, int );
void vm_clear( struct ColmProgram * );
typedef Tree *SW;
diff --git a/colm/program.c b/colm/program.c
index ed983c46..5e1a6a9a 100644
--- a/colm/program.c
+++ b/colm/program.c
@@ -92,7 +92,7 @@ void vm_init( Program *prg )
prg->stackRoot = prg->sb_end;
}
-Tree **vm_grow( Program *prg, Tree **sp, int n )
+Tree **vm_bs_add( Program *prg, Tree **sp, int n )
{
/* Close off the current block. */
if ( prg->stackBlock != 0 ) {
@@ -127,32 +127,47 @@ Tree **vm_grow( Program *prg, Tree **sp, int n )
return prg->sb_end;
}
-Tree **vm_shrink( Program *prg )
+Tree **vm_bs_pop( Program *prg, Tree **sp, int n )
{
- if ( prg->stackBlock->next == 0 ) {
- /* Don't delete the sentinal stack block. Returns the end as in the
- * creation of the first stack block. */
- return prg->sb_end;
- }
- else {
+ while ( 1 ) {
+ Tree **end = prg->stackBlock->data + prg->stackBlock->len;
+ int remaining = end - sp;
+
+ /* Don't have to free this block. Remaining values to pop leave us
+ * inside it. */
+ if ( n < remaining ) {
+ sp += n;
+ return sp;
+ }
+
+ if ( prg->stackBlock->next == 0 ) {
+ /* Don't delete the sentinal stack block. Returns the end as in the
+ * creation of the first stack block. */
+ return prg->sb_end;
+ }
+
+ /* Clear any previous reserve. We are going to save this block as the
+ * reserve. */
if ( prg->reserve != 0 ) {
free( prg->reserve->data );
free( prg->reserve );
}
+ /* Pop the stack block. */
StackBlock *b = prg->stackBlock;
prg->stackBlock = prg->stackBlock->next;
-
prg->reserve = b;
- /* FIXME: need to use offset here? Maybe we can grant more space in
- * case any push that follows has fewer requirements. */
+ /* Setup the bounds. Need to use offset here? Maybe we can grant more
+ * space in case any push that follows has fewer requirements. */
prg->sb_beg = prg->stackBlock->data + prg->stackBlock->offset;
prg->sb_end = prg->stackBlock->data + prg->stackBlock->len;
+ /* Update the total stack usage. */
prg->sb_total -= prg->stackBlock->len - prg->stackBlock->offset;
- return prg->sb_beg;
+ n -= remaining;
+ sp = prg->sb_beg;
}
}