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 }