cvsuser 04/08/19 04:48:19
Modified: classes array.pmc perlhash.pmc
include/parrot dod.h hash.h
src dod.c gc_ims.c hash.c headers.c smallobject.c
t/op gc.t
Log:
gc subsystems 6 - hash write barrier
* add new_pmc_hash to put the container PMC into the hash
* write barrier in hash_put
* strings and other buffers are now created black with the
incremental GC
* preserve object flags from the allocator
Revision Changes Path
1.89 +5 -5 parrot/classes/array.pmc
Index: array.pmc
===================================================================
RCS file: /cvs/public/parrot/classes/array.pmc,v
retrieving revision 1.88
retrieving revision 1.89
diff -u -w -r1.88 -r1.89
--- array.pmc 10 Jul 2004 16:56:53 -0000 1.88
+++ array.pmc 19 Aug 2004 11:48:14 -0000 1.89
@@ -1,6 +1,6 @@
/*
Copyright: 2001-2003 The Perl Foundation. All Rights Reserved.
-$Id: array.pmc,v 1.88 2004/07/10 16:56:53 leo Exp $
+$Id: array.pmc,v 1.89 2004/08/19 11:48:14 leo Exp $
=head1 NAME
1.88 +7 -5 parrot/classes/perlhash.pmc
Index: perlhash.pmc
===================================================================
RCS file: /cvs/public/parrot/classes/perlhash.pmc,v
retrieving revision 1.87
retrieving revision 1.88
diff -u -w -r1.87 -r1.88
--- perlhash.pmc 29 Jul 2004 09:12:38 -0000 1.87
+++ perlhash.pmc 19 Aug 2004 11:48:14 -0000 1.88
@@ -1,6 +1,6 @@
/*
Copyright: 2001-2003 The Perl Foundation. All Rights Reserved.
-$Id: perlhash.pmc,v 1.87 2004/07/29 09:12:38 leo Exp $
+$Id: perlhash.pmc,v 1.88 2004/08/19 11:48:14 leo Exp $
=head1 NAME
@@ -85,11 +85,12 @@
INTVAL start, end, step;
Hash* hash;
parrot_range_t *range = PMC_struct_val(keys);
- new_hash_x(interpreter, &hash, enum_type_ptr,
+
+ new_pmc_hash_x(interpreter, self, enum_type_ptr,
0, Hash_key_type_int,
int_compare, key_hash_int,
(hash_mark_key_fn) NULL);
- PMC_struct_val(self) = hash;
+ hash = PMC_struct_val(self);
start = RVal_int(range->start);
end = RVal_int(range->end);
step = RVal_int(range->step);
@@ -214,7 +215,7 @@
void init () {
PObj_custom_mark_SET(SELF);
- new_hash(INTERP, (Hash**)&PMC_struct_val(SELF));
+ new_pmc_hash(INTERP, SELF);
}
/*
@@ -289,6 +290,7 @@
PMC* clone () {
PMC* dest = pmc_new_noinit(INTERP, SELF->vtable->base_type);
PObj_custom_mark_SET(dest);
+ ((Hash*)PMC_struct_val(dest))->container = dest;
hash_clone(INTERP, (Hash *)PMC_struct_val(SELF),
(Hash**)&PMC_struct_val(dest));
return dest;
1.19 +2 -2 parrot/include/parrot/dod.h
Index: dod.h
===================================================================
RCS file: /cvs/public/parrot/include/parrot/dod.h,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -w -r1.18 -r1.19
--- dod.h 18 Aug 2004 12:53:28 -0000 1.18
+++ dod.h 19 Aug 2004 11:48:16 -0000 1.19
@@ -1,7 +1,7 @@
/* dod.h
* Copyright: 2001-2003 The Perl Foundation. All Rights Reserved.
* CVS Info
- * $Id: dod.h,v 1.18 2004/08/18 12:53:28 leo Exp $
+ * $Id: dod.h,v 1.19 2004/08/19 11:48:16 leo Exp $
* Overview:
* Handles dead object destruction of the various headers
* Data Structure and Algorithms:
@@ -86,7 +86,7 @@
#if PARROT_GC_IMS
# define DOD_WRITE_BARRIER(interp, agg, old, new) \
do { \
- if ( \
+ if ( !PMC_IS_NULL(new) && \
PObj_live_TEST(agg) && \
(PObj_get_FLAGS(agg) & PObj_custom_GC_FLAG) && \
!PObj_live_TEST(new)) { \
1.24 +5 -1 parrot/include/parrot/hash.h
Index: hash.h
===================================================================
RCS file: /cvs/public/parrot/include/parrot/hash.h,v
retrieving revision 1.23
retrieving revision 1.24
diff -u -w -r1.23 -r1.24
--- hash.h 22 Apr 2004 08:55:05 -0000 1.23
+++ hash.h 19 Aug 2004 11:48:17 -0000 1.24
@@ -1,7 +1,7 @@
/* hash.h
* Copyright: 2001-2003 The Perl Foundation. All Rights Reserved.
* CVS Info
- * $Id: hash.h,v 1.23 2004/04/22 08:55:05 leo Exp $
+ * $Id: hash.h,v 1.24 2004/08/19 11:48:17 leo Exp $
* Overview:
* Hashtable implementation
* Data Structure and Algorithms:
@@ -64,6 +64,7 @@
UINTVAL entries; /* Number of values stored in hashtable */
Buffer *bucket_pool; /* Buffer full of buckets, used and unused */
BucketIndex free_list;
+ PMC *container; /* e.g. the PerlHash PMC */
PARROT_DATA_TYPES entry_type; /* type of value */
size_t value_size; /* currently unused, if set this size
at value is copied as a hash_entry */
@@ -76,8 +77,11 @@
};
void new_hash(Interp * interpreter, Hash **hptr);
+void new_pmc_hash(Interp * interpreter, PMC *container);
void new_hash_x(Interp *, Hash**, PARROT_DATA_TYPES, size_t val_size,
Hash_key_type, hash_comp_fn, hash_hash_key_fn, hash_mark_key_fn);
+void new_pmc_hash_x(Interp *, PMC*, PARROT_DATA_TYPES, size_t val_size,
+ Hash_key_type, hash_comp_fn, hash_hash_key_fn, hash_mark_key_fn);
void new_cstring_hash(Interp *interpreter, Hash **);
void hash_clone(Interp * interpreter, Hash * src, Hash **dest);
INTVAL hash_size(Interp * interpreter, Hash *hash);
1.128 +4 -2 parrot/src/dod.c
Index: dod.c
===================================================================
RCS file: /cvs/public/parrot/src/dod.c,v
retrieving revision 1.127
retrieving revision 1.128
diff -u -w -r1.127 -r1.128
--- dod.c 18 Aug 2004 12:53:29 -0000 1.127
+++ dod.c 19 Aug 2004 11:48:18 -0000 1.128
@@ -1,6 +1,6 @@
/*
Copyright: 2001-2003 The Perl Foundation. All Rights Reserved.
-$Id: dod.c,v 1.127 2004/08/18 12:53:29 leo Exp $
+$Id: dod.c,v 1.128 2004/08/19 11:48:18 leo Exp $
=head1 NAME
@@ -127,9 +127,11 @@
arena_base->dod_mark_ptr = PMC_next_for_GC(obj) = obj;
}
}
- else if (PObj_custom_mark_TEST(obj))
+ else if (PObj_custom_mark_TEST(obj)) {
+ PObj_get_FLAGS(obj) |= PObj_custom_GC_FLAG;
VTABLE_mark(interpreter, obj);
}
+}
#if ARENA_DOD_FLAGS
1.6 +18 -11 parrot/src/gc_ims.c
Index: gc_ims.c
===================================================================
RCS file: /cvs/public/parrot/src/gc_ims.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -w -r1.5 -r1.6
--- gc_ims.c 18 Aug 2004 12:53:29 -0000 1.5
+++ gc_ims.c 19 Aug 2004 11:48:18 -0000 1.6
@@ -1,6 +1,6 @@
/*
Copyright: 2001-2004 The Perl Foundation. All Rights Reserved.
-$Id: gc_ims.c,v 1.5 2004/08/18 12:53:29 leo Exp $
+$Id: gc_ims.c,v 1.6 2004/08/19 11:48:18 leo Exp $
=head1 NAME
@@ -436,22 +436,28 @@
gc_ims_get_free_object(Interp *interpreter,
struct Small_Object_Pool *pool)
{
- void *ptr;
+ PObj *ptr;
+ struct Arenas *arena_base;
Gc_ims_private *g_ims;
+ arena_base = interpreter->arena_base;
/* if we don't have any objects */
if (!pool->free_list)
(*pool->alloc_objects) (interpreter, pool);
ptr = pool->free_list;
pool->free_list = *(void **)ptr;
- PObj_on_free_list_CLEAR((PObj*) ptr);
- PObj_get_FLAGS((PObj*)ptr) &= ~PObj_custom_GC_FLAG;
+ /*
+ * buffers are born black, PMCs not yet?
+ * XXX this does not solve the problem of storing keys in hashes
+ * in the next DOD cycle (if the key isn't marked elsewhere ?)
+ */
+ PObj_flags_SETTO(ptr, pool == arena_base->pmc_pool ? 0 : PObj_live_FLAG);
--pool->num_free_objects;
#if ! DISABLE_GC_DEBUG
if (GC_DEBUG(interpreter))
- PObj_version((Buffer*)ptr) = interpreter->arena_base->dod_runs;
+ PObj_version((Buffer*)ptr) = arena_base->dod_runs;
#endif
- g_ims = interpreter->arena_base->gc_private;
+ g_ims = arena_base->gc_private;
if (++g_ims->allocations >= g_ims->alloc_trigger)
parrot_gc_ims_run_increment(interpreter);
return ptr;
@@ -683,6 +689,8 @@
Gc_ims_private *g_ims;
struct Arenas *arena_base = interpreter->arena_base;
+ if (Parrot_is_blocked_DOD(interpreter))
+ return;
g_ims = arena_base->gc_private;
g_ims->allocations = 0;
++g_ims->increments;
@@ -695,9 +703,7 @@
g_ims->throttle = THROTTLE;
break;
case GC_IMS_STARTING:
- if (Parrot_is_blocked_DOD(interpreter))
- break;
- /* else fall through and start */
+ /* fall through and start */
case GC_IMS_RE_INIT:
parrot_gc_ims_reinit(interpreter);
break;
@@ -839,8 +845,9 @@
Parrot_dod_ims_wb(Interp* interpreter, PMC *agg, PMC *new)
{
#if DOD_IMS_GREY_NEW
- IMS_DEBUG((stderr, "%d ", ((Gc_ims_private *)interpreter->arena_base->
- gc_private)->state));
+ IMS_DEBUG((stderr, "%d agg %p mark %p\n",
+ ((Gc_ims_private *)interpreter->arena_base->
+ gc_private)->state, agg, new));
pobject_lives(interpreter, (PObj*)new);
#else
PObj_get_FLAGS(agg) &= ~ (PObj_live_FLAG|PObj_custom_GC_FLAG);
1.84 +70 -15 parrot/src/hash.c
Index: hash.c
===================================================================
RCS file: /cvs/public/parrot/src/hash.c,v
retrieving revision 1.83
retrieving revision 1.84
diff -u -w -r1.83 -r1.84
--- hash.c 10 Jul 2004 11:40:55 -0000 1.83
+++ hash.c 19 Aug 2004 11:48:18 -0000 1.84
@@ -1,6 +1,6 @@
/*
Copyright: 2001-2003 The Perl Foundation. All Rights Reserved.
-$Id: hash.c,v 1.83 2004/07/10 11:40:55 leo Exp $
+$Id: hash.c,v 1.84 2004/08/19 11:48:18 leo Exp $
=head1 NAME
@@ -547,6 +547,10 @@
Returns a new Parrot string hash in C<hptr>.
+new_pmc_hash(Interp *interpreter, PMC *container)>
+
+Create a new Parrot string hash in PMC_struct_val(container)
+
=cut
*/
@@ -563,6 +567,17 @@
pobject_lives); /* mark */
}
+void
+new_pmc_hash(Interp *interpreter, PMC *container)
+{
+ new_pmc_hash_x(interpreter, container,
+ enum_type_PMC,
+ 0,
+ Hash_key_type_ascii,
+ STRING_compare, /* STRING compare */
+ key_hash_STRING, /* hash */
+ pobject_lives); /* mark */
+}
/*
=item C<void
@@ -607,19 +622,28 @@
on the stack I<including> this newly constructed Hash, so that it gets
marked properly.
+=item C<void
+new_pmc_hash_x(Interp *interpreter, PMC *container,
+ PARROT_DATA_TYPES val_type, size_t val_size,
+ Hash_key_type hkey_type,
+ hash_comp_fn compare, hash_hash_key_fn keyhash,
+ hash_mark_key_fn mark)>
+
+Like above but w/o the decribed problems. The passed in C<container> PMC gets
+stored in the Hash end the newly created Hash is in PMC_struct_val(container).
+
=cut
*/
-void
-new_hash_x(Interp *interpreter, Hash **hptr,
+static void
+init_hash(Interp *interpreter, Hash *hash,
PARROT_DATA_TYPES val_type, size_t val_size,
Hash_key_type hkey_type,
hash_comp_fn compare, hash_hash_key_fn keyhash,
hash_mark_key_fn mark)
{
- Hash *hash = (Hash *)new_bufferlike_header(interpreter, sizeof(*hash));
- *hptr = hash;
+
hash->compare = compare;
hash->hash_val = keyhash;
hash->mark_key = mark;
@@ -650,6 +674,33 @@
expand_hash(interpreter, hash);
}
+void
+new_hash_x(Interp *interpreter, Hash **hptr,
+ PARROT_DATA_TYPES val_type, size_t val_size,
+ Hash_key_type hkey_type,
+ hash_comp_fn compare, hash_hash_key_fn keyhash,
+ hash_mark_key_fn mark)
+{
+ Hash *hash = (Hash *)new_bufferlike_header(interpreter, sizeof(*hash));
+ *hptr = hash;
+ init_hash(interpreter, hash, val_type, val_size, hkey_type,
+ compare, keyhash, mark);
+}
+
+void
+new_pmc_hash_x(Interp *interpreter, PMC *container,
+ PARROT_DATA_TYPES val_type, size_t val_size,
+ Hash_key_type hkey_type,
+ hash_comp_fn compare, hash_hash_key_fn keyhash,
+ hash_mark_key_fn mark)
+{
+ Hash *hash = (Hash *)new_bufferlike_header(interpreter, sizeof(*hash));
+ PMC_struct_val(container) = hash;
+ hash->container = container;
+ init_hash(interpreter, hash, val_type, val_size, hkey_type,
+ compare, keyhash, mark);
+}
+
/*
=item C<INTVAL
@@ -718,9 +769,9 @@
/*
=item C<HashBucket *
-hash_get_bucket(Interp *interpreter, Hash *hash, void *okey)>
+hash_get_bucket(Interp *interpreter, Hash *hash, void *key)>
-Returns the bucket for C<okey>.
+Returns the bucket for C<key>.
=cut
@@ -774,9 +825,9 @@
/*
=item C<HashBucket*
-hash_put(Interp *interpreter, Hash *hash, void *okey, void *value)>
+hash_put(Interp *interpreter, Hash *hash, void *key, void *value)>
-Puts the key and value into the hash. Note that C<okey> is B<not>
+Puts the key and value into the hash. Note that C<key> is B<not>
copied.
=cut
@@ -784,7 +835,7 @@
*/
HashBucket*
-hash_put(Interp *interpreter, Hash *hash, void *okey, void *value)
+hash_put(Interp *interpreter, Hash *hash, void *key, void *value)
{
BucketIndex *table;
UINTVAL hashval;
@@ -792,8 +843,6 @@
BucketIndex chain;
HashBucket *bucket;
- void *key = okey;
-
/* dump_hash(interpreter, hash); */
hashval = (hash->hash_val)(interpreter, hash, key);
@@ -806,10 +855,17 @@
/* hash, PObj_bufstart(&hash->buffer), chain, bucket,
string_to_cstring(interpreter, key)); */
if (bucket) {
+ if (hash->entry_type == enum_type_PMC && hash->container) {
+ DOD_WRITE_BARRIER(interpreter, hash->container,
+ (PMC*)bucket->value, (PMC*)value);
+ }
/* Replacing old value */
bucket->value = value; /* TODO copy value_size */
}
else {
+ if (hash->entry_type == enum_type_PMC && hash->container) {
+ DOD_WRITE_BARRIER(interpreter, hash->container, NULL, (PMC*)value);
+ }
/* Create new bucket */
hash->entries++;
bucket_index = new_bucket(interpreter, hash, key, value);
@@ -825,7 +881,7 @@
/*
=item C<void
-hash_delete(Interp *interpreter, Hash *hash, void *okey)>
+hash_delete(Interp *interpreter, Hash *hash, void *key)>
Deletes the key from the hash.
@@ -834,13 +890,12 @@
*/
void
-hash_delete(Interp *interpreter, Hash *hash, void *okey)
+hash_delete(Interp *interpreter, Hash *hash, void *key)
{
UINTVAL hashval;
HashIndex slot;
HashBucket *bucket;
HashBucket *prev = NULL;
- void *key = okey;
hashval = (hash->hash_val)(interpreter, hash, key);
slot = hashval & hash->max_chain;
1.57 +10 -6 parrot/src/headers.c
Index: headers.c
===================================================================
RCS file: /cvs/public/parrot/src/headers.c,v
retrieving revision 1.56
retrieving revision 1.57
diff -u -w -r1.56 -r1.57
--- headers.c 16 Aug 2004 10:33:35 -0000 1.56
+++ headers.c 19 Aug 2004 11:48:18 -0000 1.57
@@ -1,6 +1,6 @@
/*
Copyright: 2001-2003 The Perl Foundation. All Rights Reserved.
-$Id: headers.c,v 1.56 2004/08/16 10:33:35 leo Exp $
+$Id: headers.c,v 1.57 2004/08/19 11:48:18 leo Exp $
=head1 NAME
@@ -53,10 +53,14 @@
get_free_buffer(Interp *interpreter,
struct Small_Object_Pool *pool)
{
- Buffer *buffer = pool->get_free_object(interpreter, pool);
+ PObj *buffer = pool->get_free_object(interpreter, pool);
- memset(buffer, 0, pool->object_size);
- SET_NULL(PObj_bufstart(buffer));
+ /* don't mess around with flags */
+ PObj_bufstart(buffer) = NULL;
+ PObj_buflen(buffer) = 0;
+
+ if (pool->object_size > sizeof(PObj))
+ memset(buffer + 1, 0, pool->object_size - sizeof(PObj));
return buffer;
}
@@ -266,7 +270,7 @@
}
else
pmc->pmc_ext = NULL;
- PObj_flags_SETTO(pmc, PObj_is_PMC_FLAG|flags);
+ PObj_get_FLAGS(pmc) |= PObj_is_PMC_FLAG|flags;
pmc->vtable = NULL;
#if ! PMC_DATA_IN_EXT
PMC_data(pmc) = NULL;
@@ -340,7 +344,7 @@
? interpreter->
arena_base->constant_string_header_pool :
interpreter->arena_base->string_header_pool);
- PObj_flags_SETTO(string, flags | PObj_is_string_FLAG);
+ PObj_get_FLAGS(string) |= flags | PObj_is_string_FLAG;
SET_NULL(string->strstart);
return string;
}
1.50 +5 -1 parrot/src/smallobject.c
Index: smallobject.c
===================================================================
RCS file: /cvs/public/parrot/src/smallobject.c,v
retrieving revision 1.49
retrieving revision 1.50
diff -u -w -r1.49 -r1.50
--- smallobject.c 15 Aug 2004 15:24:17 -0000 1.49
+++ smallobject.c 19 Aug 2004 11:48:18 -0000 1.50
@@ -1,6 +1,6 @@
/*
Copyright: 2001-2003 The Perl Foundation. All Rights Reserved.
-$Id: smallobject.c,v 1.49 2004/08/15 15:24:17 leo Exp $
+$Id: smallobject.c,v 1.50 2004/08/19 11:48:18 leo Exp $
=head1 NAME
@@ -183,7 +183,10 @@
(*pool->more_objects) (interpreter, pool);
ptr = pool->free_list;
pool->free_list = *(void **)ptr;
+ PObj_flags_SETTO( (PObj*) ptr, 0);
+#if ARENA_DOD_FLAGS
PObj_on_free_list_CLEAR((PObj*) ptr);
+#endif
--pool->num_free_objects;
#if ! DISABLE_GC_DEBUG
if (GC_DEBUG(interpreter))
@@ -207,6 +210,7 @@
--pool->num_free_objects;
*((Dead_PObj*)ptr)->arena_dod_flag_ptr &=
~ (PObj_on_free_list_FLAG << ((Dead_PObj*)ptr)->flag_shift);
+ PObj_flags_SETTO( (PObj*) ptr, 0);
return ptr;
}
1.16 +58 -2 parrot/t/op/gc.t
Index: gc.t
===================================================================
RCS file: /cvs/public/parrot/t/op/gc.t,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -w -r1.15 -r1.16
--- gc.t 18 Aug 2004 12:53:31 -0000 1.15
+++ gc.t 19 Aug 2004 11:48:19 -0000 1.16
@@ -1,6 +1,6 @@
#! perl -w
# Copyright: 2001-2003 The Perl Foundation. All Rights Reserved.
-# $Id: gc.t,v 1.15 2004/08/18 12:53:31 leo Exp $
+# $Id: gc.t,v 1.16 2004/08/19 11:48:19 leo Exp $
=head1 NAME
@@ -17,7 +17,7 @@
=cut
-use Parrot::Test tests => 15;
+use Parrot::Test tests => 16;
output_is( <<'CODE', '1', "sweep 1" );
interpinfo I1, 2 # How many DOD runs have we done already?
@@ -526,3 +526,59 @@
CODE
ok
OUTPUT
+
+output_is(<<'CODE', <<OUTPUT, "write barrier 2 - hash");
+ null I2
+ set I3, 100
+lp3:
+ null I0
+ set I1, 100
+ new P1, .PerlHash
+lp1:
+ new P2, .PerlHash
+ new P0, .Integer
+ set P0, I0
+ set S0, I0
+ set P2["first"], P0
+ set P1[S0], P2
+ if I0, not_0
+ new P0, .Integer
+ needs_destroy P0
+ null P0
+ # force full sweep
+ sweep 0
+not_0:
+ new P3, .Undef
+ new P4, .Undef
+ inc I0
+ lt I0, I1, lp1
+
+ null I0
+ # trace 1
+lp2:
+ set S0, I0
+ set P2, P1[S0]
+ set P2, P2["first"]
+ eq P2, I0, ok
+ print "nok\n"
+ print "I0: "
+ print I0
+ print " P2: "
+ print P2
+ print " type: "
+ typeof S0, P2
+ print S0
+ print " I2: "
+ print I2
+ print "\n"
+ exit 1
+ok:
+ inc I0
+ lt I0, I1, lp2
+ inc I2
+ lt I2, I3, lp3
+ print "ok\n"
+ end
+CODE
+ok
+OUTPUT