parrotcode: Register handling routines | |
Contents | C |
src/gc/register.c - Register handling routines
Parrot has 4 register sets, one for each of its basic types. The amount of registers in each set varies depending on the use counts of the respective subroutine and is determined by the PASM/PIR compiler in the register allocation pass (imcc/reg_alloc.c).
There is one register stack to support the saveall
and restoreall
opcodes.
The former copies all registers to a newly allocated storage and points the register base pointers to this storage.
In Parrot_pop_regs
the register base pointers are restored to the previous values and the allocated register memory is discarded.
+----------++----+------+------------+----+
| context || N | I | P | S +
+----------++----+------+------------+----+
^ ^ ^ ^
| | ctx.bp ctx.bp_ps
ctx.state opt
padding
Registers are addressed as usual via the register base pointer ctx.bp.
The macro CONTEXT() hides these details
There are two allocation strategies: chunked memory and malloced with a free list.
CHUNKED_CTX_MEM = 1
ctx_mem.data
is a pointer to an allocated chunk of memory. The pointer ctx_mem.free
holds the next usable location. With (full) continuations the ctx_mem.free
pointer can't be moved below the ctx_mem.threshold
, which is the highest context pointer of all active continuations. [the code for this is incomplete; it had suffered some bit-rot and was getting in the way of maintaining the other case. -- rgr, 4-Feb-06.]
RT#46177 GC has to lower this threshold when collecting continuations.
CHUNKED_CTX_MEM = 0
Context/register memory is malloced. ctx_mem.free
is used as a free list of reusable items.
Round register allocation size up to the nearest multiple of 8. A granularity of 8 is arbitrary, it could have been some bigger power of 2. A "slot" is an index into the free_list array. Each slot in free_list has a linked list of pointers to already allocated contexts available for (re)use. The slot where an available context is stored corresponds to the size of the context.
void destroy_context(PARROT_INTERP)
void create_initial_context(PARROT_INTERP)
PARROT_API void parrot_gc_context(PARROT_INTERP)
static void clear_regs(PARROT_INTERP, NOTNULL(parrot_context_t *ctx))
static void init_context(PARROT_INTERP, NOTNULL(parrot_context_t *ctx), ARGIN_NULLOK(const parrot_context_t *old))
PARROT_WARN_UNUSED_RESULT PARROT_CANNOT_RETURN_NULL struct Parrot_Context *Parrot_dup_context(PARROT_INTERP, ARGIN(const struct Parrot_Context *old))
PARROT_API PARROT_WARN_UNUSED_RESULT PARROT_CANNOT_RETURN_NULL struct Parrot_Context *Parrot_push_context(PARROT_INTERP, NOTNULL(INTVAL *n_regs_used))
caller_ctx
, suitable to use with Parrot_pop_context
.PARROT_API void Parrot_pop_context(PARROT_INTERP)
Parrot_push_context
and restore the previous context.PARROT_CANNOT_RETURN_NULL PARROT_WARN_UNUSED_RESULT struct Parrot_Context *Parrot_alloc_context(PARROT_INTERP, NOTNULL(INTVAL *number_regs_used))
n_regs_used
is copied. The function returns the new context.PARROT_API void Parrot_free_context(PARROT_INTERP, NOTNULL(struct Parrot_Context *ctxp), int re_use)
re_use
is true, this function is called by a return continuation invoke, else from the destructor of a continuation.PARROT_API void Parrot_set_context_threshold(PARROT_INTERP, NULLOK(struct Parrot_Context *ctxp))
void setup_register_stacks(PARROT_INTERP)
PARROT_API void Parrot_push_regs(PARROT_INTERP)
PARROT_API void Parrot_pop_regs(PARROT_INTERP)
void mark_register_stack(PARROT_INTERP, NOTNULL(Stack_Chunk_t *chunk))
PARROT_API void Parrot_clear_i(PARROT_INTERP)
PARROT_API void Parrot_clear_s(PARROT_INTERP)
PARROT_API void Parrot_clear_p(PARROT_INTERP)
PARROT_API void Parrot_clear_n(PARROT_INTERP)
include/parrot/register.h and src/stack_common.c
|