Mercurial > hg > xemacs-beta
comparison src/elhash.c @ 424:11054d720c21 r21-2-20
Import from CVS: tag r21-2-20
author | cvs |
---|---|
date | Mon, 13 Aug 2007 11:26:11 +0200 |
parents | 41dbb7a9d5f2 |
children |
comparison
equal
deleted
inserted
replaced
423:28d9c139be4c | 424:11054d720c21 |
---|---|
25 #include <config.h> | 25 #include <config.h> |
26 #include "lisp.h" | 26 #include "lisp.h" |
27 #include "bytecode.h" | 27 #include "bytecode.h" |
28 #include "elhash.h" | 28 #include "elhash.h" |
29 | 29 |
30 Lisp_Object Qhash_tablep, Qhashtable, Qhash_table; | 30 Lisp_Object Qhash_tablep; |
31 Lisp_Object Qweak, Qkey_weak, Qvalue_weak, Qnon_weak; | 31 static Lisp_Object Qhashtable, Qhash_table; |
32 static Lisp_Object Qweakness, Qvalue; | |
32 static Lisp_Object Vall_weak_hash_tables; | 33 static Lisp_Object Vall_weak_hash_tables; |
33 static Lisp_Object Qrehash_size, Qrehash_threshold; | 34 static Lisp_Object Qrehash_size, Qrehash_threshold; |
34 static Lisp_Object Q_size, Q_test, Q_type, Q_rehash_size, Q_rehash_threshold; | 35 static Lisp_Object Q_size, Q_test, Q_weakness, Q_rehash_size, Q_rehash_threshold; |
36 | |
37 /* obsolete as of 19990901 in xemacs-21.2 */ | |
38 static Lisp_Object Qweak, Qkey_weak, Qvalue_weak, Qnon_weak, Q_type; | |
35 | 39 |
36 typedef struct hentry | 40 typedef struct hentry |
37 { | 41 { |
38 Lisp_Object key; | 42 Lisp_Object key; |
39 Lisp_Object value; | 43 Lisp_Object value; |
49 double rehash_threshold; | 53 double rehash_threshold; |
50 size_t golden_ratio; | 54 size_t golden_ratio; |
51 hash_table_hash_function_t hash_function; | 55 hash_table_hash_function_t hash_function; |
52 hash_table_test_function_t test_function; | 56 hash_table_test_function_t test_function; |
53 hentry *hentries; | 57 hentry *hentries; |
54 enum hash_table_type type; /* whether and how this hash table is weak */ | 58 enum hash_table_weakness weakness; |
55 Lisp_Object next_weak; /* Used to chain together all of the weak | 59 Lisp_Object next_weak; /* Used to chain together all of the weak |
56 hash tables. Don't mark through this. */ | 60 hash tables. Don't mark through this. */ |
57 }; | 61 }; |
58 typedef struct Lisp_Hash_Table Lisp_Hash_Table; | 62 typedef struct Lisp_Hash_Table Lisp_Hash_Table; |
59 | 63 |
60 #define HENTRY_CLEAR_P(hentry) ((*(EMACS_UINT*)(&((hentry)->key))) == 0) | 64 #define HENTRY_CLEAR_P(hentry) ((*(EMACS_UINT*)(&((hentry)->key))) == 0) |
61 #define CLEAR_HENTRY(hentry) ((*(EMACS_UINT*)(&((hentry)->key))) = 0) | 65 #define CLEAR_HENTRY(hentry) \ |
66 ((*(EMACS_UINT*)(&((hentry)->key))) = 0, \ | |
67 (*(EMACS_UINT*)(&((hentry)->value))) = 0) | |
62 | 68 |
63 #define HASH_TABLE_DEFAULT_SIZE 16 | 69 #define HASH_TABLE_DEFAULT_SIZE 16 |
64 #define HASH_TABLE_DEFAULT_REHASH_SIZE 1.3 | 70 #define HASH_TABLE_DEFAULT_REHASH_SIZE 1.3 |
65 #define HASH_TABLE_MIN_SIZE 10 | 71 #define HASH_TABLE_MIN_SIZE 10 |
66 | 72 |
188 return internal_hash (obj, 0); | 194 return internal_hash (obj, 0); |
189 } | 195 } |
190 | 196 |
191 | 197 |
192 static Lisp_Object | 198 static Lisp_Object |
193 mark_hash_table (Lisp_Object obj, void (*markobj) (Lisp_Object)) | 199 mark_hash_table (Lisp_Object obj) |
194 { | 200 { |
195 Lisp_Hash_Table *ht = XHASH_TABLE (obj); | 201 Lisp_Hash_Table *ht = XHASH_TABLE (obj); |
196 | 202 |
197 /* If the hash table is weak, we don't want to mark the keys and | 203 /* If the hash table is weak, we don't want to mark the keys and |
198 values (we scan over them after everything else has been marked, | 204 values (we scan over them after everything else has been marked, |
199 and mark or remove them as necessary). */ | 205 and mark or remove them as necessary). */ |
200 if (ht->type == HASH_TABLE_NON_WEAK) | 206 if (ht->weakness == HASH_TABLE_NON_WEAK) |
201 { | 207 { |
202 hentry *e, *sentinel; | 208 hentry *e, *sentinel; |
203 | 209 |
204 for (e = ht->hentries, sentinel = e + ht->size; e < sentinel; e++) | 210 for (e = ht->hentries, sentinel = e + ht->size; e < sentinel; e++) |
205 if (!HENTRY_CLEAR_P (e)) | 211 if (!HENTRY_CLEAR_P (e)) |
206 { | 212 { |
207 markobj (e->key); | 213 mark_object (e->key); |
208 markobj (e->value); | 214 mark_object (e->value); |
209 } | 215 } |
210 } | 216 } |
211 return Qnil; | 217 return Qnil; |
212 } | 218 } |
213 | 219 |
214 /* Equality of hash tables. Two hash tables are equal when they are of | 220 /* Equality of hash tables. Two hash tables are equal when they are of |
215 the same type and test function, they have the same number of | 221 the same weakness and test function, they have the same number of |
216 elements, and for each key in the hash table, the values are `equal'. | 222 elements, and for each key in the hash table, the values are `equal'. |
217 | 223 |
218 This is similar to Common Lisp `equalp' of hash tables, with the | 224 This is similar to Common Lisp `equalp' of hash tables, with the |
219 difference that CL requires the keys to be compared with the test | 225 difference that CL requires the keys to be compared with the test |
220 function, which we don't do. Doing that would require consing, and | 226 function, which we don't do. Doing that would require consing, and |
227 Lisp_Hash_Table *ht1 = XHASH_TABLE (hash_table1); | 233 Lisp_Hash_Table *ht1 = XHASH_TABLE (hash_table1); |
228 Lisp_Hash_Table *ht2 = XHASH_TABLE (hash_table2); | 234 Lisp_Hash_Table *ht2 = XHASH_TABLE (hash_table2); |
229 hentry *e, *sentinel; | 235 hentry *e, *sentinel; |
230 | 236 |
231 if ((ht1->test_function != ht2->test_function) || | 237 if ((ht1->test_function != ht2->test_function) || |
232 (ht1->type != ht2->type) || | 238 (ht1->weakness != ht2->weakness) || |
233 (ht1->count != ht2->count)) | 239 (ht1->count != ht2->count)) |
234 return 0; | 240 return 0; |
235 | 241 |
236 depth++; | 242 depth++; |
237 | 243 |
254 syntax for hash tables. This means that a typical hash table will be | 260 syntax for hash tables. This means that a typical hash table will be |
255 readably printed in the form of: | 261 readably printed in the form of: |
256 | 262 |
257 #s(hash-table size 2 data (key1 value1 key2 value2)) | 263 #s(hash-table size 2 data (key1 value1 key2 value2)) |
258 | 264 |
259 The supported keywords are `type' (non-weak (or nil), weak, | 265 The supported hash table structure keywords and their values are: |
260 key-weak and value-weak), `test' (eql (or nil), eq or equal), | 266 `test' (eql (or nil), eq or equal) |
261 `size' (a natnum or nil) and `data' (a list). | 267 `size' (a natnum or nil) |
268 `rehash-size' (a float) | |
269 `rehash-threshold' (a float) | |
270 `weakness' (nil, t, key or value) | |
271 `data' (a list) | |
262 | 272 |
263 If `print-readably' is non-nil, then a simpler syntax is used; for | 273 If `print-readably' is non-nil, then a simpler syntax is used; for |
264 instance: | 274 instance: |
265 | 275 |
266 #<hash-table size 2/13 data (key1 value1 key2 value2) 0x874d> | 276 #<hash-table size 2/13 data (key1 value1 key2 value2) 0x874d> |
305 char buf[128]; | 315 char buf[128]; |
306 | 316 |
307 write_c_string (print_readably ? "#s(hash-table" : "#<hash-table", | 317 write_c_string (print_readably ? "#s(hash-table" : "#<hash-table", |
308 printcharfun); | 318 printcharfun); |
309 | 319 |
310 if (ht->type != HASH_TABLE_NON_WEAK) | |
311 { | |
312 sprintf (buf, " type %s", | |
313 (ht->type == HASH_TABLE_WEAK ? "weak" : | |
314 ht->type == HASH_TABLE_KEY_WEAK ? "key-weak" : | |
315 ht->type == HASH_TABLE_VALUE_WEAK ? "value-weak" : | |
316 "you-d-better-not-see-this")); | |
317 write_c_string (buf, printcharfun); | |
318 } | |
319 | |
320 /* These checks have a kludgy look to them, but they are safe. | 320 /* These checks have a kludgy look to them, but they are safe. |
321 Due to nature of hashing, you cannot use arbitrary | 321 Due to nature of hashing, you cannot use arbitrary |
322 test functions anyway. */ | 322 test functions anyway. */ |
323 if (!ht->test_function) | 323 if (!ht->test_function) |
324 write_c_string (" test eq", printcharfun); | 324 write_c_string (" test eq", printcharfun); |
338 (unsigned long) ht->count, | 338 (unsigned long) ht->count, |
339 (unsigned long) ht->size); | 339 (unsigned long) ht->size); |
340 write_c_string (buf, printcharfun); | 340 write_c_string (buf, printcharfun); |
341 } | 341 } |
342 | 342 |
343 if (ht->weakness != HASH_TABLE_NON_WEAK) | |
344 { | |
345 sprintf (buf, " weakness %s", | |
346 (ht->weakness == HASH_TABLE_WEAK ? "t" : | |
347 ht->weakness == HASH_TABLE_KEY_WEAK ? "key" : | |
348 ht->weakness == HASH_TABLE_VALUE_WEAK ? "value" : | |
349 "you-d-better-not-see-this")); | |
350 write_c_string (buf, printcharfun); | |
351 } | |
352 | |
343 if (ht->count) | 353 if (ht->count) |
344 print_hash_table_data (ht, printcharfun); | 354 print_hash_table_data (ht, printcharfun); |
345 | 355 |
346 if (print_readably) | 356 if (print_readably) |
347 write_c_string (")", printcharfun); | 357 write_c_string (")", printcharfun); |
372 static const struct struct_description hentry_description = { | 382 static const struct struct_description hentry_description = { |
373 sizeof(hentry), | 383 sizeof(hentry), |
374 hentry_description_1 | 384 hentry_description_1 |
375 }; | 385 }; |
376 | 386 |
377 static const struct lrecord_description hash_table_description[] = { | 387 const struct lrecord_description hash_table_description[] = { |
378 { XD_SIZE_T, offsetof(Lisp_Hash_Table, size) }, | 388 { XD_SIZE_T, offsetof(Lisp_Hash_Table, size) }, |
379 { XD_STRUCT_PTR, offsetof(Lisp_Hash_Table, hentries), XD_INDIRECT(0), &hentry_description }, | 389 { XD_STRUCT_PTR, offsetof(Lisp_Hash_Table, hentries), XD_INDIRECT(0, 1), &hentry_description }, |
390 { XD_LO_LINK, offsetof(Lisp_Hash_Table, next_weak) }, | |
380 { XD_END } | 391 { XD_END } |
381 }; | 392 }; |
382 | 393 |
383 DEFINE_LRECORD_IMPLEMENTATION ("hash-table", hash_table, | 394 DEFINE_LRECORD_IMPLEMENTATION ("hash-table", hash_table, |
384 mark_hash_table, print_hash_table, | 395 mark_hash_table, print_hash_table, |
419 ht->golden_ratio = (size_t) | 430 ht->golden_ratio = (size_t) |
420 ((double) ht->size * (.6180339887 / (double) sizeof (Lisp_Object))); | 431 ((double) ht->size * (.6180339887 / (double) sizeof (Lisp_Object))); |
421 } | 432 } |
422 | 433 |
423 Lisp_Object | 434 Lisp_Object |
424 make_general_lisp_hash_table (size_t size, | 435 make_general_lisp_hash_table (enum hash_table_test test, |
425 enum hash_table_type type, | 436 size_t size, |
426 enum hash_table_test test, | 437 double rehash_size, |
427 double rehash_size, | 438 double rehash_threshold, |
428 double rehash_threshold) | 439 enum hash_table_weakness weakness) |
429 { | 440 { |
430 Lisp_Object hash_table; | 441 Lisp_Object hash_table; |
431 Lisp_Hash_Table *ht = alloc_lcrecord_type (Lisp_Hash_Table, &lrecord_hash_table); | 442 Lisp_Hash_Table *ht = alloc_lcrecord_type (Lisp_Hash_Table, &lrecord_hash_table); |
432 | 443 |
433 ht->type = type; | |
434 ht->rehash_size = rehash_size; | 444 ht->rehash_size = rehash_size; |
435 ht->rehash_threshold = rehash_threshold; | 445 ht->rehash_threshold = rehash_threshold; |
446 ht->weakness = weakness; | |
436 | 447 |
437 switch (test) | 448 switch (test) |
438 { | 449 { |
439 case HASH_TABLE_EQ: | 450 case HASH_TABLE_EQ: |
440 ht->test_function = 0; | 451 ht->test_function = 0; |
475 CLEAR_HENTRY (e); | 486 CLEAR_HENTRY (e); |
476 } | 487 } |
477 | 488 |
478 XSETHASH_TABLE (hash_table, ht); | 489 XSETHASH_TABLE (hash_table, ht); |
479 | 490 |
480 if (type == HASH_TABLE_NON_WEAK) | 491 if (weakness == HASH_TABLE_NON_WEAK) |
481 ht->next_weak = Qunbound; | 492 ht->next_weak = Qunbound; |
482 else | 493 else |
483 ht->next_weak = Vall_weak_hash_tables, Vall_weak_hash_tables = hash_table; | 494 ht->next_weak = Vall_weak_hash_tables, Vall_weak_hash_tables = hash_table; |
484 | 495 |
485 return hash_table; | 496 return hash_table; |
486 } | 497 } |
487 | 498 |
488 Lisp_Object | 499 Lisp_Object |
489 make_lisp_hash_table (size_t size, | 500 make_lisp_hash_table (size_t size, |
490 enum hash_table_type type, | 501 enum hash_table_weakness weakness, |
491 enum hash_table_test test) | 502 enum hash_table_test test) |
492 { | 503 { |
493 return make_general_lisp_hash_table (size, type, test, | 504 return make_general_lisp_hash_table |
494 HASH_TABLE_DEFAULT_REHASH_SIZE, -1.0); | 505 (test, size, HASH_TABLE_DEFAULT_REHASH_SIZE, -1.0, weakness); |
495 } | 506 } |
496 | 507 |
497 /* Pretty reading of hash tables. | 508 /* Pretty reading of hash tables. |
498 | 509 |
499 Here we use the existing structures mechanism (which is, | 510 Here we use the existing structures mechanism (which is, |
522 { | 533 { |
523 return NILP (obj) ? HASH_TABLE_DEFAULT_SIZE : XINT (obj); | 534 return NILP (obj) ? HASH_TABLE_DEFAULT_SIZE : XINT (obj); |
524 } | 535 } |
525 | 536 |
526 static int | 537 static int |
527 hash_table_type_validate (Lisp_Object keyword, Lisp_Object value, | 538 hash_table_weakness_validate (Lisp_Object keyword, Lisp_Object value, |
528 Error_behavior errb) | 539 Error_behavior errb) |
529 { | 540 { |
530 if (EQ (value, Qnil)) return 1; | 541 if (EQ (value, Qnil)) return 1; |
542 if (EQ (value, Qt)) return 1; | |
543 if (EQ (value, Qkey)) return 1; | |
544 if (EQ (value, Qvalue)) return 1; | |
545 | |
546 /* Following values are obsolete as of 19990901 in xemacs-21.2 */ | |
531 if (EQ (value, Qnon_weak)) return 1; | 547 if (EQ (value, Qnon_weak)) return 1; |
532 if (EQ (value, Qweak)) return 1; | 548 if (EQ (value, Qweak)) return 1; |
533 if (EQ (value, Qkey_weak)) return 1; | 549 if (EQ (value, Qkey_weak)) return 1; |
534 if (EQ (value, Qvalue_weak)) return 1; | 550 if (EQ (value, Qvalue_weak)) return 1; |
535 | 551 |
536 maybe_signal_simple_error ("Invalid hash table type", | 552 maybe_signal_simple_error ("Invalid hash table weakness", |
537 value, Qhash_table, errb); | 553 value, Qhash_table, errb); |
538 return 0; | 554 return 0; |
539 } | 555 } |
540 | 556 |
541 static enum hash_table_type | 557 static enum hash_table_weakness |
542 decode_hash_table_type (Lisp_Object obj) | 558 decode_hash_table_weakness (Lisp_Object obj) |
543 { | 559 { |
544 if (EQ (obj, Qnil)) return HASH_TABLE_NON_WEAK; | 560 if (EQ (obj, Qnil)) return HASH_TABLE_NON_WEAK; |
561 if (EQ (obj, Qt)) return HASH_TABLE_WEAK; | |
562 if (EQ (obj, Qkey)) return HASH_TABLE_KEY_WEAK; | |
563 if (EQ (obj, Qvalue)) return HASH_TABLE_VALUE_WEAK; | |
564 | |
565 /* Following values are obsolete as of 19990901 in xemacs-21.2 */ | |
545 if (EQ (obj, Qnon_weak)) return HASH_TABLE_NON_WEAK; | 566 if (EQ (obj, Qnon_weak)) return HASH_TABLE_NON_WEAK; |
546 if (EQ (obj, Qweak)) return HASH_TABLE_WEAK; | 567 if (EQ (obj, Qweak)) return HASH_TABLE_WEAK; |
547 if (EQ (obj, Qkey_weak)) return HASH_TABLE_KEY_WEAK; | 568 if (EQ (obj, Qkey_weak)) return HASH_TABLE_KEY_WEAK; |
548 if (EQ (obj, Qvalue_weak)) return HASH_TABLE_VALUE_WEAK; | 569 if (EQ (obj, Qvalue_weak)) return HASH_TABLE_VALUE_WEAK; |
549 | 570 |
550 signal_simple_error ("Invalid hash table type", obj); | 571 signal_simple_error ("Invalid hash table weakness", obj); |
551 return HASH_TABLE_NON_WEAK; /* not reached */ | 572 return HASH_TABLE_NON_WEAK; /* not reached */ |
552 } | 573 } |
553 | 574 |
554 static int | 575 static int |
555 hash_table_test_validate (Lisp_Object keyword, Lisp_Object value, | 576 hash_table_test_validate (Lisp_Object keyword, Lisp_Object value, |
577 return HASH_TABLE_EQ; /* not reached */ | 598 return HASH_TABLE_EQ; /* not reached */ |
578 } | 599 } |
579 | 600 |
580 static int | 601 static int |
581 hash_table_rehash_size_validate (Lisp_Object keyword, Lisp_Object value, | 602 hash_table_rehash_size_validate (Lisp_Object keyword, Lisp_Object value, |
582 Error_behavior errb) | 603 Error_behavior errb) |
583 { | 604 { |
584 if (!FLOATP (value)) | 605 if (!FLOATP (value)) |
585 { | 606 { |
586 maybe_signal_error (Qwrong_type_argument, list2 (Qfloatp, value), | 607 maybe_signal_error (Qwrong_type_argument, list2 (Qfloatp, value), |
587 Qhash_table, errb); | 608 Qhash_table, errb); |
666 static Lisp_Object | 687 static Lisp_Object |
667 hash_table_instantiate (Lisp_Object plist) | 688 hash_table_instantiate (Lisp_Object plist) |
668 { | 689 { |
669 Lisp_Object hash_table; | 690 Lisp_Object hash_table; |
670 Lisp_Object test = Qnil; | 691 Lisp_Object test = Qnil; |
671 Lisp_Object type = Qnil; | |
672 Lisp_Object size = Qnil; | 692 Lisp_Object size = Qnil; |
673 Lisp_Object data = Qnil; | |
674 Lisp_Object rehash_size = Qnil; | 693 Lisp_Object rehash_size = Qnil; |
675 Lisp_Object rehash_threshold = Qnil; | 694 Lisp_Object rehash_threshold = Qnil; |
695 Lisp_Object weakness = Qnil; | |
696 Lisp_Object data = Qnil; | |
676 | 697 |
677 while (!NILP (plist)) | 698 while (!NILP (plist)) |
678 { | 699 { |
679 Lisp_Object key, value; | 700 Lisp_Object key, value; |
680 key = XCAR (plist); plist = XCDR (plist); | 701 key = XCAR (plist); plist = XCDR (plist); |
681 value = XCAR (plist); plist = XCDR (plist); | 702 value = XCAR (plist); plist = XCDR (plist); |
682 | 703 |
683 if (EQ (key, Qtest)) test = value; | 704 if (EQ (key, Qtest)) test = value; |
684 else if (EQ (key, Qtype)) type = value; | |
685 else if (EQ (key, Qsize)) size = value; | 705 else if (EQ (key, Qsize)) size = value; |
686 else if (EQ (key, Qdata)) data = value; | |
687 else if (EQ (key, Qrehash_size)) rehash_size = value; | 706 else if (EQ (key, Qrehash_size)) rehash_size = value; |
688 else if (EQ (key, Qrehash_threshold)) rehash_threshold = value; | 707 else if (EQ (key, Qrehash_threshold)) rehash_threshold = value; |
708 else if (EQ (key, Qweakness)) weakness = value; | |
709 else if (EQ (key, Qdata)) data = value; | |
710 else if (EQ (key, Qtype))/*obsolete*/ weakness = value; | |
689 else | 711 else |
690 abort (); | 712 abort (); |
691 } | 713 } |
692 | 714 |
693 /* Create the hash table. */ | 715 /* Create the hash table. */ |
694 hash_table = make_general_lisp_hash_table | 716 hash_table = make_general_lisp_hash_table |
695 (decode_hash_table_size (size), | 717 (decode_hash_table_test (test), |
696 decode_hash_table_type (type), | 718 decode_hash_table_size (size), |
697 decode_hash_table_test (test), | |
698 decode_hash_table_rehash_size (rehash_size), | 719 decode_hash_table_rehash_size (rehash_size), |
699 decode_hash_table_rehash_threshold (rehash_threshold)); | 720 decode_hash_table_rehash_threshold (rehash_threshold), |
721 decode_hash_table_weakness (weakness)); | |
700 | 722 |
701 /* I'm not sure whether this can GC, but better safe than sorry. */ | 723 /* I'm not sure whether this can GC, but better safe than sorry. */ |
702 { | 724 { |
703 struct gcpro gcpro1; | 725 struct gcpro gcpro1; |
704 GCPRO1 (hash_table); | 726 GCPRO1 (hash_table); |
721 structure_type_create_hash_table_structure_name (Lisp_Object structure_name) | 743 structure_type_create_hash_table_structure_name (Lisp_Object structure_name) |
722 { | 744 { |
723 struct structure_type *st; | 745 struct structure_type *st; |
724 | 746 |
725 st = define_structure_type (structure_name, 0, hash_table_instantiate); | 747 st = define_structure_type (structure_name, 0, hash_table_instantiate); |
748 define_structure_type_keyword (st, Qtest, hash_table_test_validate); | |
726 define_structure_type_keyword (st, Qsize, hash_table_size_validate); | 749 define_structure_type_keyword (st, Qsize, hash_table_size_validate); |
727 define_structure_type_keyword (st, Qtest, hash_table_test_validate); | |
728 define_structure_type_keyword (st, Qtype, hash_table_type_validate); | |
729 define_structure_type_keyword (st, Qdata, hash_table_data_validate); | |
730 define_structure_type_keyword (st, Qrehash_size, hash_table_rehash_size_validate); | 750 define_structure_type_keyword (st, Qrehash_size, hash_table_rehash_size_validate); |
731 define_structure_type_keyword (st, Qrehash_threshold, hash_table_rehash_threshold_validate); | 751 define_structure_type_keyword (st, Qrehash_threshold, hash_table_rehash_threshold_validate); |
752 define_structure_type_keyword (st, Qweakness, hash_table_weakness_validate); | |
753 define_structure_type_keyword (st, Qdata, hash_table_data_validate); | |
754 | |
755 /* obsolete as of 19990901 in xemacs-21.2 */ | |
756 define_structure_type_keyword (st, Qtype, hash_table_weakness_validate); | |
732 } | 757 } |
733 | 758 |
734 /* Create a built-in Lisp structure type named `hash-table'. | 759 /* Create a built-in Lisp structure type named `hash-table'. |
735 We make #s(hashtable ...) equivalent to #s(hash-table ...), | 760 We make #s(hashtable ...) equivalent to #s(hash-table ...), |
736 for backward comptabibility. | 761 for backward compatibility. |
737 This is called from emacs.c. */ | 762 This is called from emacs.c. */ |
738 void | 763 void |
739 structure_type_create_hash_table (void) | 764 structure_type_create_hash_table (void) |
740 { | 765 { |
741 structure_type_create_hash_table_structure_name (Qhash_table); | 766 structure_type_create_hash_table_structure_name (Qhash_table); |
756 } | 781 } |
757 | 782 |
758 DEFUN ("make-hash-table", Fmake_hash_table, 0, MANY, 0, /* | 783 DEFUN ("make-hash-table", Fmake_hash_table, 0, MANY, 0, /* |
759 Return a new empty hash table object. | 784 Return a new empty hash table object. |
760 Use Common Lisp style keywords to specify hash table properties. | 785 Use Common Lisp style keywords to specify hash table properties. |
761 (make-hash-table &key :size :test :type :rehash-size :rehash-threshold) | 786 (make-hash-table &key test size rehash-size rehash-threshold weakness) |
762 | |
763 Keyword :size specifies the number of keys likely to be inserted. | |
764 This number of entries can be inserted without enlarging the hash table. | |
765 | 787 |
766 Keyword :test can be `eq', `eql' (default) or `equal'. | 788 Keyword :test can be `eq', `eql' (default) or `equal'. |
767 Comparison between keys is done using this function. | 789 Comparison between keys is done using this function. |
768 If speed is important, consider using `eq'. | 790 If speed is important, consider using `eq'. |
769 When storing strings in the hash table, you will likely need to use `equal'. | 791 When storing strings in the hash table, you will likely need to use `equal'. |
770 | 792 |
771 Keyword :type can be `non-weak' (default), `weak', `key-weak' or `value-weak'. | 793 Keyword :size specifies the number of keys likely to be inserted. |
794 This number of entries can be inserted without enlarging the hash table. | |
795 | |
796 Keyword :rehash-size must be a float greater than 1.0, and specifies | |
797 the factor by which to increase the size of the hash table when enlarging. | |
798 | |
799 Keyword :rehash-threshold must be a float between 0.0 and 1.0, | |
800 and specifies the load factor of the hash table which triggers enlarging. | |
801 | |
802 Non-standard keyword :weakness can be `nil' (default), `t', `key' or `value'. | |
772 | 803 |
773 A weak hash table is one whose pointers do not count as GC referents: | 804 A weak hash table is one whose pointers do not count as GC referents: |
774 for any key-value pair in the hash table, if the only remaining pointer | 805 for any key-value pair in the hash table, if the only remaining pointer |
775 to either the key or the value is in a weak hash table, then the pair | 806 to either the key or the value is in a weak hash table, then the pair |
776 will be removed from the hash table, and the key and value collected. | 807 will be removed from the hash table, and the key and value collected. |
786 A value-weak hash table is similar to a fully-weak hash table except | 817 A value-weak hash table is similar to a fully-weak hash table except |
787 that a key-value pair will be removed only if the value remains | 818 that a key-value pair will be removed only if the value remains |
788 unmarked outside of weak hash tables. The pair will remain in the | 819 unmarked outside of weak hash tables. The pair will remain in the |
789 hash table if the value is pointed to by something other than a weak | 820 hash table if the value is pointed to by something other than a weak |
790 hash table, even if the key is not. | 821 hash table, even if the key is not. |
791 | |
792 Keyword :rehash-size must be a float greater than 1.0, and specifies | |
793 the factor by which to increase the size of the hash table when enlarging. | |
794 | |
795 Keyword :rehash-threshold must be a float between 0.0 and 1.0, | |
796 and specifies the load factor of the hash table which triggers enlarging. | |
797 | |
798 */ | 822 */ |
799 (int nargs, Lisp_Object *args)) | 823 (int nargs, Lisp_Object *args)) |
800 { | 824 { |
801 int j = 0; | 825 int i = 0; |
826 Lisp_Object test = Qnil; | |
802 Lisp_Object size = Qnil; | 827 Lisp_Object size = Qnil; |
803 Lisp_Object type = Qnil; | |
804 Lisp_Object test = Qnil; | |
805 Lisp_Object rehash_size = Qnil; | 828 Lisp_Object rehash_size = Qnil; |
806 Lisp_Object rehash_threshold = Qnil; | 829 Lisp_Object rehash_threshold = Qnil; |
807 | 830 Lisp_Object weakness = Qnil; |
808 while (j < nargs) | 831 |
809 { | 832 while (i + 1 < nargs) |
810 Lisp_Object keyword, value; | 833 { |
811 | 834 Lisp_Object keyword = args[i++]; |
812 keyword = args[j++]; | 835 Lisp_Object value = args[i++]; |
813 if (!KEYWORDP (keyword)) | 836 |
814 signal_simple_error ("Invalid hash table property keyword", keyword); | 837 if (EQ (keyword, Q_test)) test = value; |
815 if (j == nargs) | 838 else if (EQ (keyword, Q_size)) size = value; |
816 signal_simple_error ("Hash table property requires a value", keyword); | |
817 | |
818 value = args[j++]; | |
819 | |
820 if (EQ (keyword, Q_size)) size = value; | |
821 else if (EQ (keyword, Q_type)) type = value; | |
822 else if (EQ (keyword, Q_test)) test = value; | |
823 else if (EQ (keyword, Q_rehash_size)) rehash_size = value; | 839 else if (EQ (keyword, Q_rehash_size)) rehash_size = value; |
824 else if (EQ (keyword, Q_rehash_threshold)) rehash_threshold = value; | 840 else if (EQ (keyword, Q_rehash_threshold)) rehash_threshold = value; |
841 else if (EQ (keyword, Q_weakness)) weakness = value; | |
842 else if (EQ (keyword, Q_type))/*obsolete*/ weakness = value; | |
825 else signal_simple_error ("Invalid hash table property keyword", keyword); | 843 else signal_simple_error ("Invalid hash table property keyword", keyword); |
826 } | 844 } |
845 | |
846 if (i < nargs) | |
847 signal_simple_error ("Hash table property requires a value", args[i]); | |
827 | 848 |
828 #define VALIDATE_VAR(var) \ | 849 #define VALIDATE_VAR(var) \ |
829 if (!NILP (var)) hash_table_##var##_validate (Q##var, var, ERROR_ME); | 850 if (!NILP (var)) hash_table_##var##_validate (Q##var, var, ERROR_ME); |
830 | 851 |
852 VALIDATE_VAR (test); | |
831 VALIDATE_VAR (size); | 853 VALIDATE_VAR (size); |
832 VALIDATE_VAR (type); | |
833 VALIDATE_VAR (test); | |
834 VALIDATE_VAR (rehash_size); | 854 VALIDATE_VAR (rehash_size); |
835 VALIDATE_VAR (rehash_threshold); | 855 VALIDATE_VAR (rehash_threshold); |
856 VALIDATE_VAR (weakness); | |
836 | 857 |
837 return make_general_lisp_hash_table | 858 return make_general_lisp_hash_table |
838 (decode_hash_table_size (size), | 859 (decode_hash_table_test (test), |
839 decode_hash_table_type (type), | 860 decode_hash_table_size (size), |
840 decode_hash_table_test (test), | |
841 decode_hash_table_rehash_size (rehash_size), | 861 decode_hash_table_rehash_size (rehash_size), |
842 decode_hash_table_rehash_threshold (rehash_threshold)); | 862 decode_hash_table_rehash_threshold (rehash_threshold), |
863 decode_hash_table_weakness (weakness)); | |
843 } | 864 } |
844 | 865 |
845 DEFUN ("copy-hash-table", Fcopy_hash_table, 1, 1, 0, /* | 866 DEFUN ("copy-hash-table", Fcopy_hash_table, 1, 1, 0, /* |
846 Return a new hash table containing the same keys and values as HASH-TABLE. | 867 Return a new hash table containing the same keys and values as HASH-TABLE. |
847 The keys and values will not themselves be copied. | 868 The keys and values will not themselves be copied. |
866 | 887 |
867 return hash_table; | 888 return hash_table; |
868 } | 889 } |
869 | 890 |
870 static void | 891 static void |
871 enlarge_hash_table (Lisp_Hash_Table *ht) | 892 resize_hash_table (Lisp_Hash_Table *ht, size_t new_size) |
872 { | 893 { |
873 hentry *old_entries, *new_entries, *old_sentinel, *new_sentinel, *e; | 894 hentry *old_entries, *new_entries, *old_sentinel, *new_sentinel, *e; |
874 size_t old_size, new_size; | 895 size_t old_size; |
875 | 896 |
876 old_size = ht->size; | 897 old_size = ht->size; |
877 new_size = ht->size = | 898 ht->size = new_size; |
878 hash_table_size ((size_t) ((double) old_size * ht->rehash_size)); | |
879 | 899 |
880 old_entries = ht->hentries; | 900 old_entries = ht->hentries; |
881 | 901 |
882 ht->hentries = xnew_array (hentry, new_size + 1); | 902 ht->hentries = xnew_array (hentry, new_size + 1); |
883 new_entries = ht->hentries; | 903 new_entries = ht->hentries; |
897 LINEAR_PROBING_LOOP (probe, new_entries, new_size) | 917 LINEAR_PROBING_LOOP (probe, new_entries, new_size) |
898 ; | 918 ; |
899 *probe = *e; | 919 *probe = *e; |
900 } | 920 } |
901 | 921 |
902 xfree (old_entries); | 922 if (!DUMPEDP (old_entries)) |
923 xfree (old_entries); | |
924 } | |
925 | |
926 void | |
927 reorganize_hash_table (Lisp_Hash_Table *ht) | |
928 { | |
929 resize_hash_table (ht, ht->size); | |
930 } | |
931 | |
932 static void | |
933 enlarge_hash_table (Lisp_Hash_Table *ht) | |
934 { | |
935 size_t new_size = | |
936 hash_table_size ((size_t) ((double) ht->size * ht->rehash_size)); | |
937 resize_hash_table (ht, new_size); | |
903 } | 938 } |
904 | 939 |
905 static hentry * | 940 static hentry * |
906 find_hentry (Lisp_Object key, CONST Lisp_Hash_Table *ht) | 941 find_hentry (Lisp_Object key, CONST Lisp_Hash_Table *ht) |
907 { | 942 { |
953 We don't use tombstones - too wasteful. */ | 988 We don't use tombstones - too wasteful. */ |
954 static void | 989 static void |
955 remhash_1 (Lisp_Hash_Table *ht, hentry *entries, hentry *probe) | 990 remhash_1 (Lisp_Hash_Table *ht, hentry *entries, hentry *probe) |
956 { | 991 { |
957 size_t size = ht->size; | 992 size_t size = ht->size; |
958 CLEAR_HENTRY (probe++); | 993 CLEAR_HENTRY (probe); |
994 probe++; | |
959 ht->count--; | 995 ht->count--; |
960 | 996 |
961 LINEAR_PROBING_LOOP (probe, entries, size) | 997 LINEAR_PROBING_LOOP (probe, entries, size) |
962 { | 998 { |
963 Lisp_Object key = probe->key; | 999 Lisp_Object key = probe->key; |
1014 (hash_table)) | 1050 (hash_table)) |
1015 { | 1051 { |
1016 return make_int (xhash_table (hash_table)->count); | 1052 return make_int (xhash_table (hash_table)->count); |
1017 } | 1053 } |
1018 | 1054 |
1055 DEFUN ("hash-table-test", Fhash_table_test, 1, 1, 0, /* | |
1056 Return the test function of HASH-TABLE. | |
1057 This can be one of `eq', `eql' or `equal'. | |
1058 */ | |
1059 (hash_table)) | |
1060 { | |
1061 hash_table_test_function_t fun = xhash_table (hash_table)->test_function; | |
1062 | |
1063 return (fun == lisp_object_eql_equal ? Qeql : | |
1064 fun == lisp_object_equal_equal ? Qequal : | |
1065 Qeq); | |
1066 } | |
1067 | |
1019 DEFUN ("hash-table-size", Fhash_table_size, 1, 1, 0, /* | 1068 DEFUN ("hash-table-size", Fhash_table_size, 1, 1, 0, /* |
1020 Return the size of HASH-TABLE. | 1069 Return the size of HASH-TABLE. |
1021 This is the current number of slots in HASH-TABLE, whether occupied or not. | 1070 This is the current number of slots in HASH-TABLE, whether occupied or not. |
1022 */ | 1071 */ |
1023 (hash_table)) | 1072 (hash_table)) |
1024 { | 1073 { |
1025 return make_int (xhash_table (hash_table)->size); | 1074 return make_int (xhash_table (hash_table)->size); |
1026 } | 1075 } |
1027 | 1076 |
1077 DEFUN ("hash-table-rehash-size", Fhash_table_rehash_size, 1, 1, 0, /* | |
1078 Return the current rehash size of HASH-TABLE. | |
1079 This is a float greater than 1.0; the factor by which HASH-TABLE | |
1080 is enlarged when the rehash threshold is exceeded. | |
1081 */ | |
1082 (hash_table)) | |
1083 { | |
1084 return make_float (xhash_table (hash_table)->rehash_size); | |
1085 } | |
1086 | |
1087 DEFUN ("hash-table-rehash-threshold", Fhash_table_rehash_threshold, 1, 1, 0, /* | |
1088 Return the current rehash threshold of HASH-TABLE. | |
1089 This is a float between 0.0 and 1.0; the maximum `load factor' of HASH-TABLE, | |
1090 beyond which the HASH-TABLE is enlarged by rehashing. | |
1091 */ | |
1092 (hash_table)) | |
1093 { | |
1094 return make_float (hash_table_rehash_threshold (xhash_table (hash_table))); | |
1095 } | |
1096 | |
1097 DEFUN ("hash-table-weakness", Fhash_table_weakness, 1, 1, 0, /* | |
1098 Return the weakness of HASH-TABLE. | |
1099 This can be one of `nil', `t', `key' or `value'. | |
1100 */ | |
1101 (hash_table)) | |
1102 { | |
1103 switch (xhash_table (hash_table)->weakness) | |
1104 { | |
1105 case HASH_TABLE_WEAK: return Qt; | |
1106 case HASH_TABLE_KEY_WEAK: return Qkey; | |
1107 case HASH_TABLE_VALUE_WEAK: return Qvalue; | |
1108 default: return Qnil; | |
1109 } | |
1110 } | |
1111 | |
1112 /* obsolete as of 19990901 in xemacs-21.2 */ | |
1028 DEFUN ("hash-table-type", Fhash_table_type, 1, 1, 0, /* | 1113 DEFUN ("hash-table-type", Fhash_table_type, 1, 1, 0, /* |
1029 Return the type of HASH-TABLE. | 1114 Return the type of HASH-TABLE. |
1030 This can be one of `non-weak', `weak', `key-weak' or `value-weak'. | 1115 This can be one of `non-weak', `weak', `key-weak' or `value-weak'. |
1031 */ | 1116 */ |
1032 (hash_table)) | 1117 (hash_table)) |
1033 { | 1118 { |
1034 switch (xhash_table (hash_table)->type) | 1119 switch (xhash_table (hash_table)->weakness) |
1035 { | 1120 { |
1036 case HASH_TABLE_WEAK: return Qweak; | 1121 case HASH_TABLE_WEAK: return Qweak; |
1037 case HASH_TABLE_KEY_WEAK: return Qkey_weak; | 1122 case HASH_TABLE_KEY_WEAK: return Qkey_weak; |
1038 case HASH_TABLE_VALUE_WEAK: return Qvalue_weak; | 1123 case HASH_TABLE_VALUE_WEAK: return Qvalue_weak; |
1039 default: return Qnon_weak; | 1124 default: return Qnon_weak; |
1040 } | 1125 } |
1041 } | |
1042 | |
1043 DEFUN ("hash-table-test", Fhash_table_test, 1, 1, 0, /* | |
1044 Return the test function of HASH-TABLE. | |
1045 This can be one of `eq', `eql' or `equal'. | |
1046 */ | |
1047 (hash_table)) | |
1048 { | |
1049 hash_table_test_function_t fun = xhash_table (hash_table)->test_function; | |
1050 | |
1051 return (fun == lisp_object_eql_equal ? Qeql : | |
1052 fun == lisp_object_equal_equal ? Qequal : | |
1053 Qeq); | |
1054 } | |
1055 | |
1056 DEFUN ("hash-table-rehash-size", Fhash_table_rehash_size, 1, 1, 0, /* | |
1057 Return the current rehash size of HASH-TABLE. | |
1058 This is a float greater than 1.0; the factor by which HASH-TABLE | |
1059 is enlarged when the rehash threshold is exceeded. | |
1060 */ | |
1061 (hash_table)) | |
1062 { | |
1063 return make_float (xhash_table (hash_table)->rehash_size); | |
1064 } | |
1065 | |
1066 DEFUN ("hash-table-rehash-threshold", Fhash_table_rehash_threshold, 1, 1, 0, /* | |
1067 Return the current rehash threshold of HASH-TABLE. | |
1068 This is a float between 0.0 and 1.0; the maximum `load factor' of HASH-TABLE, | |
1069 beyond which the HASH-TABLE is enlarged by rehashing. | |
1070 */ | |
1071 (hash_table)) | |
1072 { | |
1073 return make_float (hash_table_rehash_threshold (xhash_table (hash_table))); | |
1074 } | 1126 } |
1075 | 1127 |
1076 /************************************************************************/ | 1128 /************************************************************************/ |
1077 /* Mapping Functions */ | 1129 /* Mapping Functions */ |
1078 /************************************************************************/ | 1130 /************************************************************************/ |
1154 /* garbage collecting weak hash tables */ | 1206 /* garbage collecting weak hash tables */ |
1155 /************************************************************************/ | 1207 /************************************************************************/ |
1156 | 1208 |
1157 /* Complete the marking for semi-weak hash tables. */ | 1209 /* Complete the marking for semi-weak hash tables. */ |
1158 int | 1210 int |
1159 finish_marking_weak_hash_tables (int (*obj_marked_p) (Lisp_Object), | 1211 finish_marking_weak_hash_tables (void) |
1160 void (*markobj) (Lisp_Object)) | |
1161 { | 1212 { |
1162 Lisp_Object hash_table; | 1213 Lisp_Object hash_table; |
1163 int did_mark = 0; | 1214 int did_mark = 0; |
1164 | 1215 |
1165 for (hash_table = Vall_weak_hash_tables; | 1216 for (hash_table = Vall_weak_hash_tables; |
1166 !GC_NILP (hash_table); | 1217 !NILP (hash_table); |
1167 hash_table = XHASH_TABLE (hash_table)->next_weak) | 1218 hash_table = XHASH_TABLE (hash_table)->next_weak) |
1168 { | 1219 { |
1169 CONST Lisp_Hash_Table *ht = XHASH_TABLE (hash_table); | 1220 CONST Lisp_Hash_Table *ht = XHASH_TABLE (hash_table); |
1170 CONST hentry *e = ht->hentries; | 1221 CONST hentry *e = ht->hentries; |
1171 CONST hentry *sentinel = e + ht->size; | 1222 CONST hentry *sentinel = e + ht->size; |
1172 | 1223 |
1173 if (! obj_marked_p (hash_table)) | 1224 if (! marked_p (hash_table)) |
1174 /* The hash table is probably garbage. Ignore it. */ | 1225 /* The hash table is probably garbage. Ignore it. */ |
1175 continue; | 1226 continue; |
1176 | 1227 |
1177 /* Now, scan over all the pairs. For all pairs that are | 1228 /* Now, scan over all the pairs. For all pairs that are |
1178 half-marked, we may need to mark the other half if we're | 1229 half-marked, we may need to mark the other half if we're |
1179 keeping this pair. */ | 1230 keeping this pair. */ |
1180 #define MARK_OBJ(obj) \ | 1231 #define MARK_OBJ(obj) \ |
1181 do { if (!obj_marked_p (obj)) markobj (obj), did_mark = 1; } while (0) | 1232 do { if (!marked_p (obj)) mark_object (obj), did_mark = 1; } while (0) |
1182 | 1233 |
1183 switch (ht->type) | 1234 switch (ht->weakness) |
1184 { | 1235 { |
1185 case HASH_TABLE_KEY_WEAK: | 1236 case HASH_TABLE_KEY_WEAK: |
1186 for (; e < sentinel; e++) | 1237 for (; e < sentinel; e++) |
1187 if (!HENTRY_CLEAR_P (e)) | 1238 if (!HENTRY_CLEAR_P (e)) |
1188 if (obj_marked_p (e->key)) | 1239 if (marked_p (e->key)) |
1189 MARK_OBJ (e->value); | 1240 MARK_OBJ (e->value); |
1190 break; | 1241 break; |
1191 | 1242 |
1192 case HASH_TABLE_VALUE_WEAK: | 1243 case HASH_TABLE_VALUE_WEAK: |
1193 for (; e < sentinel; e++) | 1244 for (; e < sentinel; e++) |
1194 if (!HENTRY_CLEAR_P (e)) | 1245 if (!HENTRY_CLEAR_P (e)) |
1195 if (obj_marked_p (e->value)) | 1246 if (marked_p (e->value)) |
1196 MARK_OBJ (e->key); | 1247 MARK_OBJ (e->key); |
1197 break; | 1248 break; |
1198 | 1249 |
1199 case HASH_TABLE_KEY_CAR_WEAK: | 1250 case HASH_TABLE_KEY_CAR_WEAK: |
1200 for (; e < sentinel; e++) | 1251 for (; e < sentinel; e++) |
1201 if (!HENTRY_CLEAR_P (e)) | 1252 if (!HENTRY_CLEAR_P (e)) |
1202 if (!CONSP (e->key) || obj_marked_p (XCAR (e->key))) | 1253 if (!CONSP (e->key) || marked_p (XCAR (e->key))) |
1203 { | 1254 { |
1204 MARK_OBJ (e->key); | 1255 MARK_OBJ (e->key); |
1205 MARK_OBJ (e->value); | 1256 MARK_OBJ (e->value); |
1206 } | 1257 } |
1207 break; | 1258 break; |
1208 | 1259 |
1209 case HASH_TABLE_VALUE_CAR_WEAK: | 1260 case HASH_TABLE_VALUE_CAR_WEAK: |
1210 for (; e < sentinel; e++) | 1261 for (; e < sentinel; e++) |
1211 if (!HENTRY_CLEAR_P (e)) | 1262 if (!HENTRY_CLEAR_P (e)) |
1212 if (!CONSP (e->value) || obj_marked_p (XCAR (e->value))) | 1263 if (!CONSP (e->value) || marked_p (XCAR (e->value))) |
1213 { | 1264 { |
1214 MARK_OBJ (e->key); | 1265 MARK_OBJ (e->key); |
1215 MARK_OBJ (e->value); | 1266 MARK_OBJ (e->value); |
1216 } | 1267 } |
1217 break; | 1268 break; |
1223 | 1274 |
1224 return did_mark; | 1275 return did_mark; |
1225 } | 1276 } |
1226 | 1277 |
1227 void | 1278 void |
1228 prune_weak_hash_tables (int (*obj_marked_p) (Lisp_Object)) | 1279 prune_weak_hash_tables (void) |
1229 { | 1280 { |
1230 Lisp_Object hash_table, prev = Qnil; | 1281 Lisp_Object hash_table, prev = Qnil; |
1231 for (hash_table = Vall_weak_hash_tables; | 1282 for (hash_table = Vall_weak_hash_tables; |
1232 !GC_NILP (hash_table); | 1283 !NILP (hash_table); |
1233 hash_table = XHASH_TABLE (hash_table)->next_weak) | 1284 hash_table = XHASH_TABLE (hash_table)->next_weak) |
1234 { | 1285 { |
1235 if (! obj_marked_p (hash_table)) | 1286 if (! marked_p (hash_table)) |
1236 { | 1287 { |
1237 /* This hash table itself is garbage. Remove it from the list. */ | 1288 /* This hash table itself is garbage. Remove it from the list. */ |
1238 if (GC_NILP (prev)) | 1289 if (NILP (prev)) |
1239 Vall_weak_hash_tables = XHASH_TABLE (hash_table)->next_weak; | 1290 Vall_weak_hash_tables = XHASH_TABLE (hash_table)->next_weak; |
1240 else | 1291 else |
1241 XHASH_TABLE (prev)->next_weak = XHASH_TABLE (hash_table)->next_weak; | 1292 XHASH_TABLE (prev)->next_weak = XHASH_TABLE (hash_table)->next_weak; |
1242 } | 1293 } |
1243 else | 1294 else |
1244 { | 1295 { |
1245 /* Now, scan over all the pairs. Remove all of the pairs | 1296 /* Now, scan over all the pairs. Remove all of the pairs |
1246 in which the key or value, or both, is unmarked | 1297 in which the key or value, or both, is unmarked |
1247 (depending on the type of weak hash table). */ | 1298 (depending on the weakness of the hash table). */ |
1248 Lisp_Hash_Table *ht = XHASH_TABLE (hash_table); | 1299 Lisp_Hash_Table *ht = XHASH_TABLE (hash_table); |
1249 hentry *entries = ht->hentries; | 1300 hentry *entries = ht->hentries; |
1250 hentry *sentinel = entries + ht->size; | 1301 hentry *sentinel = entries + ht->size; |
1251 hentry *e; | 1302 hentry *e; |
1252 | 1303 |
1253 for (e = entries; e < sentinel; e++) | 1304 for (e = entries; e < sentinel; e++) |
1254 if (!HENTRY_CLEAR_P (e)) | 1305 if (!HENTRY_CLEAR_P (e)) |
1255 { | 1306 { |
1256 again: | 1307 again: |
1257 if (!obj_marked_p (e->key) || !obj_marked_p (e->value)) | 1308 if (!marked_p (e->key) || !marked_p (e->value)) |
1258 { | 1309 { |
1259 remhash_1 (ht, entries, e); | 1310 remhash_1 (ht, entries, e); |
1260 if (!HENTRY_CLEAR_P (e)) | 1311 if (!HENTRY_CLEAR_P (e)) |
1261 goto again; | 1312 goto again; |
1262 } | 1313 } |
1335 } | 1386 } |
1336 | 1387 |
1337 return LISP_HASH (obj); | 1388 return LISP_HASH (obj); |
1338 } | 1389 } |
1339 | 1390 |
1391 DEFUN ("sxhash", Fsxhash, 1, 1, 0, /* | |
1392 Return a hash value for OBJECT. | |
1393 (equal obj1 obj2) implies (= (sxhash obj1) (sxhash obj2)). | |
1394 */ | |
1395 (object)) | |
1396 { | |
1397 return make_int (internal_hash (object, 0)); | |
1398 } | |
1399 | |
1340 #if 0 | 1400 #if 0 |
1341 xxDEFUN ("internal-hash-value", Finternal_hash_value, 1, 1, 0, /* | 1401 xxDEFUN ("internal-hash-value", Finternal_hash_value, 1, 1, 0, /* |
1342 Hash value of OBJECT. For debugging. | 1402 Hash value of OBJECT. For debugging. |
1343 The value is returned as (HIGH . LOW). | 1403 The value is returned as (HIGH . LOW). |
1344 */ | 1404 */ |
1365 DEFSUBR (Fremhash); | 1425 DEFSUBR (Fremhash); |
1366 DEFSUBR (Fputhash); | 1426 DEFSUBR (Fputhash); |
1367 DEFSUBR (Fclrhash); | 1427 DEFSUBR (Fclrhash); |
1368 DEFSUBR (Fmaphash); | 1428 DEFSUBR (Fmaphash); |
1369 DEFSUBR (Fhash_table_count); | 1429 DEFSUBR (Fhash_table_count); |
1430 DEFSUBR (Fhash_table_test); | |
1370 DEFSUBR (Fhash_table_size); | 1431 DEFSUBR (Fhash_table_size); |
1371 DEFSUBR (Fhash_table_rehash_size); | 1432 DEFSUBR (Fhash_table_rehash_size); |
1372 DEFSUBR (Fhash_table_rehash_threshold); | 1433 DEFSUBR (Fhash_table_rehash_threshold); |
1373 DEFSUBR (Fhash_table_type); | 1434 DEFSUBR (Fhash_table_weakness); |
1374 DEFSUBR (Fhash_table_test); | 1435 DEFSUBR (Fhash_table_type); /* obsolete */ |
1436 DEFSUBR (Fsxhash); | |
1375 #if 0 | 1437 #if 0 |
1376 DEFSUBR (Finternal_hash_value); | 1438 DEFSUBR (Finternal_hash_value); |
1377 #endif | 1439 #endif |
1378 | 1440 |
1379 defsymbol (&Qhash_tablep, "hash-table-p"); | 1441 defsymbol (&Qhash_tablep, "hash-table-p"); |
1380 defsymbol (&Qhash_table, "hash-table"); | 1442 defsymbol (&Qhash_table, "hash-table"); |
1381 defsymbol (&Qhashtable, "hashtable"); | 1443 defsymbol (&Qhashtable, "hashtable"); |
1382 defsymbol (&Qweak, "weak"); | 1444 defsymbol (&Qweakness, "weakness"); |
1383 defsymbol (&Qkey_weak, "key-weak"); | 1445 defsymbol (&Qvalue, "value"); |
1384 defsymbol (&Qvalue_weak, "value-weak"); | |
1385 defsymbol (&Qnon_weak, "non-weak"); | |
1386 defsymbol (&Qrehash_size, "rehash-size"); | 1446 defsymbol (&Qrehash_size, "rehash-size"); |
1387 defsymbol (&Qrehash_threshold, "rehash-threshold"); | 1447 defsymbol (&Qrehash_threshold, "rehash-threshold"); |
1388 | 1448 |
1449 defsymbol (&Qweak, "weak"); /* obsolete */ | |
1450 defsymbol (&Qkey_weak, "key-weak"); /* obsolete */ | |
1451 defsymbol (&Qvalue_weak, "value-weak"); /* obsolete */ | |
1452 defsymbol (&Qnon_weak, "non-weak"); /* obsolete */ | |
1453 | |
1454 defkeyword (&Q_test, ":test"); | |
1389 defkeyword (&Q_size, ":size"); | 1455 defkeyword (&Q_size, ":size"); |
1390 defkeyword (&Q_test, ":test"); | |
1391 defkeyword (&Q_type, ":type"); | |
1392 defkeyword (&Q_rehash_size, ":rehash-size"); | 1456 defkeyword (&Q_rehash_size, ":rehash-size"); |
1393 defkeyword (&Q_rehash_threshold, ":rehash-threshold"); | 1457 defkeyword (&Q_rehash_threshold, ":rehash-threshold"); |
1458 defkeyword (&Q_weakness, ":weakness"); | |
1459 defkeyword (&Q_type, ":type"); /* obsolete */ | |
1394 } | 1460 } |
1395 | 1461 |
1396 void | 1462 void |
1397 vars_of_elhash (void) | 1463 vars_of_elhash (void) |
1398 { | 1464 { |
1399 /* This must NOT be staticpro'd */ | 1465 /* This must NOT be staticpro'd */ |
1400 Vall_weak_hash_tables = Qnil; | 1466 Vall_weak_hash_tables = Qnil; |
1401 } | 1467 pdump_wire_list (&Vall_weak_hash_tables); |
1468 } |