Skip to content

Commit 44e126e

Browse files
committed
* st.c: pack tables also generic keys. patched by Sokolov Yura at
ruby#84 git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@34964 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
1 parent 9fc653a commit 44e126e

File tree

2 files changed

+67
-39
lines changed

2 files changed

+67
-39
lines changed

ChangeLog

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
Sat Mar 10 23:52:16 2012 Nobuyoshi Nakada <nobu@ruby-lang.org>
1+
Sat Mar 10 23:52:28 2012 Nobuyoshi Nakada <nobu@ruby-lang.org>
2+
3+
* st.c: pack tables also generic keys. patched by Sokolov Yura at
4+
https://github.com/ruby/ruby/pull/84
25

36
* st.c: add st_foreach_check for fixing iteration over packed table
47
and st_delete_safe. patched by Sokolov Yura at

st.c

Lines changed: 63 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ struct st_table_entry {
2626
};
2727

2828
typedef struct st_packed_entry {
29+
st_index_t hash;
2930
st_data_t key, val;
3031
} st_packed_entry;
3132

@@ -34,7 +35,7 @@ typedef struct st_packed_entry {
3435
#define ST_DEFAULT_MAX_DENSITY 5
3536
#define ST_DEFAULT_INIT_TABLE_SIZE 11
3637
#define ST_DEFAULT_SECOND_TABLE_SIZE 19
37-
#define ST_DEFAULT_PACKED_TABLE_SIZE ST_DEFAULT_INIT_TABLE_SIZE
38+
#define ST_DEFAULT_PACKED_TABLE_SIZE 18
3839
#define PACKED_UNIT (int)(sizeof(st_packed_entry) / sizeof(st_table_entry*))
3940
#define MAX_PACKED_HASH (int)(ST_DEFAULT_PACKED_TABLE_SIZE * sizeof(st_table_entry*) / sizeof(st_packed_entry))
4041

@@ -112,9 +113,10 @@ st_realloc_bins(st_table_entry **bins, st_index_t newsize, st_index_t oldsize)
112113
#define PACKED_ENT(table, i) PACKED_BINS(table)[i]
113114
#define PKEY(table, i) PACKED_ENT((table), (i)).key
114115
#define PVAL(table, i) PACKED_ENT((table), (i)).val
115-
#define PHASH(table, i) PKEY((table), (i))
116+
#define PHASH(table, i) PACKED_ENT((table), (i)).hash
116117
#define PKEY_SET(table, i, v) (PKEY((table), (i)) = (v))
117118
#define PVAL_SET(table, i, v) (PVAL((table), (i)) = (v))
119+
#define PHASH_SET(table, i, v) (PHASH((table), (i)) = (v))
118120

119121
/* this function depends much on packed layout, so that it placed here */
120122
static inline void
@@ -232,12 +234,17 @@ st_init_table_with_size(const struct st_hash_type *type, st_index_t size)
232234
}
233235
#endif
234236

235-
size = new_size(size); /* round up to prime number */
236237

237238
tbl = st_alloc_table();
238239
tbl->type = type;
239240
tbl->num_entries = 0;
240-
tbl->entries_packed = type == &type_numhash && size/PACKED_UNIT <= MAX_PACKED_HASH;
241+
tbl->entries_packed = size <= MAX_PACKED_HASH;
242+
if (tbl->entries_packed) {
243+
size = ST_DEFAULT_PACKED_TABLE_SIZE;
244+
}
245+
else {
246+
size = new_size(size); /* round up to prime number */
247+
}
241248
tbl->num_bins = size;
242249
tbl->bins = st_alloc_bins(size);
243250
tbl->head = 0;
@@ -377,10 +384,13 @@ find_entry(st_table *table, st_data_t key, st_index_t hash_val, st_index_t bin_p
377384
}
378385

379386
static inline st_index_t
380-
find_packed_index(st_table *table, st_data_t key)
387+
find_packed_index(st_table *table, st_index_t hash_val, st_data_t key)
381388
{
382389
st_index_t i = 0;
383-
while (i < table->real_entries && PKEY(table, i) != key) i++;
390+
while (i < table->real_entries &&
391+
(PHASH(table, i) != hash_val || !EQUAL(table, key, PKEY(table, i)))) {
392+
i++;
393+
}
384394
return i;
385395
}
386396

@@ -392,16 +402,17 @@ st_lookup(st_table *table, register st_data_t key, st_data_t *value)
392402
st_index_t hash_val;
393403
register st_table_entry *ptr;
394404

405+
hash_val = do_hash(key, table);
406+
395407
if (table->entries_packed) {
396-
st_index_t i = find_packed_index(table, key);
408+
st_index_t i = find_packed_index(table, hash_val, key);
397409
if (i < table->real_entries) {
398410
if (value != 0) *value = PVAL(table, i);
399411
return 1;
400412
}
401413
return 0;
402414
}
403415

404-
hash_val = do_hash(key, table);
405416
ptr = find_entry(table, key, hash_val, hash_val % table->num_bins);
406417

