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;
}
}
}
}
Thread Previous