cvsuser 03/06/06 01:29:18
Modified: . MANIFEST MANIFEST.detailed dod.c headers.c
interpreter.c jit_debug.c pmc.c resources.c
smallobject.c
Log:
arena-dod-flags: s. notes on p6i
Revision Changes Path
1.350 +2 -0 parrot/MANIFEST
Index: MANIFEST
===================================================================
RCS file: /cvs/public/parrot/MANIFEST,v
retrieving revision 1.349
retrieving revision 1.350
diff -u -w -r1.349 -r1.350
--- MANIFEST 30 May 2003 17:17:00 -0000 1.349
+++ MANIFEST 6 Jun 2003 08:29:18 -0000 1.350
@@ -71,6 +71,7 @@
config/auto/jit/test_c.in
config/auto/memalign.pl
config/auto/memalign/test_c.in
+config/auto/memalign/test_c2.in
config/auto/pack.pl
config/auto/sizes.pl
config/auto/sizes/test_c.in
@@ -107,6 +108,7 @@
config/gen/platform/generic.c
config/gen/platform/generic.h
config/gen/platform/ia64.s
+config/gen/platform/platform_interface.h
config/gen/platform/win32.c
config/gen/platform/win32.h
config/init/data.pl
1.23 +2 -0 parrot/MANIFEST.detailed
Index: MANIFEST.detailed
===================================================================
RCS file: /cvs/public/parrot/MANIFEST.detailed,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -w -r1.22 -r1.23
--- MANIFEST.detailed 28 May 2003 14:56:29 -0000 1.22
+++ MANIFEST.detailed 6 Jun 2003 08:29:18 -0000 1.23
@@ -70,6 +70,7 @@
[] config/auto/jit/test_c.in
[] config/auto/memalign.pl
[] config/auto/memalign/test_c.in
+[] config/auto/memalign/test_c2.in
[] config/auto/pack.pl
[] config/auto/sizes.pl
[] config/auto/sizes/test_c.in
@@ -106,6 +107,7 @@
[] config/gen/platform/generic.c
[] config/gen/platform/generic.h
[] config/gen/platform/ia64.s
+[] config/gen/platform/platform_interface.h
[] config/gen/platform/win32.c
[] config/gen/platform/win32.h
[] config/init/data.pl
1.55 +229 -31 parrot/dod.c
Index: dod.c
===================================================================
RCS file: /cvs/public/parrot/dod.c,v
retrieving revision 1.54
retrieving revision 1.55
diff -u -w -r1.54 -r1.55
--- dod.c 1 Jun 2003 00:17:43 -0000 1.54
+++ dod.c 6 Jun 2003 08:29:18 -0000 1.55
@@ -1,7 +1,7 @@
/* dod.c
* Copyright: (When this is determined...it will go here)
* CVS Info
- * $Id: dod.c,v 1.54 2003/06/01 00:17:43 josh Exp $
+ * $Id: dod.c,v 1.55 2003/06/06 08:29:18 leo Exp $
* Overview:
* Handles dead object destruction of the various headers
* Data Structure and Algorithms:
@@ -12,6 +12,7 @@
* References:
*/
+#define DOD_C_SOURCE
#include "parrot/parrot.h"
#include "parrot/method_util.h"
#include <assert.h>
@@ -31,6 +32,37 @@
static size_t find_common_mask(size_t val1, size_t val2);
+#if ARENA_DOD_FLAGS
+
+void pobject_lives(struct Parrot_Interp *interpreter, PObj *obj)
+{
+
+ struct Small_Object_Arena *arena = GET_ARENA(obj);
+ size_t n = GET_OBJ_N(arena, obj);
+ size_t ns = n >> ARENA_FLAG_SHIFT;
+ UINTVAL nm = (n & ARENA_FLAG_MASK) << 2;
+ UINTVAL *dod_flags = arena->dod_flags + ns;
+ if (*dod_flags & ((PObj_on_free_list_FLAG | PObj_live_FLAG) << nm))
+ return;
+ ++arena->live_objects;
+ *dod_flags |= PObj_live_FLAG << nm;
+
+ if (*dod_flags & (PObj_is_special_PMC_FLAG << nm)) {
+ if (((PMC*)obj)->pmc_ext) {
+ /* put it on the end of the list */
+ interpreter->mark_ptr->next_for_GC = (PMC *)obj;
+ /* Explicitly make the tail of the linked list be
+ * self-referential */
+ interpreter->mark_ptr = ((PMC*)obj)->next_for_GC = (PMC *)obj;
+ }
+ else if (PObj_custom_mark_TEST(obj))
+ VTABLE_mark(interpreter, (PMC *) obj);
+ return;
+ }
+}
+
+#else
+
/* Tag a buffer header as alive. Used by the GC system when tracing
* the root set, and used by the PMC GC handling routines to tag their
* individual pieces if they have private ones */
@@ -55,16 +87,16 @@
/* if object is a PMC and contains buffers or PMCs, then attach
* the PMC to the chained mark list
*/
- if (PObj_is_PMC_TEST(obj)) {
- UINTVAL mask = PObj_is_PMC_ptr_FLAG | PObj_is_buffer_ptr_FLAG
- | PObj_custom_mark_FLAG;
- if ( (PObj_get_FLAGS(obj) & mask) || ((PMC*)obj)->metadata) {
+ if (PObj_is_special_PMC_TEST(obj)) {
+ if (((PMC*)obj)->pmc_ext) {
/* put it on the end of the list */
interpreter->mark_ptr->next_for_GC = (PMC *)obj;
/* Explicitly make the tail of the linked list be
* self-referential */
interpreter->mark_ptr = ((PMC*)obj)->next_for_GC = (PMC *)obj;
}
+ else if (PObj_custom_mark_TEST(obj))
+ VTABLE_mark(interpreter, (PMC *) obj);
return;
}
#if GC_VERBOSE
@@ -79,6 +111,8 @@
#endif
}
+#endif
+
/* Do a full trace run and mark all the PMCs as active if they are */
static void
@@ -317,6 +351,75 @@
}
#endif /* GC_IS_MALLOC */
+#if ARENA_DOD_FLAGS
+static void
+clear_live_counter(struct Parrot_Interp *interpreter,
+ struct Small_Object_Pool *pool)
+{
+ struct Small_Object_Arena *arena;
+ for (arena = pool->last_Arena; arena; arena = arena->prev)
+ arena->live_objects = 0;
+}
+
+# define REDUCE_ARENAS 0
+
+# if REDUCE_ARENAS
+/* -lt:
+ * count free objects per arena
+ * - if we find more then one totally unused arena
+ * free all but one arena - this is the only possibility to
+ * reduce the amount of free objects
+ *
+ * doesn't really work or speed things up - disabled
+ */
+# define REDUCE_ARENA_DEBUG 0
+
+#if REDUCE_ARENA_DEBUG
+#define debug(x) printf x
+#else
+#define debug(x)
+#endif
+
+static void
+reduce_arenas(struct Parrot_Interp *interpreter,
+ struct Small_Object_Pool *pool, UINTVAL free_arenas)
+{
+ struct Small_Object_Arena *arena, *next, *prev;
+ int i;
+ PObj * o;
+
+ /* debugging stuff */
+ for (i = 0, arena = pool->last_Arena; arena; arena = arena->prev)
+ i++;
+ debug(("\ttotal %d arenas - ", i));
+
+ for (next = arena = pool->last_Arena; arena; ) {
+ prev = arena->prev;
+ if (arena->live_objects == 0) {
+ if (--free_arenas <= 0)
+ break;
+ next->prev = prev;
+ pool->total_objects -= arena->used;
+#if ! ARENA_DOD_FLAGS
+ mem_sys_free(arena->start_objects);
+#endif
+ mem_sys_free(arena);
+
+ }
+ else {
+ next = arena;
+ }
+ arena = prev;
+ }
+ for (i = 0, arena = pool->last_Arena; arena; arena = arena->prev)
+ i++;
+ debug(("now %d arenas\n", i));
+
+}
+
+# endif
+#endif
+
/* Put any buffers/PMCs that are now unused, on to the pools free list.
* If GC_IS_MALLOC bufstart gets freed too if possible.
* Avoid buffers that are immune from collection (ie, constant) */
@@ -327,7 +430,10 @@
struct Small_Object_Arena *cur_arena;
UINTVAL i, total_used = 0;
UINTVAL object_size = pool->object_size;
- UINTVAL wash_size = object_size - sizeof(Buffer);
+ size_t nm;
+#if REDUCE_ARENAS
+ UINTVAL free_arenas = 0, old_total_used = 0;
+#endif
/* We have no impatient things. Yet. */
interpreter->impatient_things = 0;
@@ -337,12 +443,53 @@
NULL != cur_arena; cur_arena = cur_arena->prev) {
Buffer *b = cur_arena->start_objects;
- for (i = 0; i < cur_arena->used; i++) {
+#if ARENA_DOD_FLAGS
+ UINTVAL * dod_flags = cur_arena->dod_flags - 1;
+#endif
+ for (i = nm = 0; i < cur_arena->used; i++) {
+#if ARENA_DOD_FLAGS
+ if (! (i & ARENA_FLAG_MASK)) {
+ /* reset live bits for previous bunch of objects */
+ if (i)
+ *dod_flags &= ~ALL_LIVE_MASK;
+ ++dod_flags;
+ /* if all are on free list, skip one bunch */
+ if (*dod_flags == ALL_FREE_MASK) { /* all on free list */
+ i += ARENA_FLAG_MASK; /* + 1 in loop */
+ b = (Buffer *)((char *)b + object_size*(ARENA_FLAG_MASK+1));
+ continue;
+ }
+ nm = 0;
+ }
+ else
+ nm += 4;
/* If it's not live or on the free list, put it on the free list.
* Note that it is technically possible to have a Buffer be both
* on_free_list and live, because of our conservative stack-walk
* collection. We must be wary of this case. */
- if (!PObj_is_live_or_free_TESTALL(b)) {
+
+ if ((*dod_flags & (PObj_on_free_list_FLAG << nm)))
+ ; /* if its on free list, do nothing */
+ else if ((*dod_flags & (PObj_live_FLAG << nm)))
+#else
+ if (PObj_on_free_list_TEST(b))
+ ; /* if its on free list, do nothing */
+ else if (PObj_is_live_TEST(b))
+#endif
+ {
+ /* its live */
+ total_used++;
+#if ARENA_DOD_FLAGS
+ if ((*dod_flags & (PObj_is_impatient_FLAG << nm)))
+ interpreter->impatient_things = 1;
+#else
+ PObj_live_CLEAR(b);
+ if (PObj_is_impatient_TEST(b))
+ interpreter->impatient_things = 1;
+#endif
+ }
+ else {
+ /* it must be dead */
#if GC_VERBOSE
if (GC_DEBUG(interpreter) && PObj_report_TEST(b))
fprintf(stderr, "Freeing pobject %p -> %p\n",
@@ -350,17 +497,35 @@
#endif
/* if object is a PMC and needs destroying */
if (PObj_is_PMC_TEST(b)) {
- /* then destroy it here, add_free_pmc is called from
- * more_objects too
+ /* then destroy it here
*/
if (PObj_active_destroy_TEST(b))
VTABLE_destroy(interpreter, (PMC *)b);
+
+ if (PObj_is_PMC_EXT_TEST(b)) {
+ /* if the PMC has a PMC_EXT structure,
+ * return it to the pool/arena
+ */
+#if ARENA_DOD_FLAGS
+ struct Small_Object_Arena *ext_arena =
+ GET_ARENA(((PMC *)b)->pmc_ext);
+ ext_arena->pool->
+ add_free_object(interpreter, ext_arena,
+ ((PMC *)b)->pmc_ext);
+#else
+ struct Small_Object_Pool *ext_pool =
+ interpreter->arena_base->pmc_ext_pool;
+ ext_pool->add_free_object(interpreter, ext_pool,
+ ((PMC *)b)->pmc_ext);
+#endif
+ }
}
/* else object is a buffer(like) */
else if (PObj_sysmem_TEST(b) && b->bufstart) {
/* has sysmem allocated, e.g. string_pin */
mem_sys_free(b->bufstart);
- memset(b + 1, 0, wash_size);
+ b->bufstart = NULL;
+ b->buflen = 0;
}
else {
#ifdef GC_IS_MALLOC
@@ -385,28 +550,53 @@
((struct Memory_Pool *)
pool->mem_pool)->possibly_reclaimable += b->buflen;
#endif
- /*
- * clean memory for buffer_likes
- * this is the slow thing in the whole sub, so PMCs
- * have their own add_free function, which clears
- * PMC specific data members
- */
- memset(b + 1, 0, wash_size);
+ b->buflen = 0;
}
+#if ARENA_DOD_FLAGS
+ *dod_flags |= PObj_on_free_list_FLAG << nm;
+ pool->add_free_object(interpreter, cur_arena, b);
+#else
pool->add_free_object(interpreter, pool, b);
- }
- else if (!PObj_on_free_list_TEST(b)) {
- /* should be live then */
- total_used++;
- PObj_live_CLEAR(b);
- if (PObj_is_impatient_TEST(b)) {
- interpreter->impatient_things++;
- }
+#endif
}
b = (Buffer *)((char *)b + object_size);
}
+#if ARENA_DOD_FLAGS
+ /* reset live bits on last bunch of objects */
+ *dod_flags &= ~ALL_LIVE_MASK;
+# if REDUCE_ARENAS
+ /* not strictly only for ARENA_DOD_FLAGS, but
+ * live_objects is only defined there
+ */
+ if ( (cur_arena->live_objects = total_used - old_total_used) == 0)
+ ++free_arenas;
+ old_total_used = total_used;
+# endif
+#endif
}
pool->num_free_objects = pool->total_objects - total_used;
+#if ARENA_DOD_FLAGS
+# if REDUCE_ARENAS
+#define REPLENISH_LEVEL_FACTOR 0.3
+ if (free_arenas > 1) {
+ debug(("pool %s: %d free_arenas\n", pool->name, (int)free_arenas));
+ pool->replenish_level =
+ (size_t)(pool->total_objects * REPLENISH_LEVEL_FACTOR);
+ i = 0;
+ while (pool->num_free_objects - i * pool->last_Arena->used *
+ REPLENISH_LEVEL_FACTOR > pool->replenish_level &&
+ i < free_arenas)
+ ++i;
+ debug(("\t may free %d\n", (int)i));
+ reduce_arenas(interpreter, pool, i-1);
+ pool->replenish_level =
+ (size_t)(pool->total_objects * REPLENISH_LEVEL_FACTOR);
+ pool->num_free_objects = pool->total_objects - total_used;
+ pool->skip = 0;
+ }
+# undef debug
+# endif
+#endif
}
#ifndef PLATFORM_STACK_WALK
@@ -503,6 +693,14 @@
}
Parrot_block_DOD(interpreter);
+#if ARENA_DOD_FLAGS
+ clear_live_counter(interpreter, interpreter->arena_base->pmc_pool);
+ for (j = 0; j < (INTVAL)interpreter->arena_base->num_sized; j++) {
+ header_pool = interpreter->arena_base->sized_header_pools[j];
+ if (header_pool)
+ clear_live_counter(interpreter, header_pool);
+ }
+#endif
/* Now go trace the PMCs */
trace_active_PMCs(interpreter);
1.34 +57 -10 parrot/headers.c
Index: headers.c
===================================================================
RCS file: /cvs/public/parrot/headers.c,v
retrieving revision 1.33
retrieving revision 1.34
diff -u -w -r1.33 -r1.34
--- headers.c 13 Jan 2003 17:04:48 -0000 1.33
+++ headers.c 6 Jun 2003 08:29:18 -0000 1.34
@@ -1,7 +1,7 @@
/* headers.c
* Copyright: (When this is determined...it will go here)
* CVS Info
- * $Id: headers.c,v 1.33 2003/01/13 17:04:48 leo Exp $
+ * $Id: headers.c,v 1.34 2003/06/06 08:29:18 leo Exp $
* Overview:
* Header management functions. Handles getting of various headers,
* and pool creation
@@ -39,8 +39,8 @@
/* clear flags, set is_PMC_FLAG */
PObj_flags_SETTO(pmc, PObj_is_PMC_FLAG);
((PMC *)pmc)->data = NULL;
- ((PMC *)pmc)->metadata = NULL;
- ((PMC *)pmc)->synchronize = NULL;
+ ((PMC *)pmc)->pmc_ext = NULL;
+ /* TODO check PMCs init method, if they clear the cache */
return pmc;
}
@@ -52,11 +52,8 @@
{
Buffer *buffer = get_free_object(interpreter, pool);
- /* Don't let it point to garbage memory */
- buffer->bufstart = NULL;
- buffer->buflen = 0;
- /* Clear the flagpole (especially _on_free_list_FLAG) */
- PObj_flags_CLEARALL(buffer);
+ memset(buffer, 0, pool->object_size);
+ SET_NULL(buffer->bufstart);
return buffer;
}
@@ -169,6 +166,24 @@
return get_free_pmc(interpreter, interpreter->arena_base->pmc_pool);
}
+
+PMC_EXT *
+new_pmc_ext(struct Parrot_Interp *interpreter)
+{
+ struct Small_Object_Pool *pool = interpreter->arena_base->pmc_ext_pool;
+ void *ptr = get_free_object(interpreter, pool);
+ memset(ptr, 0, sizeof(PMC_EXT));
+ return ptr;
+}
+
+void
+add_pmc_ext(struct Parrot_Interp *interpreter, PMC *pmc)
+{
+ pmc->pmc_ext = new_pmc_ext(interpreter);
+ PObj_is_PMC_EXT_SET(pmc);
+}
+
+
STRING *
new_string_header(struct Parrot_Interp *interpreter, UINTVAL flags)
{
@@ -308,6 +323,8 @@
/* Init the constant string header pool */
interpreter->arena_base->constant_string_header_pool =
new_string_pool(interpreter, 1);
+ interpreter->arena_base->constant_string_header_pool->name =
+ "constant_string_header";
/* Init the buffer header pool
@@ -317,14 +334,23 @@
* here for faster access in new_*_header
*/
interpreter->arena_base->buffer_header_pool = new_buffer_pool(interpreter);
+ interpreter->arena_base->buffer_header_pool->name = "buffer_header";
/* Init the string header pool */
interpreter->arena_base->string_header_pool =
new_string_pool(interpreter, 0);
+ interpreter->arena_base->string_header_pool->name = "string_header";
/* Init the PMC header pool */
interpreter->arena_base->pmc_pool = new_pmc_pool(interpreter);
+ interpreter->arena_base->pmc_pool->name = "pmc";
+ interpreter->arena_base->pmc_ext_pool =
+ new_small_object_pool(interpreter, sizeof(struct PMC_EXT), 1024);
+ interpreter->arena_base->pmc_ext_pool->more_objects =
+ alloc_objects;
+ interpreter->arena_base->pmc_ext_pool->name = "pmc_ext";
interpreter->arena_base->constant_pmc_pool = new_pmc_pool(interpreter);
+ interpreter->arena_base->constant_pmc_pool->name = "constant_pmc";
interpreter->arena_base->constant_pmc_pool->objects_per_alloc =
CONSTANT_PMC_HEADERS_PER_ALLOC;
}
@@ -336,8 +362,17 @@
struct Small_Object_Arena *cur_arena, *next;
int i, j, start;
- /* const/non const COW strings live in different pools * so in first pass
- * * * * COW refcount is done, in 2. refcounting * in 3rd freeing */
+ /* TODO: -lt make a command line option for cleaning up:
+ * - the last interpreter may just die
+ * - created interpreters should always get destroyed
+ * - move the check to interpreter.c
+ */
+ return;
+ /* const/non const COW strings life in different pools
+ * so in first pass
+ * COW refcount is done, in 2. refcounting
+ * in 3rd freeing
+ */
#ifdef GC_IS_MALLOC
start = 0;
#else
@@ -372,7 +407,9 @@
if (i == 2 && pool) {
for (cur_arena = pool->last_Arena; cur_arena;) {
next = cur_arena->prev;
+#if ! ARENA_DOD_FLAGS
mem_sys_free(cur_arena->start_objects);
+#endif
mem_sys_free(cur_arena);
cur_arena = next;
}
@@ -381,6 +418,16 @@
}
}
+ pool = interpreter->arena_base->pmc_ext_pool;
+ for (cur_arena = pool->last_Arena; cur_arena;) {
+ next = cur_arena->prev;
+#if ! ARENA_DOD_FLAGS
+ mem_sys_free(cur_arena->start_objects);
+#endif
+ mem_sys_free(cur_arena);
+ cur_arena = next;
+ }
+ mem_sys_free(interpreter->arena_base->pmc_ext_pool);
mem_sys_free(interpreter->arena_base->sized_header_pools);
}
1.154 +17 -13 parrot/interpreter.c
Index: interpreter.c
===================================================================
RCS file: /cvs/public/parrot/interpreter.c,v
retrieving revision 1.153
retrieving revision 1.154
diff -u -w -r1.153 -r1.154
--- interpreter.c 1 Jun 2003 00:17:44 -0000 1.153
+++ interpreter.c 6 Jun 2003 08:29:18 -0000 1.154
@@ -1,7 +1,7 @@
/* interpreter.c
* Copyright: (When this is determined...it will go here)
* CVS Info
- * $Id: interpreter.c,v 1.153 2003/06/01 00:17:44 josh Exp $
+ * $Id: interpreter.c,v 1.154 2003/06/06 08:29:18 leo Exp $
* Overview:
* The interpreter api handles running the operations
* Data Structure and Algorithms:
@@ -28,6 +28,9 @@
#define ATEXIT_DESTROY
+#define PREDEREF_NORMAL 0
+#define PREDEREF_FOR_CGP 1
+#define PREDEREF_FOR_SWITCH 2
static void setup_default_compreg(Parrot_Interp interpreter);
@@ -124,7 +127,8 @@
break;
case PARROT_ARG_S:
- pc_prederef[i] = (void *)&interpreter->ctx.string_reg.registers[pc[i]];
+ pc_prederef[i] =
+ (void *)&interpreter->ctx.string_reg.registers[pc[i]];
break;
case PARROT_ARG_KIC:
@@ -159,7 +163,7 @@
break;
}
- if (opinfo->types[i] != PARROT_ARG_IC && pc_prederef[i] == 0) {
+ if (pc_prederef[i] == 0) {
internal_exception(INTERP_ERROR,
"Prederef generated a NULL pointer for arg of type
%d!\n",
opinfo->types[i]);
@@ -197,8 +201,8 @@
if (!interpreter->prederef_code) {
size_t N = interpreter->code->cur_cs->base.size;
size_t i;
- /* void **temp = (void **)mem_sys_allocate(N * sizeof(void *)); */
- void **temp = (void **)Parrot_memalign(256, N * sizeof(void *));
+ void **temp = (void **)Parrot_memalign_if_possible(256,
+ N * sizeof(void *));
for (i = 0; i < N; i++) {
temp[i] = (void *)(ptrcast_t)prederef;
@@ -206,7 +210,7 @@
interpreter->prederef_code = temp;
interpreter->code->cur_cs->prederef_code = temp;
- if (cgp == 2) {
+ if (cgp == PREDEREF_FOR_SWITCH) {
opcode_t *pc = interpreter->code->cur_cs->base.data;
size_t n;
for (i = 0; i < N; ) {
@@ -219,7 +223,7 @@
}
}
#ifdef HAVE_COMPUTED_GOTO
- if (cgp == 1) {
+ if (cgp == PREDEREF_FOR_CGP) {
opcode_t *pc = interpreter->code->cur_cs->base.data;
size_t n;
for (i = 0; i < N; ) {
@@ -261,7 +265,7 @@
# ifdef HAVE_COMPUTED_GOTO
# ifdef __GNUC__
# ifdef I386
- init_prederef(interpreter, 1);
+ init_prederef(interpreter, PREDEREF_FOR_CGP);
# endif
# endif
# endif
@@ -298,7 +302,7 @@
opcode_t *code_start = (opcode_t *)interpreter->code->byte_code;
void **pc_prederef;
- init_prederef(interpreter, 0);
+ init_prederef(interpreter, PREDEREF_NORMAL);
pc_prederef = interpreter->prederef_code + (pc - code_start);
while (pc_prederef) {
@@ -317,7 +321,7 @@
#ifdef HAVE_COMPUTED_GOTO
opcode_t *code_start = (opcode_t *)interpreter->code->byte_code;
void **pc_prederef;
- init_prederef(interpreter, 1);
+ init_prederef(interpreter, PREDEREF_FOR_CGP);
pc_prederef = interpreter->prederef_code + (pc - code_start);
pc = cgp_core((opcode_t*)pc_prederef, interpreter);
return pc;
@@ -334,7 +338,7 @@
{
opcode_t *code_start = (opcode_t *)interpreter->code->byte_code;
void **pc_prederef;
- init_prederef(interpreter, 2);
+ init_prederef(interpreter, PREDEREF_FOR_SWITCH);
pc_prederef = interpreter->prederef_code + (pc - code_start);
pc = switch_core((opcode_t*)pc_prederef, interpreter);
return pc;
1.12 +4 -4 parrot/jit_debug.c
Index: jit_debug.c
===================================================================
RCS file: /cvs/public/parrot/jit_debug.c,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -w -r1.11 -r1.12
--- jit_debug.c 1 Jun 2003 00:17:44 -0000 1.11
+++ jit_debug.c 6 Jun 2003 08:29:18 -0000 1.12
@@ -1,7 +1,7 @@
/*
* jit_debug.c
*
- * $Id: jit_debug.c,v 1.11 2003/06/01 00:17:44 josh Exp $
+ * $Id: jit_debug.c,v 1.12 2003/06/06 08:29:18 leo Exp $
*
* write stabs file for jit code
* when debugging jit code with gdb, do:
@@ -149,8 +149,8 @@
i + 3, BIT_OFFSET(PMC, vtable), BIT_SIZE(void*));
fprintf(stabs, "data:(0,14),%d,%d;",
BIT_OFFSET(PMC, data), BIT_SIZE(void*));
- fprintf(stabs, "metadata:*(0,%d),%d,%d;",
- i, BIT_OFFSET(PMC, metadata), BIT_SIZE(void*));
+ fprintf(stabs, "pmc_ext:*(0,%d),%d,%d;",
+ i, BIT_OFFSET(PMC, pmc_ext), BIT_SIZE(void*));
fprintf(stabs, ";\"");
fprintf(stabs, "," N_LSYM ",0,0,0\n");
1.23 +16 -2 parrot/pmc.c
Index: pmc.c
===================================================================
RCS file: /cvs/public/parrot/pmc.c,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -w -r1.22 -r1.23
--- pmc.c 19 May 2003 13:06:52 -0000 1.22
+++ pmc.c 6 Jun 2003 08:29:18 -0000 1.23
@@ -1,7 +1,7 @@
/* pmc.c
* Copyright: (When this is determined...it will go here)
* CVS Info
- * $Id: pmc.c,v 1.22 2003/05/19 13:06:52 leo Exp $
+ * $Id: pmc.c,v 1.23 2003/06/06 08:29:18 leo Exp $
* Overview:
* The base vtable calling functions.
* Data Structure and Algorithms:
@@ -73,8 +73,22 @@
PMC *
pmc_new_noinit(struct Parrot_Interp *interpreter, INTVAL base_type)
{
- return get_new_pmc_header(interpreter, base_type,
+ PMC *pmc = get_new_pmc_header(interpreter, base_type,
interpreter->arena_base->pmc_pool);
+ switch (base_type) {
+ case enum_class_PerlInt:
+ case enum_class_PerlNum:
+ case enum_class_PerlString:
+ case enum_class_PerlUndef:
+ break;
+ default:
+ /* TODO optimize this, mainly only aggregates need
+ * the extra header part
+ */
+ add_pmc_ext(interpreter, pmc);
+ break;
+ }
+ return pmc;
}
/*=for api pmc constant_pmc_new_noinit
1.106 +4 -4 parrot/resources.c
Index: resources.c
===================================================================
RCS file: /cvs/public/parrot/resources.c,v
retrieving revision 1.105
retrieving revision 1.106
diff -u -w -r1.105 -r1.106
--- resources.c 10 Feb 2003 15:29:15 -0000 1.105
+++ resources.c 6 Jun 2003 08:29:18 -0000 1.106
@@ -1,7 +1,7 @@
/* resources.c
* Copyright: (When this is determined...it will go here)
* CVS Info
- * $Id: resources.c,v 1.105 2003/02/10 15:29:15 scog Exp $
+ * $Id: resources.c,v 1.106 2003/06/06 08:29:18 leo Exp $
* Overview:
* Allocate and deallocate tracked resources
* Data Structure and Algorithms:
@@ -213,7 +213,7 @@
for (i = 0; i < cur_buffer_arena->used; i++) {
/* ! (immobile | on_free_list | constant | external) */
- if (b->bufstart && PObj_is_movable_TESTALL(b)) {
+ if (b->buflen && PObj_is_movable_TESTALL(b)) {
struct Buffer_Tail *tail =
(struct Buffer_Tail *)((char *)b->bufstart +
b->buflen);
1.22 +187 -19 parrot/smallobject.c
Index: smallobject.c
===================================================================
RCS file: /cvs/public/parrot/smallobject.c,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -w -r1.21 -r1.22
--- smallobject.c 13 Jan 2003 17:04:48 -0000 1.21
+++ smallobject.c 6 Jun 2003 08:29:18 -0000 1.22
@@ -1,7 +1,7 @@
/* resources.c
* Copyright: (When this is determined...it will go here)
* CVS Info
- * $Id: smallobject.c,v 1.21 2003/01/13 17:04:48 leo Exp $
+ * $Id: smallobject.c,v 1.22 2003/06/06 08:29:18 leo Exp $
* Overview:
* Handles the accessing of small object pools (header pools)
* Data Structure and Algorithms:
@@ -13,6 +13,7 @@
*/
#include "parrot/parrot.h"
+#include <assert.h>
#define GC_DEBUG_REPLENISH_LEVEL_FACTOR 0.0
#define GC_DEBUG_UNITS_PER_ALLOC_GROWTH_FACTOR 1
@@ -33,24 +34,39 @@
if (0 <= ptr_diff
&& ptr_diff <
- (ptrdiff_t)(arena->total_objects * pool->object_size)
+ (ptrdiff_t)(arena->used * pool->object_size)
&& ptr_diff % pool->object_size == 0)
return 1;
}
return 0;
}
+static int find_free_list(struct Small_Object_Pool *pool);
+
/* We're out of traceable objects. Try a DOD, then get some more if needed */
void
more_traceable_objects(struct Parrot_Interp *interpreter,
struct Small_Object_Pool *pool)
{
+ if (pool->skip)
+ pool->skip = 0;
+ else {
Parrot_do_dod_run(interpreter);
+ if (pool->num_free_objects <= pool->replenish_level)
+ pool->skip = 1;
+ }
+
/* requires that num_free_objects be updated in Parrot_do_dod_run. If dod
* is disabled, then we must check the free list directly. */
- if (!pool->free_list || pool->num_free_objects <= pool->replenish_level) {
+#if ARENA_DOD_FLAGS
+ if (!find_free_list(pool)) {
+ (*pool->alloc_objects) (interpreter, pool);
+ }
+#else
+ if (!pool->free_list) {
(*pool->alloc_objects) (interpreter, pool);
}
+#endif
}
/* We're out of non-traceable objects. Get some more */
@@ -61,6 +77,59 @@
(*pool->alloc_objects) (interpreter, pool);
}
+#if ARENA_DOD_FLAGS
+static int
+find_free_list(struct Small_Object_Pool *pool)
+{
+ struct Small_Object_Arena *arena;
+
+ for (arena = pool->last_Arena; arena; arena = arena->prev) {
+ if (arena->free_list) {
+ pool->free_arena = arena;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+void
+add_free_object(struct Parrot_Interp *interpreter,
+ struct Small_Object_Arena *arena, void *to_add)
+{
+ *(void **)to_add = arena->free_list;
+ arena->free_list = to_add;
+}
+
+/* Get a new object from the free pool and return it */
+void *
+get_free_object(struct Parrot_Interp *interpreter,
+ struct Small_Object_Pool *pool)
+{
+ void *ptr;
+ struct Small_Object_Arena *arena;
+ size_t n;
+
+ /* if we don't have any objects */
+ if (!pool->free_arena)
+ (*pool->alloc_objects) (interpreter, pool);
+ if (!pool->free_arena->free_list)
+ if (!find_free_list(pool))
+ (*pool->more_objects) (interpreter, pool);
+
+ arena = pool->free_arena;
+ ptr = arena->free_list;
+ arena->free_list = *(void **)ptr;
+ n = GET_OBJ_N(arena, ptr);
+ arena->dod_flags[ n >> ARENA_FLAG_SHIFT ] &=
+ ~((PObj_on_free_list_FLAG << (( n & ARENA_FLAG_MASK ) << 2)));
+#if ! DISABLE_GC_DEBUG
+ if (GC_DEBUG(interpreter))
+ ((Buffer*)ptr)->version++;
+#endif
+ return ptr;
+}
+
+#else
/* Add an unused object back to the free pool for later reuse */
void
add_free_object(struct Parrot_Interp *interpreter,
@@ -69,7 +138,6 @@
PObj_flags_SETTO((PObj *)to_add, PObj_on_free_list_FLAG);
*(void **)to_add = pool->free_list;
pool->free_list = to_add;
- pool->num_free_objects++;
}
/* Get a new object from the free pool and return it */
@@ -85,13 +153,56 @@
ptr = pool->free_list;
pool->free_list = *(void **)ptr;
- pool->num_free_objects--;
#if ! DISABLE_GC_DEBUG
if (GC_DEBUG(interpreter))
((Buffer*)ptr)->version++;
#endif
return ptr;
}
+#endif
+
+
+static void
+add_to_free_list(struct Parrot_Interp *interpreter,
+ struct Small_Object_Pool *pool,
+ struct Small_Object_Arena *arena,
+ UINTVAL start,
+ UINTVAL end)
+{
+#if ARENA_DOD_FLAGS
+ UINTVAL *dod_flags;
+#endif
+ UINTVAL i;
+ void *object;
+
+ pool->total_objects += end - start;
+ arena->used = end;
+
+ /* Move all the new objects into the free list */
+ object = (void *)((char *)arena->start_objects +
+ start * pool->object_size);
+#if ARENA_DOD_FLAGS
+ pool->replenish_level =
+ (size_t)(pool->total_objects * REPLENISH_LEVEL_FACTOR);
+ dod_flags = arena->dod_flags + (start >> ARENA_FLAG_SHIFT);
+#endif
+ for (i = start; i < end; i++) {
+#if ARENA_DOD_FLAGS
+ if (! (i & ARENA_FLAG_MASK)) {
+ *dod_flags = ALL_FREE_MASK;
+ ++dod_flags;
+ }
+ pool->add_free_object (interpreter, arena, object);
+#else
+ pool->add_free_object (interpreter, pool, object);
+#endif
+ object = (void *)((char *)object + pool->object_size);
+ }
+#if ARENA_DOD_FLAGS
+ /* set last */
+ *dod_flags = ALL_FREE_MASK;
+#endif
+}
/* We have no more headers on the free header pool. Go allocate more
* and put them on */
@@ -100,14 +211,60 @@
struct Small_Object_Pool *pool)
{
struct Small_Object_Arena *new_arena;
- void *object;
- UINTVAL i;
- size_t size = pool->object_size * pool->objects_per_alloc;
-
- new_arena = mem_sys_allocate(sizeof(struct Small_Object_Arena));
+ size_t size;
+ UINTVAL start, end;
/* Setup memory for the new objects */
+#if ARENA_DOD_FLAGS
+ size_t offset;
+
+ /* check old arena first */
+ if (pool->last_Arena &&
+ pool->last_Arena->used < pool->last_Arena->total_objects) {
+ start = pool->last_Arena->used;
+ end = start << 2;
+ if (end > pool->last_Arena->total_objects)
+ end = pool->last_Arena->total_objects;
+ add_to_free_list(interpreter, pool, pool->last_Arena, start, end);
+ return;
+ }
+
+ size = ARENA_SIZE;
+ /*
+ * [ Note: Linux ]
+ * Albeit we reserve 8 pools with 4MB each, the memory footprint
+ * of a running program is much smaller, if only a few objects per pool
+ * are used. The unused pages of the arenas are only mapped (they use space
+ * in the page tables, but no physical memory).
+ * Because of the COW pages strategy of the kernel, there shouldn't
+ * be a problem with many running instances too at least if these get
+ * fork'ed or were created as threads.
+ * For many unique parrot processes, you might either reduce ARENA_SIZE
+ * or turn off ARENA_DOD_FLAGS.
+ */
+ new_arena = Parrot_memalign(ARENA_ALIGN, size);
+ /* offset in bytes of whole Objects */
+ offset = ( 1 + sizeof(struct Small_Object_Arena) / pool->object_size) *
+ pool->object_size;
+ new_arena->start_objects = (char *)new_arena + offset;
+ size -= offset;
+ pool->objects_per_alloc = size / pool->object_size;
+ new_arena->object_size = pool->object_size;
+#ifdef SIMULATE_DIRTY_AND_RUN_SLOW
+ /* memory gets washed in get_free_*, so we don't need zeroed
+ * memory here
+ */
+ memset(new_arena->start_objects, 0xff, size); /* simulate dirty */
+#endif
+ new_arena->dod_flags = mem_sys_allocate(ARENA_FLAG_SIZE(pool));
+ new_arena->pool = pool;
+ new_arena->free_list = NULL;
+#else
+ new_arena = mem_sys_allocate(sizeof(struct Small_Object_Arena));
+ size = pool->object_size * pool->objects_per_alloc;
+ /* could be mem_sys_allocate too, but calloc is fast */
new_arena->start_objects = mem_sys_allocate_zeroed(size);
+#endif
/* Maintain the *_arena_memory invariant for stack walking code. Set it
* regardless if we're the first pool to be added. */
@@ -120,7 +277,22 @@
pool->end_arena_memory = (size_t)new_arena->start_objects + size;
/* Hook up the new object block into the object pool */
- new_arena->used = pool->objects_per_alloc;
+#if ARENA_DOD_FLAGS
+ /* not the first one - put all on free list */
+ if (pool->last_Arena) {
+ start = 0;
+ end = pool->objects_per_alloc;
+ }
+ else {
+ /* first arena, start with x objects */
+ start = 0;
+ end = 1024;
+ }
+ pool->free_arena = new_arena;
+#else
+ start = 0;
+ end = pool->objects_per_alloc;
+#endif
new_arena->total_objects = pool->objects_per_alloc;
new_arena->next = NULL;
new_arena->prev = pool->last_Arena;
@@ -130,14 +302,9 @@
pool->last_Arena = new_arena;
interpreter->header_allocs_since_last_collect++;
- /* Move all the new objects into the free list */
- object = new_arena->start_objects;
- for (i = 0; i < pool->objects_per_alloc; i++) {
- add_free_object (interpreter, pool, object);
- object = (void *)((char *)object + pool->object_size);
- }
- pool->total_objects += pool->objects_per_alloc;
+ add_to_free_list(interpreter, pool, new_arena, start, end);
+#if ! ARENA_DOD_FLAGS
/* Allocate more next time */
if (GC_DEBUG(interpreter)) {
pool->objects_per_alloc *= GC_DEBUG_UNITS_PER_ALLOC_GROWTH_FACTOR;
@@ -156,6 +323,7 @@
if (size > POOL_MAX_BYTES) {
pool->objects_per_alloc = POOL_MAX_BYTES / pool->object_size;
}
+#endif
}
struct Small_Object_Pool *