407418
if (ptr == 0) {
@@ -419,16 +430,17 @@ st_get_key(st_table *table, register st_data_t key, st_data_t *result)
419430
st_index_t hash_val;
420431
register st_table_entry *ptr;
421432

433+
hash_val = do_hash(key, table);
434+
422435
if (table->entries_packed) {
423-
st_index_t i = find_packed_index(table, key);
436+
st_index_t i = find_packed_index(table, hash_val, key);
424437
if (i < table->real_entries) {
425438
if (result != 0) *result = PKEY(table, i);
426439
return 1;
427440
}
428441
return 0;
429442
}
430443

431-
hash_val = do_hash(key, table);
432444
ptr = find_entry(table, key, hash_val, hash_val % table->num_bins);
433445

434446
if (ptr == 0) {
@@ -504,8 +516,7 @@ unpack_entries(register st_table *table)
504516
do {
505517
st_data_t key = packed_bins[i].key;
506518
st_data_t val = packed_bins[i].val;
507-
/* packed table should be numhash */
508-
st_index_t hash = st_numhash(key);
519+
st_index_t hash = packed_bins[i].hash;
509520
entry = new_entry(&tmp_table, key, val, hash,
510521
hash % ST_DEFAULT_INIT_TABLE_SIZE);
511522
*chain = entry;
@@ -519,17 +530,18 @@ unpack_entries(register st_table *table)
519530
}
520531

521532
static void
522-
add_packed_direct(st_table *table, st_data_t key, st_data_t value)
533+
add_packed_direct(st_table *table, st_data_t key, st_data_t value, st_index_t hash_val)
523534
{
524535
if (table->real_entries < MAX_PACKED_HASH) {
525536
st_index_t i = table->real_entries++;
526537
PKEY_SET(table, i, key);
527538
PVAL_SET(table, i, value);
539+
PHASH_SET(table, i, hash_val);
528540
table->num_entries++;
529541
}
530542
else {
531543
unpack_entries(table);
532-
add_direct(table, key, value, key, key % table->num_bins);
544+
add_direct(table, key, value, hash_val, hash_val % table->num_bins);
533545
}
534546
}
535547

@@ -541,17 +553,18 @@ st_insert(register st_table *table, register st_data_t key, st_data_t value)
541553
register st_index_t bin_pos;
542554
register st_table_entry *ptr;
543555

556+
hash_val = do_hash(key, table);
557+
544558
if (table->entries_packed) {
545-
st_index_t i = find_packed_index(table, key);
559+
st_index_t i = find_packed_index(table, hash_val, key);
546560
if (i < table->real_entries) {
547561
PVAL_SET(table, i, value);
548562
return 1;
549563
}
550-
add_packed_direct(table, key, value);
564+
add_packed_direct(table, key, value, hash_val);
551565
return 0;
552566
}
553567

554-
hash_val = do_hash(key, table);
555568
FIND_ENTRY(table, ptr, hash_val, bin_pos);
556569

557570
if (ptr == 0) {
@@ -572,17 +585,19 @@ st_insert2(register st_table *table, register st_data_t key, st_data_t value,
572585
register st_index_t bin_pos;
573586
register st_table_entry *ptr;
574587

588+
hash_val = do_hash(key, table);
589+
575590
if (table->entries_packed) {
576-
st_index_t i = find_packed_index(table, key);
591+
st_index_t i = find_packed_index(table, hash_val, key);
577592
if (i < table->real_entries) {
578593
PVAL_SET(table, i, value);
579594
return 1;
580-
}
581-
add_packed_direct(table, key, value);
595+
}
596+
key = (*func)(key);
597+
add_packed_direct(table, key, value, hash_val);
582598
return 0;
583599
}
584600

585-
hash_val = do_hash(key, table);
586601
FIND_ENTRY(table, ptr, hash_val, bin_pos);
587602

588603
if (ptr == 0) {
@@ -601,12 +616,12 @@ st_add_direct(st_table *table, st_data_t key, st_data_t value)
601616
{
602617
st_index_t hash_val;
603618

619+
hash_val = do_hash(key, table);
604620
if (table->entries_packed) {
605-
add_packed_direct(table, key, value);
621+
add_packed_direct(table, key, value, hash_val);
606622
return;
607623
}
608624

609-
hash_val = do_hash(key, table);
610625
add_direct(table, key, value, hash_val, hash_val % table->num_bins);
611626
}
612627

@@ -703,20 +718,22 @@ st_delete(register st_table *table, register st_data_t *key, st_data_t *value)
703718
st_table_entry **prev;
704719
register st_table_entry *ptr;
705720

721+
hash_val = do_hash(*key, table);
722+
706723
if (table->entries_packed) {
707-
st_index_t i = find_packed_index(table, *key);
724+
st_index_t i = find_packed_index(table, hash_val, *key);
708725
if (i < table->num_entries) {
709726
if (value != 0) *value = PVAL(table, i);
727+
*key = PKEY(table, i);
710728
remove_packed_entry(table, i);
711729
return 1;
712730
}
713731
if (value != 0) *value = 0;
714732
return 0;
715733
}
716734

717-
hash_val = do_hash_bin(*key, table);
718-
719-
for (prev = &table->bins[hash_val]; (ptr = *prev) != 0; prev = &ptr->next) {
735+
prev = &table->bins[hash_val % table->num_bins];
736+
for (;(ptr = *prev) != 0; prev = &ptr->next) {
720737
if (EQUAL(table, *key, ptr->key)) {
721738
*prev = ptr->next;
722739
remove_entry(table, ptr);
@@ -737,20 +754,24 @@ st_delete_safe(register st_table *table, register st_data_t *key, st_data_t *val
737754
st_index_t hash_val;
738755
register st_table_entry *ptr;
739756

757+
hash_val = do_hash(*key, table);
758+
740759
if (table->entries_packed) {
741-
st_index_t i = find_packed_index(table, *key);
760+
st_index_t i = find_packed_index(table, hash_val, *key);
742761
if (i < table->real_entries) {
743762
if (value != 0) *value = PVAL(table, i);
763+
*key = PKEY(table, i);
744764
PKEY_SET(table, i, never);
765+
PVAL_SET(table, i, never);
766+
PHASH_SET(table, i, 0);
745767
table->num_entries--;
746768
return 1;
747769
}
748770
if (value != 0) *value = 0;
749771
return 0;
750772
}
751773

752-
hash_val = do_hash_bin(*key, table);
753-
ptr = table->bins[hash_val];
774+
ptr = table->bins[hash_val % table->num_bins];
754775

755776
for (; ptr != 0; ptr = ptr->next) {
756777
if ((ptr->key != never) && EQUAL(table, ptr->key, *key)) {
@@ -811,13 +832,14 @@ st_update(st_table *table, st_data_t key, int (*func)(st_data_t key, st_data_t *
811832
st_data_t value;
812833
int retval;
813834

835+
hash_val = do_hash(key, table);
836+
814837
if (table->entries_packed) {
815-
st_index_t i = find_packed_index(table, key);
838+
st_index_t i = find_packed_index(table, hash_val, key);
816839
if (i < table->real_entries) {
817840
value = PVAL(table, i);
818841
retval = (*func)(key, &value, arg);
819842
if (!table->entries_packed) {
820-
hash_val = do_hash(key, table);
821843
FIND_ENTRY(table, ptr, hash_val, bin_pos);
822844
if (ptr == 0) return 0;
823845
goto unpacked;
@@ -834,7 +856,6 @@ st_update(st_table *table, st_data_t key, int (*func)(st_data_t key, st_data_t *
834856
return 0;
835857
}
836858

837-
hash_val = do_hash(key, table);
838859
FIND_ENTRY(table, ptr, hash_val, bin_pos);
839860

840861
if (ptr == 0) {
@@ -875,12 +896,14 @@ st_foreach_check(st_table *table, int (*func)(ANYARGS), st_data_t arg, st_data_t
875896
if (table->entries_packed) {
876897
for (i = 0; i < table->real_entries; i++) {
877898
st_data_t key, val;
899+
st_index_t hash;
878900
key = PKEY(table, i);
879901
val = PVAL(table, i);
902+
hash = PHASH(table, i);
880903
if (key == never) continue;
881904
retval = (*func)(key, val, arg);
882905
if (!table->entries_packed) {
883-
FIND_ENTRY(table, ptr, key, i);
906+
FIND_ENTRY(table, ptr, hash, i);
884907
if (retval == ST_CHECK) {
885908
if (!ptr) goto deleted;
886909
goto unpacked_continue;
@@ -889,10 +912,11 @@ st_foreach_check(st_table *table, int (*func)(ANYARGS), st_data_t arg, st_data_t
889912
}
890913
switch (retval) {
891914
case ST_CHECK: /* check if hash is modified during iteration */
892-
if (PKEY(table, i) == never) {
915+
if (PHASH(table, i) == 0 && PKEY(table, i) == never) {
893916
break;
894917
}
895-
if (i != find_packed_index(table, key)) {
918+
i = find_packed_index(table, hash, key);
919+
if (i == table->real_entries) {
896920
goto deleted;
897921
}
898922
/* fall through */
@@ -964,12 +988,13 @@ st_foreach(st_table *table, int (*func)(ANYARGS), st_data_t arg)
964988

965989
if (table->entries_packed) {
966990
for (i = 0; i < table->real_entries; i++) {
967-
st_data_t key, val;
991+
st_data_t key, val, hash;
968992
key = PKEY(table, i);
969993
val = PVAL(table, i);
994+
hash = PHASH(table, i);
970995
retval = (*func)(key, val, arg);
971996
if (!table->entries_packed) {
972-
FIND_ENTRY(table, ptr, key, i);
997+
FIND_ENTRY(table, ptr, hash, i);
973998
if (!ptr) return 0;
974999
goto unpacked;
9751000
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy