Okay, I've checked in the final bits needed to do memory allocations and such within Parrot. Here's the scoop.
For memory you need to allocate from the system, use mem_sys_allocate. Takes a size, returns a void pointer to the allocated memory. Free it up with mem_sys_free, or it leaks. To resize, call mem_sys_realloc. You may *only* free or realloc memory this way if it came from mem_sys_allocate. Otherwise Bad Things Happen. (These are small wrappers around malloc, free, and realloc) You generally should *not* do that if you can avoid it, and do *not* hang this memory off a PMC or a buffer unless you set flag bits properly. For GCable memory, it's a little easier. All GCable memory must hang off something that looks like a Buffer. (As defined in string.h at the moment) A base Buffer structure has a memory pointer, buffer length, and flag field. You may have anything after this that you like. (More on that later) To allocate a buffer header, call new_tracked_header(interpreter, size). The interpreter is the interpreter you're allocating the buffer from (Better be the current one) and size is how big the buffer header should be in bytes. Anything after the first three fields is yours to play with if you need it. To allocate a string header, call new_string_header(interpreter). This is equivalent to calling new_tracked_header(interpreter, sizeof(struct STRING)) with some extra setup after the buffer header has been allocated. To allocate memory that is GCable, call Parrot_allocate(interpreter, size). Then stash the pointer and size in your buffer header, or it'll go missing later. To resize a chunk of memory, call mem_realloc(interpreter, from, oldsize, newsize). If your buffer points to non-moveable memory, set the BUFFER_immobile_FLAG bit in the buffer struct. The memory then won't be moved. Do *not* set this for memory allocated with Parrot_allocate! If the memory is system memory and should be freed when the buffer is GC'd, set the BUFFER_sysmem_FLAG bit. Generally you'll set both. (The exception is for memory owned externally, in which case immobile will be set but sysmem won't be. In that case the buffer will be neither moved nor freed on cleanup) When you're done with memory or a buffer header or a string header, just let them fall on the floor. The GC will pick them up. You may call free_string or free_tracked if you want, in which case the GC won't need to do any work. Only do this if you're sure that nobody is pointing to the string/buffer header. If your memory cleanup routine is called from within the GC (we'll get to that in another message), call gc_used on the memory you want to retain. The parameters are the same as for mem_realloc, which gives you the chance to shrink (*not* grow) the chunk of memory you have. Call it even if things don't change--if there's a compacting collector your memory will be moved. Possible bugs: ============== If you're not careful, here's what can happen. If your buffer header can't be reached from the root set, you'll end up having it reclaimed when a sweep is made. If you store a pointer to memory but don't have it hanging off a reachable buffer header, it'll get stomped on and reused. If you do have memory in a buffer but cache the pointer, you can find it yanked out from under you by the GC system. (I.e. the pointer not in the buffer may be invalid) -- Dan --------------------------------------"it's like this"------------------- Dan Sugalski even samurai [EMAIL PROTECTED] have teddy bears and even teddy bears get drunk