Mercurial > hg > xemacs-beta
comparison src/elhash.c @ 5133:444a448b2f53
Merge branch ben-lisp-object into default branch
author | Ben Wing <ben@xemacs.org> |
---|---|
date | Sun, 07 Mar 2010 06:47:37 -0600 |
parents | 7be849cb8828 |
children | f965e31a35f0 |
comparison
equal
deleted
inserted
replaced
5113:b2dcf6a6d8ab | 5133:444a448b2f53 |
---|---|
1 /* Implementation of the hash table lisp object type. | 1 /* Implementation of the hash table lisp object type. |
2 Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc. | 2 Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc. |
3 Copyright (C) 1995, 1996, 2002, 2004 Ben Wing. | 3 Copyright (C) 1995, 1996, 2002, 2004, 2010 Ben Wing. |
4 Copyright (C) 1997 Free Software Foundation, Inc. | 4 Copyright (C) 1997 Free Software Foundation, Inc. |
5 | 5 |
6 This file is part of XEmacs. | 6 This file is part of XEmacs. |
7 | 7 |
8 XEmacs is free software; you can redistribute it and/or modify it | 8 XEmacs is free software; you can redistribute it and/or modify it |
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, Q_data; | 95 static Lisp_Object Qnon_weak, Q_type, Q_data; |
96 | 96 |
97 struct Lisp_Hash_Table | 97 struct Lisp_Hash_Table |
98 { | 98 { |
99 struct LCRECORD_HEADER header; | 99 NORMAL_LISP_OBJECT_HEADER header; |
100 Elemcount size; | 100 Elemcount size; |
101 Elemcount count; | 101 Elemcount count; |
102 Elemcount rehash_count; | 102 Elemcount rehash_count; |
103 double rehash_size; | 103 double rehash_size; |
104 double rehash_threshold; | 104 double rehash_threshold; |
419 if (!DUMPEDP (hentries)) | 419 if (!DUMPEDP (hentries)) |
420 xfree (hentries); | 420 xfree (hentries); |
421 } | 421 } |
422 | 422 |
423 static void | 423 static void |
424 finalize_hash_table (void *header, int for_disksave) | 424 finalize_hash_table (Lisp_Object obj) |
425 { | 425 { |
426 if (!for_disksave) | 426 Lisp_Hash_Table *ht = XHASH_TABLE (obj); |
427 { | 427 free_hentries (ht->hentries, ht->size); |
428 Lisp_Hash_Table *ht = (Lisp_Hash_Table *) header; | 428 ht->hentries = 0; |
429 free_hentries (ht->hentries, ht->size); | |
430 ht->hentries = 0; | |
431 } | |
432 } | 429 } |
433 #endif /* not NEW_GC */ | 430 #endif /* not NEW_GC */ |
434 | 431 |
435 static const struct memory_description htentry_description_1[] = { | 432 static const struct memory_description htentry_description_1[] = { |
436 { XD_LISP_OBJECT, offsetof (htentry, key) }, | 433 { XD_LISP_OBJECT, offsetof (htentry, key) }, |
453 static const struct sized_memory_description htentry_weak_description = { | 450 static const struct sized_memory_description htentry_weak_description = { |
454 sizeof (htentry), | 451 sizeof (htentry), |
455 htentry_weak_description_1 | 452 htentry_weak_description_1 |
456 }; | 453 }; |
457 | 454 |
458 DEFINE_LRECORD_IMPLEMENTATION ("hash-table-entry", hash_table_entry, | 455 DEFINE_DUMPABLE_INTERNAL_LISP_OBJECT ("hash-table-entry", hash_table_entry, |
459 1, /*dumpable-flag*/ | 456 0, htentry_description_1, |
460 0, 0, 0, 0, 0, | 457 Lisp_Hash_Table_Entry); |
461 htentry_description_1, | |
462 Lisp_Hash_Table_Entry); | |
463 #endif /* NEW_GC */ | 458 #endif /* NEW_GC */ |
464 | 459 |
465 static const struct memory_description htentry_union_description_1[] = { | 460 static const struct memory_description htentry_union_description_1[] = { |
466 /* Note: XD_INDIRECT in this table refers to the surrounding table, | 461 /* Note: XD_INDIRECT in this table refers to the surrounding table, |
467 and so this will work. */ | 462 and so this will work. */ |
492 { XD_LO_LINK, offsetof (Lisp_Hash_Table, next_weak) }, | 487 { XD_LO_LINK, offsetof (Lisp_Hash_Table, next_weak) }, |
493 { XD_END } | 488 { XD_END } |
494 }; | 489 }; |
495 | 490 |
496 #ifdef NEW_GC | 491 #ifdef NEW_GC |
497 DEFINE_LRECORD_IMPLEMENTATION ("hash-table", hash_table, | 492 DEFINE_DUMPABLE_LISP_OBJECT ("hash-table", hash_table, |
498 1, /*dumpable-flag*/ | 493 mark_hash_table, print_hash_table, |
499 mark_hash_table, print_hash_table, | 494 0, hash_table_equal, hash_table_hash, |
500 0, hash_table_equal, hash_table_hash, | 495 hash_table_description, |
501 hash_table_description, | 496 Lisp_Hash_Table); |
502 Lisp_Hash_Table); | |
503 #else /* not NEW_GC */ | 497 #else /* not NEW_GC */ |
504 DEFINE_LRECORD_IMPLEMENTATION ("hash-table", hash_table, | 498 DEFINE_DUMPABLE_LISP_OBJECT ("hash-table", hash_table, |
505 1, /*dumpable-flag*/ | 499 mark_hash_table, print_hash_table, |
506 mark_hash_table, print_hash_table, | 500 finalize_hash_table, |
507 finalize_hash_table, | 501 hash_table_equal, hash_table_hash, |
508 hash_table_equal, hash_table_hash, | 502 hash_table_description, |
509 hash_table_description, | 503 Lisp_Hash_Table); |
510 Lisp_Hash_Table); | |
511 #endif /* not NEW_GC */ | 504 #endif /* not NEW_GC */ |
512 | 505 |
513 static Lisp_Hash_Table * | 506 static Lisp_Hash_Table * |
514 xhash_table (Lisp_Object hash_table) | 507 xhash_table (Lisp_Object hash_table) |
515 { | 508 { |
531 { | 524 { |
532 ht->rehash_count = (Elemcount) | 525 ht->rehash_count = (Elemcount) |
533 ((double) ht->size * ht->rehash_threshold); | 526 ((double) ht->size * ht->rehash_threshold); |
534 ht->golden_ratio = (Elemcount) | 527 ht->golden_ratio = (Elemcount) |
535 ((double) ht->size * (.6180339887 / (double) sizeof (Lisp_Object))); | 528 ((double) ht->size * (.6180339887 / (double) sizeof (Lisp_Object))); |
529 } | |
530 | |
531 static htentry * | |
532 allocate_hash_table_entries (Elemcount size) | |
533 { | |
534 #ifdef NEW_GC | |
535 return XHASH_TABLE_ENTRY (alloc_lrecord_array | |
536 (size, &lrecord_hash_table_entry)); | |
537 #else /* not NEW_GC */ | |
538 return xnew_array_and_zero (htentry, size); | |
539 #endif /* not NEW_GC */ | |
536 } | 540 } |
537 | 541 |
538 Lisp_Object | 542 Lisp_Object |
539 make_standard_lisp_hash_table (enum hash_table_test test, | 543 make_standard_lisp_hash_table (enum hash_table_test test, |
540 Elemcount size, | 544 Elemcount size, |
577 Elemcount size, | 581 Elemcount size, |
578 double rehash_size, | 582 double rehash_size, |
579 double rehash_threshold, | 583 double rehash_threshold, |
580 enum hash_table_weakness weakness) | 584 enum hash_table_weakness weakness) |
581 { | 585 { |
582 Lisp_Object hash_table; | 586 Lisp_Object hash_table = ALLOC_NORMAL_LISP_OBJECT (hash_table); |
583 Lisp_Hash_Table *ht = ALLOC_LCRECORD_TYPE (Lisp_Hash_Table, &lrecord_hash_table); | 587 Lisp_Hash_Table *ht = XHASH_TABLE (hash_table); |
584 | 588 |
585 ht->test_function = test_function; | 589 ht->test_function = test_function; |
586 ht->hash_function = hash_function; | 590 ht->hash_function = hash_function; |
587 ht->weakness = weakness; | 591 ht->weakness = weakness; |
588 | 592 |
600 ht->count = 0; | 604 ht->count = 0; |
601 | 605 |
602 compute_hash_table_derived_values (ht); | 606 compute_hash_table_derived_values (ht); |
603 | 607 |
604 /* We leave room for one never-occupied sentinel htentry at the end. */ | 608 /* We leave room for one never-occupied sentinel htentry at the end. */ |
605 #ifdef NEW_GC | 609 ht->hentries = allocate_hash_table_entries (ht->size + 1); |
606 ht->hentries = (htentry *) alloc_lrecord_array (sizeof (htentry), | |
607 ht->size + 1, | |
608 &lrecord_hash_table_entry); | |
609 #else /* not NEW_GC */ | |
610 ht->hentries = xnew_array_and_zero (htentry, ht->size + 1); | |
611 #endif /* not NEW_GC */ | |
612 | |
613 hash_table = wrap_hash_table (ht); | |
614 | 610 |
615 if (weakness == HASH_TABLE_NON_WEAK) | 611 if (weakness == HASH_TABLE_NON_WEAK) |
616 ht->next_weak = Qunbound; | 612 ht->next_weak = Qunbound; |
617 else | 613 else |
618 ht->next_weak = Vall_weak_hash_tables, Vall_weak_hash_tables = hash_table; | 614 ht->next_weak = Vall_weak_hash_tables, Vall_weak_hash_tables = hash_table; |
1037 The keys and values will not themselves be copied. | 1033 The keys and values will not themselves be copied. |
1038 */ | 1034 */ |
1039 (hash_table)) | 1035 (hash_table)) |
1040 { | 1036 { |
1041 const Lisp_Hash_Table *ht_old = xhash_table (hash_table); | 1037 const Lisp_Hash_Table *ht_old = xhash_table (hash_table); |
1042 Lisp_Hash_Table *ht = ALLOC_LCRECORD_TYPE (Lisp_Hash_Table, &lrecord_hash_table); | 1038 Lisp_Object obj = ALLOC_NORMAL_LISP_OBJECT (hash_table); |
1043 COPY_LCRECORD (ht, ht_old); | 1039 Lisp_Hash_Table *ht = XHASH_TABLE (obj); |
1044 | 1040 copy_lisp_object (obj, hash_table); |
1045 #ifdef NEW_GC | 1041 |
1046 ht->hentries = (htentry *) alloc_lrecord_array (sizeof (htentry), | 1042 /* We leave room for one never-occupied sentinel htentry at the end. */ |
1047 ht_old->size + 1, | 1043 ht->hentries = allocate_hash_table_entries (ht_old->size + 1); |
1048 &lrecord_hash_table_entry); | |
1049 #else /* not NEW_GC */ | |
1050 ht->hentries = xnew_array (htentry, ht_old->size + 1); | |
1051 #endif /* not NEW_GC */ | |
1052 memcpy (ht->hentries, ht_old->hentries, (ht_old->size + 1) * sizeof (htentry)); | 1044 memcpy (ht->hentries, ht_old->hentries, (ht_old->size + 1) * sizeof (htentry)); |
1053 | 1045 |
1054 hash_table = wrap_hash_table (ht); | |
1055 | |
1056 if (! EQ (ht->next_weak, Qunbound)) | 1046 if (! EQ (ht->next_weak, Qunbound)) |
1057 { | 1047 { |
1058 ht->next_weak = Vall_weak_hash_tables; | 1048 ht->next_weak = Vall_weak_hash_tables; |
1059 Vall_weak_hash_tables = hash_table; | 1049 Vall_weak_hash_tables = obj; |
1060 } | 1050 } |
1061 | 1051 |
1062 return hash_table; | 1052 return obj; |
1063 } | 1053 } |
1064 | 1054 |
1065 static void | 1055 static void |
1066 resize_hash_table (Lisp_Hash_Table *ht, Elemcount new_size) | 1056 resize_hash_table (Lisp_Hash_Table *ht, Elemcount new_size) |
1067 { | 1057 { |
1071 old_size = ht->size; | 1061 old_size = ht->size; |
1072 ht->size = new_size; | 1062 ht->size = new_size; |
1073 | 1063 |
1074 old_entries = ht->hentries; | 1064 old_entries = ht->hentries; |
1075 | 1065 |
1076 #ifdef NEW_GC | 1066 /* We leave room for one never-occupied sentinel htentry at the end. */ |
1077 ht->hentries = (htentry *) alloc_lrecord_array (sizeof (htentry), | 1067 ht->hentries = allocate_hash_table_entries (new_size + 1); |
1078 new_size + 1, | |
1079 &lrecord_hash_table_entry); | |
1080 #else /* not NEW_GC */ | |
1081 ht->hentries = xnew_array_and_zero (htentry, new_size + 1); | |
1082 #endif /* not NEW_GC */ | |
1083 new_entries = ht->hentries; | 1068 new_entries = ht->hentries; |
1084 | 1069 |
1085 compute_hash_table_derived_values (ht); | 1070 compute_hash_table_derived_values (ht); |
1086 | 1071 |
1087 for (e = old_entries, sentinel = e + old_size; e < sentinel; e++) | 1072 for (e = old_entries, sentinel = e + old_size; e < sentinel; e++) |
1103 and thus their HASHCODEs have changed. */ | 1088 and thus their HASHCODEs have changed. */ |
1104 void | 1089 void |
1105 pdump_reorganize_hash_table (Lisp_Object hash_table) | 1090 pdump_reorganize_hash_table (Lisp_Object hash_table) |
1106 { | 1091 { |
1107 const Lisp_Hash_Table *ht = xhash_table (hash_table); | 1092 const Lisp_Hash_Table *ht = xhash_table (hash_table); |
1108 #ifdef NEW_GC | 1093 /* We leave room for one never-occupied sentinel htentry at the end. */ |
1109 htentry *new_entries = | 1094 htentry *new_entries = allocate_hash_table_entries (ht->size + 1); |
1110 (htentry *) alloc_lrecord_array (sizeof (htentry), ht->size + 1, | |
1111 &lrecord_hash_table_entry); | |
1112 #else /* not NEW_GC */ | |
1113 htentry *new_entries = xnew_array_and_zero (htentry, ht->size + 1); | |
1114 #endif /* not NEW_GC */ | |
1115 htentry *e, *sentinel; | 1095 htentry *e, *sentinel; |
1116 | 1096 |
1117 for (e = ht->hentries, sentinel = e + ht->size; e < sentinel; e++) | 1097 for (e = ht->hentries, sentinel = e + ht->size; e < sentinel; e++) |
1118 if (!HTENTRY_CLEAR_P (e)) | 1098 if (!HTENTRY_CLEAR_P (e)) |
1119 { | 1099 { |
1876 } | 1856 } |
1877 | 1857 |
1878 void | 1858 void |
1879 init_elhash_once_early (void) | 1859 init_elhash_once_early (void) |
1880 { | 1860 { |
1881 INIT_LRECORD_IMPLEMENTATION (hash_table); | 1861 INIT_LISP_OBJECT (hash_table); |
1882 #ifdef NEW_GC | 1862 #ifdef NEW_GC |
1883 INIT_LRECORD_IMPLEMENTATION (hash_table_entry); | 1863 INIT_LISP_OBJECT (hash_table_entry); |
1884 #endif /* NEW_GC */ | 1864 #endif /* NEW_GC */ |
1885 | 1865 |
1886 /* This must NOT be staticpro'd */ | 1866 /* This must NOT be staticpro'd */ |
1887 Vall_weak_hash_tables = Qnil; | 1867 Vall_weak_hash_tables = Qnil; |
1888 dump_add_weak_object_chain (&Vall_weak_hash_tables); | 1868 dump_add_weak_object_chain (&Vall_weak_hash_tables); |