cvsuser 04/05/08 09:27:52
Modified: src list.c
Log:
2x faster DOD for lists with scalars
Revision Changes Path
1.48 +111 -2 parrot/src/list.c
Index: list.c
===================================================================
RCS file: /cvs/public/parrot/src/list.c,v
retrieving revision 1.47
retrieving revision 1.48
diff -u -w -r1.47 -r1.48
--- list.c 8 May 2004 13:54:15 -0000 1.47
+++ list.c 8 May 2004 16:27:52 -0000 1.48
@@ -1,7 +1,7 @@
/*
Copyright: (c) 2002 Leopold Toetsch <[EMAIL PROTECTED]>
License: Artistic/GPL, see README and LICENSES for details
-$Id: list.c,v 1.47 2004/05/08 13:54:15 leo Exp $
+$Id: list.c,v 1.48 2004/05/08 16:27:52 leo Exp $
=head1 NAME
@@ -1348,6 +1348,115 @@
*/
+#if ARENA_DOD_FLAGS
+/*
+ * when a big array is filled one by one
+ * *and* when these are plain scalars or strings
+ * we can use the arena->dod_flags to mark
+ * the whole chunk faster
+ */
+static void
+mark_chunk(Interp *interpreter, List_chunk *chunk, int obj_size)
+{
+ UINTVAL i;
+ PObj **pp = ((PObj **) PObj_bufstart(&chunk->data));
+ PObj *p = *pp;
+ PObj *next = pp[1];
+ int dist;
+ i = 0;
+ if (p && next && (( dist = (char*)next - (char*)p ) == obj_size ||
+ -dist == obj_size)) {
+ /* we have a first object and a nexz one - calculate it's
+ * arena values see also src/dod.c
+ */
+ struct Small_Object_Arena *arena = GET_ARENA(p);
+ size_t n = GET_OBJ_N(arena, p);
+ size_t ns = n >> ARENA_FLAG_SHIFT;
+ UINTVAL nm = (n & ARENA_FLAG_MASK) << 2;
+ UINTVAL *dod_flags = arena->dod_flags + ns;
+ int up = dist > 0;
+ for (; i < chunk->items; ++i) {
+ if (*dod_flags &
+ ((PObj_on_free_list_FLAG | PObj_live_FLAG) << nm)) {
+ /* its live or free - do nothing */
+ }
+ else if (*dod_flags & (PObj_is_special_PMC_FLAG << nm)) {
+ /* mark it normal */
+ pobject_lives(interpreter, p);
+ }
+ else {
+ /* set live bit */
+ *dod_flags |= PObj_live_FLAG << nm;
+ ++arena->live_objects;
+ }
+ /* now as long as the next if adjacent in the objects
+ * arena, we increment or decrement the dod flags and
+ * continue marking here directly
+ */
+ p = next;
+ ++pp;
+ next = pp[1];
+ if (up) {
+ if ((char*)next - (char*)p != obj_size)
+ goto slow;
+ if (! (n & ARENA_FLAG_MASK)) {
+ ++dod_flags;
+ nm = 0;
+ }
+ else
+ nm += 4;
+ ++n;
+ }
+ else {
+ if ((char*)p - (char*)next != obj_size)
+ goto slow;
+ if (! (n & ARENA_FLAG_MASK)) {
+ --dod_flags;
+ nm = ((n-1) & ARENA_FLAG_MASK) << 2;
+ }
+ else {
+ nm -= 4;
+ assert((int)nm >= 0);
+ }
+ --n;
+ }
+ }
+ }
+ else {
+ /* do it the plain way */
+ for ( ; i < chunk->items; ++i, ++pp) {
+slow:
+ if (*pp)
+ pobject_lives(interpreter, *pp);
+ }
+ }
+}
+
+void
+list_mark(Interp *interpreter, List *list)
+{
+ List_chunk *chunk;
+ UINTVAL i;
+ int obj_size;
+ if (list->item_type == enum_type_PMC)
+ obj_size = sizeof(PMC);
+ else
+ obj_size = sizeof(STRING);
+
+ for (chunk = list->first; chunk; chunk = chunk->next) {
+ pobject_lives(interpreter, (PObj *)chunk);
+ if (list->item_type == enum_type_PMC ||
+ list->item_type == enum_type_STRING) {
+ if (!(chunk->flags & sparse)) {
+ mark_chunk(interpreter, chunk, obj_size);
+ }
+ }
+ }
+ pobject_lives(interpreter, (PObj *)list);
+ if (list->user_data)
+ pobject_lives(interpreter, (PObj *) list->user_data);
+}
+#else
void
list_mark(Interp *interpreter, List *list)
{
@@ -1373,7 +1482,7 @@
if (list->user_data)
pobject_lives(interpreter, (PObj *) list->user_data);
}
-
+#endif
/*
=item C<void