Added features:

1) 'alloci(i,i|ic)' - Allocates $2 integers, sets $1 to a "reference" to
the new arena
2) 'freei(i)' - Frees the arena referenced by $1
3) 'savei(i,i,i|ic)' - Saves the integer register at $1 into arena $2,
at index $3
4) 'loadi(i,i,i|ic)' - Loads the integer from arena $2, index $3 into
register $1

The 'alloci' operator creates an isolated memory space that can be used
for local variables, global spaces, or arrays.
The 'freei' frees the memory space when it is no longer needed. The
interpreter frees space that hasn't been manually freed at the end of
the run.

'savei' and 'loadi' saves values into the memory space and loads from
it.

Arenas can be assigned to subroutines, allocated for a global variable
space, and fixed-size arrays. Since members of arenas can themselves be
arenas, this lets us create complex data structures, nesting arrays (or
eventually hashes) within arrays, a bit of compiler support and PMCs can
let us implement simple hashes...

One other item that would require some rewriting would be to make the
references more opaque. Currently the references are simply the position
in the linked-list of arenas. I chose the simplest implementation, but
doing something like assigning pseudorandom values to the various
elements of the linked list makes it pretty much impossible to get
access to an arena by simply setting a register to a known value. I
don't think it's a security issue, but it is a concern for compiler
writers debugging their code. Making things pseudorandom makes it
unlikely that an arena can be accessed by accident.

--Jeff
<[EMAIL PROTECTED]>

diff -ru parrot/core.ops parrot_old/core.ops
--- parrot/core.ops     Wed Oct 31 23:39:40 2001
+++ parrot_old/core.ops Wed Oct 31 19:56:44 2001
@@ -105,65 +105,6 @@
 
 ###############################################################################
 
-=head2 Memory creation and destruction operations
-
-These operations create and destroy blocks of memory cells
-
-=over 4
-
-=cut
-
-
-########################################
-
-=item B<alloci>(i, i|ic)
-
-Allocate $2 integer cells, create an identifier and store a reference in $1.
-
-=cut
-
-=item B<freei>(i)
-
-Free the allocated cell block,
-
-=cut
-
-=item B<loadi>(i,i,i|ic)
-
-Copy the integer cell at index $3 in chunk $2 into register $1
-
-=cut
-
-=item B<savei>(i,i,i|ic)
-
-Copy the integer register $1 into index $3 of chunk $2
-
-=cut
-
-
-AUTO_OP alloci(i, i|ic) {
-  $1 = VarChunk_alloc_i(interpreter,$2);
-}
-
-AUTO_OP freei(i) {
-  VarChunk_free_i(interpreter,$1);
-}
-
-AUTO_OP loadi(i,i,i|ic) {
-  $1 = VarChunk_load_i(interpreter,$2,$3);
-}
-
-AUTO_OP savei(i,i,i|ic) {
-  VarChunk_save_i(interpreter,$2,$3,$1);
-}
-
-=back
-
-=cut
-
-
-###############################################################################
-
 =head2 Register loading operations
 
 These operations load registers from constants or other registers.
diff -ru parrot/include/parrot/interpreter.h parrot_old/include/parrot/interpreter.h
--- parrot/include/parrot/interpreter.h Wed Oct 31 21:07:13 2001
+++ parrot_old/include/parrot/interpreter.h     Wed Oct 31 19:56:45 2001
@@ -34,8 +34,6 @@
                                           /* variable area */
     struct Arenas *arena_base;            /* Pointer to this */
                                           /* interpreter's arena */
-    struct VarChunk *var_head;            /* Head of the memory linked list */
-    struct VarChunk *var_tail;            /* Tail of the memory linked list */
 
     op_info_t * opcode_info;              /* Opcode info table (name, nargs, arg 
types) */
     opcode_t     *(**opcode_funcs)();     /* Opcode function table */
diff -ru parrot/include/parrot/register.h parrot_old/include/parrot/register.h
--- parrot/include/parrot/register.h    Wed Oct 31 23:11:17 2001
+++ parrot_old/include/parrot/register.h        Wed Oct 31 19:56:45 2001
@@ -63,18 +63,6 @@
     struct PReg PReg[FRAMES_PER_CHUNK];
 };
 
-struct VarChunk {
-    struct VarChunk *next;
-    struct VarChunk *prev;
-    INTVAL *data;
-};
-
-int VarChunk_alloc_i(struct Parrot_Interp *, int);
-void VarChunk_free_i(struct Parrot_Interp *, int);
-
-int VarChunk_load_i(struct Parrot_Interp *, int, int);
-void VarChunk_save_i(struct Parrot_Interp *, int, int, int);
-
 /* These macros masks off the low bits of a register chunk address,
    since we're guaranteed to be aligned */
 #define INT_CHUNK_BASE(x) (void *)(MASK_INT_CHUNK_LOW_BITS & (ptrcast_t)x)
