The Parrot_Context allocator in src/gc/register.c tries to be clever. As
contexts can contain a variable number of each type of register, the theory
goes that Parrot_Contexts can have variable sizes. There's an array of free
lists of various sizes. Instead of the malloc()/free() pair for each context
created and destroyed, the system uses this free list.
Of course, it still uses malloc()/free() to manage the lifecycle of the arrays
used to *store* the number of each type of register used. These arrays all
have four INTVAL members. For each new context used -- not allocated and
recycled to the free list, but *used* -- Parrot malloc()s a new four-INTVAL
array. For each context recycled to the free list, Parrot free()s that four-
INTVAL array.
This stupid little patch makes the smallest, least invasive change to allocate
that array used for *every* Parrot_Context as part of the context itself. It
halves the cost of creating a context and reduces the cost of recycling a
context by 2/3. This is most noticable when calling a lot of PIR functions.
This patch could use some cleanup; getting rid of accesses to this array is
probably an improvement for encapsulation. I'm attaching it now instead of
applying it because it needs testing on other platforms, and it's too close to
Tuesday's release for my comfort. The release manager may disagree, which is
fine.
-- c
=== include/parrot/interpreter.h
==================================================================
--- include/parrot/interpreter.h (revision 38917)
+++ include/parrot/interpreter.h (local)
@@ -231,6 +231,10 @@
/* code->prederefed.code - code->base.data in opcodes
* to simplify conversion between code ptrs in e.g. invoke */
size_t pred_offset;
+ INTVAL num_int_regs_used;
+ INTVAL num_num_regs_used;
+ INTVAL num_str_regs_used;
+ INTVAL num_pmc_regs_used;
};
struct _Thread_data; /* in thread.h */
=== src/gc/register.c
==================================================================
--- src/gc/register.c (revision 38917)
+++ src/gc/register.c (local)
@@ -307,8 +307,8 @@
ctx->outer_ctx = NULL;
ctx->current_cont = NULL;
ctx->current_object = NULL;
- ctx->current_HLL = 0;
ctx->handlers = PMCNULL;
+ ctx->caller_ctx = NULL;
if (old) {
/* some items should better be COW copied */
@@ -322,6 +322,16 @@
/* end COW */
ctx->recursion_depth = old->recursion_depth;
}
+ else {
+ ctx->constants = NULL;
+ ctx->warns = 0;
+ ctx->errors = 0;
+ ctx->trace_flags = 0;
+ ctx->pred_offset = 0;
+ ctx->current_HLL = 0;
+ ctx->current_namespace = PMCNULL;
+ ctx->recursion_depth = 0;
+ }
/* other stuff is set inside Sub.invoke */
clear_regs(interp, ctx);
@@ -431,11 +441,7 @@
const int slot = CALCULATE_SLOT_NUM(reg_alloc);
/* this gets attached to the context, which should free it */
- INTVAL * const n_regs_used = mem_allocate_n_zeroed_typed(4, INTVAL);
- n_regs_used[REGNO_INT] = number_regs_used[REGNO_INT];
- n_regs_used[REGNO_NUM] = number_regs_used[REGNO_NUM];
- n_regs_used[REGNO_STR] = number_regs_used[REGNO_STR];
- n_regs_used[REGNO_PMC] = number_regs_used[REGNO_PMC];
+ INTVAL *n_regs_used;
/*
* If slot is beyond the end of the allocated list, extend the list to
@@ -470,17 +476,23 @@
}
else {
const size_t to_alloc = reg_alloc + ALIGNED_CTX_SIZE;
- ctx = (Parrot_Context *)mem_sys_allocate_zeroed(to_alloc);
+ ctx = (Parrot_Context *)mem_sys_allocate(to_alloc);
}
+ n_regs_used = &(ctx->num_int_regs_used);
+ n_regs_used[REGNO_INT] = number_regs_used[REGNO_INT];
+ n_regs_used[REGNO_NUM] = number_regs_used[REGNO_NUM];
+ n_regs_used[REGNO_STR] = number_regs_used[REGNO_STR];
+ n_regs_used[REGNO_PMC] = number_regs_used[REGNO_PMC];
+
#if CTX_LEAK_DEBUG
if (Interp_debug_TEST(interp, PARROT_CTX_DESTROY_DEBUG_FLAG)) {
fprintf(stderr, "[alloc ctx %p]\n", ctx);
}
#endif
- ctx->regs_mem_size = reg_alloc;
- ctx->n_regs_used = n_regs_used;
+ ctx->regs_mem_size = reg_alloc;
+ ctx->n_regs_used = n_regs_used;
/* regs start past the context */
p = (void *) ((char *)ctx + ALIGNED_CTX_SIZE);
@@ -590,10 +602,8 @@
if (ctx->outer_ctx)
Parrot_free_context(interp, ctx->outer_ctx, 1);
- if (ctx->n_regs_used) {
- mem_sys_free(ctx->n_regs_used);
+ if (ctx->n_regs_used)
ctx->n_regs_used = NULL;
- }
#if CTX_LEAK_DEBUG_FULL
/* for debugging, poison the freed context in case anything
_______________________________________________
http://lists.parrot.org/mailman/listinfo/parrot-dev