@@ -26,6 +26,7 @@ struct st_table_entry {
26
26
};
27
27
28
28
typedef struct st_packed_entry {
29
+ st_index_t hash ;
29
30
st_data_t key , val ;
30
31
} st_packed_entry ;
31
32
@@ -34,7 +35,7 @@ typedef struct st_packed_entry {
34
35
#define ST_DEFAULT_MAX_DENSITY 5
35
36
#define ST_DEFAULT_INIT_TABLE_SIZE 11
36
37
#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
38
39
#define PACKED_UNIT (int)(sizeof(st_packed_entry) / sizeof(st_table_entry*))
39
40
#define MAX_PACKED_HASH (int)(ST_DEFAULT_PACKED_TABLE_SIZE * sizeof(st_table_entry*) / sizeof(st_packed_entry))
40
41
@@ -112,9 +113,10 @@ st_realloc_bins(st_table_entry **bins, st_index_t newsize, st_index_t oldsize)
112
113
#define PACKED_ENT (table , i ) PACKED_BINS(table)[i]
113
114
#define PKEY (table , i ) PACKED_ENT((table), (i)).key
114
115
#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
116
117
#define PKEY_SET (table , i , v ) (PKEY((table), (i)) = (v))
117
118
#define PVAL_SET (table , i , v ) (PVAL((table), (i)) = (v))
119
+ #define PHASH_SET (table , i , v ) (PHASH((table), (i)) = (v))
118
120
119
121
/* this function depends much on packed layout, so that it placed here */
120
122
static inline void
@@ -232,12 +234,17 @@ st_init_table_with_size(const struct st_hash_type *type, st_index_t size)
232
234
}
233
235
#endif
234
236
235
- size = new_size (size ); /* round up to prime number */
236
237
237
238
tbl = st_alloc_table ();
238
239
tbl -> type = type ;
239
240
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
+ }
241
248
tbl -> num_bins = size ;
242
249
tbl -> bins = st_alloc_bins (size );
243
250
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
377
384
}
378
385
379
386
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 )
381
388
{
382
389
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
+ }
384
394
return i ;
385
395
}
386
396
@@ -392,16 +402,17 @@ st_lookup(st_table *table, register st_data_t key, st_data_t *value)
392
402
st_index_t hash_val ;
393
403
register st_table_entry * ptr ;
394
404
405
+ hash_val = do_hash (key , table );
406
+
395
407
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 );
397
409
if (i < table -> real_entries ) {
398
410
if (value != 0 ) * value = PVAL (table , i );
399
411
return 1 ;
400
412
}
401
413
return 0 ;
402
414
}
403
415
404
- hash_val = do_hash (key , table );
405
416
ptr = find_entry (table , key , hash_val , hash_val % table -> num_bins );
406
417
407
418
if (ptr == 0 ) {
@@ -419,16 +430,17 @@ st_get_key(st_table *table, register st_data_t key, st_data_t *result)
419
430
st_index_t hash_val ;
420
431
register st_table_entry * ptr ;
421
432
433
+ hash_val = do_hash (key , table );
434
+
422
435
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 );
424
437
if (i < table -> real_entries ) {
425
438
if (result != 0 ) * result = PKEY (table , i );
426
439
return 1 ;
427
440
}
428
441
return 0 ;
429
442
}
430
443
431
- hash_val = do_hash (key , table );
432
444
ptr = find_entry (table , key , hash_val , hash_val % table -> num_bins );
433
445
434
446
if (ptr == 0 ) {
@@ -504,8 +516,7 @@ unpack_entries(register st_table *table)
504
516
do {
505
517
st_data_t key = packed_bins [i ].key ;
506
518
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 ;
509
520
entry = new_entry (& tmp_table , key , val , hash ,
510
521
hash % ST_DEFAULT_INIT_TABLE_SIZE );
511
522
* chain = entry ;
@@ -519,17 +530,18 @@ unpack_entries(register st_table *table)
519
530
}
520
531
521
532
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 )
523
534
{
524
535
if (table -> real_entries < MAX_PACKED_HASH ) {
525
536
st_index_t i = table -> real_entries ++ ;
526
537
PKEY_SET (table , i , key );
527
538
PVAL_SET (table , i , value );
539
+ PHASH_SET (table , i , hash_val );
528
540
table -> num_entries ++ ;
529
541
}
530
542
else {
531
543
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 );
533
545
}
534
546
}
535
547
@@ -541,17 +553,18 @@ st_insert(register st_table *table, register st_data_t key, st_data_t value)
541
553
register st_index_t bin_pos ;
542
554
register st_table_entry * ptr ;
543
555
556
+ hash_val = do_hash (key , table );
557
+
544
558
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 );
546
560
if (i < table -> real_entries ) {
547
561
PVAL_SET (table , i , value );
548
562
return 1 ;
549
563
}
550
- add_packed_direct (table , key , value );
564
+ add_packed_direct (table , key , value , hash_val );
551
565
return 0 ;
552
566
}
553
567
554
- hash_val = do_hash (key , table );
555
568
FIND_ENTRY (table , ptr , hash_val , bin_pos );
556
569
557
570
if (ptr == 0 ) {
@@ -572,17 +585,19 @@ st_insert2(register st_table *table, register st_data_t key, st_data_t value,
572
585
register st_index_t bin_pos ;
573
586
register st_table_entry * ptr ;
574
587
588
+ hash_val = do_hash (key , table );
589
+
575
590
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 );
577
592
if (i < table -> real_entries ) {
578
593
PVAL_SET (table , i , value );
579
594
return 1 ;
580
- }
581
- add_packed_direct (table , key , value );
595
+ }
596
+ key = (* func )(key );
597
+ add_packed_direct (table , key , value , hash_val );
582
598
return 0 ;
583
599
}
584
600
585
- hash_val = do_hash (key , table );
586
601
FIND_ENTRY (table , ptr , hash_val , bin_pos );
587
602
588
603
if (ptr == 0 ) {
@@ -601,12 +616,12 @@ st_add_direct(st_table *table, st_data_t key, st_data_t value)
601
616
{
602
617
st_index_t hash_val ;
603
618
619
+ hash_val = do_hash (key , table );
604
620
if (table -> entries_packed ) {
605
- add_packed_direct (table , key , value );
621
+ add_packed_direct (table , key , value , hash_val );
606
622
return ;
607
623
}
608
624
609
- hash_val = do_hash (key , table );
610
625
add_direct (table , key , value , hash_val , hash_val % table -> num_bins );
611
626
}
612
627
@@ -703,20 +718,22 @@ st_delete(register st_table *table, register st_data_t *key, st_data_t *value)
703
718
st_table_entry * * prev ;
704
719
register st_table_entry * ptr ;
705
720
721
+ hash_val = do_hash (* key , table );
722
+
706
723
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 );
708
725
if (i < table -> num_entries ) {
709
726
if (value != 0 ) * value = PVAL (table , i );
727
+ * key = PKEY (table , i );
710
728
remove_packed_entry (table , i );
711
729
return 1 ;
712
730
}
713
731
if (value != 0 ) * value = 0 ;
714
732
return 0 ;
715
733
}
716
734
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 ) {
720
737
if (EQUAL (table , * key , ptr -> key )) {
721
738
* prev = ptr -> next ;
722
739
remove_entry (table , ptr );
@@ -737,20 +754,24 @@ st_delete_safe(register st_table *table, register st_data_t *key, st_data_t *val
737
754
st_index_t hash_val ;
738
755
register st_table_entry * ptr ;
739
756
757
+ hash_val = do_hash (* key , table );
758
+
740
759
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 );
742
761
if (i < table -> real_entries ) {
743
762
if (value != 0 ) * value = PVAL (table , i );
763
+ * key = PKEY (table , i );
744
764
PKEY_SET (table , i , never );
765
+ PVAL_SET (table , i , never );
766
+ PHASH_SET (table , i , 0 );
745
767
table -> num_entries -- ;
746
768
return 1 ;
747
769
}
748
770
if (value != 0 ) * value = 0 ;
749
771
return 0 ;
750
772
}
751
773
752
- hash_val = do_hash_bin (* key , table );
753
- ptr = table -> bins [hash_val ];
774
+ ptr = table -> bins [hash_val % table -> num_bins ];
754
775
755
776
for (; ptr != 0 ; ptr = ptr -> next ) {
756
777
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 *
811
832
st_data_t value ;
812
833
int retval ;
813
834
835
+ hash_val = do_hash (key , table );
836
+
814
837
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 );
816
839
if (i < table -> real_entries ) {
817
840
value = PVAL (table , i );
818
841
retval = (* func )(key , & value , arg );
819
842
if (!table -> entries_packed ) {
820
- hash_val = do_hash (key , table );
821
843
FIND_ENTRY (table , ptr , hash_val , bin_pos );
822
844
if (ptr == 0 ) return 0 ;
823
845
goto unpacked ;
@@ -834,7 +856,6 @@ st_update(st_table *table, st_data_t key, int (*func)(st_data_t key, st_data_t *
834
856
return 0 ;
835
857
}
836
858
837
- hash_val = do_hash (key , table );
838
859
FIND_ENTRY (table , ptr , hash_val , bin_pos );
839
860
840
861
if (ptr == 0 ) {
@@ -875,12 +896,14 @@ st_foreach_check(st_table *table, int (*func)(ANYARGS), st_data_t arg, st_data_t
875
896
if (table -> entries_packed ) {
876
897
for (i = 0 ; i < table -> real_entries ; i ++ ) {
877
898
st_data_t key , val ;
899
+ st_index_t hash ;
878
900
key = PKEY (table , i );
879
901
val = PVAL (table , i );
902
+ hash = PHASH (table , i );
880
903
if (key == never ) continue ;
881
904
retval = (* func )(key , val , arg );
882
905
if (!table -> entries_packed ) {
883
- FIND_ENTRY (table , ptr , key , i );
906
+ FIND_ENTRY (table , ptr , hash , i );
884
907
if (retval == ST_CHECK ) {
885
908
if (!ptr ) goto deleted ;
886
909
goto unpacked_continue ;
@@ -889,10 +912,11 @@ st_foreach_check(st_table *table, int (*func)(ANYARGS), st_data_t arg, st_data_t
889
912
}
890
913
switch (retval ) {
891
914
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 ) {
893
916
break ;
894
917
}
895
- if (i != find_packed_index (table , key )) {
918
+ i = find_packed_index (table , hash , key );
919
+ if (i == table -> real_entries ) {
896
920
goto deleted ;
897
921
}
898
922
/* fall through */
@@ -964,12 +988,13 @@ st_foreach(st_table *table, int (*func)(ANYARGS), st_data_t arg)
964
988
965
989
if (table -> entries_packed ) {
966
990
for (i = 0 ; i < table -> real_entries ; i ++ ) {
967
- st_data_t key , val ;
991
+ st_data_t key , val , hash ;
968
992
key = PKEY (table , i );
969
993
val = PVAL (table , i );
994
+ hash = PHASH (table , i );
970
995
retval = (* func )(key , val , arg );
971
996
if (!table -> entries_packed ) {
972
- FIND_ENTRY (table , ptr , key , i );
997
+ FIND_ENTRY (table , ptr , hash , i );
973
998
if (!ptr ) return 0 ;
974
999
goto unpacked ;
975
1000
}
0 commit comments