Dan Sugalski wrote:

> This feels excessively hackish. It's OK if we were welding in COW to
> an existing code base, but we're not--if we put it in, we put it in
> right.
>
> Right, in this case, is using the COW flag bit in the Buffer
> structure and making the changes to the appropriate string_*
> functions to use it, I think.

The COW flag bit in the string header is used by the string functions;
however, for GC purposes, I need a flag within the buffer as well, to
identify buffers which have already been copied, since multiple string
headers could point to the same physical buffer. That is the best I can do,
so perhaps we should leave COW for somebody else to implement later.

For interest, I am attaching an extract from my version of resources.c (not
in diff format, because I have not completed syncing yet - things keep
changing!)

strstart is a void* field in STRING, pointing to the start of the string of
interest in the buffer; this could be omitted if substrings were not COWed
The last byte of the allocated buffer is always set to zero by string_make
and other string creators
When a buffer is copied, the address of the first STRING that referenced it
is stored in the (old copy of the) buffer, and the in-buffer flag is set; if
the same buffer is encountered later, the second header is simply adjusted
to point to the new location.

--
Peter Gibbs
EmKel Systems

/* Run through all the string header pools and copy */
 for (cur_string_arena = interpreter->arena_base->last_STRING_Arena;
       NULL != cur_string_arena;
       cur_string_arena = cur_string_arena->prev) {
    UINTVAL i;
    STRING *string_array = cur_string_arena->start_STRING;
    for (i = 0; i < cur_string_arena->used; i++) {
      /* Is the string live, and can we move it? */
      if (string_array[i].flags & BUFFER_live_FLAG
          && !(string_array[i].flags & BUFFER_immobile_FLAG)
          && string_array[i].bufstart) {
          UINTVAL offset = (char *)string_array[i].strstart
                         - (char *)string_array[i].bufstart;
         if (string_array[i].flags & BUFFER_COW_FLAG
         && ((char*)(string_array[i].bufstart))[string_array[i].buflen]) {
           /* buffer has already been copied; just change the header */
           STRING* hdr = *(STRING **)(string_array[i].bufstart);
           hdr->flags |= BUFFER_COW_FLAG;
           string_array[i].bufstart = hdr->bufstart;
           string_array[i].strstart = (char *)(string_array[i].bufstart) +
offse
t;
         }
         else {
           memcpy(cur_spot, string_array[i].bufstart,
                  string_array[i].buflen+1);
           if (string_array[i].flags & BUFFER_COW_FLAG) {
             /* store new address and set 'buffer already copied' flag */
             *(STRING **)(string_array[i].bufstart) = &string_array[i];
             string_array[i].flags &= ~BUFFER_COW_FLAG;
             ((char*)(string_array[i].bufstart))[string_array[i].buflen] =
1;
           }
           string_array[i].bufstart = cur_spot;
           string_array[i].strstart = (char *)(string_array[i].bufstart) +
offse
t;
           cur_size = string_array[i].buflen;
           cur_size += 16;
           cur_size &= ~0x0f;
           cur_spot += cur_size;
         }
      }
    }
  }




Reply via email to