Well, actually two bugs.
The first is an off-by-one error in key.c than can cause parrot to segfault if hash % NUM_BUCKETS happens to be zero. The other is a bug in the PerlHash init() code that causes new PerlHash PMCs to start with the wrong size. Both fixed below; also tests to prevent them recurring. Simon --- key.c.old Wed Jan 9 20:00:01 2002 +++ key.c Thu Jan 10 17:41:01 2002 @@ -327,7 +327,7 @@ if(bucket != NULL) { hash = hash % NUM_BUCKETS; /* Resize the hash here rather than set an initial size. */ - if(hash > key->size) { + if(hash >= key->size) { key_set_size(interpreter,key,hash+1); } if(key->keys[hash].type != enum_key_undef) { --- perlhash.pmc.old Thu Jan 10 15:40:08 2002 +++ perlhash.pmc Thu Jan 10 17:40:32 2002 @@ -24,7 +24,7 @@ void init () { SELF->cache.struct_val = key_new(INTERP); - key_set_size(INTERP,SELF->cache.struct_val,1); + key_set_size(INTERP,SELF->cache.struct_val,0); } void clone (PMC* dest) { --- pmc_perlhash.t.old Thu Jan 10 15:41:47 2002 +++ pmc_perlhash.t Thu Jan 10 17:56:55 2002 @@ -1,6 +1,6 @@ #! perl -use Parrot::Test tests => 5; +use Parrot::Test tests => 7; output_is(<<'CODE', <<OUTPUT, "simple set / get"); new P0, PerlHash @@ -23,6 +23,28 @@ 2 OUTPUT +output_is(<<'CODE', <<OUTPUT, "more than one PerlHash"); + new P0, PerlHash + set S0, "key" + set P0, 1, S0 + + new P1, PerlHash + set S1, "another_key" + set P1, 2, S1 + + set I0, P0, S0 + set I1, P1, S1 + + print I0 + print "\n" + print I1 + print "\n" + end +CODE +1 +2 +OUTPUT + output_is(<<'CODE', <<OUTPUT, "hash keys with nulls in them"); new P0, PerlHash set S0, "parp\0me" @@ -112,5 +134,23 @@ 2 2 OUTPUT + + +# NB Next test depends on "key2" hashing to zero, which it does with +# the current algorithm; if the algorithm changes, change the test! + +output_is(<<'CODE', <<OUTPUT, "key that hashes to zero"); + new P0, PerlHash + set S0, "key2" + set P0, 1, S0 + set I0, P0, S0 + print I0 + print "\n" + end +CODE +1 +OUTPUT + + 1;