Mercurial > hg > xemacs-beta
comparison src/elhash.c @ 5118:e0db3c197671 ben-lisp-object
merge up to latest default branch, doesn't compile yet
author | Ben Wing <ben@xemacs.org> |
---|---|
date | Sat, 26 Dec 2009 21:18:49 -0600 |
parents | 3742ea8250b5 fd98353950a4 |
children | d1247f3cc363 |
comparison
equal
deleted
inserted
replaced
5117:3742ea8250b5 | 5118:e0db3c197671 |
---|---|
91 static Lisp_Object Q_size, Q_test, Q_weakness, Q_rehash_size, Q_rehash_threshold; | 91 static Lisp_Object Q_size, Q_test, Q_weakness, Q_rehash_size, Q_rehash_threshold; |
92 | 92 |
93 /* obsolete as of 19990901 in xemacs-21.2 */ | 93 /* obsolete as of 19990901 in xemacs-21.2 */ |
94 static Lisp_Object Qweak, Qkey_weak, Qvalue_weak, Qkey_or_value_weak; | 94 static Lisp_Object Qweak, Qkey_weak, Qvalue_weak, Qkey_or_value_weak; |
95 static Lisp_Object Qnon_weak, Q_type; | 95 static Lisp_Object Qnon_weak, Q_type; |
96 | |
97 typedef struct htentry | |
98 { | |
99 Lisp_Object key; | |
100 Lisp_Object value; | |
101 } htentry; | |
102 | 96 |
103 struct Lisp_Hash_Table | 97 struct Lisp_Hash_Table |
104 { | 98 { |
105 struct LCRECORD_HEADER header; | 99 struct LCRECORD_HEADER header; |
106 Elemcount size; | 100 Elemcount size; |
115 enum hash_table_weakness weakness; | 109 enum hash_table_weakness weakness; |
116 Lisp_Object next_weak; /* Used to chain together all of the weak | 110 Lisp_Object next_weak; /* Used to chain together all of the weak |
117 hash tables. Don't mark through this. */ | 111 hash tables. Don't mark through this. */ |
118 }; | 112 }; |
119 | 113 |
120 #define HTENTRY_CLEAR_P(htentry) ((*(EMACS_UINT*)(&((htentry)->key))) == 0) | |
121 #define CLEAR_HTENTRY(htentry) \ | 114 #define CLEAR_HTENTRY(htentry) \ |
122 ((*(EMACS_UINT*)(&((htentry)->key))) = 0, \ | 115 ((*(EMACS_UINT*)(&((htentry)->key))) = 0, \ |
123 (*(EMACS_UINT*)(&((htentry)->value))) = 0) | 116 (*(EMACS_UINT*)(&((htentry)->value))) = 0) |
124 | 117 |
125 #define HASH_TABLE_DEFAULT_SIZE 16 | 118 #define HASH_TABLE_DEFAULT_SIZE 16 |
126 #define HASH_TABLE_DEFAULT_REHASH_SIZE 1.3 | 119 #define HASH_TABLE_DEFAULT_REHASH_SIZE 1.3 |
127 #define HASH_TABLE_MIN_SIZE 10 | 120 #define HASH_TABLE_MIN_SIZE 10 |
121 #define HASH_TABLE_DEFAULT_REHASH_THRESHOLD(size, test_function) \ | |
122 (((size) > 4096 && NULL == (test_function)) ? 0.7 : 0.6) | |
128 | 123 |
129 #define HASHCODE(key, ht) \ | 124 #define HASHCODE(key, ht) \ |
130 ((((ht)->hash_function ? (ht)->hash_function (key) : LISP_HASH (key)) \ | 125 ((((ht)->hash_function ? (ht)->hash_function (key) : LISP_HASH (key)) \ |
131 * (ht)->golden_ratio) \ | 126 * (ht)->golden_ratio) \ |
132 % (ht)->size) | 127 % (ht)->size) |
358 static void | 353 static void |
359 print_hash_table (Lisp_Object obj, Lisp_Object printcharfun, | 354 print_hash_table (Lisp_Object obj, Lisp_Object printcharfun, |
360 int UNUSED (escapeflag)) | 355 int UNUSED (escapeflag)) |
361 { | 356 { |
362 Lisp_Hash_Table *ht = XHASH_TABLE (obj); | 357 Lisp_Hash_Table *ht = XHASH_TABLE (obj); |
358 Ascbyte pigbuf[350]; | |
363 | 359 |
364 write_c_string (printcharfun, | 360 write_c_string (printcharfun, |
365 print_readably ? "#s(hash-table" : "#<hash-table"); | 361 print_readably ? "#s(hash-table" : "#<hash-table"); |
366 | 362 |
367 /* These checks have a kludgy look to them, but they are safe. | 363 /* These checks have a kludgy look to them, but they are safe. |
394 ht->weakness == HASH_TABLE_VALUE_WEAK ? "value" : | 390 ht->weakness == HASH_TABLE_VALUE_WEAK ? "value" : |
395 ht->weakness == HASH_TABLE_KEY_VALUE_WEAK ? "key-or-value" : | 391 ht->weakness == HASH_TABLE_KEY_VALUE_WEAK ? "key-or-value" : |
396 "you-d-better-not-see-this")); | 392 "you-d-better-not-see-this")); |
397 } | 393 } |
398 | 394 |
395 if (ht->rehash_size != HASH_TABLE_DEFAULT_REHASH_SIZE) | |
396 { | |
397 float_to_string (pigbuf, ht->rehash_size); | |
398 write_fmt_string (printcharfun, " rehash-size %s", pigbuf); | |
399 } | |
400 | |
401 if (ht->rehash_threshold | |
402 != HASH_TABLE_DEFAULT_REHASH_THRESHOLD (ht->size, | |
403 ht->test_function)) | |
404 { | |
405 float_to_string (pigbuf, ht->rehash_threshold); | |
406 write_fmt_string (printcharfun, " rehash-threshold %s", pigbuf); | |
407 } | |
408 | |
399 if (ht->count) | 409 if (ht->count) |
400 print_hash_table_data (ht, printcharfun); | 410 print_hash_table_data (ht, printcharfun); |
401 | 411 |
402 if (print_readably) | 412 if (print_readably) |
403 write_c_string (printcharfun, ")"); | 413 write_c_string (printcharfun, ")"); |
404 else | 414 else |
405 write_fmt_string (printcharfun, " 0x%x>", ht->header.uid); | 415 write_fmt_string (printcharfun, " 0x%x>", ht->header.uid); |
406 } | 416 } |
407 | 417 |
418 #ifndef NEW_GC | |
408 static void | 419 static void |
409 free_hentries (htentry *hentries, | 420 free_hentries (htentry *hentries, |
410 #ifdef ERROR_CHECK_STRUCTURES | 421 #ifdef ERROR_CHECK_STRUCTURES |
411 size_t size | 422 size_t size |
412 #else | 423 #else /* not ERROR_CHECK_STRUCTURES) */ |
413 size_t UNUSED (size) | 424 size_t UNUSED (size) |
414 #endif | 425 #endif /* not ERROR_CHECK_STRUCTURES) */ |
415 ) | 426 ) |
416 { | 427 { |
417 #ifdef ERROR_CHECK_STRUCTURES | 428 #ifdef ERROR_CHECK_STRUCTURES |
418 /* Ensure a crash if other code uses the discarded entries afterwards. */ | 429 /* Ensure a crash if other code uses the discarded entries afterwards. */ |
419 htentry *e, *sentinel; | 430 htentry *e, *sentinel; |
434 Lisp_Hash_Table *ht = (Lisp_Hash_Table *) header; | 445 Lisp_Hash_Table *ht = (Lisp_Hash_Table *) header; |
435 free_hentries (ht->hentries, ht->size); | 446 free_hentries (ht->hentries, ht->size); |
436 ht->hentries = 0; | 447 ht->hentries = 0; |
437 } | 448 } |
438 } | 449 } |
450 #endif /* not NEW_GC */ | |
439 | 451 |
440 static const struct memory_description htentry_description_1[] = { | 452 static const struct memory_description htentry_description_1[] = { |
441 { XD_LISP_OBJECT, offsetof (htentry, key) }, | 453 { XD_LISP_OBJECT, offsetof (htentry, key) }, |
442 { XD_LISP_OBJECT, offsetof (htentry, value) }, | 454 { XD_LISP_OBJECT, offsetof (htentry, value) }, |
443 { XD_END } | 455 { XD_END } |
446 static const struct sized_memory_description htentry_description = { | 458 static const struct sized_memory_description htentry_description = { |
447 sizeof (htentry), | 459 sizeof (htentry), |
448 htentry_description_1 | 460 htentry_description_1 |
449 }; | 461 }; |
450 | 462 |
463 #ifdef NEW_GC | |
464 static const struct memory_description htentry_weak_description_1[] = { | |
465 { XD_LISP_OBJECT, offsetof (htentry, key), 0, { 0 }, XD_FLAG_NO_KKCC}, | |
466 { XD_LISP_OBJECT, offsetof (htentry, value), 0, { 0 }, XD_FLAG_NO_KKCC}, | |
467 { XD_END } | |
468 }; | |
469 | |
470 static const struct sized_memory_description htentry_weak_description = { | |
471 sizeof (htentry), | |
472 htentry_weak_description_1 | |
473 }; | |
474 | |
475 DEFINE_DUMPABLE_INTERNAL_LISP_OBJECT ("hash-table-entry", hash_table_entry, | |
476 0, htentry_description_1, | |
477 Lisp_Hash_Table_Entry); | |
478 #endif /* NEW_GC */ | |
479 | |
451 static const struct memory_description htentry_union_description_1[] = { | 480 static const struct memory_description htentry_union_description_1[] = { |
452 /* Note: XD_INDIRECT in this table refers to the surrounding table, | 481 /* Note: XD_INDIRECT in this table refers to the surrounding table, |
453 and so this will work. */ | 482 and so this will work. */ |
483 #ifdef NEW_GC | |
484 { XD_LISP_OBJECT_BLOCK_PTR, HASH_TABLE_NON_WEAK, | |
485 XD_INDIRECT (0, 1), { &htentry_description } }, | |
486 { XD_LISP_OBJECT_BLOCK_PTR, 0, XD_INDIRECT (0, 1), | |
487 { &htentry_weak_description }, XD_FLAG_UNION_DEFAULT_ENTRY }, | |
488 #else /* not NEW_GC */ | |
454 { XD_BLOCK_PTR, HASH_TABLE_NON_WEAK, XD_INDIRECT (0, 1), | 489 { XD_BLOCK_PTR, HASH_TABLE_NON_WEAK, XD_INDIRECT (0, 1), |
455 { &htentry_description } }, | 490 { &htentry_description } }, |
456 { XD_BLOCK_PTR, 0, XD_INDIRECT (0, 1), { &htentry_description }, | 491 { XD_BLOCK_PTR, 0, XD_INDIRECT (0, 1), { &htentry_description }, |
457 XD_FLAG_UNION_DEFAULT_ENTRY | XD_FLAG_NO_KKCC }, | 492 XD_FLAG_UNION_DEFAULT_ENTRY | XD_FLAG_NO_KKCC }, |
493 #endif /* not NEW_GC */ | |
458 { XD_END } | 494 { XD_END } |
459 }; | 495 }; |
460 | 496 |
461 static const struct sized_memory_description htentry_union_description = { | 497 static const struct sized_memory_description htentry_union_description = { |
462 sizeof (htentry *), | 498 sizeof (htentry *), |
470 { &htentry_union_description } }, | 506 { &htentry_union_description } }, |
471 { XD_LO_LINK, offsetof (Lisp_Hash_Table, next_weak) }, | 507 { XD_LO_LINK, offsetof (Lisp_Hash_Table, next_weak) }, |
472 { XD_END } | 508 { XD_END } |
473 }; | 509 }; |
474 | 510 |
475 DEFINE_LISP_OBJECT ("hash-table", hash_table, | 511 #ifdef NEW_GC |
476 mark_hash_table, print_hash_table, | 512 DEFINE_DUMPABLE_LISP_OBJECT ("hash-table", hash_table, |
477 finalize_hash_table, | 513 mark_hash_table, print_hash_table, |
478 hash_table_equal, hash_table_hash, | 514 0, hash_table_equal, hash_table_hash, |
479 hash_table_description, | 515 hash_table_description, |
480 Lisp_Hash_Table); | 516 Lisp_Hash_Table); |
517 #else /* not NEW_GC */ | |
518 DEFINE_DUMPABLE_LISP_OBJECT ("hash-table", hash_table, | |
519 mark_hash_table, print_hash_table, | |
520 finalize_hash_table, | |
521 hash_table_equal, hash_table_hash, | |
522 hash_table_description, | |
523 Lisp_Hash_Table); | |
524 #endif /* not NEW_GC */ | |
481 | 525 |
482 static Lisp_Hash_Table * | 526 static Lisp_Hash_Table * |
483 xhash_table (Lisp_Object hash_table) | 527 xhash_table (Lisp_Object hash_table) |
484 { | 528 { |
485 /* #### What's going on here? Why the gc_in_progress check? */ | 529 /* #### What's going on here? Why the gc_in_progress check? */ |
500 { | 544 { |
501 ht->rehash_count = (Elemcount) | 545 ht->rehash_count = (Elemcount) |
502 ((double) ht->size * ht->rehash_threshold); | 546 ((double) ht->size * ht->rehash_threshold); |
503 ht->golden_ratio = (Elemcount) | 547 ht->golden_ratio = (Elemcount) |
504 ((double) ht->size * (.6180339887 / (double) sizeof (Lisp_Object))); | 548 ((double) ht->size * (.6180339887 / (double) sizeof (Lisp_Object))); |
549 } | |
550 | |
551 static htentry * | |
552 allocate_hash_table_entries (Elemcount size) | |
553 { | |
554 #ifdef NEW_GC | |
555 return XHASH_TABLE_ENTRY (alloc_lrecord_array | |
556 (size, &lrecord_hash_table_entry)); | |
557 #else /* not NEW_GC */ | |
558 return xnew_array_and_zero (htentry, size); | |
559 #endif /* not NEW_GC */ | |
505 } | 560 } |
506 | 561 |
507 Lisp_Object | 562 Lisp_Object |
508 make_standard_lisp_hash_table (enum hash_table_test test, | 563 make_standard_lisp_hash_table (enum hash_table_test test, |
509 Elemcount size, | 564 Elemcount size, |
558 ht->rehash_size = | 613 ht->rehash_size = |
559 rehash_size > 1.0 ? rehash_size : HASH_TABLE_DEFAULT_REHASH_SIZE; | 614 rehash_size > 1.0 ? rehash_size : HASH_TABLE_DEFAULT_REHASH_SIZE; |
560 | 615 |
561 ht->rehash_threshold = | 616 ht->rehash_threshold = |
562 rehash_threshold > 0.0 ? rehash_threshold : | 617 rehash_threshold > 0.0 ? rehash_threshold : |
563 size > 4096 && !ht->test_function ? 0.7 : 0.6; | 618 HASH_TABLE_DEFAULT_REHASH_THRESHOLD (size, ht->test_function); |
564 | 619 |
565 if (size < HASH_TABLE_MIN_SIZE) | 620 if (size < HASH_TABLE_MIN_SIZE) |
566 size = HASH_TABLE_MIN_SIZE; | 621 size = HASH_TABLE_MIN_SIZE; |
567 ht->size = hash_table_size ((Elemcount) (((double) size / ht->rehash_threshold) | 622 ht->size = hash_table_size ((Elemcount) (((double) size / ht->rehash_threshold) |
568 + 1.0)); | 623 + 1.0)); |
569 ht->count = 0; | 624 ht->count = 0; |
570 | 625 |
571 compute_hash_table_derived_values (ht); | 626 compute_hash_table_derived_values (ht); |
572 | 627 |
573 /* We leave room for one never-occupied sentinel htentry at the end. */ | 628 /* We leave room for one never-occupied sentinel htentry at the end. */ |
574 ht->hentries = xnew_array_and_zero (htentry, ht->size + 1); | 629 ht->hentries = allocate_hash_table_entries (ht->size + 1); |
575 | 630 |
576 if (weakness == HASH_TABLE_NON_WEAK) | 631 if (weakness == HASH_TABLE_NON_WEAK) |
577 ht->next_weak = Qunbound; | 632 ht->next_weak = Qunbound; |
578 else | 633 else |
579 ht->next_weak = Vall_weak_hash_tables, Vall_weak_hash_tables = hash_table; | 634 ht->next_weak = Vall_weak_hash_tables, Vall_weak_hash_tables = hash_table; |
714 } | 769 } |
715 | 770 |
716 static double | 771 static double |
717 decode_hash_table_rehash_size (Lisp_Object rehash_size) | 772 decode_hash_table_rehash_size (Lisp_Object rehash_size) |
718 { | 773 { |
774 /* -1.0 signals make_general_lisp_hash_table to use the default. */ | |
719 return NILP (rehash_size) ? -1.0 : XFLOAT_DATA (rehash_size); | 775 return NILP (rehash_size) ? -1.0 : XFLOAT_DATA (rehash_size); |
720 } | 776 } |
721 | 777 |
722 static int | 778 static int |
723 hash_table_rehash_threshold_validate (Lisp_Object UNUSED (keyword), | 779 hash_table_rehash_threshold_validate (Lisp_Object UNUSED (keyword), |
745 } | 801 } |
746 | 802 |
747 static double | 803 static double |
748 decode_hash_table_rehash_threshold (Lisp_Object rehash_threshold) | 804 decode_hash_table_rehash_threshold (Lisp_Object rehash_threshold) |
749 { | 805 { |
806 /* -1.0 signals make_general_lisp_hash_table to use the default. */ | |
750 return NILP (rehash_threshold) ? -1.0 : XFLOAT_DATA (rehash_threshold); | 807 return NILP (rehash_threshold) ? -1.0 : XFLOAT_DATA (rehash_threshold); |
751 } | 808 } |
752 | 809 |
753 static int | 810 static int |
754 hash_table_data_validate (Lisp_Object UNUSED (keyword), Lisp_Object value, | 811 hash_table_data_validate (Lisp_Object UNUSED (keyword), Lisp_Object value, |
755 Error_Behavior errb) | 812 Error_Behavior errb) |
756 { | 813 { |
757 int len; | 814 int len; |
758 | 815 |
816 /* Check for improper lists while getting length. */ | |
759 GET_EXTERNAL_LIST_LENGTH (value, len); | 817 GET_EXTERNAL_LIST_LENGTH (value, len); |
760 | 818 |
761 if (len & 1) | 819 if (len & 1) |
762 { | 820 { |
763 maybe_sferror | 821 maybe_sferror |
764 ("Hash table data must have alternating key/value pairs", | 822 ("Hash table data must have alternating key/value pairs", |
765 value, Qhash_table, errb); | 823 value, Qhash_table, errb); |
766 return 0; | 824 return 0; |
767 } | 825 } |
826 | |
768 return 1; | 827 return 1; |
769 } | 828 } |
770 | 829 |
771 /* The actual instantiation of a hash table. This does practically no | 830 /* The actual instantiation of a hash table. This does practically no |
772 error checking, because it relies on the fact that the paranoid | 831 error checking, because it relies on the fact that the paranoid |
867 } | 926 } |
868 | 927 |
869 DEFUN ("make-hash-table", Fmake_hash_table, 0, MANY, 0, /* | 928 DEFUN ("make-hash-table", Fmake_hash_table, 0, MANY, 0, /* |
870 Return a new empty hash table object. | 929 Return a new empty hash table object. |
871 Use Common Lisp style keywords to specify hash table properties. | 930 Use Common Lisp style keywords to specify hash table properties. |
872 (make-hash-table &key test size rehash-size rehash-threshold weakness) | |
873 | 931 |
874 Keyword :test can be `eq', `eql' (default) or `equal'. | 932 Keyword :test can be `eq', `eql' (default) or `equal'. |
875 Comparison between keys is done using this function. | 933 Comparison between keys is done using this function. |
876 If speed is important, consider using `eq'. | 934 If speed is important, consider using `eq'. |
877 When storing strings in the hash table, you will likely need to use `equal'. | 935 When storing strings in the hash table, you will likely need to use `equal'. |
911 A key-or-value-weak hash table is similar to a fully-weak hash table except | 969 A key-or-value-weak hash table is similar to a fully-weak hash table except |
912 that a key-value pair will be removed only if the value and the key remain | 970 that a key-value pair will be removed only if the value and the key remain |
913 unmarked outside of weak hash tables. The pair will remain in the | 971 unmarked outside of weak hash tables. The pair will remain in the |
914 hash table if the value or key are pointed to by something other than a weak | 972 hash table if the value or key are pointed to by something other than a weak |
915 hash table, even if the other is not. | 973 hash table, even if the other is not. |
974 | |
975 arguments: (&key TEST SIZE REHASH-SIZE REHASH-THRESHOLD WEAKNESS) | |
916 */ | 976 */ |
917 (int nargs, Lisp_Object *args)) | 977 (int nargs, Lisp_Object *args)) |
918 { | 978 { |
919 int i = 0; | 979 int i = 0; |
920 Lisp_Object test = Qnil; | 980 Lisp_Object test = Qnil; |
966 const Lisp_Hash_Table *ht_old = xhash_table (hash_table); | 1026 const Lisp_Hash_Table *ht_old = xhash_table (hash_table); |
967 Lisp_Object obj = ALLOC_LISP_OBJECT (hash_table); | 1027 Lisp_Object obj = ALLOC_LISP_OBJECT (hash_table); |
968 Lisp_Hash_Table *ht = XHASH_TABLE (obj); | 1028 Lisp_Hash_Table *ht = XHASH_TABLE (obj); |
969 COPY_LCRECORD (ht, ht_old); | 1029 COPY_LCRECORD (ht, ht_old); |
970 | 1030 |
971 ht->hentries = xnew_array (htentry, ht_old->size + 1); | 1031 /* We leave room for one never-occupied sentinel htentry at the end. */ |
1032 ht->hentries = allocate_hash_table_entries (ht_old->size + 1); | |
972 memcpy (ht->hentries, ht_old->hentries, (ht_old->size + 1) * sizeof (htentry)); | 1033 memcpy (ht->hentries, ht_old->hentries, (ht_old->size + 1) * sizeof (htentry)); |
973 | 1034 |
974 if (! EQ (ht->next_weak, Qunbound)) | 1035 if (! EQ (ht->next_weak, Qunbound)) |
975 { | 1036 { |
976 ht->next_weak = Vall_weak_hash_tables; | 1037 ht->next_weak = Vall_weak_hash_tables; |
989 old_size = ht->size; | 1050 old_size = ht->size; |
990 ht->size = new_size; | 1051 ht->size = new_size; |
991 | 1052 |
992 old_entries = ht->hentries; | 1053 old_entries = ht->hentries; |
993 | 1054 |
994 ht->hentries = xnew_array_and_zero (htentry, new_size + 1); | 1055 /* We leave room for one never-occupied sentinel htentry at the end. */ |
1056 ht->hentries = allocate_hash_table_entries (new_size + 1); | |
995 new_entries = ht->hentries; | 1057 new_entries = ht->hentries; |
996 | 1058 |
997 compute_hash_table_derived_values (ht); | 1059 compute_hash_table_derived_values (ht); |
998 | 1060 |
999 for (e = old_entries, sentinel = e + old_size; e < sentinel; e++) | 1061 for (e = old_entries, sentinel = e + old_size; e < sentinel; e++) |
1003 LINEAR_PROBING_LOOP (probe, new_entries, new_size) | 1065 LINEAR_PROBING_LOOP (probe, new_entries, new_size) |
1004 ; | 1066 ; |
1005 *probe = *e; | 1067 *probe = *e; |
1006 } | 1068 } |
1007 | 1069 |
1070 #ifndef NEW_GC | |
1008 free_hentries (old_entries, old_size); | 1071 free_hentries (old_entries, old_size); |
1072 #endif /* not NEW_GC */ | |
1009 } | 1073 } |
1010 | 1074 |
1011 /* After a hash table has been saved to disk and later restored by the | 1075 /* After a hash table has been saved to disk and later restored by the |
1012 portable dumper, it contains the same objects, but their addresses | 1076 portable dumper, it contains the same objects, but their addresses |
1013 and thus their HASHCODEs have changed. */ | 1077 and thus their HASHCODEs have changed. */ |
1014 void | 1078 void |
1015 pdump_reorganize_hash_table (Lisp_Object hash_table) | 1079 pdump_reorganize_hash_table (Lisp_Object hash_table) |
1016 { | 1080 { |
1017 const Lisp_Hash_Table *ht = xhash_table (hash_table); | 1081 const Lisp_Hash_Table *ht = xhash_table (hash_table); |
1018 htentry *new_entries = xnew_array_and_zero (htentry, ht->size + 1); | 1082 /* We leave room for one never-occupied sentinel htentry at the end. */ |
1083 htentry *new_entries = allocate_hash_table_entries (ht->size + 1); | |
1019 htentry *e, *sentinel; | 1084 htentry *e, *sentinel; |
1020 | 1085 |
1021 for (e = ht->hentries, sentinel = e + ht->size; e < sentinel; e++) | 1086 for (e = ht->hentries, sentinel = e + ht->size; e < sentinel; e++) |
1022 if (!HTENTRY_CLEAR_P (e)) | 1087 if (!HTENTRY_CLEAR_P (e)) |
1023 { | 1088 { |
1027 *probe = *e; | 1092 *probe = *e; |
1028 } | 1093 } |
1029 | 1094 |
1030 memcpy (ht->hentries, new_entries, ht->size * sizeof (htentry)); | 1095 memcpy (ht->hentries, new_entries, ht->size * sizeof (htentry)); |
1031 | 1096 |
1097 #ifndef NEW_GC | |
1032 xfree (new_entries, htentry *); | 1098 xfree (new_entries, htentry *); |
1099 #endif /* not NEW_GC */ | |
1033 } | 1100 } |
1034 | 1101 |
1035 static void | 1102 static void |
1036 enlarge_hash_table (Lisp_Hash_Table *ht) | 1103 enlarge_hash_table (Lisp_Hash_Table *ht) |
1037 { | 1104 { |
1038 Elemcount new_size = | 1105 Elemcount new_size = |
1039 hash_table_size ((Elemcount) ((double) ht->size * ht->rehash_size)); | 1106 hash_table_size ((Elemcount) ((double) ht->size * ht->rehash_size)); |
1040 resize_hash_table (ht, new_size); | 1107 resize_hash_table (ht, new_size); |
1041 } | 1108 } |
1042 | 1109 |
1043 static htentry * | 1110 htentry * |
1044 find_htentry (Lisp_Object key, const Lisp_Hash_Table *ht) | 1111 find_htentry (Lisp_Object key, const Lisp_Hash_Table *ht) |
1045 { | 1112 { |
1046 hash_table_test_function_t test_function = ht->test_function; | 1113 hash_table_test_function_t test_function = ht->test_function; |
1047 htentry *entries = ht->hentries; | 1114 htentry *entries = ht->hentries; |
1048 htentry *probe = entries + HASHCODE (key, ht); | 1115 htentry *probe = entries + HASHCODE (key, ht); |
1094 | 1161 |
1095 return HTENTRY_CLEAR_P (e) ? default_ : e->value; | 1162 return HTENTRY_CLEAR_P (e) ? default_ : e->value; |
1096 } | 1163 } |
1097 | 1164 |
1098 DEFUN ("puthash", Fputhash, 3, 3, 0, /* | 1165 DEFUN ("puthash", Fputhash, 3, 3, 0, /* |
1099 Hash KEY to VALUE in HASH-TABLE. | 1166 Hash KEY to VALUE in HASH-TABLE, and return VALUE. |
1100 */ | 1167 */ |
1101 (key, value, hash_table)) | 1168 (key, value, hash_table)) |
1102 { | 1169 { |
1103 Lisp_Hash_Table *ht = xhash_table (hash_table); | 1170 Lisp_Hash_Table *ht = xhash_table (hash_table); |
1104 htentry *e = find_htentry (key, ht); | 1171 htentry *e = find_htentry (key, ht); |
1158 return Qt; | 1225 return Qt; |
1159 } | 1226 } |
1160 | 1227 |
1161 DEFUN ("clrhash", Fclrhash, 1, 1, 0, /* | 1228 DEFUN ("clrhash", Fclrhash, 1, 1, 0, /* |
1162 Remove all entries from HASH-TABLE, leaving it empty. | 1229 Remove all entries from HASH-TABLE, leaving it empty. |
1230 Return HASH-TABLE. | |
1163 */ | 1231 */ |
1164 (hash_table)) | 1232 (hash_table)) |
1165 { | 1233 { |
1166 Lisp_Hash_Table *ht = xhash_table (hash_table); | 1234 Lisp_Hash_Table *ht = xhash_table (hash_table); |
1167 htentry *e, *sentinel; | 1235 htentry *e, *sentinel; |
1655 Hashcode | 1723 Hashcode |
1656 internal_hash (Lisp_Object obj, int depth) | 1724 internal_hash (Lisp_Object obj, int depth) |
1657 { | 1725 { |
1658 if (depth > 5) | 1726 if (depth > 5) |
1659 return 0; | 1727 return 0; |
1660 if (CONSP (obj)) | 1728 |
1661 { | 1729 if (CONSP(obj)) |
1662 /* no point in worrying about tail recursion, since we're not | 1730 { |
1663 going very deep */ | 1731 Hashcode hash, h; |
1664 return HASH2 (internal_hash (XCAR (obj), depth + 1), | 1732 int s; |
1665 internal_hash (XCDR (obj), depth + 1)); | 1733 |
1734 depth += 1; | |
1735 | |
1736 if (!CONSP(XCDR(obj))) | |
1737 { | |
1738 /* special case for '(a . b) conses */ | |
1739 return HASH2(internal_hash(XCAR(obj), depth), | |
1740 internal_hash(XCDR(obj), depth)); | |
1741 } | |
1742 | |
1743 /* Don't simply tail recurse; we want to hash lists with the | |
1744 same contents in distinct orders differently. */ | |
1745 hash = internal_hash(XCAR(obj), depth); | |
1746 | |
1747 obj = XCDR(obj); | |
1748 for (s = 1; s < 6 && CONSP(obj); obj = XCDR(obj), s++) | |
1749 { | |
1750 h = internal_hash(XCAR(obj), depth); | |
1751 hash = HASH3(hash, h, s); | |
1752 } | |
1753 | |
1754 return hash; | |
1666 } | 1755 } |
1667 if (STRINGP (obj)) | 1756 if (STRINGP (obj)) |
1668 { | 1757 { |
1669 return hash_string (XSTRING_DATA (obj), XSTRING_LENGTH (obj)); | 1758 return hash_string (XSTRING_DATA (obj), XSTRING_LENGTH (obj)); |
1670 } | 1759 } |
1755 | 1844 |
1756 void | 1845 void |
1757 init_elhash_once_early (void) | 1846 init_elhash_once_early (void) |
1758 { | 1847 { |
1759 INIT_LISP_OBJECT (hash_table); | 1848 INIT_LISP_OBJECT (hash_table); |
1849 #ifdef NEW_GC | |
1850 INIT_LISP_OBJECT (hash_table_entry); | |
1851 #endif /* NEW_GC */ | |
1760 | 1852 |
1761 /* This must NOT be staticpro'd */ | 1853 /* This must NOT be staticpro'd */ |
1762 Vall_weak_hash_tables = Qnil; | 1854 Vall_weak_hash_tables = Qnil; |
1763 dump_add_weak_object_chain (&Vall_weak_hash_tables); | 1855 dump_add_weak_object_chain (&Vall_weak_hash_tables); |
1764 } | 1856 } |