diff -ru parrot/interpreter.c parrot_old/interpreter.c
--- parrot/interpreter.c        Wed Oct 31 23:30:32 2001
+++ parrot_old/interpreter.c    Wed Oct 31 19:56:44 2001
@@ -187,10 +187,6 @@
     
     /* Need an empty stash */
     interpreter->perl_stash = mem_allocate_new_stash();
-
-    /* Initialize the memory arena pointers */
-    interpreter->var_head = NULL;
-    interpreter->var_tail = NULL;
     
     /* Load the core op func and info tables */
 
@@ -206,10 +202,6 @@
     interpreter->profile = (INTVAL *)NULL;
 
     interpreter->resume_addr = (opcode_t *)NULL;
-
-    while(interpreter->var_head != NULL) {
-        VarChunk_free_i(interpreter,0);
-    }
 
     return interpreter;   
 }
diff -ru parrot/register.c parrot_old/register.c
--- parrot/register.c   Wed Oct 31 23:15:46 2001
+++ parrot_old/register.c       Wed Oct 31 19:56:44 2001
@@ -12,114 +12,6 @@
 
 #include "parrot/parrot.h"
 
-
-/*=for api register VarChunk_local_alloc_i
-  Creates a new integer memory range and returns that pointer
-*/
-static struct VarChunk*
-VarChunk_local_alloc_i(int size) {
-    struct VarChunk* new_chunk = malloc(sizeof(struct VarChunk));
-    new_chunk->data = malloc(sizeof(INTVAL)*size);
-    return new_chunk;
-}
-
-/*=for api register VarChunk_local_free_i
-  Frees an integer memory range
-*/
-static void
-VarChunk_local_free_i(struct VarChunk* free_me) {
-    free(free_me->data);
-    free(free_me);
-}
-
-/*=for api register VarChunk_alloc_i
-*/
-int
-VarChunk_alloc_i(struct Parrot_Interp* interpreter, int size) {
-  struct VarChunk *new_chunk = VarChunk_local_alloc_i(size);
-  struct VarChunk *tmp_chunk;
-  int count = 0;
-
-  new_chunk->next = NULL;
-  new_chunk->prev = NULL;
-  if(interpreter->var_head==NULL) {
-    interpreter->var_head = new_chunk;
-    interpreter->var_tail = new_chunk;
-  } else {
-    interpreter->var_tail->next = new_chunk;
-    new_chunk->prev = interpreter->var_tail;
-    interpreter->var_tail = new_chunk;
-  }
-  tmp_chunk = interpreter->var_head;
-  while(tmp_chunk->next != NULL) {
-    tmp_chunk = tmp_chunk->next;
-    count++;
-  }
-  return count;
-}
-
-/*=for api register VarChunk_free_i
-*/
-void
-VarChunk_free_i(struct Parrot_Interp* interpreter, int chunk) {
-
-  if(interpreter->var_head == NULL &&
-     interpreter->var_tail == NULL) {
-  }
-  else if(interpreter->var_head ==
-          interpreter->var_tail) {
-    VarChunk_local_free_i(interpreter->var_head);
-    interpreter->var_head = NULL;
-    interpreter->var_tail = NULL;
-  }
-  else {
-    struct VarChunk *cur = interpreter->var_head;
-    struct VarChunk *prev;
-    struct VarChunk *next;
-    while(--chunk>0) {
-      cur = cur->next;
-    }
-    prev = cur->prev;
-    next = cur->next;
-
-    if(prev == NULL) {
-      interpreter->var_head = next;
-      interpreter->var_head->prev = NULL;
-    }
-    else if(next == NULL) {
-      interpreter->var_tail = prev;
-      interpreter->var_tail->next = NULL;
-    }
-    else {
-      prev->next = next;
-      next->prev = prev;
-    }
-    VarChunk_local_free_i(cur);
-  }
-}
-
-/*=for VarChunk_load_i
-*/
-int
-VarChunk_load_i(struct Parrot_Interp* interpreter, int chunk, int index ) {
-  struct VarChunk *cur = interpreter->var_head;
-  while(--chunk>0) {
-    cur = cur->next;
-  }
-  return cur->data[index];
-}
-
-/*=for VarChunk_save_i
-*/
-void
-VarChunk_save_i(struct Parrot_Interp* interpreter, int chunk, int index, int value ) {
-  struct VarChunk *cur = interpreter->var_head;
-  while(--chunk>0) {
-    cur = cur->next;
-  }
-  cur->data[index] = value;
-}
-
 /*=for api register Parrot_push_i
   pushes a new integer register frame on the frame stack
 */
#! perl -w

use Parrot::Test tests => 2;

output_is(<<CODE, <<OUTPUT, "basic allocation");
alloci I0,5
freei I0
end
CODE
OUTPUT

output_is(<<CODE, <<OUTPUT, "Allocate and store");
set I1,-7
set I2,5
set I3,81
alloci I0,5
savei I1,I0,0
savei I2,I0,1
savei I3,I0,2
cleari
loadi I4,I0,0
loadi I5,I0,1
loadi I6,I0,2
freei I0
print I4
print "\\n"
print I5
print "\\n"
print I6
print "\\n"
end
CODE
-7
5
81
OUTPUT

Reply via email to