Mercurial > hg > xemacs-beta
comparison src/elhash.c @ 412:697ef44129c6 r21-2-14
Import from CVS: tag r21-2-14
author | cvs |
---|---|
date | Mon, 13 Aug 2007 11:20:41 +0200 |
parents | de805c49cfc1 |
children | 41dbb7a9d5f2 |
comparison
equal
deleted
inserted
replaced
411:12e008d41344 | 412:697ef44129c6 |
---|---|
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; | 30 Lisp_Object Qhash_tablep, Qhashtable, Qhash_table; |
31 static Lisp_Object Qhashtable, Qhash_table; | 31 Lisp_Object Qweak, Qkey_weak, Qvalue_weak, Qnon_weak; |
32 static Lisp_Object Qweakness, Qvalue, Qkey_value; | |
33 static Lisp_Object Vall_weak_hash_tables; | 32 static Lisp_Object Vall_weak_hash_tables; |
34 static Lisp_Object Qrehash_size, Qrehash_threshold; | 33 static Lisp_Object Qrehash_size, Qrehash_threshold; |
35 static Lisp_Object Q_size, Q_test, Q_weakness, Q_rehash_size, Q_rehash_threshold; | 34 static Lisp_Object Q_size, Q_test, Q_type, 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, Qkey_value_weak; | |
39 static Lisp_Object Qnon_weak, Q_type; | |
40 | 35 |
41 typedef struct hentry | 36 typedef struct hentry |
42 { | 37 { |
43 Lisp_Object key; | 38 Lisp_Object key; |
44 Lisp_Object value; | 39 Lisp_Object value; |
54 double rehash_threshold; | 49 double rehash_threshold; |
55 size_t golden_ratio; | 50 size_t golden_ratio; |
56 hash_table_hash_function_t hash_function; | 51 hash_table_hash_function_t hash_function; |
57 hash_table_test_function_t test_function; | 52 hash_table_test_function_t test_function; |
58 hentry *hentries; | 53 hentry *hentries; |
59 enum hash_table_weakness weakness; | 54 enum hash_table_type type; /* whether and how this hash table is weak */ |
60 Lisp_Object next_weak; /* Used to chain together all of the weak | 55 Lisp_Object next_weak; /* Used to chain together all of the weak |
61 hash tables. Don't mark through this. */ | 56 hash tables. Don't mark through this. */ |
62 }; | 57 }; |
58 typedef struct Lisp_Hash_Table Lisp_Hash_Table; | |
63 | 59 |
64 #define HENTRY_CLEAR_P(hentry) ((*(EMACS_UINT*)(&((hentry)->key))) == 0) | 60 #define HENTRY_CLEAR_P(hentry) ((*(EMACS_UINT*)(&((hentry)->key))) == 0) |
65 #define CLEAR_HENTRY(hentry) \ | 61 #define CLEAR_HENTRY(hentry) ((*(EMACS_UINT*)(&((hentry)->key))) = 0) |
66 ((*(EMACS_UINT*)(&((hentry)->key))) = 0, \ | |
67 (*(EMACS_UINT*)(&((hentry)->value))) = 0) | |
68 | 62 |
69 #define HASH_TABLE_DEFAULT_SIZE 16 | 63 #define HASH_TABLE_DEFAULT_SIZE 16 |
70 #define HASH_TABLE_DEFAULT_REHASH_SIZE 1.3 | 64 #define HASH_TABLE_DEFAULT_REHASH_SIZE 1.3 |
71 #define HASH_TABLE_MIN_SIZE 10 | 65 #define HASH_TABLE_MIN_SIZE 10 |
72 | 66 |
73 #define HASH_CODE(key, ht) \ | 67 #define HASH_CODE(key, ht) \ |
74 ((((ht)->hash_function ? (ht)->hash_function (key) : LISP_HASH (key)) \ | 68 (((((ht)->hash_function ? (ht)->hash_function (key) : LISP_HASH (key)) \ |
75 * (ht)->golden_ratio) \ | 69 * (ht)->golden_ratio) \ |
76 % (ht)->size) | 70 % (ht)->size)) |
77 | 71 |
78 #define KEYS_EQUAL_P(key1, key2, testfun) \ | 72 #define KEYS_EQUAL_P(key1, key2, testfun) \ |
79 (EQ (key1, key2) || ((testfun) && (testfun) (key1, key2))) | 73 (EQ ((key1), (key2)) || ((testfun) && (testfun) ((key1), (key2)))) |
80 | 74 |
81 #define LINEAR_PROBING_LOOP(probe, entries, size) \ | 75 #define LINEAR_PROBING_LOOP(probe, entries, size) \ |
82 for (; \ | 76 for (; \ |
83 !HENTRY_CLEAR_P (probe) || \ | 77 !HENTRY_CLEAR_P (probe) || \ |
84 (probe == entries + size ? \ | 78 (probe == entries + size ? \ |
121 hash_table_size (size_t requested_size) | 115 hash_table_size (size_t requested_size) |
122 { | 116 { |
123 /* Return some prime near, but greater than or equal to, SIZE. | 117 /* Return some prime near, but greater than or equal to, SIZE. |
124 Decades from the time of writing, someone will have a system large | 118 Decades from the time of writing, someone will have a system large |
125 enough that the list below will be too short... */ | 119 enough that the list below will be too short... */ |
126 static const size_t primes [] = | 120 static CONST size_t primes [] = |
127 { | 121 { |
128 19, 29, 41, 59, 79, 107, 149, 197, 263, 347, 457, 599, 787, 1031, | 122 19, 29, 41, 59, 79, 107, 149, 197, 263, 347, 457, 599, 787, 1031, |
129 1361, 1777, 2333, 3037, 3967, 5167, 6719, 8737, 11369, 14783, | 123 1361, 1777, 2333, 3037, 3967, 5167, 6719, 8737, 11369, 14783, |
130 19219, 24989, 32491, 42257, 54941, 71429, 92861, 120721, 156941, | 124 19219, 24989, 32491, 42257, 54941, 71429, 92861, 120721, 156941, |
131 204047, 265271, 344857, 448321, 582821, 757693, 985003, 1280519, | 125 204047, 265271, 344857, 448321, 582821, 757693, 985003, 1280519, |
194 return internal_hash (obj, 0); | 188 return internal_hash (obj, 0); |
195 } | 189 } |
196 | 190 |
197 | 191 |
198 static Lisp_Object | 192 static Lisp_Object |
199 mark_hash_table (Lisp_Object obj) | 193 mark_hash_table (Lisp_Object obj, void (*markobj) (Lisp_Object)) |
200 { | 194 { |
201 Lisp_Hash_Table *ht = XHASH_TABLE (obj); | 195 Lisp_Hash_Table *ht = XHASH_TABLE (obj); |
202 | 196 |
203 /* If the hash table is weak, we don't want to mark the keys and | 197 /* If the hash table is weak, we don't want to mark the keys and |
204 values (we scan over them after everything else has been marked, | 198 values (we scan over them after everything else has been marked, |
205 and mark or remove them as necessary). */ | 199 and mark or remove them as necessary). */ |
206 if (ht->weakness == HASH_TABLE_NON_WEAK) | 200 if (ht->type == HASH_TABLE_NON_WEAK) |
207 { | 201 { |
208 hentry *e, *sentinel; | 202 hentry *e, *sentinel; |
209 | 203 |
210 for (e = ht->hentries, sentinel = e + ht->size; e < sentinel; e++) | 204 for (e = ht->hentries, sentinel = e + ht->size; e < sentinel; e++) |
211 if (!HENTRY_CLEAR_P (e)) | 205 if (!HENTRY_CLEAR_P (e)) |
212 { | 206 { |
213 mark_object (e->key); | 207 markobj (e->key); |
214 mark_object (e->value); | 208 markobj (e->value); |
215 } | 209 } |
216 } | 210 } |
217 return Qnil; | 211 return Qnil; |
218 } | 212 } |
219 | 213 |
220 /* Equality of hash tables. Two hash tables are equal when they are of | 214 /* Equality of hash tables. Two hash tables are equal when they are of |
221 the same weakness and test function, they have the same number of | 215 the same type and test function, they have the same number of |
222 elements, and for each key in the hash table, the values are `equal'. | 216 elements, and for each key in the hash table, the values are `equal'. |
223 | 217 |
224 This is similar to Common Lisp `equalp' of hash tables, with the | 218 This is similar to Common Lisp `equalp' of hash tables, with the |
225 difference that CL requires the keys to be compared with the test | 219 difference that CL requires the keys to be compared with the test |
226 function, which we don't do. Doing that would require consing, and | 220 function, which we don't do. Doing that would require consing, and |
233 Lisp_Hash_Table *ht1 = XHASH_TABLE (hash_table1); | 227 Lisp_Hash_Table *ht1 = XHASH_TABLE (hash_table1); |
234 Lisp_Hash_Table *ht2 = XHASH_TABLE (hash_table2); | 228 Lisp_Hash_Table *ht2 = XHASH_TABLE (hash_table2); |
235 hentry *e, *sentinel; | 229 hentry *e, *sentinel; |
236 | 230 |
237 if ((ht1->test_function != ht2->test_function) || | 231 if ((ht1->test_function != ht2->test_function) || |
238 (ht1->weakness != ht2->weakness) || | 232 (ht1->type != ht2->type) || |
239 (ht1->count != ht2->count)) | 233 (ht1->count != ht2->count)) |
240 return 0; | 234 return 0; |
241 | 235 |
242 depth++; | 236 depth++; |
243 | 237 |
251 return 0; /* Give up */ | 245 return 0; /* Give up */ |
252 } | 246 } |
253 | 247 |
254 return 1; | 248 return 1; |
255 } | 249 } |
256 | |
257 /* This is not a great hash function, but it _is_ correct and fast. | |
258 Examining all entries is too expensive, and examining a random | |
259 subset does not yield a correct hash function. */ | |
260 static hashcode_t | |
261 hash_table_hash (Lisp_Object hash_table, int depth) | |
262 { | |
263 return XHASH_TABLE (hash_table)->count; | |
264 } | |
265 | |
266 | 250 |
267 /* Printing hash tables. | 251 /* Printing hash tables. |
268 | 252 |
269 This is non-trivial, because we use a readable structure-style | 253 This is non-trivial, because we use a readable structure-style |
270 syntax for hash tables. This means that a typical hash table will be | 254 syntax for hash tables. This means that a typical hash table will be |
271 readably printed in the form of: | 255 readably printed in the form of: |
272 | 256 |
273 #s(hash-table size 2 data (key1 value1 key2 value2)) | 257 #s(hash-table size 2 data (key1 value1 key2 value2)) |
274 | 258 |
275 The supported hash table structure keywords and their values are: | 259 The supported keywords are `type' (non-weak (or nil), weak, |
276 `test' (eql (or nil), eq or equal) | 260 key-weak and value-weak), `test' (eql (or nil), eq or equal), |
277 `size' (a natnum or nil) | 261 `size' (a natnum or nil) and `data' (a list). |
278 `rehash-size' (a float) | 262 |
279 `rehash-threshold' (a float) | 263 If `print-readably' is non-nil, then a simpler syntax is used; for |
280 `weakness' (nil, t, key or value) | 264 instance: |
281 `data' (a list) | |
282 | |
283 If `print-readably' is nil, then a simpler syntax is used, for example | |
284 | 265 |
285 #<hash-table size 2/13 data (key1 value1 key2 value2) 0x874d> | 266 #<hash-table size 2/13 data (key1 value1 key2 value2) 0x874d> |
286 | 267 |
287 The data is truncated to four pairs, and the rest is shown with | 268 The data is truncated to four pairs, and the rest is shown with |
288 `...'. This printer does not cons. */ | 269 `...'. This printer does not cons. */ |
324 char buf[128]; | 305 char buf[128]; |
325 | 306 |
326 write_c_string (print_readably ? "#s(hash-table" : "#<hash-table", | 307 write_c_string (print_readably ? "#s(hash-table" : "#<hash-table", |
327 printcharfun); | 308 printcharfun); |
328 | 309 |
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 | |
329 /* 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. |
330 Due to nature of hashing, you cannot use arbitrary | 321 Due to nature of hashing, you cannot use arbitrary |
331 test functions anyway. */ | 322 test functions anyway. */ |
332 if (!ht->test_function) | 323 if (!ht->test_function) |
333 write_c_string (" test eq", printcharfun); | 324 write_c_string (" test eq", printcharfun); |
347 (unsigned long) ht->count, | 338 (unsigned long) ht->count, |
348 (unsigned long) ht->size); | 339 (unsigned long) ht->size); |
349 write_c_string (buf, printcharfun); | 340 write_c_string (buf, printcharfun); |
350 } | 341 } |
351 | 342 |
352 if (ht->weakness != HASH_TABLE_NON_WEAK) | |
353 { | |
354 sprintf (buf, " weakness %s", | |
355 (ht->weakness == HASH_TABLE_WEAK ? "t" : | |
356 ht->weakness == HASH_TABLE_KEY_WEAK ? "key" : | |
357 ht->weakness == HASH_TABLE_VALUE_WEAK ? "value" : | |
358 ht->weakness == HASH_TABLE_KEY_VALUE_WEAK ? "key-value" : | |
359 "you-d-better-not-see-this")); | |
360 write_c_string (buf, printcharfun); | |
361 } | |
362 | |
363 if (ht->count) | 343 if (ht->count) |
364 print_hash_table_data (ht, printcharfun); | 344 print_hash_table_data (ht, printcharfun); |
365 | 345 |
366 if (print_readably) | 346 if (print_readably) |
367 write_c_string (")", printcharfun); | 347 write_c_string (")", printcharfun); |
382 xfree (ht->hentries); | 362 xfree (ht->hentries); |
383 ht->hentries = 0; | 363 ht->hentries = 0; |
384 } | 364 } |
385 } | 365 } |
386 | 366 |
387 static const struct lrecord_description hentry_description_1[] = { | |
388 { XD_LISP_OBJECT, offsetof (hentry, key) }, | |
389 { XD_LISP_OBJECT, offsetof (hentry, value) }, | |
390 { XD_END } | |
391 }; | |
392 | |
393 static const struct struct_description hentry_description = { | |
394 sizeof (hentry), | |
395 hentry_description_1 | |
396 }; | |
397 | |
398 const struct lrecord_description hash_table_description[] = { | |
399 { XD_SIZE_T, offsetof (Lisp_Hash_Table, size) }, | |
400 { XD_STRUCT_PTR, offsetof (Lisp_Hash_Table, hentries), XD_INDIRECT(0, 1), &hentry_description }, | |
401 { XD_LO_LINK, offsetof (Lisp_Hash_Table, next_weak) }, | |
402 { XD_END } | |
403 }; | |
404 | |
405 DEFINE_LRECORD_IMPLEMENTATION ("hash-table", hash_table, | 367 DEFINE_LRECORD_IMPLEMENTATION ("hash-table", hash_table, |
406 mark_hash_table, print_hash_table, | 368 mark_hash_table, print_hash_table, |
407 finalize_hash_table, | 369 finalize_hash_table, |
408 hash_table_equal, hash_table_hash, | 370 /* #### Implement hash_table_hash()! */ |
409 hash_table_description, | 371 hash_table_equal, 0, |
410 Lisp_Hash_Table); | 372 Lisp_Hash_Table); |
411 | 373 |
412 static Lisp_Hash_Table * | 374 static Lisp_Hash_Table * |
413 xhash_table (Lisp_Object hash_table) | 375 xhash_table (Lisp_Object hash_table) |
414 { | 376 { |
422 /************************************************************************/ | 384 /************************************************************************/ |
423 /* Creation of Hash Tables */ | 385 /* Creation of Hash Tables */ |
424 /************************************************************************/ | 386 /************************************************************************/ |
425 | 387 |
426 /* Creation of hash tables, without error-checking. */ | 388 /* Creation of hash tables, without error-checking. */ |
389 static double | |
390 hash_table_rehash_threshold (Lisp_Hash_Table *ht) | |
391 { | |
392 return | |
393 ht->rehash_threshold > 0.0 ? ht->rehash_threshold : | |
394 ht->size > 4096 && !ht->test_function ? 0.7 : 0.6; | |
395 } | |
396 | |
427 static void | 397 static void |
428 compute_hash_table_derived_values (Lisp_Hash_Table *ht) | 398 compute_hash_table_derived_values (Lisp_Hash_Table *ht) |
429 { | 399 { |
430 ht->rehash_count = (size_t) | 400 ht->rehash_count = (size_t) |
431 ((double) ht->size * ht->rehash_threshold); | 401 ((double) ht->size * hash_table_rehash_threshold (ht)); |
432 ht->golden_ratio = (size_t) | 402 ht->golden_ratio = (size_t) |
433 ((double) ht->size * (.6180339887 / (double) sizeof (Lisp_Object))); | 403 ((double) ht->size * (.6180339887 / (double) sizeof (Lisp_Object))); |
434 } | 404 } |
435 | 405 |
436 Lisp_Object | 406 Lisp_Object |
437 make_general_lisp_hash_table (enum hash_table_test test, | 407 make_general_lisp_hash_table (size_t size, |
438 size_t size, | 408 enum hash_table_type type, |
439 double rehash_size, | 409 enum hash_table_test test, |
440 double rehash_threshold, | 410 double rehash_size, |
441 enum hash_table_weakness weakness) | 411 double rehash_threshold) |
442 { | 412 { |
443 Lisp_Object hash_table; | 413 Lisp_Object hash_table; |
444 Lisp_Hash_Table *ht = alloc_lcrecord_type (Lisp_Hash_Table, &lrecord_hash_table); | 414 Lisp_Hash_Table *ht = alloc_lcrecord_type (Lisp_Hash_Table, &lrecord_hash_table); |
415 | |
416 ht->type = type; | |
417 ht->rehash_size = rehash_size; | |
418 ht->rehash_threshold = rehash_threshold; | |
445 | 419 |
446 switch (test) | 420 switch (test) |
447 { | 421 { |
448 case HASH_TABLE_EQ: | 422 case HASH_TABLE_EQ: |
449 ht->test_function = 0; | 423 ht->test_function = 0; |
462 | 436 |
463 default: | 437 default: |
464 abort (); | 438 abort (); |
465 } | 439 } |
466 | 440 |
467 ht->weakness = weakness; | 441 if (ht->rehash_size <= 0.0) |
468 | 442 ht->rehash_size = HASH_TABLE_DEFAULT_REHASH_SIZE; |
469 ht->rehash_size = | |
470 rehash_size > 1.0 ? rehash_size : HASH_TABLE_DEFAULT_REHASH_SIZE; | |
471 | |
472 ht->rehash_threshold = | |
473 rehash_threshold > 0.0 ? rehash_threshold : | |
474 size > 4096 && !ht->test_function ? 0.7 : 0.6; | |
475 | |
476 if (size < HASH_TABLE_MIN_SIZE) | 443 if (size < HASH_TABLE_MIN_SIZE) |
477 size = HASH_TABLE_MIN_SIZE; | 444 size = HASH_TABLE_MIN_SIZE; |
478 ht->size = hash_table_size ((size_t) (((double) size / ht->rehash_threshold) | 445 if (rehash_threshold < 0.0) |
479 + 1.0)); | 446 rehash_threshold = 0.75; |
447 ht->size = | |
448 hash_table_size ((size_t) ((double) size / hash_table_rehash_threshold (ht)) + 1); | |
480 ht->count = 0; | 449 ht->count = 0; |
481 | |
482 compute_hash_table_derived_values (ht); | 450 compute_hash_table_derived_values (ht); |
483 | 451 |
484 /* We leave room for one never-occupied sentinel hentry at the end. */ | 452 /* We leave room for one never-occupied sentinel hentry at the end. */ |
485 ht->hentries = xnew_array (hentry, ht->size + 1); | 453 ht->hentries = xnew_array (hentry, ht->size + 1); |
486 | 454 |
490 CLEAR_HENTRY (e); | 458 CLEAR_HENTRY (e); |
491 } | 459 } |
492 | 460 |
493 XSETHASH_TABLE (hash_table, ht); | 461 XSETHASH_TABLE (hash_table, ht); |
494 | 462 |
495 if (weakness == HASH_TABLE_NON_WEAK) | 463 if (type == HASH_TABLE_NON_WEAK) |
496 ht->next_weak = Qunbound; | 464 ht->next_weak = Qunbound; |
497 else | 465 else |
498 ht->next_weak = Vall_weak_hash_tables, Vall_weak_hash_tables = hash_table; | 466 ht->next_weak = Vall_weak_hash_tables, Vall_weak_hash_tables = hash_table; |
499 | 467 |
500 return hash_table; | 468 return hash_table; |
501 } | 469 } |
502 | 470 |
503 Lisp_Object | 471 Lisp_Object |
504 make_lisp_hash_table (size_t size, | 472 make_lisp_hash_table (size_t size, |
505 enum hash_table_weakness weakness, | 473 enum hash_table_type type, |
506 enum hash_table_test test) | 474 enum hash_table_test test) |
507 { | 475 { |
508 return make_general_lisp_hash_table (test, size, -1.0, -1.0, weakness); | 476 return make_general_lisp_hash_table (size, type, test, |
477 HASH_TABLE_DEFAULT_REHASH_SIZE, -1.0); | |
509 } | 478 } |
510 | 479 |
511 /* Pretty reading of hash tables. | 480 /* Pretty reading of hash tables. |
512 | 481 |
513 Here we use the existing structures mechanism (which is, | 482 Here we use the existing structures mechanism (which is, |
536 { | 505 { |
537 return NILP (obj) ? HASH_TABLE_DEFAULT_SIZE : XINT (obj); | 506 return NILP (obj) ? HASH_TABLE_DEFAULT_SIZE : XINT (obj); |
538 } | 507 } |
539 | 508 |
540 static int | 509 static int |
541 hash_table_weakness_validate (Lisp_Object keyword, Lisp_Object value, | 510 hash_table_type_validate (Lisp_Object keyword, Lisp_Object value, |
542 Error_behavior errb) | 511 Error_behavior errb) |
543 { | 512 { |
544 if (EQ (value, Qnil)) return 1; | 513 if (EQ (value, Qnil)) return 1; |
545 if (EQ (value, Qt)) return 1; | |
546 if (EQ (value, Qkey)) return 1; | |
547 if (EQ (value, Qkey_value)) return 1; | |
548 if (EQ (value, Qvalue)) return 1; | |
549 | |
550 /* Following values are obsolete as of 19990901 in xemacs-21.2 */ | |
551 if (EQ (value, Qnon_weak)) return 1; | 514 if (EQ (value, Qnon_weak)) return 1; |
552 if (EQ (value, Qweak)) return 1; | 515 if (EQ (value, Qweak)) return 1; |
553 if (EQ (value, Qkey_weak)) return 1; | 516 if (EQ (value, Qkey_weak)) return 1; |
554 if (EQ (value, Qkey_value_weak)) return 1; | |
555 if (EQ (value, Qvalue_weak)) return 1; | 517 if (EQ (value, Qvalue_weak)) return 1; |
556 | 518 |
557 maybe_signal_simple_error ("Invalid hash table weakness", | 519 maybe_signal_simple_error ("Invalid hash table type", |
558 value, Qhash_table, errb); | 520 value, Qhash_table, errb); |
559 return 0; | 521 return 0; |
560 } | 522 } |
561 | 523 |
562 static enum hash_table_weakness | 524 static enum hash_table_type |
563 decode_hash_table_weakness (Lisp_Object obj) | 525 decode_hash_table_type (Lisp_Object obj) |
564 { | 526 { |
565 if (EQ (obj, Qnil)) return HASH_TABLE_NON_WEAK; | 527 if (EQ (obj, Qnil)) return HASH_TABLE_NON_WEAK; |
566 if (EQ (obj, Qt)) return HASH_TABLE_WEAK; | |
567 if (EQ (obj, Qkey)) return HASH_TABLE_KEY_WEAK; | |
568 if (EQ (obj, Qkey_value)) return HASH_TABLE_KEY_VALUE_WEAK; | |
569 if (EQ (obj, Qvalue)) return HASH_TABLE_VALUE_WEAK; | |
570 | |
571 /* Following values are obsolete as of 19990901 in xemacs-21.2 */ | |
572 if (EQ (obj, Qnon_weak)) return HASH_TABLE_NON_WEAK; | 528 if (EQ (obj, Qnon_weak)) return HASH_TABLE_NON_WEAK; |
573 if (EQ (obj, Qweak)) return HASH_TABLE_WEAK; | 529 if (EQ (obj, Qweak)) return HASH_TABLE_WEAK; |
574 if (EQ (obj, Qkey_weak)) return HASH_TABLE_KEY_WEAK; | 530 if (EQ (obj, Qkey_weak)) return HASH_TABLE_KEY_WEAK; |
575 if (EQ (obj, Qkey_value_weak)) return HASH_TABLE_KEY_VALUE_WEAK; | |
576 if (EQ (obj, Qvalue_weak)) return HASH_TABLE_VALUE_WEAK; | 531 if (EQ (obj, Qvalue_weak)) return HASH_TABLE_VALUE_WEAK; |
577 | 532 |
578 signal_simple_error ("Invalid hash table weakness", obj); | 533 signal_simple_error ("Invalid hash table type", obj); |
579 return HASH_TABLE_NON_WEAK; /* not reached */ | 534 return HASH_TABLE_NON_WEAK; /* not reached */ |
580 } | 535 } |
581 | 536 |
582 static int | 537 static int |
583 hash_table_test_validate (Lisp_Object keyword, Lisp_Object value, | 538 hash_table_test_validate (Lisp_Object keyword, Lisp_Object value, |
605 return HASH_TABLE_EQ; /* not reached */ | 560 return HASH_TABLE_EQ; /* not reached */ |
606 } | 561 } |
607 | 562 |
608 static int | 563 static int |
609 hash_table_rehash_size_validate (Lisp_Object keyword, Lisp_Object value, | 564 hash_table_rehash_size_validate (Lisp_Object keyword, Lisp_Object value, |
610 Error_behavior errb) | 565 Error_behavior errb) |
611 { | 566 { |
612 if (!FLOATP (value)) | 567 if (!FLOATP (value)) |
613 { | 568 { |
614 maybe_signal_error (Qwrong_type_argument, list2 (Qfloatp, value), | 569 maybe_signal_error (Qwrong_type_argument, list2 (Qfloatp, value), |
615 Qhash_table, errb); | 570 Qhash_table, errb); |
694 static Lisp_Object | 649 static Lisp_Object |
695 hash_table_instantiate (Lisp_Object plist) | 650 hash_table_instantiate (Lisp_Object plist) |
696 { | 651 { |
697 Lisp_Object hash_table; | 652 Lisp_Object hash_table; |
698 Lisp_Object test = Qnil; | 653 Lisp_Object test = Qnil; |
654 Lisp_Object type = Qnil; | |
699 Lisp_Object size = Qnil; | 655 Lisp_Object size = Qnil; |
656 Lisp_Object data = Qnil; | |
700 Lisp_Object rehash_size = Qnil; | 657 Lisp_Object rehash_size = Qnil; |
701 Lisp_Object rehash_threshold = Qnil; | 658 Lisp_Object rehash_threshold = Qnil; |
702 Lisp_Object weakness = Qnil; | |
703 Lisp_Object data = Qnil; | |
704 | 659 |
705 while (!NILP (plist)) | 660 while (!NILP (plist)) |
706 { | 661 { |
707 Lisp_Object key, value; | 662 Lisp_Object key, value; |
708 key = XCAR (plist); plist = XCDR (plist); | 663 key = XCAR (plist); plist = XCDR (plist); |
709 value = XCAR (plist); plist = XCDR (plist); | 664 value = XCAR (plist); plist = XCDR (plist); |
710 | 665 |
711 if (EQ (key, Qtest)) test = value; | 666 if (EQ (key, Qtest)) test = value; |
667 else if (EQ (key, Qtype)) type = value; | |
712 else if (EQ (key, Qsize)) size = value; | 668 else if (EQ (key, Qsize)) size = value; |
669 else if (EQ (key, Qdata)) data = value; | |
713 else if (EQ (key, Qrehash_size)) rehash_size = value; | 670 else if (EQ (key, Qrehash_size)) rehash_size = value; |
714 else if (EQ (key, Qrehash_threshold)) rehash_threshold = value; | 671 else if (EQ (key, Qrehash_threshold)) rehash_threshold = value; |
715 else if (EQ (key, Qweakness)) weakness = value; | |
716 else if (EQ (key, Qdata)) data = value; | |
717 else if (EQ (key, Qtype))/*obsolete*/ weakness = value; | |
718 else | 672 else |
719 abort (); | 673 abort (); |
720 } | 674 } |
721 | 675 |
722 /* Create the hash table. */ | 676 /* Create the hash table. */ |
723 hash_table = make_general_lisp_hash_table | 677 hash_table = make_general_lisp_hash_table |
724 (decode_hash_table_test (test), | 678 (decode_hash_table_size (size), |
725 decode_hash_table_size (size), | 679 decode_hash_table_type (type), |
680 decode_hash_table_test (test), | |
726 decode_hash_table_rehash_size (rehash_size), | 681 decode_hash_table_rehash_size (rehash_size), |
727 decode_hash_table_rehash_threshold (rehash_threshold), | 682 decode_hash_table_rehash_threshold (rehash_threshold)); |
728 decode_hash_table_weakness (weakness)); | |
729 | 683 |
730 /* I'm not sure whether this can GC, but better safe than sorry. */ | 684 /* I'm not sure whether this can GC, but better safe than sorry. */ |
731 { | 685 { |
732 struct gcpro gcpro1; | 686 struct gcpro gcpro1; |
733 GCPRO1 (hash_table); | 687 GCPRO1 (hash_table); |
750 structure_type_create_hash_table_structure_name (Lisp_Object structure_name) | 704 structure_type_create_hash_table_structure_name (Lisp_Object structure_name) |
751 { | 705 { |
752 struct structure_type *st; | 706 struct structure_type *st; |
753 | 707 |
754 st = define_structure_type (structure_name, 0, hash_table_instantiate); | 708 st = define_structure_type (structure_name, 0, hash_table_instantiate); |
709 define_structure_type_keyword (st, Qsize, hash_table_size_validate); | |
755 define_structure_type_keyword (st, Qtest, hash_table_test_validate); | 710 define_structure_type_keyword (st, Qtest, hash_table_test_validate); |
756 define_structure_type_keyword (st, Qsize, hash_table_size_validate); | 711 define_structure_type_keyword (st, Qtype, hash_table_type_validate); |
712 define_structure_type_keyword (st, Qdata, hash_table_data_validate); | |
757 define_structure_type_keyword (st, Qrehash_size, hash_table_rehash_size_validate); | 713 define_structure_type_keyword (st, Qrehash_size, hash_table_rehash_size_validate); |
758 define_structure_type_keyword (st, Qrehash_threshold, hash_table_rehash_threshold_validate); | 714 define_structure_type_keyword (st, Qrehash_threshold, hash_table_rehash_threshold_validate); |
759 define_structure_type_keyword (st, Qweakness, hash_table_weakness_validate); | |
760 define_structure_type_keyword (st, Qdata, hash_table_data_validate); | |
761 | |
762 /* obsolete as of 19990901 in xemacs-21.2 */ | |
763 define_structure_type_keyword (st, Qtype, hash_table_weakness_validate); | |
764 } | 715 } |
765 | 716 |
766 /* Create a built-in Lisp structure type named `hash-table'. | 717 /* Create a built-in Lisp structure type named `hash-table'. |
767 We make #s(hashtable ...) equivalent to #s(hash-table ...), | 718 We make #s(hashtable ...) equivalent to #s(hash-table ...), |
768 for backward compatibility. | 719 for backward comptabibility. |
769 This is called from emacs.c. */ | 720 This is called from emacs.c. */ |
770 void | 721 void |
771 structure_type_create_hash_table (void) | 722 structure_type_create_hash_table (void) |
772 { | 723 { |
773 structure_type_create_hash_table_structure_name (Qhash_table); | 724 structure_type_create_hash_table_structure_name (Qhash_table); |
788 } | 739 } |
789 | 740 |
790 DEFUN ("make-hash-table", Fmake_hash_table, 0, MANY, 0, /* | 741 DEFUN ("make-hash-table", Fmake_hash_table, 0, MANY, 0, /* |
791 Return a new empty hash table object. | 742 Return a new empty hash table object. |
792 Use Common Lisp style keywords to specify hash table properties. | 743 Use Common Lisp style keywords to specify hash table properties. |
793 (make-hash-table &key test size rehash-size rehash-threshold weakness) | 744 (make-hash-table &key :size :test :type :rehash-size :rehash-threshold) |
745 | |
746 Keyword :size specifies the number of keys likely to be inserted. | |
747 This number of entries can be inserted without enlarging the hash table. | |
794 | 748 |
795 Keyword :test can be `eq', `eql' (default) or `equal'. | 749 Keyword :test can be `eq', `eql' (default) or `equal'. |
796 Comparison between keys is done using this function. | 750 Comparison between keys is done using this function. |
797 If speed is important, consider using `eq'. | 751 If speed is important, consider using `eq'. |
798 When storing strings in the hash table, you will likely need to use `equal'. | 752 When storing strings in the hash table, you will likely need to use `equal'. |
799 | 753 |
800 Keyword :size specifies the number of keys likely to be inserted. | 754 Keyword :type can be `non-weak' (default), `weak', `key-weak' or `value-weak'. |
801 This number of entries can be inserted without enlarging the hash table. | |
802 | |
803 Keyword :rehash-size must be a float greater than 1.0, and specifies | |
804 the factor by which to increase the size of the hash table when enlarging. | |
805 | |
806 Keyword :rehash-threshold must be a float between 0.0 and 1.0, | |
807 and specifies the load factor of the hash table which triggers enlarging. | |
808 | |
809 Non-standard keyword :weakness can be `nil' (default), `t', `key', `value' | |
810 or `key-value'. | |
811 | 755 |
812 A weak hash table is one whose pointers do not count as GC referents: | 756 A weak hash table is one whose pointers do not count as GC referents: |
813 for any key-value pair in the hash table, if the only remaining pointer | 757 for any key-value pair in the hash table, if the only remaining pointer |
814 to either the key or the value is in a weak hash table, then the pair | 758 to either the key or the value is in a weak hash table, then the pair |
815 will be removed from the hash table, and the key and value collected. | 759 will be removed from the hash table, and the key and value collected. |
826 that a key-value pair will be removed only if the value remains | 770 that a key-value pair will be removed only if the value remains |
827 unmarked outside of weak hash tables. The pair will remain in the | 771 unmarked outside of weak hash tables. The pair will remain in the |
828 hash table if the value is pointed to by something other than a weak | 772 hash table if the value is pointed to by something other than a weak |
829 hash table, even if the key is not. | 773 hash table, even if the key is not. |
830 | 774 |
831 A key-value-weak hash table is similar to a fully-weak hash table except | 775 Keyword :rehash-size must be a float greater than 1.0, and specifies |
832 that a key-value pair will be removed only if the value and the key remain | 776 the factor by which to increase the size of the hash table when enlarging. |
833 unmarked outside of weak hash tables. The pair will remain in the | 777 |
834 hash table if the value or key are pointed to by something other than a weak | 778 Keyword :rehash-threshold must be a float between 0.0 and 1.0, |
835 hash table, even if the other is not. | 779 and specifies the load factor of the hash table which triggers enlarging. |
780 | |
836 */ | 781 */ |
837 (int nargs, Lisp_Object *args)) | 782 (int nargs, Lisp_Object *args)) |
838 { | 783 { |
839 int i = 0; | 784 int j = 0; |
785 Lisp_Object size = Qnil; | |
786 Lisp_Object type = Qnil; | |
840 Lisp_Object test = Qnil; | 787 Lisp_Object test = Qnil; |
841 Lisp_Object size = Qnil; | |
842 Lisp_Object rehash_size = Qnil; | 788 Lisp_Object rehash_size = Qnil; |
843 Lisp_Object rehash_threshold = Qnil; | 789 Lisp_Object rehash_threshold = Qnil; |
844 Lisp_Object weakness = Qnil; | 790 |
845 | 791 while (j < nargs) |
846 while (i + 1 < nargs) | 792 { |
847 { | 793 Lisp_Object keyword, value; |
848 Lisp_Object keyword = args[i++]; | 794 |
849 Lisp_Object value = args[i++]; | 795 keyword = args[j++]; |
850 | 796 if (!KEYWORDP (keyword)) |
851 if (EQ (keyword, Q_test)) test = value; | 797 signal_simple_error ("Invalid hash table property keyword", keyword); |
852 else if (EQ (keyword, Q_size)) size = value; | 798 if (j == nargs) |
799 signal_simple_error ("Hash table property requires a value", keyword); | |
800 | |
801 value = args[j++]; | |
802 | |
803 if (EQ (keyword, Q_size)) size = value; | |
804 else if (EQ (keyword, Q_type)) type = value; | |
805 else if (EQ (keyword, Q_test)) test = value; | |
853 else if (EQ (keyword, Q_rehash_size)) rehash_size = value; | 806 else if (EQ (keyword, Q_rehash_size)) rehash_size = value; |
854 else if (EQ (keyword, Q_rehash_threshold)) rehash_threshold = value; | 807 else if (EQ (keyword, Q_rehash_threshold)) rehash_threshold = value; |
855 else if (EQ (keyword, Q_weakness)) weakness = value; | |
856 else if (EQ (keyword, Q_type))/*obsolete*/ weakness = value; | |
857 else signal_simple_error ("Invalid hash table property keyword", keyword); | 808 else signal_simple_error ("Invalid hash table property keyword", keyword); |
858 } | 809 } |
859 | |
860 if (i < nargs) | |
861 signal_simple_error ("Hash table property requires a value", args[i]); | |
862 | 810 |
863 #define VALIDATE_VAR(var) \ | 811 #define VALIDATE_VAR(var) \ |
864 if (!NILP (var)) hash_table_##var##_validate (Q##var, var, ERROR_ME); | 812 if (!NILP (var)) hash_table_##var##_validate (Q##var, var, ERROR_ME); |
865 | 813 |
814 VALIDATE_VAR (size); | |
815 VALIDATE_VAR (type); | |
866 VALIDATE_VAR (test); | 816 VALIDATE_VAR (test); |
867 VALIDATE_VAR (size); | |
868 VALIDATE_VAR (rehash_size); | 817 VALIDATE_VAR (rehash_size); |
869 VALIDATE_VAR (rehash_threshold); | 818 VALIDATE_VAR (rehash_threshold); |
870 VALIDATE_VAR (weakness); | |
871 | 819 |
872 return make_general_lisp_hash_table | 820 return make_general_lisp_hash_table |
873 (decode_hash_table_test (test), | 821 (decode_hash_table_size (size), |
874 decode_hash_table_size (size), | 822 decode_hash_table_type (type), |
823 decode_hash_table_test (test), | |
875 decode_hash_table_rehash_size (rehash_size), | 824 decode_hash_table_rehash_size (rehash_size), |
876 decode_hash_table_rehash_threshold (rehash_threshold), | 825 decode_hash_table_rehash_threshold (rehash_threshold)); |
877 decode_hash_table_weakness (weakness)); | |
878 } | 826 } |
879 | 827 |
880 DEFUN ("copy-hash-table", Fcopy_hash_table, 1, 1, 0, /* | 828 DEFUN ("copy-hash-table", Fcopy_hash_table, 1, 1, 0, /* |
881 Return a new hash table containing the same keys and values as HASH-TABLE. | 829 Return a new hash table containing the same keys and values as HASH-TABLE. |
882 The keys and values will not themselves be copied. | 830 The keys and values will not themselves be copied. |
883 */ | 831 */ |
884 (hash_table)) | 832 (hash_table)) |
885 { | 833 { |
886 const Lisp_Hash_Table *ht_old = xhash_table (hash_table); | 834 CONST Lisp_Hash_Table *ht_old = xhash_table (hash_table); |
887 Lisp_Hash_Table *ht = alloc_lcrecord_type (Lisp_Hash_Table, &lrecord_hash_table); | 835 Lisp_Hash_Table *ht = alloc_lcrecord_type (Lisp_Hash_Table, &lrecord_hash_table); |
888 | 836 |
889 copy_lcrecord (ht, ht_old); | 837 copy_lcrecord (ht, ht_old); |
890 | 838 |
891 ht->hentries = xnew_array (hentry, ht_old->size + 1); | 839 ht->hentries = xnew_array (hentry, ht_old->size + 1); |
901 | 849 |
902 return hash_table; | 850 return hash_table; |
903 } | 851 } |
904 | 852 |
905 static void | 853 static void |
906 resize_hash_table (Lisp_Hash_Table *ht, size_t new_size) | 854 enlarge_hash_table (Lisp_Hash_Table *ht) |
907 { | 855 { |
908 hentry *old_entries, *new_entries, *sentinel, *e; | 856 hentry *old_entries, *new_entries, *old_sentinel, *new_sentinel, *e; |
909 size_t old_size; | 857 size_t old_size, new_size; |
910 | 858 |
911 old_size = ht->size; | 859 old_size = ht->size; |
912 ht->size = new_size; | 860 new_size = ht->size = |
861 hash_table_size ((size_t) ((double) old_size * ht->rehash_size)); | |
913 | 862 |
914 old_entries = ht->hentries; | 863 old_entries = ht->hentries; |
915 | 864 |
916 ht->hentries = xnew_array_and_zero (hentry, new_size + 1); | 865 ht->hentries = xnew_array (hentry, new_size + 1); |
917 new_entries = ht->hentries; | 866 new_entries = ht->hentries; |
918 | 867 |
868 old_sentinel = old_entries + old_size; | |
869 new_sentinel = new_entries + new_size; | |
870 | |
871 for (e = new_entries; e <= new_sentinel; e++) | |
872 CLEAR_HENTRY (e); | |
873 | |
919 compute_hash_table_derived_values (ht); | 874 compute_hash_table_derived_values (ht); |
920 | 875 |
921 for (e = old_entries, sentinel = e + old_size; e < sentinel; e++) | 876 for (e = old_entries; e < old_sentinel; e++) |
922 if (!HENTRY_CLEAR_P (e)) | 877 if (!HENTRY_CLEAR_P (e)) |
923 { | 878 { |
924 hentry *probe = new_entries + HASH_CODE (e->key, ht); | 879 hentry *probe = new_entries + HASH_CODE (e->key, ht); |
925 LINEAR_PROBING_LOOP (probe, new_entries, new_size) | 880 LINEAR_PROBING_LOOP (probe, new_entries, new_size) |
926 ; | 881 ; |
927 *probe = *e; | 882 *probe = *e; |
928 } | 883 } |
929 | 884 |
930 if (!DUMPEDP (old_entries)) | 885 xfree (old_entries); |
931 xfree (old_entries); | |
932 } | |
933 | |
934 /* After a hash table has been saved to disk and later restored by the | |
935 portable dumper, it contains the same objects, but their addresses | |
936 and thus their HASH_CODEs have changed. */ | |
937 void | |
938 pdump_reorganize_hash_table (Lisp_Object hash_table) | |
939 { | |
940 const Lisp_Hash_Table *ht = xhash_table (hash_table); | |
941 hentry *new_entries = xnew_array_and_zero (hentry, ht->size + 1); | |
942 hentry *e, *sentinel; | |
943 | |
944 for (e = ht->hentries, sentinel = e + ht->size; e < sentinel; e++) | |
945 if (!HENTRY_CLEAR_P (e)) | |
946 { | |
947 hentry *probe = new_entries + HASH_CODE (e->key, ht); | |
948 LINEAR_PROBING_LOOP (probe, new_entries, ht->size) | |
949 ; | |
950 *probe = *e; | |
951 } | |
952 | |
953 memcpy (ht->hentries, new_entries, ht->size * sizeof (hentry)); | |
954 | |
955 xfree (new_entries); | |
956 } | |
957 | |
958 static void | |
959 enlarge_hash_table (Lisp_Hash_Table *ht) | |
960 { | |
961 size_t new_size = | |
962 hash_table_size ((size_t) ((double) ht->size * ht->rehash_size)); | |
963 resize_hash_table (ht, new_size); | |
964 } | 886 } |
965 | 887 |
966 static hentry * | 888 static hentry * |
967 find_hentry (Lisp_Object key, const Lisp_Hash_Table *ht) | 889 find_hentry (Lisp_Object key, CONST Lisp_Hash_Table *ht) |
968 { | 890 { |
969 hash_table_test_function_t test_function = ht->test_function; | 891 hash_table_test_function_t test_function = ht->test_function; |
970 hentry *entries = ht->hentries; | 892 hentry *entries = ht->hentries; |
971 hentry *probe = entries + HASH_CODE (key, ht); | 893 hentry *probe = entries + HASH_CODE (key, ht); |
972 | 894 |
981 Find hash value for KEY in HASH-TABLE. | 903 Find hash value for KEY in HASH-TABLE. |
982 If there is no corresponding value, return DEFAULT (which defaults to nil). | 904 If there is no corresponding value, return DEFAULT (which defaults to nil). |
983 */ | 905 */ |
984 (key, hash_table, default_)) | 906 (key, hash_table, default_)) |
985 { | 907 { |
986 const Lisp_Hash_Table *ht = xhash_table (hash_table); | 908 CONST Lisp_Hash_Table *ht = xhash_table (hash_table); |
987 hentry *e = find_hentry (key, ht); | 909 hentry *e = find_hentry (key, ht); |
988 | 910 |
989 return HENTRY_CLEAR_P (e) ? default_ : e->value; | 911 return HENTRY_CLEAR_P (e) ? default_ : e->value; |
990 } | 912 } |
991 | 913 |
1014 We don't use tombstones - too wasteful. */ | 936 We don't use tombstones - too wasteful. */ |
1015 static void | 937 static void |
1016 remhash_1 (Lisp_Hash_Table *ht, hentry *entries, hentry *probe) | 938 remhash_1 (Lisp_Hash_Table *ht, hentry *entries, hentry *probe) |
1017 { | 939 { |
1018 size_t size = ht->size; | 940 size_t size = ht->size; |
1019 CLEAR_HENTRY (probe); | 941 CLEAR_HENTRY (probe++); |
1020 probe++; | |
1021 ht->count--; | 942 ht->count--; |
1022 | 943 |
1023 LINEAR_PROBING_LOOP (probe, entries, size) | 944 LINEAR_PROBING_LOOP (probe, entries, size) |
1024 { | 945 { |
1025 Lisp_Object key = probe->key; | 946 Lisp_Object key = probe->key; |
1076 (hash_table)) | 997 (hash_table)) |
1077 { | 998 { |
1078 return make_int (xhash_table (hash_table)->count); | 999 return make_int (xhash_table (hash_table)->count); |
1079 } | 1000 } |
1080 | 1001 |
1002 DEFUN ("hash-table-size", Fhash_table_size, 1, 1, 0, /* | |
1003 Return the size of HASH-TABLE. | |
1004 This is the current number of slots in HASH-TABLE, whether occupied or not. | |
1005 */ | |
1006 (hash_table)) | |
1007 { | |
1008 return make_int (xhash_table (hash_table)->size); | |
1009 } | |
1010 | |
1011 DEFUN ("hash-table-type", Fhash_table_type, 1, 1, 0, /* | |
1012 Return the type of HASH-TABLE. | |
1013 This can be one of `non-weak', `weak', `key-weak' or `value-weak'. | |
1014 */ | |
1015 (hash_table)) | |
1016 { | |
1017 switch (xhash_table (hash_table)->type) | |
1018 { | |
1019 case HASH_TABLE_WEAK: return Qweak; | |
1020 case HASH_TABLE_KEY_WEAK: return Qkey_weak; | |
1021 case HASH_TABLE_VALUE_WEAK: return Qvalue_weak; | |
1022 default: return Qnon_weak; | |
1023 } | |
1024 } | |
1025 | |
1081 DEFUN ("hash-table-test", Fhash_table_test, 1, 1, 0, /* | 1026 DEFUN ("hash-table-test", Fhash_table_test, 1, 1, 0, /* |
1082 Return the test function of HASH-TABLE. | 1027 Return the test function of HASH-TABLE. |
1083 This can be one of `eq', `eql' or `equal'. | 1028 This can be one of `eq', `eql' or `equal'. |
1084 */ | 1029 */ |
1085 (hash_table)) | 1030 (hash_table)) |
1087 hash_table_test_function_t fun = xhash_table (hash_table)->test_function; | 1032 hash_table_test_function_t fun = xhash_table (hash_table)->test_function; |
1088 | 1033 |
1089 return (fun == lisp_object_eql_equal ? Qeql : | 1034 return (fun == lisp_object_eql_equal ? Qeql : |
1090 fun == lisp_object_equal_equal ? Qequal : | 1035 fun == lisp_object_equal_equal ? Qequal : |
1091 Qeq); | 1036 Qeq); |
1092 } | |
1093 | |
1094 DEFUN ("hash-table-size", Fhash_table_size, 1, 1, 0, /* | |
1095 Return the size of HASH-TABLE. | |
1096 This is the current number of slots in HASH-TABLE, whether occupied or not. | |
1097 */ | |
1098 (hash_table)) | |
1099 { | |
1100 return make_int (xhash_table (hash_table)->size); | |
1101 } | 1037 } |
1102 | 1038 |
1103 DEFUN ("hash-table-rehash-size", Fhash_table_rehash_size, 1, 1, 0, /* | 1039 DEFUN ("hash-table-rehash-size", Fhash_table_rehash_size, 1, 1, 0, /* |
1104 Return the current rehash size of HASH-TABLE. | 1040 Return the current rehash size of HASH-TABLE. |
1105 This is a float greater than 1.0; the factor by which HASH-TABLE | 1041 This is a float greater than 1.0; the factor by which HASH-TABLE |
1115 This is a float between 0.0 and 1.0; the maximum `load factor' of HASH-TABLE, | 1051 This is a float between 0.0 and 1.0; the maximum `load factor' of HASH-TABLE, |
1116 beyond which the HASH-TABLE is enlarged by rehashing. | 1052 beyond which the HASH-TABLE is enlarged by rehashing. |
1117 */ | 1053 */ |
1118 (hash_table)) | 1054 (hash_table)) |
1119 { | 1055 { |
1120 return make_float (xhash_table (hash_table)->rehash_threshold); | 1056 return make_float (hash_table_rehash_threshold (xhash_table (hash_table))); |
1121 } | |
1122 | |
1123 DEFUN ("hash-table-weakness", Fhash_table_weakness, 1, 1, 0, /* | |
1124 Return the weakness of HASH-TABLE. | |
1125 This can be one of `nil', `t', `key' or `value'. | |
1126 */ | |
1127 (hash_table)) | |
1128 { | |
1129 switch (xhash_table (hash_table)->weakness) | |
1130 { | |
1131 case HASH_TABLE_WEAK: return Qt; | |
1132 case HASH_TABLE_KEY_WEAK: return Qkey; | |
1133 case HASH_TABLE_KEY_VALUE_WEAK: return Qkey_value; | |
1134 case HASH_TABLE_VALUE_WEAK: return Qvalue; | |
1135 default: return Qnil; | |
1136 } | |
1137 } | |
1138 | |
1139 /* obsolete as of 19990901 in xemacs-21.2 */ | |
1140 DEFUN ("hash-table-type", Fhash_table_type, 1, 1, 0, /* | |
1141 Return the type of HASH-TABLE. | |
1142 This can be one of `non-weak', `weak', `key-weak' or `value-weak'. | |
1143 */ | |
1144 (hash_table)) | |
1145 { | |
1146 switch (xhash_table (hash_table)->weakness) | |
1147 { | |
1148 case HASH_TABLE_WEAK: return Qweak; | |
1149 case HASH_TABLE_KEY_WEAK: return Qkey_weak; | |
1150 case HASH_TABLE_KEY_VALUE_WEAK: return Qkey_value_weak; | |
1151 case HASH_TABLE_VALUE_WEAK: return Qvalue_weak; | |
1152 default: return Qnon_weak; | |
1153 } | |
1154 } | 1057 } |
1155 | 1058 |
1156 /************************************************************************/ | 1059 /************************************************************************/ |
1157 /* Mapping Functions */ | 1060 /* Mapping Functions */ |
1158 /************************************************************************/ | 1061 /************************************************************************/ |
1163 FUNCTION may not modify HASH-TABLE, with the one exception that FUNCTION | 1066 FUNCTION may not modify HASH-TABLE, with the one exception that FUNCTION |
1164 may remhash or puthash the entry currently being processed by FUNCTION. | 1067 may remhash or puthash the entry currently being processed by FUNCTION. |
1165 */ | 1068 */ |
1166 (function, hash_table)) | 1069 (function, hash_table)) |
1167 { | 1070 { |
1168 const Lisp_Hash_Table *ht = xhash_table (hash_table); | 1071 CONST Lisp_Hash_Table *ht = xhash_table (hash_table); |
1169 const hentry *e, *sentinel; | 1072 CONST hentry *e, *sentinel; |
1170 | 1073 |
1171 for (e = ht->hentries, sentinel = e + ht->size; e < sentinel; e++) | 1074 for (e = ht->hentries, sentinel = e + ht->size; e < sentinel; e++) |
1172 if (!HENTRY_CLEAR_P (e)) | 1075 if (!HENTRY_CLEAR_P (e)) |
1173 { | 1076 { |
1174 Lisp_Object args[3], key; | 1077 Lisp_Object args[3], key; |
1189 /* Map *C* function FUNCTION over the elements of a lisp hash table. */ | 1092 /* Map *C* function FUNCTION over the elements of a lisp hash table. */ |
1190 void | 1093 void |
1191 elisp_maphash (maphash_function_t function, | 1094 elisp_maphash (maphash_function_t function, |
1192 Lisp_Object hash_table, void *extra_arg) | 1095 Lisp_Object hash_table, void *extra_arg) |
1193 { | 1096 { |
1194 const Lisp_Hash_Table *ht = XHASH_TABLE (hash_table); | 1097 CONST Lisp_Hash_Table *ht = XHASH_TABLE (hash_table); |
1195 const hentry *e, *sentinel; | 1098 CONST hentry *e, *sentinel; |
1196 | 1099 |
1197 for (e = ht->hentries, sentinel = e + ht->size; e < sentinel; e++) | 1100 for (e = ht->hentries, sentinel = e + ht->size; e < sentinel; e++) |
1198 if (!HENTRY_CLEAR_P (e)) | 1101 if (!HENTRY_CLEAR_P (e)) |
1199 { | 1102 { |
1200 Lisp_Object key; | 1103 Lisp_Object key; |
1231 | 1134 |
1232 | 1135 |
1233 /************************************************************************/ | 1136 /************************************************************************/ |
1234 /* garbage collecting weak hash tables */ | 1137 /* garbage collecting weak hash tables */ |
1235 /************************************************************************/ | 1138 /************************************************************************/ |
1236 #define MARK_OBJ(obj) do { \ | |
1237 Lisp_Object mo_obj = (obj); \ | |
1238 if (!marked_p (mo_obj)) \ | |
1239 { \ | |
1240 mark_object (mo_obj); \ | |
1241 did_mark = 1; \ | |
1242 } \ | |
1243 } while (0) | |
1244 | |
1245 | 1139 |
1246 /* Complete the marking for semi-weak hash tables. */ | 1140 /* Complete the marking for semi-weak hash tables. */ |
1247 int | 1141 int |
1248 finish_marking_weak_hash_tables (void) | 1142 finish_marking_weak_hash_tables (int (*obj_marked_p) (Lisp_Object), |
1143 void (*markobj) (Lisp_Object)) | |
1249 { | 1144 { |
1250 Lisp_Object hash_table; | 1145 Lisp_Object hash_table; |
1251 int did_mark = 0; | 1146 int did_mark = 0; |
1252 | 1147 |
1253 for (hash_table = Vall_weak_hash_tables; | 1148 for (hash_table = Vall_weak_hash_tables; |
1254 !NILP (hash_table); | 1149 !GC_NILP (hash_table); |
1255 hash_table = XHASH_TABLE (hash_table)->next_weak) | 1150 hash_table = XHASH_TABLE (hash_table)->next_weak) |
1256 { | 1151 { |
1257 const Lisp_Hash_Table *ht = XHASH_TABLE (hash_table); | 1152 CONST Lisp_Hash_Table *ht = XHASH_TABLE (hash_table); |
1258 const hentry *e = ht->hentries; | 1153 CONST hentry *e = ht->hentries; |
1259 const hentry *sentinel = e + ht->size; | 1154 CONST hentry *sentinel = e + ht->size; |
1260 | 1155 |
1261 if (! marked_p (hash_table)) | 1156 if (! obj_marked_p (hash_table)) |
1262 /* The hash table is probably garbage. Ignore it. */ | 1157 /* The hash table is probably garbage. Ignore it. */ |
1263 continue; | 1158 continue; |
1264 | 1159 |
1265 /* Now, scan over all the pairs. For all pairs that are | 1160 /* Now, scan over all the pairs. For all pairs that are |
1266 half-marked, we may need to mark the other half if we're | 1161 half-marked, we may need to mark the other half if we're |
1267 keeping this pair. */ | 1162 keeping this pair. */ |
1268 switch (ht->weakness) | 1163 #define MARK_OBJ(obj) \ |
1164 do { if (!obj_marked_p (obj)) markobj (obj), did_mark = 1; } while (0) | |
1165 | |
1166 switch (ht->type) | |
1269 { | 1167 { |
1270 case HASH_TABLE_KEY_WEAK: | 1168 case HASH_TABLE_KEY_WEAK: |
1271 for (; e < sentinel; e++) | 1169 for (; e < sentinel; e++) |
1272 if (!HENTRY_CLEAR_P (e)) | 1170 if (!HENTRY_CLEAR_P (e)) |
1273 if (marked_p (e->key)) | 1171 if (obj_marked_p (e->key)) |
1274 MARK_OBJ (e->value); | 1172 MARK_OBJ (e->value); |
1275 break; | 1173 break; |
1276 | 1174 |
1277 case HASH_TABLE_VALUE_WEAK: | 1175 case HASH_TABLE_VALUE_WEAK: |
1278 for (; e < sentinel; e++) | 1176 for (; e < sentinel; e++) |
1279 if (!HENTRY_CLEAR_P (e)) | 1177 if (!HENTRY_CLEAR_P (e)) |
1280 if (marked_p (e->value)) | 1178 if (obj_marked_p (e->value)) |
1281 MARK_OBJ (e->key); | 1179 MARK_OBJ (e->key); |
1282 break; | |
1283 | |
1284 case HASH_TABLE_KEY_VALUE_WEAK: | |
1285 for (; e < sentinel; e++) | |
1286 if (!HENTRY_CLEAR_P (e)) | |
1287 { | |
1288 if (marked_p (e->value)) | |
1289 MARK_OBJ (e->key); | |
1290 else if (marked_p (e->key)) | |
1291 MARK_OBJ (e->value); | |
1292 } | |
1293 break; | 1180 break; |
1294 | 1181 |
1295 case HASH_TABLE_KEY_CAR_WEAK: | 1182 case HASH_TABLE_KEY_CAR_WEAK: |
1296 for (; e < sentinel; e++) | 1183 for (; e < sentinel; e++) |
1297 if (!HENTRY_CLEAR_P (e)) | 1184 if (!HENTRY_CLEAR_P (e)) |
1298 if (!CONSP (e->key) || marked_p (XCAR (e->key))) | 1185 if (!CONSP (e->key) || obj_marked_p (XCAR (e->key))) |
1299 { | 1186 { |
1300 MARK_OBJ (e->key); | 1187 MARK_OBJ (e->key); |
1301 MARK_OBJ (e->value); | 1188 MARK_OBJ (e->value); |
1302 } | 1189 } |
1303 break; | 1190 break; |
1304 | 1191 |
1305 case HASH_TABLE_VALUE_CAR_WEAK: | 1192 case HASH_TABLE_VALUE_CAR_WEAK: |
1306 for (; e < sentinel; e++) | 1193 for (; e < sentinel; e++) |
1307 if (!HENTRY_CLEAR_P (e)) | 1194 if (!HENTRY_CLEAR_P (e)) |
1308 if (!CONSP (e->value) || marked_p (XCAR (e->value))) | 1195 if (!CONSP (e->value) || obj_marked_p (XCAR (e->value))) |
1309 { | 1196 { |
1310 MARK_OBJ (e->key); | 1197 MARK_OBJ (e->key); |
1311 MARK_OBJ (e->value); | 1198 MARK_OBJ (e->value); |
1312 } | 1199 } |
1313 break; | 1200 break; |
1319 | 1206 |
1320 return did_mark; | 1207 return did_mark; |
1321 } | 1208 } |
1322 | 1209 |
1323 void | 1210 void |
1324 prune_weak_hash_tables (void) | 1211 prune_weak_hash_tables (int (*obj_marked_p) (Lisp_Object)) |
1325 { | 1212 { |
1326 Lisp_Object hash_table, prev = Qnil; | 1213 Lisp_Object hash_table, prev = Qnil; |
1327 for (hash_table = Vall_weak_hash_tables; | 1214 for (hash_table = Vall_weak_hash_tables; |
1328 !NILP (hash_table); | 1215 !GC_NILP (hash_table); |
1329 hash_table = XHASH_TABLE (hash_table)->next_weak) | 1216 hash_table = XHASH_TABLE (hash_table)->next_weak) |
1330 { | 1217 { |
1331 if (! marked_p (hash_table)) | 1218 if (! obj_marked_p (hash_table)) |
1332 { | 1219 { |
1333 /* This hash table itself is garbage. Remove it from the list. */ | 1220 /* This hash table itself is garbage. Remove it from the list. */ |
1334 if (NILP (prev)) | 1221 if (GC_NILP (prev)) |
1335 Vall_weak_hash_tables = XHASH_TABLE (hash_table)->next_weak; | 1222 Vall_weak_hash_tables = XHASH_TABLE (hash_table)->next_weak; |
1336 else | 1223 else |
1337 XHASH_TABLE (prev)->next_weak = XHASH_TABLE (hash_table)->next_weak; | 1224 XHASH_TABLE (prev)->next_weak = XHASH_TABLE (hash_table)->next_weak; |
1338 } | 1225 } |
1339 else | 1226 else |
1340 { | 1227 { |
1341 /* Now, scan over all the pairs. Remove all of the pairs | 1228 /* Now, scan over all the pairs. Remove all of the pairs |
1342 in which the key or value, or both, is unmarked | 1229 in which the key or value, or both, is unmarked |
1343 (depending on the weakness of the hash table). */ | 1230 (depending on the type of weak hash table). */ |
1344 Lisp_Hash_Table *ht = XHASH_TABLE (hash_table); | 1231 Lisp_Hash_Table *ht = XHASH_TABLE (hash_table); |
1345 hentry *entries = ht->hentries; | 1232 hentry *entries = ht->hentries; |
1346 hentry *sentinel = entries + ht->size; | 1233 hentry *sentinel = entries + ht->size; |
1347 hentry *e; | 1234 hentry *e; |
1348 | 1235 |
1349 for (e = entries; e < sentinel; e++) | 1236 for (e = entries; e < sentinel; e++) |
1350 if (!HENTRY_CLEAR_P (e)) | 1237 if (!HENTRY_CLEAR_P (e)) |
1351 { | 1238 { |
1352 again: | 1239 again: |
1353 if (!marked_p (e->key) || !marked_p (e->value)) | 1240 if (!obj_marked_p (e->key) || !obj_marked_p (e->value)) |
1354 { | 1241 { |
1355 remhash_1 (ht, entries, e); | 1242 remhash_1 (ht, entries, e); |
1356 if (!HENTRY_CLEAR_P (e)) | 1243 if (!HENTRY_CLEAR_P (e)) |
1357 goto again; | 1244 goto again; |
1358 } | 1245 } |
1367 | 1254 |
1368 hashcode_t | 1255 hashcode_t |
1369 internal_array_hash (Lisp_Object *arr, int size, int depth) | 1256 internal_array_hash (Lisp_Object *arr, int size, int depth) |
1370 { | 1257 { |
1371 int i; | 1258 int i; |
1372 hashcode_t hash = 0; | 1259 unsigned long hash = 0; |
1373 depth++; | |
1374 | 1260 |
1375 if (size <= 5) | 1261 if (size <= 5) |
1376 { | 1262 { |
1377 for (i = 0; i < size; i++) | 1263 for (i = 0; i < size; i++) |
1378 hash = HASH2 (hash, internal_hash (arr[i], depth)); | 1264 hash = HASH2 (hash, internal_hash (arr[i], depth + 1)); |
1379 return hash; | 1265 return hash; |
1380 } | 1266 } |
1381 | 1267 |
1382 /* just pick five elements scattered throughout the array. | 1268 /* just pick five elements scattered throughout the array. |
1383 A slightly better approach would be to offset by some | 1269 A slightly better approach would be to offset by some |
1384 noise factor from the points chosen below. */ | 1270 noise factor from the points chosen below. */ |
1385 for (i = 0; i < 5; i++) | 1271 for (i = 0; i < 5; i++) |
1386 hash = HASH2 (hash, internal_hash (arr[i*size/5], depth)); | 1272 hash = HASH2 (hash, internal_hash (arr[i*size/5], depth + 1)); |
1387 | 1273 |
1388 return hash; | 1274 return hash; |
1389 } | 1275 } |
1390 | 1276 |
1391 /* Return a hash value for a Lisp_Object. This is for use when hashing | 1277 /* Return a hash value for a Lisp_Object. This is for use when hashing |
1414 } | 1300 } |
1415 if (STRINGP (obj)) | 1301 if (STRINGP (obj)) |
1416 { | 1302 { |
1417 return hash_string (XSTRING_DATA (obj), XSTRING_LENGTH (obj)); | 1303 return hash_string (XSTRING_DATA (obj), XSTRING_LENGTH (obj)); |
1418 } | 1304 } |
1305 if (VECTORP (obj)) | |
1306 { | |
1307 return HASH2 (XVECTOR_LENGTH (obj), | |
1308 internal_array_hash (XVECTOR_DATA (obj), | |
1309 XVECTOR_LENGTH (obj), | |
1310 depth + 1)); | |
1311 } | |
1419 if (LRECORDP (obj)) | 1312 if (LRECORDP (obj)) |
1420 { | 1313 { |
1421 const struct lrecord_implementation | 1314 CONST struct lrecord_implementation |
1422 *imp = XRECORD_LHEADER_IMPLEMENTATION (obj); | 1315 *imp = XRECORD_LHEADER_IMPLEMENTATION (obj); |
1423 if (imp->hash) | 1316 if (imp->hash) |
1424 return imp->hash (obj, depth); | 1317 return imp->hash (obj, depth); |
1425 } | 1318 } |
1426 | 1319 |
1427 return LISP_HASH (obj); | 1320 return LISP_HASH (obj); |
1428 } | |
1429 | |
1430 DEFUN ("sxhash", Fsxhash, 1, 1, 0, /* | |
1431 Return a hash value for OBJECT. | |
1432 (equal obj1 obj2) implies (= (sxhash obj1) (sxhash obj2)). | |
1433 */ | |
1434 (object)) | |
1435 { | |
1436 return make_int (internal_hash (object, 0)); | |
1437 } | 1321 } |
1438 | 1322 |
1439 #if 0 | 1323 #if 0 |
1440 xxDEFUN ("internal-hash-value", Finternal_hash_value, 1, 1, 0, /* | 1324 xxDEFUN ("internal-hash-value", Finternal_hash_value, 1, 1, 0, /* |
1441 Hash value of OBJECT. For debugging. | 1325 Hash value of OBJECT. For debugging. |
1442 The value is returned as (HIGH . LOW). | 1326 The value is returned as (HIGH . LOW). |
1443 */ | 1327 */ |
1444 (object)) | 1328 (object)) |
1445 { | 1329 { |
1446 /* This function is pretty 32bit-centric. */ | 1330 /* This function is pretty 32bit-centric. */ |
1447 hashcode_t hash = internal_hash (object, 0); | 1331 unsigned long hash = internal_hash (object, 0); |
1448 return Fcons (hash >> 16, hash & 0xffff); | 1332 return Fcons (hash >> 16, hash & 0xffff); |
1449 } | 1333 } |
1450 #endif | 1334 #endif |
1451 | 1335 |
1452 | 1336 |
1455 /************************************************************************/ | 1339 /************************************************************************/ |
1456 | 1340 |
1457 void | 1341 void |
1458 syms_of_elhash (void) | 1342 syms_of_elhash (void) |
1459 { | 1343 { |
1460 INIT_LRECORD_IMPLEMENTATION (hash_table); | |
1461 | |
1462 DEFSUBR (Fhash_table_p); | 1344 DEFSUBR (Fhash_table_p); |
1463 DEFSUBR (Fmake_hash_table); | 1345 DEFSUBR (Fmake_hash_table); |
1464 DEFSUBR (Fcopy_hash_table); | 1346 DEFSUBR (Fcopy_hash_table); |
1465 DEFSUBR (Fgethash); | 1347 DEFSUBR (Fgethash); |
1466 DEFSUBR (Fremhash); | 1348 DEFSUBR (Fremhash); |
1467 DEFSUBR (Fputhash); | 1349 DEFSUBR (Fputhash); |
1468 DEFSUBR (Fclrhash); | 1350 DEFSUBR (Fclrhash); |
1469 DEFSUBR (Fmaphash); | 1351 DEFSUBR (Fmaphash); |
1470 DEFSUBR (Fhash_table_count); | 1352 DEFSUBR (Fhash_table_count); |
1471 DEFSUBR (Fhash_table_test); | |
1472 DEFSUBR (Fhash_table_size); | 1353 DEFSUBR (Fhash_table_size); |
1473 DEFSUBR (Fhash_table_rehash_size); | 1354 DEFSUBR (Fhash_table_rehash_size); |
1474 DEFSUBR (Fhash_table_rehash_threshold); | 1355 DEFSUBR (Fhash_table_rehash_threshold); |
1475 DEFSUBR (Fhash_table_weakness); | 1356 DEFSUBR (Fhash_table_type); |
1476 DEFSUBR (Fhash_table_type); /* obsolete */ | 1357 DEFSUBR (Fhash_table_test); |
1477 DEFSUBR (Fsxhash); | |
1478 #if 0 | 1358 #if 0 |
1479 DEFSUBR (Finternal_hash_value); | 1359 DEFSUBR (Finternal_hash_value); |
1480 #endif | 1360 #endif |
1481 | 1361 |
1482 defsymbol (&Qhash_tablep, "hash-table-p"); | 1362 defsymbol (&Qhash_tablep, "hash-table-p"); |
1483 defsymbol (&Qhash_table, "hash-table"); | 1363 defsymbol (&Qhash_table, "hash-table"); |
1484 defsymbol (&Qhashtable, "hashtable"); | 1364 defsymbol (&Qhashtable, "hashtable"); |
1485 defsymbol (&Qweakness, "weakness"); | 1365 defsymbol (&Qweak, "weak"); |
1486 defsymbol (&Qvalue, "value"); | 1366 defsymbol (&Qkey_weak, "key-weak"); |
1487 defsymbol (&Qkey_value, "key-value"); | 1367 defsymbol (&Qvalue_weak, "value-weak"); |
1368 defsymbol (&Qnon_weak, "non-weak"); | |
1488 defsymbol (&Qrehash_size, "rehash-size"); | 1369 defsymbol (&Qrehash_size, "rehash-size"); |
1489 defsymbol (&Qrehash_threshold, "rehash-threshold"); | 1370 defsymbol (&Qrehash_threshold, "rehash-threshold"); |
1490 | 1371 |
1491 defsymbol (&Qweak, "weak"); /* obsolete */ | 1372 defkeyword (&Q_size, ":size"); |
1492 defsymbol (&Qkey_weak, "key-weak"); /* obsolete */ | |
1493 defsymbol (&Qkey_value_weak, "key-value-weak"); /* obsolete */ | |
1494 defsymbol (&Qvalue_weak, "value-weak"); /* obsolete */ | |
1495 defsymbol (&Qnon_weak, "non-weak"); /* obsolete */ | |
1496 | |
1497 defkeyword (&Q_test, ":test"); | 1373 defkeyword (&Q_test, ":test"); |
1498 defkeyword (&Q_size, ":size"); | 1374 defkeyword (&Q_type, ":type"); |
1499 defkeyword (&Q_rehash_size, ":rehash-size"); | 1375 defkeyword (&Q_rehash_size, ":rehash-size"); |
1500 defkeyword (&Q_rehash_threshold, ":rehash-threshold"); | 1376 defkeyword (&Q_rehash_threshold, ":rehash-threshold"); |
1501 defkeyword (&Q_weakness, ":weakness"); | |
1502 defkeyword (&Q_type, ":type"); /* obsolete */ | |
1503 } | 1377 } |
1504 | 1378 |
1505 void | 1379 void |
1506 vars_of_elhash (void) | 1380 vars_of_elhash (void) |
1507 { | 1381 { |
1508 /* This must NOT be staticpro'd */ | 1382 /* This must NOT be staticpro'd */ |
1509 Vall_weak_hash_tables = Qnil; | 1383 Vall_weak_hash_tables = Qnil; |
1510 pdump_wire_list (&Vall_weak_hash_tables); | 1384 } |
1511 } |