428
|
1 /* Implementation of the hash table lisp object type.
|
|
2 Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc.
|
2421
|
3 Copyright (C) 1995, 1996, 2002, 2004 Ben Wing.
|
428
|
4 Copyright (C) 1997 Free Software Foundation, Inc.
|
|
5
|
|
6 This file is part of XEmacs.
|
|
7
|
|
8 XEmacs is free software; you can redistribute it and/or modify it
|
|
9 under the terms of the GNU General Public License as published by the
|
|
10 Free Software Foundation; either version 2, or (at your option) any
|
|
11 later version.
|
|
12
|
|
13 XEmacs is distributed in the hope that it will be useful, but WITHOUT
|
|
14 ANY WARRANTY; without even the implied warranty of MERCNTABILITY or
|
|
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
16 for more details.
|
|
17
|
|
18 You should have received a copy of the GNU General Public License
|
|
19 along with XEmacs; see the file COPYING. If not, write to
|
|
20 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
21 Boston, MA 02111-1307, USA. */
|
|
22
|
|
23 /* Synched up with: Not in FSF. */
|
|
24
|
1292
|
25 /* Author: Lost in the mists of history. At least back to Lucid 19.3,
|
|
26 circa Sep 1992. Early hash table implementation allowed only `eq' as a
|
|
27 test -- other tests possible only when these objects were created from
|
|
28 the C code.
|
|
29
|
|
30 Expansion to allow general `equal'-test Lisp-creatable tables, and hash
|
|
31 methods for the various Lisp objects in existence at the time, added
|
|
32 during 19.12 I think (early 1995?), by Ben Wing.
|
|
33
|
|
34 Weak hash tables added by Jamie (maybe?) early on, perhaps around 19.6,
|
|
35 maybe earlier; again, only possible through the C code, and only
|
|
36 supported fully weak hash tables. Expansion to other kinds of weakness,
|
|
37 and exporting of the interface to Lisp, by Ben Wing during 19.12
|
|
38 (early-mid 1995) or maybe 19.13 cycle (mid 1995).
|
|
39
|
|
40 Expansion to full Common Lisp spec and interface, redoing of the
|
|
41 implementation, by Martin Buchholz, 1997? (Former hash table
|
|
42 implementation used "double hashing", I'm pretty sure, and was weirdly
|
|
43 tied into the generic hash.c code. Martin completely separated them.)
|
|
44 */
|
|
45
|
489
|
46 /* This file implements the hash table lisp object type.
|
|
47
|
504
|
48 This implementation was mostly written by Martin Buchholz in 1997.
|
|
49
|
|
50 The Lisp-level API (derived from Common Lisp) is almost completely
|
|
51 compatible with GNU Emacs 21, even though the implementations are
|
|
52 totally independent.
|
|
53
|
489
|
54 The hash table technique used is "linear probing". Collisions are
|
|
55 resolved by putting the item in the next empty place in the array
|
|
56 following the collision. Finding a hash entry performs a linear
|
|
57 search in the cluster starting at the hash value.
|
|
58
|
|
59 On deletions from the hash table, the entries immediately following
|
|
60 the deleted entry are re-entered in the hash table. We do not have
|
|
61 a special way to mark deleted entries (known as "tombstones").
|
|
62
|
|
63 At the end of the hash entries ("hentries"), we leave room for an
|
|
64 entry that is always empty (the "sentinel").
|
|
65
|
|
66 The traditional literature on hash table implementation
|
|
67 (e.g. Knuth) suggests that too much "primary clustering" occurs
|
|
68 with linear probing. However, this literature was written when
|
|
69 locality of reference was not a factor. The discrepancy between
|
|
70 CPU speeds and memory speeds is increasing, and the speed of access
|
|
71 to memory is highly dependent on memory caches which work best when
|
|
72 there is high locality of data reference. Random access to memory
|
|
73 is up to 20 times as expensive as access to the nearest address
|
|
74 (and getting worse). So linear probing makes sense.
|
|
75
|
|
76 But the representation doesn't actually matter that much with the
|
|
77 current elisp engine. Funcall is sufficiently slow that the choice
|
|
78 of hash table implementation is noise. */
|
|
79
|
428
|
80 #include <config.h>
|
|
81 #include "lisp.h"
|
|
82 #include "bytecode.h"
|
|
83 #include "elhash.h"
|
489
|
84 #include "opaque.h"
|
428
|
85
|
|
86 Lisp_Object Qhash_tablep;
|
|
87 static Lisp_Object Qhashtable, Qhash_table;
|
442
|
88 static Lisp_Object Qweakness, Qvalue, Qkey_or_value, Qkey_and_value;
|
428
|
89 static Lisp_Object Vall_weak_hash_tables;
|
|
90 static Lisp_Object Qrehash_size, Qrehash_threshold;
|
|
91 static Lisp_Object Q_size, Q_test, Q_weakness, Q_rehash_size, Q_rehash_threshold;
|
|
92
|
|
93 /* obsolete as of 19990901 in xemacs-21.2 */
|
442
|
94 static Lisp_Object Qweak, Qkey_weak, Qvalue_weak, Qkey_or_value_weak;
|
|
95 static Lisp_Object Qnon_weak, Q_type;
|
428
|
96
|
|
97 struct Lisp_Hash_Table
|
|
98 {
|
3017
|
99 struct LCRECORD_HEADER header;
|
665
|
100 Elemcount size;
|
|
101 Elemcount count;
|
|
102 Elemcount rehash_count;
|
428
|
103 double rehash_size;
|
|
104 double rehash_threshold;
|
665
|
105 Elemcount golden_ratio;
|
428
|
106 hash_table_hash_function_t hash_function;
|
|
107 hash_table_test_function_t test_function;
|
1204
|
108 htentry *hentries;
|
428
|
109 enum hash_table_weakness weakness;
|
|
110 Lisp_Object next_weak; /* Used to chain together all of the weak
|
|
111 hash tables. Don't mark through this. */
|
|
112 };
|
|
113
|
1204
|
114 #define CLEAR_HTENTRY(htentry) \
|
|
115 ((*(EMACS_UINT*)(&((htentry)->key))) = 0, \
|
|
116 (*(EMACS_UINT*)(&((htentry)->value))) = 0)
|
428
|
117
|
|
118 #define HASH_TABLE_DEFAULT_SIZE 16
|
|
119 #define HASH_TABLE_DEFAULT_REHASH_SIZE 1.3
|
|
120 #define HASH_TABLE_MIN_SIZE 10
|
|
121
|
665
|
122 #define HASHCODE(key, ht) \
|
444
|
123 ((((ht)->hash_function ? (ht)->hash_function (key) : LISP_HASH (key)) \
|
|
124 * (ht)->golden_ratio) \
|
|
125 % (ht)->size)
|
428
|
126
|
|
127 #define KEYS_EQUAL_P(key1, key2, testfun) \
|
434
|
128 (EQ (key1, key2) || ((testfun) && (testfun) (key1, key2)))
|
428
|
129
|
|
130 #define LINEAR_PROBING_LOOP(probe, entries, size) \
|
|
131 for (; \
|
1204
|
132 !HTENTRY_CLEAR_P (probe) || \
|
428
|
133 (probe == entries + size ? \
|
1204
|
134 (probe = entries, !HTENTRY_CLEAR_P (probe)) : 0); \
|
428
|
135 probe++)
|
|
136
|
800
|
137 #ifdef ERROR_CHECK_STRUCTURES
|
428
|
138 static void
|
|
139 check_hash_table_invariants (Lisp_Hash_Table *ht)
|
|
140 {
|
|
141 assert (ht->count < ht->size);
|
|
142 assert (ht->count <= ht->rehash_count);
|
|
143 assert (ht->rehash_count < ht->size);
|
|
144 assert ((double) ht->count * ht->rehash_threshold - 1 <= (double) ht->rehash_count);
|
1204
|
145 assert (HTENTRY_CLEAR_P (ht->hentries + ht->size));
|
428
|
146 }
|
|
147 #else
|
|
148 #define check_hash_table_invariants(ht)
|
|
149 #endif
|
|
150
|
|
151 /* Return a suitable size for a hash table, with at least SIZE slots. */
|
665
|
152 static Elemcount
|
|
153 hash_table_size (Elemcount requested_size)
|
428
|
154 {
|
|
155 /* Return some prime near, but greater than or equal to, SIZE.
|
|
156 Decades from the time of writing, someone will have a system large
|
|
157 enough that the list below will be too short... */
|
665
|
158 static const Elemcount primes [] =
|
428
|
159 {
|
|
160 19, 29, 41, 59, 79, 107, 149, 197, 263, 347, 457, 599, 787, 1031,
|
|
161 1361, 1777, 2333, 3037, 3967, 5167, 6719, 8737, 11369, 14783,
|
|
162 19219, 24989, 32491, 42257, 54941, 71429, 92861, 120721, 156941,
|
|
163 204047, 265271, 344857, 448321, 582821, 757693, 985003, 1280519,
|
|
164 1664681, 2164111, 2813353, 3657361, 4754591, 6180989, 8035301,
|
|
165 10445899, 13579681, 17653589, 22949669, 29834603, 38784989,
|
|
166 50420551, 65546729, 85210757, 110774011, 144006217, 187208107,
|
|
167 243370577, 316381771, 411296309, 534685237, 695090819, 903618083,
|
647
|
168 1174703521, 1527114613, 1985248999 /* , 2580823717UL, 3355070839UL */
|
428
|
169 };
|
|
170 /* We've heard of binary search. */
|
|
171 int low, high;
|
|
172 for (low = 0, high = countof (primes) - 1; high - low > 1;)
|
|
173 {
|
|
174 /* Loop Invariant: size < primes [high] */
|
|
175 int mid = (low + high) / 2;
|
|
176 if (primes [mid] < requested_size)
|
|
177 low = mid;
|
|
178 else
|
|
179 high = mid;
|
|
180 }
|
|
181 return primes [high];
|
|
182 }
|
|
183
|
|
184
|
|
185 #if 0 /* I don't think these are needed any more.
|
|
186 If using the general lisp_object_equal_*() functions
|
|
187 causes efficiency problems, these can be resurrected. --ben */
|
|
188 /* equality and hash functions for Lisp strings */
|
|
189 int
|
|
190 lisp_string_equal (Lisp_Object str1, Lisp_Object str2)
|
|
191 {
|
|
192 /* This is wrong anyway. You can't use strcmp() on Lisp strings,
|
|
193 because they can contain zero characters. */
|
|
194 return !strcmp ((char *) XSTRING_DATA (str1), (char *) XSTRING_DATA (str2));
|
|
195 }
|
|
196
|
665
|
197 static Hashcode
|
428
|
198 lisp_string_hash (Lisp_Object obj)
|
|
199 {
|
|
200 return hash_string (XSTRING_DATA (str), XSTRING_LENGTH (str));
|
|
201 }
|
|
202
|
|
203 #endif /* 0 */
|
|
204
|
|
205 static int
|
|
206 lisp_object_eql_equal (Lisp_Object obj1, Lisp_Object obj2)
|
|
207 {
|
|
208 return EQ (obj1, obj2) || (FLOATP (obj1) && internal_equal (obj1, obj2, 0));
|
|
209 }
|
|
210
|
665
|
211 static Hashcode
|
428
|
212 lisp_object_eql_hash (Lisp_Object obj)
|
|
213 {
|
|
214 return FLOATP (obj) ? internal_hash (obj, 0) : LISP_HASH (obj);
|
|
215 }
|
|
216
|
|
217 static int
|
|
218 lisp_object_equal_equal (Lisp_Object obj1, Lisp_Object obj2)
|
|
219 {
|
|
220 return internal_equal (obj1, obj2, 0);
|
|
221 }
|
|
222
|
665
|
223 static Hashcode
|
428
|
224 lisp_object_equal_hash (Lisp_Object obj)
|
|
225 {
|
|
226 return internal_hash (obj, 0);
|
|
227 }
|
|
228
|
|
229
|
|
230 static Lisp_Object
|
|
231 mark_hash_table (Lisp_Object obj)
|
|
232 {
|
|
233 Lisp_Hash_Table *ht = XHASH_TABLE (obj);
|
|
234
|
|
235 /* If the hash table is weak, we don't want to mark the keys and
|
|
236 values (we scan over them after everything else has been marked,
|
|
237 and mark or remove them as necessary). */
|
|
238 if (ht->weakness == HASH_TABLE_NON_WEAK)
|
|
239 {
|
1204
|
240 htentry *e, *sentinel;
|
428
|
241
|
|
242 for (e = ht->hentries, sentinel = e + ht->size; e < sentinel; e++)
|
1204
|
243 if (!HTENTRY_CLEAR_P (e))
|
428
|
244 {
|
|
245 mark_object (e->key);
|
|
246 mark_object (e->value);
|
|
247 }
|
|
248 }
|
|
249 return Qnil;
|
|
250 }
|
|
251
|
|
252 /* Equality of hash tables. Two hash tables are equal when they are of
|
|
253 the same weakness and test function, they have the same number of
|
|
254 elements, and for each key in the hash table, the values are `equal'.
|
|
255
|
|
256 This is similar to Common Lisp `equalp' of hash tables, with the
|
|
257 difference that CL requires the keys to be compared with the test
|
|
258 function, which we don't do. Doing that would require consing, and
|
|
259 consing is a bad idea in `equal'. Anyway, our method should provide
|
|
260 the same result -- if the keys are not equal according to the test
|
|
261 function, then Fgethash() in hash_table_equal_mapper() will fail. */
|
|
262 static int
|
|
263 hash_table_equal (Lisp_Object hash_table1, Lisp_Object hash_table2, int depth)
|
|
264 {
|
|
265 Lisp_Hash_Table *ht1 = XHASH_TABLE (hash_table1);
|
|
266 Lisp_Hash_Table *ht2 = XHASH_TABLE (hash_table2);
|
1204
|
267 htentry *e, *sentinel;
|
428
|
268
|
|
269 if ((ht1->test_function != ht2->test_function) ||
|
|
270 (ht1->weakness != ht2->weakness) ||
|
|
271 (ht1->count != ht2->count))
|
|
272 return 0;
|
|
273
|
|
274 depth++;
|
|
275
|
|
276 for (e = ht1->hentries, sentinel = e + ht1->size; e < sentinel; e++)
|
1204
|
277 if (!HTENTRY_CLEAR_P (e))
|
428
|
278 /* Look up the key in the other hash table, and compare the values. */
|
|
279 {
|
|
280 Lisp_Object value_in_other = Fgethash (e->key, hash_table2, Qunbound);
|
|
281 if (UNBOUNDP (value_in_other) ||
|
|
282 !internal_equal (e->value, value_in_other, depth))
|
|
283 return 0; /* Give up */
|
|
284 }
|
|
285
|
|
286 return 1;
|
|
287 }
|
442
|
288
|
|
289 /* This is not a great hash function, but it _is_ correct and fast.
|
|
290 Examining all entries is too expensive, and examining a random
|
|
291 subset does not yield a correct hash function. */
|
665
|
292 static Hashcode
|
2286
|
293 hash_table_hash (Lisp_Object hash_table, int UNUSED (depth))
|
442
|
294 {
|
|
295 return XHASH_TABLE (hash_table)->count;
|
|
296 }
|
|
297
|
428
|
298
|
|
299 /* Printing hash tables.
|
|
300
|
|
301 This is non-trivial, because we use a readable structure-style
|
|
302 syntax for hash tables. This means that a typical hash table will be
|
|
303 readably printed in the form of:
|
|
304
|
|
305 #s(hash-table size 2 data (key1 value1 key2 value2))
|
|
306
|
|
307 The supported hash table structure keywords and their values are:
|
|
308 `test' (eql (or nil), eq or equal)
|
|
309 `size' (a natnum or nil)
|
|
310 `rehash-size' (a float)
|
|
311 `rehash-threshold' (a float)
|
442
|
312 `weakness' (nil, key, value, key-and-value, or key-or-value)
|
428
|
313 `data' (a list)
|
|
314
|
430
|
315 If `print-readably' is nil, then a simpler syntax is used, for example
|
428
|
316
|
|
317 #<hash-table size 2/13 data (key1 value1 key2 value2) 0x874d>
|
|
318
|
|
319 The data is truncated to four pairs, and the rest is shown with
|
|
320 `...'. This printer does not cons. */
|
|
321
|
|
322
|
|
323 /* Print the data of the hash table. This maps through a Lisp
|
|
324 hash table and prints key/value pairs using PRINTCHARFUN. */
|
|
325 static void
|
|
326 print_hash_table_data (Lisp_Hash_Table *ht, Lisp_Object printcharfun)
|
|
327 {
|
|
328 int count = 0;
|
1204
|
329 htentry *e, *sentinel;
|
428
|
330
|
826
|
331 write_c_string (printcharfun, " data (");
|
428
|
332
|
|
333 for (e = ht->hentries, sentinel = e + ht->size; e < sentinel; e++)
|
1204
|
334 if (!HTENTRY_CLEAR_P (e))
|
428
|
335 {
|
|
336 if (count > 0)
|
826
|
337 write_c_string (printcharfun, " ");
|
428
|
338 if (!print_readably && count > 3)
|
|
339 {
|
826
|
340 write_c_string (printcharfun, "...");
|
428
|
341 break;
|
|
342 }
|
|
343 print_internal (e->key, printcharfun, 1);
|
800
|
344 write_fmt_string_lisp (printcharfun, " %S", 1, e->value);
|
428
|
345 count++;
|
|
346 }
|
|
347
|
826
|
348 write_c_string (printcharfun, ")");
|
428
|
349 }
|
|
350
|
|
351 static void
|
2286
|
352 print_hash_table (Lisp_Object obj, Lisp_Object printcharfun,
|
|
353 int UNUSED (escapeflag))
|
428
|
354 {
|
|
355 Lisp_Hash_Table *ht = XHASH_TABLE (obj);
|
|
356
|
826
|
357 write_c_string (printcharfun,
|
|
358 print_readably ? "#s(hash-table" : "#<hash-table");
|
428
|
359
|
|
360 /* These checks have a kludgy look to them, but they are safe.
|
|
361 Due to nature of hashing, you cannot use arbitrary
|
|
362 test functions anyway. */
|
|
363 if (!ht->test_function)
|
826
|
364 write_c_string (printcharfun, " test eq");
|
428
|
365 else if (ht->test_function == lisp_object_equal_equal)
|
826
|
366 write_c_string (printcharfun, " test equal");
|
428
|
367 else if (ht->test_function == lisp_object_eql_equal)
|
|
368 DO_NOTHING;
|
|
369 else
|
2500
|
370 ABORT ();
|
428
|
371
|
|
372 if (ht->count || !print_readably)
|
|
373 {
|
|
374 if (print_readably)
|
800
|
375 write_fmt_string (printcharfun, " size %ld", (long) ht->count);
|
428
|
376 else
|
800
|
377 write_fmt_string (printcharfun, " size %ld/%ld", (long) ht->count,
|
|
378 (long) ht->size);
|
428
|
379 }
|
|
380
|
|
381 if (ht->weakness != HASH_TABLE_NON_WEAK)
|
|
382 {
|
800
|
383 write_fmt_string
|
|
384 (printcharfun, " weakness %s",
|
|
385 (ht->weakness == HASH_TABLE_WEAK ? "key-and-value" :
|
|
386 ht->weakness == HASH_TABLE_KEY_WEAK ? "key" :
|
|
387 ht->weakness == HASH_TABLE_VALUE_WEAK ? "value" :
|
|
388 ht->weakness == HASH_TABLE_KEY_VALUE_WEAK ? "key-or-value" :
|
|
389 "you-d-better-not-see-this"));
|
428
|
390 }
|
|
391
|
|
392 if (ht->count)
|
|
393 print_hash_table_data (ht, printcharfun);
|
|
394
|
|
395 if (print_readably)
|
826
|
396 write_c_string (printcharfun, ")");
|
428
|
397 else
|
2421
|
398 write_fmt_string (printcharfun, " 0x%x>", ht->header.uid);
|
428
|
399 }
|
|
400
|
|
401 static void
|
3092
|
402 free_hentries (
|
|
403 #if defined (NEW_GC) && !defined (ERROR_CHECK_STRUCTURES)
|
|
404 htentry *UNUSED (hentries),
|
|
405 #else
|
|
406 htentry *hentries,
|
|
407 #endif
|
2333
|
408 #ifdef ERROR_CHECK_STRUCTURES
|
|
409 size_t size
|
3263
|
410 #else /* not (NEW_GC && ! ERROR_CHECK_STRUCTURES) */
|
2333
|
411 size_t UNUSED (size)
|
3263
|
412 #endif /* not (NEW_GC && ! ERROR_CHECK_STRUCTURES) */
|
2333
|
413 )
|
489
|
414 {
|
3092
|
415 #ifdef NEW_GC
|
|
416 #ifdef ERROR_CHECK_STRUCTURES
|
|
417 htentry *e, *sentinel;
|
|
418
|
|
419 for (e = hentries, sentinel = e + size; e < sentinel; e++)
|
|
420 mc_free (e);
|
|
421 #endif
|
|
422 #else /* not NEW_GC */
|
800
|
423 #ifdef ERROR_CHECK_STRUCTURES
|
489
|
424 /* Ensure a crash if other code uses the discarded entries afterwards. */
|
1204
|
425 htentry *e, *sentinel;
|
489
|
426
|
|
427 for (e = hentries, sentinel = e + size; e < sentinel; e++)
|
1204
|
428 * (unsigned long *) e = 0xdeadbeef; /* -559038737 base 10 */
|
489
|
429 #endif
|
|
430
|
|
431 if (!DUMPEDP (hentries))
|
1726
|
432 xfree (hentries, htentry *);
|
3092
|
433 #endif /* not NEW_GC */
|
489
|
434 }
|
|
435
|
3263
|
436 #ifndef NEW_GC
|
489
|
437 static void
|
428
|
438 finalize_hash_table (void *header, int for_disksave)
|
|
439 {
|
|
440 if (!for_disksave)
|
|
441 {
|
|
442 Lisp_Hash_Table *ht = (Lisp_Hash_Table *) header;
|
489
|
443 free_hentries (ht->hentries, ht->size);
|
428
|
444 ht->hentries = 0;
|
|
445 }
|
|
446 }
|
3263
|
447 #endif /* not NEW_GC */
|
428
|
448
|
1204
|
449 static const struct memory_description htentry_description_1[] = {
|
|
450 { XD_LISP_OBJECT, offsetof (htentry, key) },
|
|
451 { XD_LISP_OBJECT, offsetof (htentry, value) },
|
428
|
452 { XD_END }
|
|
453 };
|
|
454
|
1204
|
455 static const struct sized_memory_description htentry_description = {
|
|
456 sizeof (htentry),
|
|
457 htentry_description_1
|
428
|
458 };
|
|
459
|
3092
|
460 #ifdef NEW_GC
|
|
461 static const struct memory_description htentry_weak_description_1[] = {
|
|
462 { XD_LISP_OBJECT, offsetof (htentry, key), 0, { 0 }, XD_FLAG_NO_KKCC},
|
|
463 { XD_LISP_OBJECT, offsetof (htentry, value), 0, { 0 }, XD_FLAG_NO_KKCC},
|
|
464 { XD_END }
|
|
465 };
|
|
466
|
|
467 static const struct sized_memory_description htentry_weak_description = {
|
|
468 sizeof (htentry),
|
|
469 htentry_weak_description_1
|
|
470 };
|
|
471
|
|
472 DEFINE_LRECORD_IMPLEMENTATION ("hash-table-entry", hash_table_entry,
|
|
473 1, /*dumpable-flag*/
|
|
474 0, 0, 0, 0, 0,
|
|
475 htentry_description_1,
|
|
476 Lisp_Hash_Table_Entry);
|
|
477 #endif /* NEW_GC */
|
|
478
|
1204
|
479 static const struct memory_description htentry_union_description_1[] = {
|
|
480 /* Note: XD_INDIRECT in this table refers to the surrounding table,
|
|
481 and so this will work. */
|
3092
|
482 #ifdef NEW_GC
|
|
483 { XD_LISP_OBJECT_BLOCK_PTR, HASH_TABLE_NON_WEAK,
|
|
484 XD_INDIRECT (0, 1), { &htentry_description } },
|
|
485 { XD_LISP_OBJECT_BLOCK_PTR, 0, XD_INDIRECT (0, 1),
|
|
486 { &htentry_weak_description }, XD_FLAG_UNION_DEFAULT_ENTRY },
|
|
487 #else /* not NEW_GC */
|
2367
|
488 { XD_BLOCK_PTR, HASH_TABLE_NON_WEAK, XD_INDIRECT (0, 1),
|
2551
|
489 { &htentry_description } },
|
|
490 { XD_BLOCK_PTR, 0, XD_INDIRECT (0, 1), { &htentry_description },
|
1204
|
491 XD_FLAG_UNION_DEFAULT_ENTRY | XD_FLAG_NO_KKCC },
|
3092
|
492 #endif /* not NEW_GC */
|
1204
|
493 { XD_END }
|
|
494 };
|
|
495
|
|
496 static const struct sized_memory_description htentry_union_description = {
|
|
497 sizeof (htentry *),
|
|
498 htentry_union_description_1
|
|
499 };
|
|
500
|
|
501 const struct memory_description hash_table_description[] = {
|
|
502 { XD_ELEMCOUNT, offsetof (Lisp_Hash_Table, size) },
|
|
503 { XD_INT, offsetof (Lisp_Hash_Table, weakness) },
|
|
504 { XD_UNION, offsetof (Lisp_Hash_Table, hentries), XD_INDIRECT (1, 0),
|
2551
|
505 { &htentry_union_description } },
|
440
|
506 { XD_LO_LINK, offsetof (Lisp_Hash_Table, next_weak) },
|
428
|
507 { XD_END }
|
|
508 };
|
|
509
|
3263
|
510 #ifdef NEW_GC
|
|
511 DEFINE_LRECORD_IMPLEMENTATION ("hash-table", hash_table,
|
|
512 1, /*dumpable-flag*/
|
|
513 mark_hash_table, print_hash_table,
|
|
514 0, hash_table_equal, hash_table_hash,
|
|
515 hash_table_description,
|
|
516 Lisp_Hash_Table);
|
|
517 #else /* not NEW_GC */
|
934
|
518 DEFINE_LRECORD_IMPLEMENTATION ("hash-table", hash_table,
|
|
519 1, /*dumpable-flag*/
|
|
520 mark_hash_table, print_hash_table,
|
|
521 finalize_hash_table,
|
|
522 hash_table_equal, hash_table_hash,
|
|
523 hash_table_description,
|
|
524 Lisp_Hash_Table);
|
3263
|
525 #endif /* not NEW_GC */
|
428
|
526
|
|
527 static Lisp_Hash_Table *
|
|
528 xhash_table (Lisp_Object hash_table)
|
|
529 {
|
1123
|
530 /* #### What's going on here? Why the gc_in_progress check? */
|
428
|
531 if (!gc_in_progress)
|
|
532 CHECK_HASH_TABLE (hash_table);
|
|
533 check_hash_table_invariants (XHASH_TABLE (hash_table));
|
|
534 return XHASH_TABLE (hash_table);
|
|
535 }
|
|
536
|
|
537
|
|
538 /************************************************************************/
|
|
539 /* Creation of Hash Tables */
|
|
540 /************************************************************************/
|
|
541
|
|
542 /* Creation of hash tables, without error-checking. */
|
|
543 static void
|
|
544 compute_hash_table_derived_values (Lisp_Hash_Table *ht)
|
|
545 {
|
665
|
546 ht->rehash_count = (Elemcount)
|
438
|
547 ((double) ht->size * ht->rehash_threshold);
|
665
|
548 ht->golden_ratio = (Elemcount)
|
428
|
549 ((double) ht->size * (.6180339887 / (double) sizeof (Lisp_Object)));
|
|
550 }
|
|
551
|
|
552 Lisp_Object
|
450
|
553 make_standard_lisp_hash_table (enum hash_table_test test,
|
665
|
554 Elemcount size,
|
450
|
555 double rehash_size,
|
|
556 double rehash_threshold,
|
|
557 enum hash_table_weakness weakness)
|
|
558 {
|
462
|
559 hash_table_hash_function_t hash_function = 0;
|
450
|
560 hash_table_test_function_t test_function = 0;
|
|
561
|
|
562 switch (test)
|
|
563 {
|
|
564 case HASH_TABLE_EQ:
|
|
565 test_function = 0;
|
|
566 hash_function = 0;
|
|
567 break;
|
|
568
|
|
569 case HASH_TABLE_EQL:
|
|
570 test_function = lisp_object_eql_equal;
|
|
571 hash_function = lisp_object_eql_hash;
|
|
572 break;
|
|
573
|
|
574 case HASH_TABLE_EQUAL:
|
|
575 test_function = lisp_object_equal_equal;
|
|
576 hash_function = lisp_object_equal_hash;
|
|
577 break;
|
|
578
|
|
579 default:
|
2500
|
580 ABORT ();
|
450
|
581 }
|
|
582
|
|
583 return make_general_lisp_hash_table (hash_function, test_function,
|
|
584 size, rehash_size, rehash_threshold,
|
|
585 weakness);
|
|
586 }
|
|
587
|
|
588 Lisp_Object
|
|
589 make_general_lisp_hash_table (hash_table_hash_function_t hash_function,
|
|
590 hash_table_test_function_t test_function,
|
665
|
591 Elemcount size,
|
428
|
592 double rehash_size,
|
|
593 double rehash_threshold,
|
|
594 enum hash_table_weakness weakness)
|
|
595 {
|
|
596 Lisp_Object hash_table;
|
3017
|
597 Lisp_Hash_Table *ht = ALLOC_LCRECORD_TYPE (Lisp_Hash_Table, &lrecord_hash_table);
|
428
|
598
|
450
|
599 ht->test_function = test_function;
|
|
600 ht->hash_function = hash_function;
|
438
|
601 ht->weakness = weakness;
|
|
602
|
|
603 ht->rehash_size =
|
|
604 rehash_size > 1.0 ? rehash_size : HASH_TABLE_DEFAULT_REHASH_SIZE;
|
|
605
|
|
606 ht->rehash_threshold =
|
|
607 rehash_threshold > 0.0 ? rehash_threshold :
|
|
608 size > 4096 && !ht->test_function ? 0.7 : 0.6;
|
|
609
|
428
|
610 if (size < HASH_TABLE_MIN_SIZE)
|
|
611 size = HASH_TABLE_MIN_SIZE;
|
665
|
612 ht->size = hash_table_size ((Elemcount) (((double) size / ht->rehash_threshold)
|
438
|
613 + 1.0));
|
428
|
614 ht->count = 0;
|
438
|
615
|
428
|
616 compute_hash_table_derived_values (ht);
|
|
617
|
1204
|
618 /* We leave room for one never-occupied sentinel htentry at the end. */
|
3092
|
619 #ifdef NEW_GC
|
|
620 ht->hentries = (htentry *) alloc_lrecord_array (sizeof (htentry),
|
|
621 ht->size + 1,
|
|
622 &lrecord_hash_table_entry);
|
|
623 #else /* not NEW_GC */
|
1204
|
624 ht->hentries = xnew_array_and_zero (htentry, ht->size + 1);
|
3092
|
625 #endif /* not NEW_GC */
|
428
|
626
|
793
|
627 hash_table = wrap_hash_table (ht);
|
428
|
628
|
|
629 if (weakness == HASH_TABLE_NON_WEAK)
|
|
630 ht->next_weak = Qunbound;
|
|
631 else
|
|
632 ht->next_weak = Vall_weak_hash_tables, Vall_weak_hash_tables = hash_table;
|
|
633
|
|
634 return hash_table;
|
|
635 }
|
|
636
|
|
637 Lisp_Object
|
665
|
638 make_lisp_hash_table (Elemcount size,
|
428
|
639 enum hash_table_weakness weakness,
|
|
640 enum hash_table_test test)
|
|
641 {
|
450
|
642 return make_standard_lisp_hash_table (test, size, -1.0, -1.0, weakness);
|
428
|
643 }
|
|
644
|
|
645 /* Pretty reading of hash tables.
|
|
646
|
|
647 Here we use the existing structures mechanism (which is,
|
|
648 unfortunately, pretty cumbersome) for validating and instantiating
|
|
649 the hash tables. The idea is that the side-effect of reading a
|
|
650 #s(hash-table PLIST) object is creation of a hash table with desired
|
|
651 properties, and that the hash table is returned. */
|
|
652
|
|
653 /* Validation functions: each keyword provides its own validation
|
|
654 function. The errors should maybe be continuable, but it is
|
|
655 unclear how this would cope with ERRB. */
|
|
656 static int
|
2286
|
657 hash_table_size_validate (Lisp_Object UNUSED (keyword), Lisp_Object value,
|
|
658 Error_Behavior errb)
|
428
|
659 {
|
|
660 if (NATNUMP (value))
|
|
661 return 1;
|
|
662
|
563
|
663 maybe_signal_error_1 (Qwrong_type_argument, list2 (Qnatnump, value),
|
2286
|
664 Qhash_table, errb);
|
428
|
665 return 0;
|
|
666 }
|
|
667
|
665
|
668 static Elemcount
|
428
|
669 decode_hash_table_size (Lisp_Object obj)
|
|
670 {
|
|
671 return NILP (obj) ? HASH_TABLE_DEFAULT_SIZE : XINT (obj);
|
|
672 }
|
|
673
|
|
674 static int
|
2286
|
675 hash_table_weakness_validate (Lisp_Object UNUSED (keyword), Lisp_Object value,
|
578
|
676 Error_Behavior errb)
|
428
|
677 {
|
442
|
678 if (EQ (value, Qnil)) return 1;
|
|
679 if (EQ (value, Qt)) return 1;
|
|
680 if (EQ (value, Qkey)) return 1;
|
|
681 if (EQ (value, Qkey_and_value)) return 1;
|
|
682 if (EQ (value, Qkey_or_value)) return 1;
|
|
683 if (EQ (value, Qvalue)) return 1;
|
428
|
684
|
|
685 /* Following values are obsolete as of 19990901 in xemacs-21.2 */
|
442
|
686 if (EQ (value, Qnon_weak)) return 1;
|
|
687 if (EQ (value, Qweak)) return 1;
|
|
688 if (EQ (value, Qkey_weak)) return 1;
|
|
689 if (EQ (value, Qkey_or_value_weak)) return 1;
|
|
690 if (EQ (value, Qvalue_weak)) return 1;
|
428
|
691
|
563
|
692 maybe_invalid_constant ("Invalid hash table weakness",
|
428
|
693 value, Qhash_table, errb);
|
|
694 return 0;
|
|
695 }
|
|
696
|
|
697 static enum hash_table_weakness
|
|
698 decode_hash_table_weakness (Lisp_Object obj)
|
|
699 {
|
442
|
700 if (EQ (obj, Qnil)) return HASH_TABLE_NON_WEAK;
|
|
701 if (EQ (obj, Qt)) return HASH_TABLE_WEAK;
|
|
702 if (EQ (obj, Qkey_and_value)) return HASH_TABLE_WEAK;
|
|
703 if (EQ (obj, Qkey)) return HASH_TABLE_KEY_WEAK;
|
|
704 if (EQ (obj, Qkey_or_value)) return HASH_TABLE_KEY_VALUE_WEAK;
|
|
705 if (EQ (obj, Qvalue)) return HASH_TABLE_VALUE_WEAK;
|
428
|
706
|
|
707 /* Following values are obsolete as of 19990901 in xemacs-21.2 */
|
442
|
708 if (EQ (obj, Qnon_weak)) return HASH_TABLE_NON_WEAK;
|
|
709 if (EQ (obj, Qweak)) return HASH_TABLE_WEAK;
|
|
710 if (EQ (obj, Qkey_weak)) return HASH_TABLE_KEY_WEAK;
|
|
711 if (EQ (obj, Qkey_or_value_weak)) return HASH_TABLE_KEY_VALUE_WEAK;
|
|
712 if (EQ (obj, Qvalue_weak)) return HASH_TABLE_VALUE_WEAK;
|
428
|
713
|
563
|
714 invalid_constant ("Invalid hash table weakness", obj);
|
1204
|
715 RETURN_NOT_REACHED (HASH_TABLE_NON_WEAK);
|
428
|
716 }
|
|
717
|
|
718 static int
|
2286
|
719 hash_table_test_validate (Lisp_Object UNUSED (keyword), Lisp_Object value,
|
|
720 Error_Behavior errb)
|
428
|
721 {
|
|
722 if (EQ (value, Qnil)) return 1;
|
|
723 if (EQ (value, Qeq)) return 1;
|
|
724 if (EQ (value, Qequal)) return 1;
|
|
725 if (EQ (value, Qeql)) return 1;
|
|
726
|
563
|
727 maybe_invalid_constant ("Invalid hash table test",
|
2286
|
728 value, Qhash_table, errb);
|
428
|
729 return 0;
|
|
730 }
|
|
731
|
|
732 static enum hash_table_test
|
|
733 decode_hash_table_test (Lisp_Object obj)
|
|
734 {
|
|
735 if (EQ (obj, Qnil)) return HASH_TABLE_EQL;
|
|
736 if (EQ (obj, Qeq)) return HASH_TABLE_EQ;
|
|
737 if (EQ (obj, Qequal)) return HASH_TABLE_EQUAL;
|
|
738 if (EQ (obj, Qeql)) return HASH_TABLE_EQL;
|
|
739
|
563
|
740 invalid_constant ("Invalid hash table test", obj);
|
1204
|
741 RETURN_NOT_REACHED (HASH_TABLE_EQ);
|
428
|
742 }
|
|
743
|
|
744 static int
|
2286
|
745 hash_table_rehash_size_validate (Lisp_Object UNUSED (keyword),
|
|
746 Lisp_Object value, Error_Behavior errb)
|
428
|
747 {
|
|
748 if (!FLOATP (value))
|
|
749 {
|
563
|
750 maybe_signal_error_1 (Qwrong_type_argument, list2 (Qfloatp, value),
|
428
|
751 Qhash_table, errb);
|
|
752 return 0;
|
|
753 }
|
|
754
|
|
755 {
|
|
756 double rehash_size = XFLOAT_DATA (value);
|
|
757 if (rehash_size <= 1.0)
|
|
758 {
|
563
|
759 maybe_invalid_argument
|
428
|
760 ("Hash table rehash size must be greater than 1.0",
|
|
761 value, Qhash_table, errb);
|
|
762 return 0;
|
|
763 }
|
|
764 }
|
|
765
|
|
766 return 1;
|
|
767 }
|
|
768
|
|
769 static double
|
|
770 decode_hash_table_rehash_size (Lisp_Object rehash_size)
|
|
771 {
|
|
772 return NILP (rehash_size) ? -1.0 : XFLOAT_DATA (rehash_size);
|
|
773 }
|
|
774
|
|
775 static int
|
2286
|
776 hash_table_rehash_threshold_validate (Lisp_Object UNUSED (keyword),
|
|
777 Lisp_Object value, Error_Behavior errb)
|
428
|
778 {
|
|
779 if (!FLOATP (value))
|
|
780 {
|
563
|
781 maybe_signal_error_1 (Qwrong_type_argument, list2 (Qfloatp, value),
|
428
|
782 Qhash_table, errb);
|
|
783 return 0;
|
|
784 }
|
|
785
|
|
786 {
|
|
787 double rehash_threshold = XFLOAT_DATA (value);
|
|
788 if (rehash_threshold <= 0.0 || rehash_threshold >= 1.0)
|
|
789 {
|
563
|
790 maybe_invalid_argument
|
428
|
791 ("Hash table rehash threshold must be between 0.0 and 1.0",
|
|
792 value, Qhash_table, errb);
|
|
793 return 0;
|
|
794 }
|
|
795 }
|
|
796
|
|
797 return 1;
|
|
798 }
|
|
799
|
|
800 static double
|
|
801 decode_hash_table_rehash_threshold (Lisp_Object rehash_threshold)
|
|
802 {
|
|
803 return NILP (rehash_threshold) ? -1.0 : XFLOAT_DATA (rehash_threshold);
|
|
804 }
|
|
805
|
|
806 static int
|
2286
|
807 hash_table_data_validate (Lisp_Object UNUSED (keyword), Lisp_Object value,
|
|
808 Error_Behavior errb)
|
428
|
809 {
|
|
810 int len;
|
|
811
|
|
812 GET_EXTERNAL_LIST_LENGTH (value, len);
|
|
813
|
|
814 if (len & 1)
|
|
815 {
|
563
|
816 maybe_sferror
|
428
|
817 ("Hash table data must have alternating key/value pairs",
|
|
818 value, Qhash_table, errb);
|
|
819 return 0;
|
|
820 }
|
|
821 return 1;
|
|
822 }
|
|
823
|
|
824 /* The actual instantiation of a hash table. This does practically no
|
|
825 error checking, because it relies on the fact that the paranoid
|
|
826 functions above have error-checked everything to the last details.
|
|
827 If this assumption is wrong, we will get a crash immediately (with
|
|
828 error-checking compiled in), and we'll know if there is a bug in
|
|
829 the structure mechanism. So there. */
|
|
830 static Lisp_Object
|
|
831 hash_table_instantiate (Lisp_Object plist)
|
|
832 {
|
|
833 Lisp_Object hash_table;
|
|
834 Lisp_Object test = Qnil;
|
|
835 Lisp_Object size = Qnil;
|
|
836 Lisp_Object rehash_size = Qnil;
|
|
837 Lisp_Object rehash_threshold = Qnil;
|
|
838 Lisp_Object weakness = Qnil;
|
|
839 Lisp_Object data = Qnil;
|
|
840
|
2421
|
841 PROPERTY_LIST_LOOP_3 (key, value, plist)
|
428
|
842 {
|
|
843 if (EQ (key, Qtest)) test = value;
|
|
844 else if (EQ (key, Qsize)) size = value;
|
|
845 else if (EQ (key, Qrehash_size)) rehash_size = value;
|
|
846 else if (EQ (key, Qrehash_threshold)) rehash_threshold = value;
|
|
847 else if (EQ (key, Qweakness)) weakness = value;
|
|
848 else if (EQ (key, Qdata)) data = value;
|
|
849 else if (EQ (key, Qtype))/*obsolete*/ weakness = value;
|
|
850 else
|
2500
|
851 ABORT ();
|
428
|
852 }
|
|
853
|
|
854 /* Create the hash table. */
|
450
|
855 hash_table = make_standard_lisp_hash_table
|
428
|
856 (decode_hash_table_test (test),
|
|
857 decode_hash_table_size (size),
|
|
858 decode_hash_table_rehash_size (rehash_size),
|
|
859 decode_hash_table_rehash_threshold (rehash_threshold),
|
|
860 decode_hash_table_weakness (weakness));
|
|
861
|
|
862 /* I'm not sure whether this can GC, but better safe than sorry. */
|
|
863 {
|
|
864 struct gcpro gcpro1;
|
|
865 GCPRO1 (hash_table);
|
|
866
|
|
867 /* And fill it with data. */
|
|
868 while (!NILP (data))
|
|
869 {
|
|
870 Lisp_Object key, value;
|
|
871 key = XCAR (data); data = XCDR (data);
|
|
872 value = XCAR (data); data = XCDR (data);
|
|
873 Fputhash (key, value, hash_table);
|
|
874 }
|
|
875 UNGCPRO;
|
|
876 }
|
|
877
|
|
878 return hash_table;
|
|
879 }
|
|
880
|
|
881 static void
|
|
882 structure_type_create_hash_table_structure_name (Lisp_Object structure_name)
|
|
883 {
|
|
884 struct structure_type *st;
|
|
885
|
|
886 st = define_structure_type (structure_name, 0, hash_table_instantiate);
|
|
887 define_structure_type_keyword (st, Qtest, hash_table_test_validate);
|
|
888 define_structure_type_keyword (st, Qsize, hash_table_size_validate);
|
|
889 define_structure_type_keyword (st, Qrehash_size, hash_table_rehash_size_validate);
|
|
890 define_structure_type_keyword (st, Qrehash_threshold, hash_table_rehash_threshold_validate);
|
|
891 define_structure_type_keyword (st, Qweakness, hash_table_weakness_validate);
|
|
892 define_structure_type_keyword (st, Qdata, hash_table_data_validate);
|
|
893
|
|
894 /* obsolete as of 19990901 in xemacs-21.2 */
|
|
895 define_structure_type_keyword (st, Qtype, hash_table_weakness_validate);
|
|
896 }
|
|
897
|
|
898 /* Create a built-in Lisp structure type named `hash-table'.
|
|
899 We make #s(hashtable ...) equivalent to #s(hash-table ...),
|
|
900 for backward compatibility.
|
|
901 This is called from emacs.c. */
|
|
902 void
|
|
903 structure_type_create_hash_table (void)
|
|
904 {
|
|
905 structure_type_create_hash_table_structure_name (Qhash_table);
|
|
906 structure_type_create_hash_table_structure_name (Qhashtable); /* compat */
|
|
907 }
|
|
908
|
|
909
|
|
910 /************************************************************************/
|
|
911 /* Definition of Lisp-visible methods */
|
|
912 /************************************************************************/
|
|
913
|
|
914 DEFUN ("hash-table-p", Fhash_table_p, 1, 1, 0, /*
|
|
915 Return t if OBJECT is a hash table, else nil.
|
|
916 */
|
|
917 (object))
|
|
918 {
|
|
919 return HASH_TABLEP (object) ? Qt : Qnil;
|
|
920 }
|
|
921
|
|
922 DEFUN ("make-hash-table", Fmake_hash_table, 0, MANY, 0, /*
|
|
923 Return a new empty hash table object.
|
|
924 Use Common Lisp style keywords to specify hash table properties.
|
|
925 (make-hash-table &key test size rehash-size rehash-threshold weakness)
|
|
926
|
|
927 Keyword :test can be `eq', `eql' (default) or `equal'.
|
|
928 Comparison between keys is done using this function.
|
|
929 If speed is important, consider using `eq'.
|
|
930 When storing strings in the hash table, you will likely need to use `equal'.
|
|
931
|
|
932 Keyword :size specifies the number of keys likely to be inserted.
|
|
933 This number of entries can be inserted without enlarging the hash table.
|
|
934
|
|
935 Keyword :rehash-size must be a float greater than 1.0, and specifies
|
|
936 the factor by which to increase the size of the hash table when enlarging.
|
|
937
|
|
938 Keyword :rehash-threshold must be a float between 0.0 and 1.0,
|
|
939 and specifies the load factor of the hash table which triggers enlarging.
|
|
940
|
442
|
941 Non-standard keyword :weakness can be `nil' (default), `t', `key-and-value',
|
|
942 `key', `value' or `key-or-value'. `t' is an alias for `key-and-value'.
|
428
|
943
|
442
|
944 A key-and-value-weak hash table, also known as a fully-weak or simply
|
|
945 as a weak hash table, is one whose pointers do not count as GC
|
|
946 referents: for any key-value pair in the hash table, if the only
|
|
947 remaining pointer to either the key or the value is in a weak hash
|
|
948 table, then the pair will be removed from the hash table, and the key
|
|
949 and value collected. A non-weak hash table (or any other pointer)
|
|
950 would prevent the object from being collected.
|
428
|
951
|
|
952 A key-weak hash table is similar to a fully-weak hash table except that
|
|
953 a key-value pair will be removed only if the key remains unmarked
|
|
954 outside of weak hash tables. The pair will remain in the hash table if
|
|
955 the key is pointed to by something other than a weak hash table, even
|
|
956 if the value is not.
|
|
957
|
|
958 A value-weak hash table is similar to a fully-weak hash table except
|
|
959 that a key-value pair will be removed only if the value remains
|
|
960 unmarked outside of weak hash tables. The pair will remain in the
|
|
961 hash table if the value is pointed to by something other than a weak
|
|
962 hash table, even if the key is not.
|
442
|
963
|
|
964 A key-or-value-weak hash table is similar to a fully-weak hash table except
|
|
965 that a key-value pair will be removed only if the value and the key remain
|
|
966 unmarked outside of weak hash tables. The pair will remain in the
|
|
967 hash table if the value or key are pointed to by something other than a weak
|
|
968 hash table, even if the other is not.
|
428
|
969 */
|
|
970 (int nargs, Lisp_Object *args))
|
|
971 {
|
|
972 int i = 0;
|
|
973 Lisp_Object test = Qnil;
|
|
974 Lisp_Object size = Qnil;
|
|
975 Lisp_Object rehash_size = Qnil;
|
|
976 Lisp_Object rehash_threshold = Qnil;
|
|
977 Lisp_Object weakness = Qnil;
|
|
978
|
|
979 while (i + 1 < nargs)
|
|
980 {
|
|
981 Lisp_Object keyword = args[i++];
|
|
982 Lisp_Object value = args[i++];
|
|
983
|
|
984 if (EQ (keyword, Q_test)) test = value;
|
|
985 else if (EQ (keyword, Q_size)) size = value;
|
|
986 else if (EQ (keyword, Q_rehash_size)) rehash_size = value;
|
|
987 else if (EQ (keyword, Q_rehash_threshold)) rehash_threshold = value;
|
|
988 else if (EQ (keyword, Q_weakness)) weakness = value;
|
|
989 else if (EQ (keyword, Q_type))/*obsolete*/ weakness = value;
|
563
|
990 else invalid_constant ("Invalid hash table property keyword", keyword);
|
428
|
991 }
|
|
992
|
|
993 if (i < nargs)
|
563
|
994 sferror ("Hash table property requires a value", args[i]);
|
428
|
995
|
|
996 #define VALIDATE_VAR(var) \
|
|
997 if (!NILP (var)) hash_table_##var##_validate (Q##var, var, ERROR_ME);
|
|
998
|
|
999 VALIDATE_VAR (test);
|
|
1000 VALIDATE_VAR (size);
|
|
1001 VALIDATE_VAR (rehash_size);
|
|
1002 VALIDATE_VAR (rehash_threshold);
|
|
1003 VALIDATE_VAR (weakness);
|
|
1004
|
450
|
1005 return make_standard_lisp_hash_table
|
428
|
1006 (decode_hash_table_test (test),
|
|
1007 decode_hash_table_size (size),
|
|
1008 decode_hash_table_rehash_size (rehash_size),
|
|
1009 decode_hash_table_rehash_threshold (rehash_threshold),
|
|
1010 decode_hash_table_weakness (weakness));
|
|
1011 }
|
|
1012
|
|
1013 DEFUN ("copy-hash-table", Fcopy_hash_table, 1, 1, 0, /*
|
|
1014 Return a new hash table containing the same keys and values as HASH-TABLE.
|
|
1015 The keys and values will not themselves be copied.
|
|
1016 */
|
|
1017 (hash_table))
|
|
1018 {
|
442
|
1019 const Lisp_Hash_Table *ht_old = xhash_table (hash_table);
|
3017
|
1020 Lisp_Hash_Table *ht = ALLOC_LCRECORD_TYPE (Lisp_Hash_Table, &lrecord_hash_table);
|
|
1021 COPY_LCRECORD (ht, ht_old);
|
428
|
1022
|
3092
|
1023 #ifdef NEW_GC
|
|
1024 ht->hentries = (htentry *) alloc_lrecord_array (sizeof (htentry),
|
|
1025 ht_old->size + 1,
|
|
1026 &lrecord_hash_table_entry);
|
|
1027 #else /* not NEW_GC */
|
1204
|
1028 ht->hentries = xnew_array (htentry, ht_old->size + 1);
|
3092
|
1029 #endif /* not NEW_GC */
|
1204
|
1030 memcpy (ht->hentries, ht_old->hentries, (ht_old->size + 1) * sizeof (htentry));
|
428
|
1031
|
793
|
1032 hash_table = wrap_hash_table (ht);
|
428
|
1033
|
|
1034 if (! EQ (ht->next_weak, Qunbound))
|
|
1035 {
|
|
1036 ht->next_weak = Vall_weak_hash_tables;
|
|
1037 Vall_weak_hash_tables = hash_table;
|
|
1038 }
|
|
1039
|
|
1040 return hash_table;
|
|
1041 }
|
|
1042
|
|
1043 static void
|
665
|
1044 resize_hash_table (Lisp_Hash_Table *ht, Elemcount new_size)
|
428
|
1045 {
|
1204
|
1046 htentry *old_entries, *new_entries, *sentinel, *e;
|
665
|
1047 Elemcount old_size;
|
428
|
1048
|
|
1049 old_size = ht->size;
|
|
1050 ht->size = new_size;
|
|
1051
|
|
1052 old_entries = ht->hentries;
|
|
1053
|
3092
|
1054 #ifdef NEW_GC
|
|
1055 ht->hentries = (htentry *) alloc_lrecord_array (sizeof (htentry),
|
|
1056 new_size + 1,
|
|
1057 &lrecord_hash_table_entry);
|
|
1058 #else /* not NEW_GC */
|
1204
|
1059 ht->hentries = xnew_array_and_zero (htentry, new_size + 1);
|
3092
|
1060 #endif /* not NEW_GC */
|
428
|
1061 new_entries = ht->hentries;
|
|
1062
|
|
1063 compute_hash_table_derived_values (ht);
|
|
1064
|
440
|
1065 for (e = old_entries, sentinel = e + old_size; e < sentinel; e++)
|
1204
|
1066 if (!HTENTRY_CLEAR_P (e))
|
428
|
1067 {
|
1204
|
1068 htentry *probe = new_entries + HASHCODE (e->key, ht);
|
428
|
1069 LINEAR_PROBING_LOOP (probe, new_entries, new_size)
|
|
1070 ;
|
|
1071 *probe = *e;
|
|
1072 }
|
|
1073
|
489
|
1074 free_hentries (old_entries, old_size);
|
428
|
1075 }
|
|
1076
|
440
|
1077 /* After a hash table has been saved to disk and later restored by the
|
|
1078 portable dumper, it contains the same objects, but their addresses
|
665
|
1079 and thus their HASHCODEs have changed. */
|
428
|
1080 void
|
440
|
1081 pdump_reorganize_hash_table (Lisp_Object hash_table)
|
428
|
1082 {
|
442
|
1083 const Lisp_Hash_Table *ht = xhash_table (hash_table);
|
3092
|
1084 #ifdef NEW_GC
|
|
1085 htentry *new_entries =
|
|
1086 (htentry *) alloc_lrecord_array (sizeof (htentry), ht->size + 1,
|
|
1087 &lrecord_hash_table_entry);
|
|
1088 #else /* not NEW_GC */
|
1204
|
1089 htentry *new_entries = xnew_array_and_zero (htentry, ht->size + 1);
|
3092
|
1090 #endif /* not NEW_GC */
|
1204
|
1091 htentry *e, *sentinel;
|
440
|
1092
|
|
1093 for (e = ht->hentries, sentinel = e + ht->size; e < sentinel; e++)
|
1204
|
1094 if (!HTENTRY_CLEAR_P (e))
|
440
|
1095 {
|
1204
|
1096 htentry *probe = new_entries + HASHCODE (e->key, ht);
|
440
|
1097 LINEAR_PROBING_LOOP (probe, new_entries, ht->size)
|
|
1098 ;
|
|
1099 *probe = *e;
|
|
1100 }
|
|
1101
|
1204
|
1102 memcpy (ht->hentries, new_entries, ht->size * sizeof (htentry));
|
440
|
1103
|
3092
|
1104 #ifdef NEW_GC
|
|
1105 mc_free (new_entries);
|
|
1106 #else /* not NEW_GC */
|
1726
|
1107 xfree (new_entries, htentry *);
|
3092
|
1108 #endif /* not NEW_GC */
|
428
|
1109 }
|
|
1110
|
|
1111 static void
|
|
1112 enlarge_hash_table (Lisp_Hash_Table *ht)
|
|
1113 {
|
665
|
1114 Elemcount new_size =
|
|
1115 hash_table_size ((Elemcount) ((double) ht->size * ht->rehash_size));
|
428
|
1116 resize_hash_table (ht, new_size);
|
|
1117 }
|
|
1118
|
4072
|
1119 htentry *
|
1204
|
1120 find_htentry (Lisp_Object key, const Lisp_Hash_Table *ht)
|
428
|
1121 {
|
|
1122 hash_table_test_function_t test_function = ht->test_function;
|
1204
|
1123 htentry *entries = ht->hentries;
|
|
1124 htentry *probe = entries + HASHCODE (key, ht);
|
428
|
1125
|
|
1126 LINEAR_PROBING_LOOP (probe, entries, ht->size)
|
|
1127 if (KEYS_EQUAL_P (probe->key, key, test_function))
|
|
1128 break;
|
|
1129
|
|
1130 return probe;
|
|
1131 }
|
|
1132
|
2421
|
1133 /* A version of Fputhash() that increments the value by the specified
|
|
1134 amount and dispenses will all error checks. Assumes that tables does
|
|
1135 comparison using EQ. Used by the profiling routines to avoid
|
|
1136 overhead -- profiling overhead was being recorded at up to 15% of the
|
|
1137 total time. */
|
|
1138
|
|
1139 void
|
|
1140 inchash_eq (Lisp_Object key, Lisp_Object table, EMACS_INT offset)
|
|
1141 {
|
|
1142 Lisp_Hash_Table *ht = XHASH_TABLE (table);
|
|
1143 htentry *entries = ht->hentries;
|
|
1144 htentry *probe = entries + HASHCODE (key, ht);
|
|
1145
|
|
1146 LINEAR_PROBING_LOOP (probe, entries, ht->size)
|
|
1147 if (EQ (probe->key, key))
|
|
1148 break;
|
|
1149
|
|
1150 if (!HTENTRY_CLEAR_P (probe))
|
|
1151 probe->value = make_int (XINT (probe->value) + offset);
|
|
1152 else
|
|
1153 {
|
|
1154 probe->key = key;
|
|
1155 probe->value = make_int (offset);
|
|
1156
|
|
1157 if (++ht->count >= ht->rehash_count)
|
|
1158 enlarge_hash_table (ht);
|
|
1159 }
|
|
1160 }
|
|
1161
|
428
|
1162 DEFUN ("gethash", Fgethash, 2, 3, 0, /*
|
|
1163 Find hash value for KEY in HASH-TABLE.
|
|
1164 If there is no corresponding value, return DEFAULT (which defaults to nil).
|
|
1165 */
|
|
1166 (key, hash_table, default_))
|
|
1167 {
|
442
|
1168 const Lisp_Hash_Table *ht = xhash_table (hash_table);
|
1204
|
1169 htentry *e = find_htentry (key, ht);
|
428
|
1170
|
1204
|
1171 return HTENTRY_CLEAR_P (e) ? default_ : e->value;
|
428
|
1172 }
|
|
1173
|
|
1174 DEFUN ("puthash", Fputhash, 3, 3, 0, /*
|
|
1175 Hash KEY to VALUE in HASH-TABLE.
|
|
1176 */
|
|
1177 (key, value, hash_table))
|
|
1178 {
|
|
1179 Lisp_Hash_Table *ht = xhash_table (hash_table);
|
1204
|
1180 htentry *e = find_htentry (key, ht);
|
428
|
1181
|
1204
|
1182 if (!HTENTRY_CLEAR_P (e))
|
428
|
1183 return e->value = value;
|
|
1184
|
|
1185 e->key = key;
|
|
1186 e->value = value;
|
|
1187
|
|
1188 if (++ht->count >= ht->rehash_count)
|
|
1189 enlarge_hash_table (ht);
|
|
1190
|
|
1191 return value;
|
|
1192 }
|
|
1193
|
1204
|
1194 /* Remove htentry pointed at by PROBE.
|
428
|
1195 Subsequent entries are removed and reinserted.
|
|
1196 We don't use tombstones - too wasteful. */
|
|
1197 static void
|
1204
|
1198 remhash_1 (Lisp_Hash_Table *ht, htentry *entries, htentry *probe)
|
428
|
1199 {
|
665
|
1200 Elemcount size = ht->size;
|
1204
|
1201 CLEAR_HTENTRY (probe);
|
428
|
1202 probe++;
|
|
1203 ht->count--;
|
|
1204
|
|
1205 LINEAR_PROBING_LOOP (probe, entries, size)
|
|
1206 {
|
|
1207 Lisp_Object key = probe->key;
|
1204
|
1208 htentry *probe2 = entries + HASHCODE (key, ht);
|
428
|
1209 LINEAR_PROBING_LOOP (probe2, entries, size)
|
|
1210 if (EQ (probe2->key, key))
|
1204
|
1211 /* htentry at probe doesn't need to move. */
|
428
|
1212 goto continue_outer_loop;
|
1204
|
1213 /* Move htentry from probe to new home at probe2. */
|
428
|
1214 *probe2 = *probe;
|
1204
|
1215 CLEAR_HTENTRY (probe);
|
428
|
1216 continue_outer_loop: continue;
|
|
1217 }
|
|
1218 }
|
|
1219
|
|
1220 DEFUN ("remhash", Fremhash, 2, 2, 0, /*
|
|
1221 Remove the entry for KEY from HASH-TABLE.
|
|
1222 Do nothing if there is no entry for KEY in HASH-TABLE.
|
617
|
1223 Return non-nil if an entry was removed.
|
428
|
1224 */
|
|
1225 (key, hash_table))
|
|
1226 {
|
|
1227 Lisp_Hash_Table *ht = xhash_table (hash_table);
|
1204
|
1228 htentry *e = find_htentry (key, ht);
|
428
|
1229
|
1204
|
1230 if (HTENTRY_CLEAR_P (e))
|
428
|
1231 return Qnil;
|
|
1232
|
|
1233 remhash_1 (ht, ht->hentries, e);
|
|
1234 return Qt;
|
|
1235 }
|
|
1236
|
|
1237 DEFUN ("clrhash", Fclrhash, 1, 1, 0, /*
|
|
1238 Remove all entries from HASH-TABLE, leaving it empty.
|
|
1239 */
|
|
1240 (hash_table))
|
|
1241 {
|
|
1242 Lisp_Hash_Table *ht = xhash_table (hash_table);
|
1204
|
1243 htentry *e, *sentinel;
|
428
|
1244
|
|
1245 for (e = ht->hentries, sentinel = e + ht->size; e < sentinel; e++)
|
1204
|
1246 CLEAR_HTENTRY (e);
|
428
|
1247 ht->count = 0;
|
|
1248
|
|
1249 return hash_table;
|
|
1250 }
|
|
1251
|
|
1252 /************************************************************************/
|
|
1253 /* Accessor Functions */
|
|
1254 /************************************************************************/
|
|
1255
|
|
1256 DEFUN ("hash-table-count", Fhash_table_count, 1, 1, 0, /*
|
|
1257 Return the number of entries in HASH-TABLE.
|
|
1258 */
|
|
1259 (hash_table))
|
|
1260 {
|
|
1261 return make_int (xhash_table (hash_table)->count);
|
|
1262 }
|
|
1263
|
|
1264 DEFUN ("hash-table-test", Fhash_table_test, 1, 1, 0, /*
|
|
1265 Return the test function of HASH-TABLE.
|
|
1266 This can be one of `eq', `eql' or `equal'.
|
|
1267 */
|
|
1268 (hash_table))
|
|
1269 {
|
|
1270 hash_table_test_function_t fun = xhash_table (hash_table)->test_function;
|
|
1271
|
|
1272 return (fun == lisp_object_eql_equal ? Qeql :
|
|
1273 fun == lisp_object_equal_equal ? Qequal :
|
|
1274 Qeq);
|
|
1275 }
|
|
1276
|
|
1277 DEFUN ("hash-table-size", Fhash_table_size, 1, 1, 0, /*
|
|
1278 Return the size of HASH-TABLE.
|
|
1279 This is the current number of slots in HASH-TABLE, whether occupied or not.
|
|
1280 */
|
|
1281 (hash_table))
|
|
1282 {
|
|
1283 return make_int (xhash_table (hash_table)->size);
|
|
1284 }
|
|
1285
|
|
1286 DEFUN ("hash-table-rehash-size", Fhash_table_rehash_size, 1, 1, 0, /*
|
|
1287 Return the current rehash size of HASH-TABLE.
|
|
1288 This is a float greater than 1.0; the factor by which HASH-TABLE
|
|
1289 is enlarged when the rehash threshold is exceeded.
|
|
1290 */
|
|
1291 (hash_table))
|
|
1292 {
|
|
1293 return make_float (xhash_table (hash_table)->rehash_size);
|
|
1294 }
|
|
1295
|
|
1296 DEFUN ("hash-table-rehash-threshold", Fhash_table_rehash_threshold, 1, 1, 0, /*
|
|
1297 Return the current rehash threshold of HASH-TABLE.
|
|
1298 This is a float between 0.0 and 1.0; the maximum `load factor' of HASH-TABLE,
|
|
1299 beyond which the HASH-TABLE is enlarged by rehashing.
|
|
1300 */
|
|
1301 (hash_table))
|
|
1302 {
|
438
|
1303 return make_float (xhash_table (hash_table)->rehash_threshold);
|
428
|
1304 }
|
|
1305
|
|
1306 DEFUN ("hash-table-weakness", Fhash_table_weakness, 1, 1, 0, /*
|
|
1307 Return the weakness of HASH-TABLE.
|
442
|
1308 This can be one of `nil', `key-and-value', `key-or-value', `key' or `value'.
|
428
|
1309 */
|
|
1310 (hash_table))
|
|
1311 {
|
|
1312 switch (xhash_table (hash_table)->weakness)
|
|
1313 {
|
442
|
1314 case HASH_TABLE_WEAK: return Qkey_and_value;
|
|
1315 case HASH_TABLE_KEY_WEAK: return Qkey;
|
|
1316 case HASH_TABLE_KEY_VALUE_WEAK: return Qkey_or_value;
|
|
1317 case HASH_TABLE_VALUE_WEAK: return Qvalue;
|
|
1318 default: return Qnil;
|
428
|
1319 }
|
|
1320 }
|
|
1321
|
|
1322 /* obsolete as of 19990901 in xemacs-21.2 */
|
|
1323 DEFUN ("hash-table-type", Fhash_table_type, 1, 1, 0, /*
|
|
1324 Return the type of HASH-TABLE.
|
|
1325 This can be one of `non-weak', `weak', `key-weak' or `value-weak'.
|
|
1326 */
|
|
1327 (hash_table))
|
|
1328 {
|
|
1329 switch (xhash_table (hash_table)->weakness)
|
|
1330 {
|
442
|
1331 case HASH_TABLE_WEAK: return Qweak;
|
|
1332 case HASH_TABLE_KEY_WEAK: return Qkey_weak;
|
|
1333 case HASH_TABLE_KEY_VALUE_WEAK: return Qkey_or_value_weak;
|
|
1334 case HASH_TABLE_VALUE_WEAK: return Qvalue_weak;
|
|
1335 default: return Qnon_weak;
|
428
|
1336 }
|
|
1337 }
|
|
1338
|
|
1339 /************************************************************************/
|
|
1340 /* Mapping Functions */
|
|
1341 /************************************************************************/
|
489
|
1342
|
|
1343 /* We need to be careful when mapping over hash tables because the
|
|
1344 hash table might be modified during the mapping operation:
|
|
1345 - by the mapping function
|
|
1346 - by gc (if the hash table is weak)
|
|
1347
|
|
1348 So we make a copy of the hentries at the beginning of the mapping
|
497
|
1349 operation, and iterate over the copy. Naturally, this is
|
|
1350 expensive, but not as expensive as you might think, because no
|
|
1351 actual memory has to be collected by our notoriously inefficient
|
|
1352 GC; we use an unwind-protect instead to free the memory directly.
|
|
1353
|
|
1354 We could avoid the copying by having the hash table modifiers
|
|
1355 puthash and remhash check for currently active mapping functions.
|
|
1356 Disadvantages: it's hard to get right, and IMO hash mapping
|
|
1357 functions are basically rare, and no extra space in the hash table
|
|
1358 object and no extra cpu in puthash or remhash should be wasted to
|
|
1359 make maphash 3% faster. From a design point of view, the basic
|
|
1360 functions gethash, puthash and remhash should be implementable
|
|
1361 without having to think about maphash.
|
|
1362
|
|
1363 Note: We don't (yet) have Common Lisp's with-hash-table-iterator.
|
|
1364 If you implement this naively, you cannot have more than one
|
|
1365 concurrently active iterator over the same hash table. The `each'
|
|
1366 function in perl has this limitation.
|
|
1367
|
|
1368 Note: We GCPRO memory on the heap, not on the stack. There is no
|
|
1369 obvious reason why this is bad, but as of this writing this is the
|
|
1370 only known occurrence of this technique in the code.
|
504
|
1371
|
|
1372 -- Martin
|
|
1373 */
|
|
1374
|
|
1375 /* Ben disagrees with the "copying hentries" design, and says:
|
|
1376
|
|
1377 Another solution is the same as I've already proposed -- when
|
|
1378 mapping, mark the table as "change-unsafe", and in this case, use a
|
|
1379 secondary table to maintain changes. this could be basically a
|
|
1380 standard hash table, but with entries only for added or deleted
|
|
1381 entries in the primary table, and a marker like Qunbound to
|
|
1382 indicate a deleted entry. puthash, gethash and remhash need a
|
|
1383 single extra check for this secondary table -- totally
|
|
1384 insignificant speedwise. if you really cared about making
|
|
1385 recursive maphashes completely correct, you'd have to do a bit of
|
|
1386 extra work here -- when maphashing, if the secondary table exists,
|
|
1387 make a copy of it, and use the copy in conjunction with the primary
|
|
1388 table when mapping. the advantages of this are
|
|
1389
|
|
1390 [a] easy to demonstrate correct, even with weak hashtables.
|
|
1391
|
|
1392 [b] no extra overhead in the general maphash case -- only when you
|
|
1393 modify the table while maphashing, and even then the overhead is
|
|
1394 very small.
|
497
|
1395 */
|
|
1396
|
489
|
1397 static Lisp_Object
|
|
1398 maphash_unwind (Lisp_Object unwind_obj)
|
|
1399 {
|
|
1400 void *ptr = (void *) get_opaque_ptr (unwind_obj);
|
1726
|
1401 xfree (ptr, void *);
|
489
|
1402 free_opaque_ptr (unwind_obj);
|
|
1403 return Qnil;
|
|
1404 }
|
|
1405
|
|
1406 /* Return a malloced array of alternating key/value pairs from HT. */
|
|
1407 static Lisp_Object *
|
|
1408 copy_compress_hentries (const Lisp_Hash_Table *ht)
|
|
1409 {
|
|
1410 Lisp_Object * const objs =
|
|
1411 /* If the hash table is empty, ht->count could be 0. */
|
|
1412 xnew_array (Lisp_Object, 2 * (ht->count > 0 ? ht->count : 1));
|
1204
|
1413 const htentry *e, *sentinel;
|
489
|
1414 Lisp_Object *pobj;
|
|
1415
|
|
1416 for (e = ht->hentries, sentinel = e + ht->size, pobj = objs; e < sentinel; e++)
|
1204
|
1417 if (!HTENTRY_CLEAR_P (e))
|
489
|
1418 {
|
|
1419 *(pobj++) = e->key;
|
|
1420 *(pobj++) = e->value;
|
|
1421 }
|
|
1422
|
|
1423 type_checking_assert (pobj == objs + 2 * ht->count);
|
|
1424
|
|
1425 return objs;
|
|
1426 }
|
|
1427
|
428
|
1428 DEFUN ("maphash", Fmaphash, 2, 2, 0, /*
|
|
1429 Map FUNCTION over entries in HASH-TABLE, calling it with two args,
|
|
1430 each key and value in HASH-TABLE.
|
|
1431
|
489
|
1432 FUNCTION must not modify HASH-TABLE, with the one exception that FUNCTION
|
428
|
1433 may remhash or puthash the entry currently being processed by FUNCTION.
|
|
1434 */
|
|
1435 (function, hash_table))
|
|
1436 {
|
489
|
1437 const Lisp_Hash_Table * const ht = xhash_table (hash_table);
|
|
1438 Lisp_Object * const objs = copy_compress_hentries (ht);
|
|
1439 Lisp_Object args[3];
|
|
1440 const Lisp_Object *pobj, *end;
|
|
1441 int speccount = specpdl_depth ();
|
|
1442 struct gcpro gcpro1;
|
|
1443
|
|
1444 record_unwind_protect (maphash_unwind, make_opaque_ptr ((void *)objs));
|
|
1445 GCPRO1 (objs[0]);
|
|
1446 gcpro1.nvars = 2 * ht->count;
|
428
|
1447
|
489
|
1448 args[0] = function;
|
|
1449
|
|
1450 for (pobj = objs, end = pobj + 2 * ht->count; pobj < end; pobj += 2)
|
|
1451 {
|
|
1452 args[1] = pobj[0];
|
|
1453 args[2] = pobj[1];
|
|
1454 Ffuncall (countof (args), args);
|
|
1455 }
|
|
1456
|
771
|
1457 unbind_to (speccount);
|
489
|
1458 UNGCPRO;
|
428
|
1459
|
|
1460 return Qnil;
|
|
1461 }
|
|
1462
|
489
|
1463 /* Map *C* function FUNCTION over the elements of a non-weak lisp hash table.
|
|
1464 FUNCTION must not modify HASH-TABLE, with the one exception that FUNCTION
|
|
1465 may puthash the entry currently being processed by FUNCTION.
|
|
1466 Mapping terminates if FUNCTION returns something other than 0. */
|
428
|
1467 void
|
489
|
1468 elisp_maphash_unsafe (maphash_function_t function,
|
428
|
1469 Lisp_Object hash_table, void *extra_arg)
|
|
1470 {
|
442
|
1471 const Lisp_Hash_Table *ht = XHASH_TABLE (hash_table);
|
1204
|
1472 const htentry *e, *sentinel;
|
428
|
1473
|
|
1474 for (e = ht->hentries, sentinel = e + ht->size; e < sentinel; e++)
|
1204
|
1475 if (!HTENTRY_CLEAR_P (e))
|
489
|
1476 if (function (e->key, e->value, extra_arg))
|
|
1477 return;
|
428
|
1478 }
|
|
1479
|
489
|
1480 /* Map *C* function FUNCTION over the elements of a lisp hash table.
|
|
1481 It is safe for FUNCTION to modify HASH-TABLE.
|
|
1482 Mapping terminates if FUNCTION returns something other than 0. */
|
|
1483 void
|
|
1484 elisp_maphash (maphash_function_t function,
|
|
1485 Lisp_Object hash_table, void *extra_arg)
|
|
1486 {
|
|
1487 const Lisp_Hash_Table * const ht = xhash_table (hash_table);
|
|
1488 Lisp_Object * const objs = copy_compress_hentries (ht);
|
|
1489 const Lisp_Object *pobj, *end;
|
|
1490 int speccount = specpdl_depth ();
|
|
1491 struct gcpro gcpro1;
|
|
1492
|
|
1493 record_unwind_protect (maphash_unwind, make_opaque_ptr ((void *)objs));
|
|
1494 GCPRO1 (objs[0]);
|
|
1495 gcpro1.nvars = 2 * ht->count;
|
|
1496
|
|
1497 for (pobj = objs, end = pobj + 2 * ht->count; pobj < end; pobj += 2)
|
|
1498 if (function (pobj[0], pobj[1], extra_arg))
|
|
1499 break;
|
|
1500
|
771
|
1501 unbind_to (speccount);
|
489
|
1502 UNGCPRO;
|
|
1503 }
|
|
1504
|
|
1505 /* Remove all elements of a lisp hash table satisfying *C* predicate PREDICATE.
|
|
1506 PREDICATE must not modify HASH-TABLE. */
|
428
|
1507 void
|
|
1508 elisp_map_remhash (maphash_function_t predicate,
|
|
1509 Lisp_Object hash_table, void *extra_arg)
|
|
1510 {
|
489
|
1511 const Lisp_Hash_Table * const ht = xhash_table (hash_table);
|
|
1512 Lisp_Object * const objs = copy_compress_hentries (ht);
|
|
1513 const Lisp_Object *pobj, *end;
|
|
1514 int speccount = specpdl_depth ();
|
|
1515 struct gcpro gcpro1;
|
428
|
1516
|
489
|
1517 record_unwind_protect (maphash_unwind, make_opaque_ptr ((void *)objs));
|
|
1518 GCPRO1 (objs[0]);
|
|
1519 gcpro1.nvars = 2 * ht->count;
|
|
1520
|
|
1521 for (pobj = objs, end = pobj + 2 * ht->count; pobj < end; pobj += 2)
|
|
1522 if (predicate (pobj[0], pobj[1], extra_arg))
|
|
1523 Fremhash (pobj[0], hash_table);
|
|
1524
|
771
|
1525 unbind_to (speccount);
|
489
|
1526 UNGCPRO;
|
428
|
1527 }
|
|
1528
|
|
1529
|
|
1530 /************************************************************************/
|
|
1531 /* garbage collecting weak hash tables */
|
|
1532 /************************************************************************/
|
1598
|
1533 #ifdef USE_KKCC
|
2645
|
1534 #define MARK_OBJ(obj) do { \
|
|
1535 Lisp_Object mo_obj = (obj); \
|
|
1536 if (!marked_p (mo_obj)) \
|
|
1537 { \
|
|
1538 kkcc_gc_stack_push_lisp_object (mo_obj, 0, -1); \
|
|
1539 did_mark = 1; \
|
|
1540 } \
|
1598
|
1541 } while (0)
|
|
1542
|
|
1543 #else /* NO USE_KKCC */
|
|
1544
|
442
|
1545 #define MARK_OBJ(obj) do { \
|
|
1546 Lisp_Object mo_obj = (obj); \
|
|
1547 if (!marked_p (mo_obj)) \
|
|
1548 { \
|
|
1549 mark_object (mo_obj); \
|
|
1550 did_mark = 1; \
|
|
1551 } \
|
|
1552 } while (0)
|
1598
|
1553 #endif /*NO USE_KKCC */
|
442
|
1554
|
428
|
1555
|
|
1556 /* Complete the marking for semi-weak hash tables. */
|
|
1557 int
|
|
1558 finish_marking_weak_hash_tables (void)
|
|
1559 {
|
|
1560 Lisp_Object hash_table;
|
|
1561 int did_mark = 0;
|
|
1562
|
|
1563 for (hash_table = Vall_weak_hash_tables;
|
|
1564 !NILP (hash_table);
|
|
1565 hash_table = XHASH_TABLE (hash_table)->next_weak)
|
|
1566 {
|
442
|
1567 const Lisp_Hash_Table *ht = XHASH_TABLE (hash_table);
|
1204
|
1568 const htentry *e = ht->hentries;
|
|
1569 const htentry *sentinel = e + ht->size;
|
428
|
1570
|
|
1571 if (! marked_p (hash_table))
|
|
1572 /* The hash table is probably garbage. Ignore it. */
|
|
1573 continue;
|
|
1574
|
|
1575 /* Now, scan over all the pairs. For all pairs that are
|
|
1576 half-marked, we may need to mark the other half if we're
|
|
1577 keeping this pair. */
|
|
1578 switch (ht->weakness)
|
|
1579 {
|
|
1580 case HASH_TABLE_KEY_WEAK:
|
|
1581 for (; e < sentinel; e++)
|
1204
|
1582 if (!HTENTRY_CLEAR_P (e))
|
428
|
1583 if (marked_p (e->key))
|
|
1584 MARK_OBJ (e->value);
|
|
1585 break;
|
|
1586
|
|
1587 case HASH_TABLE_VALUE_WEAK:
|
|
1588 for (; e < sentinel; e++)
|
1204
|
1589 if (!HTENTRY_CLEAR_P (e))
|
428
|
1590 if (marked_p (e->value))
|
|
1591 MARK_OBJ (e->key);
|
|
1592 break;
|
|
1593
|
442
|
1594 case HASH_TABLE_KEY_VALUE_WEAK:
|
|
1595 for (; e < sentinel; e++)
|
1204
|
1596 if (!HTENTRY_CLEAR_P (e))
|
442
|
1597 {
|
|
1598 if (marked_p (e->value))
|
|
1599 MARK_OBJ (e->key);
|
|
1600 else if (marked_p (e->key))
|
|
1601 MARK_OBJ (e->value);
|
|
1602 }
|
|
1603 break;
|
|
1604
|
428
|
1605 case HASH_TABLE_KEY_CAR_WEAK:
|
|
1606 for (; e < sentinel; e++)
|
1204
|
1607 if (!HTENTRY_CLEAR_P (e))
|
428
|
1608 if (!CONSP (e->key) || marked_p (XCAR (e->key)))
|
|
1609 {
|
|
1610 MARK_OBJ (e->key);
|
|
1611 MARK_OBJ (e->value);
|
|
1612 }
|
|
1613 break;
|
|
1614
|
450
|
1615 /* We seem to be sprouting new weakness types at an alarming
|
|
1616 rate. At least this is not externally visible - and in
|
|
1617 fact all of these KEY_CAR_* types are only used by the
|
|
1618 glyph code. */
|
|
1619 case HASH_TABLE_KEY_CAR_VALUE_WEAK:
|
|
1620 for (; e < sentinel; e++)
|
1204
|
1621 if (!HTENTRY_CLEAR_P (e))
|
450
|
1622 {
|
|
1623 if (!CONSP (e->key) || marked_p (XCAR (e->key)))
|
|
1624 {
|
|
1625 MARK_OBJ (e->key);
|
|
1626 MARK_OBJ (e->value);
|
|
1627 }
|
|
1628 else if (marked_p (e->value))
|
|
1629 MARK_OBJ (e->key);
|
|
1630 }
|
|
1631 break;
|
|
1632
|
428
|
1633 case HASH_TABLE_VALUE_CAR_WEAK:
|
|
1634 for (; e < sentinel; e++)
|
1204
|
1635 if (!HTENTRY_CLEAR_P (e))
|
428
|
1636 if (!CONSP (e->value) || marked_p (XCAR (e->value)))
|
|
1637 {
|
|
1638 MARK_OBJ (e->key);
|
|
1639 MARK_OBJ (e->value);
|
|
1640 }
|
|
1641 break;
|
|
1642
|
|
1643 default:
|
|
1644 break;
|
|
1645 }
|
|
1646 }
|
|
1647
|
|
1648 return did_mark;
|
|
1649 }
|
|
1650
|
|
1651 void
|
|
1652 prune_weak_hash_tables (void)
|
|
1653 {
|
|
1654 Lisp_Object hash_table, prev = Qnil;
|
|
1655 for (hash_table = Vall_weak_hash_tables;
|
|
1656 !NILP (hash_table);
|
|
1657 hash_table = XHASH_TABLE (hash_table)->next_weak)
|
|
1658 {
|
|
1659 if (! marked_p (hash_table))
|
|
1660 {
|
|
1661 /* This hash table itself is garbage. Remove it from the list. */
|
|
1662 if (NILP (prev))
|
|
1663 Vall_weak_hash_tables = XHASH_TABLE (hash_table)->next_weak;
|
|
1664 else
|
|
1665 XHASH_TABLE (prev)->next_weak = XHASH_TABLE (hash_table)->next_weak;
|
|
1666 }
|
|
1667 else
|
|
1668 {
|
|
1669 /* Now, scan over all the pairs. Remove all of the pairs
|
|
1670 in which the key or value, or both, is unmarked
|
|
1671 (depending on the weakness of the hash table). */
|
|
1672 Lisp_Hash_Table *ht = XHASH_TABLE (hash_table);
|
1204
|
1673 htentry *entries = ht->hentries;
|
|
1674 htentry *sentinel = entries + ht->size;
|
|
1675 htentry *e;
|
428
|
1676
|
|
1677 for (e = entries; e < sentinel; e++)
|
1204
|
1678 if (!HTENTRY_CLEAR_P (e))
|
428
|
1679 {
|
|
1680 again:
|
|
1681 if (!marked_p (e->key) || !marked_p (e->value))
|
|
1682 {
|
|
1683 remhash_1 (ht, entries, e);
|
1204
|
1684 if (!HTENTRY_CLEAR_P (e))
|
428
|
1685 goto again;
|
|
1686 }
|
|
1687 }
|
|
1688
|
|
1689 prev = hash_table;
|
|
1690 }
|
|
1691 }
|
|
1692 }
|
|
1693
|
|
1694 /* Return a hash value for an array of Lisp_Objects of size SIZE. */
|
|
1695
|
665
|
1696 Hashcode
|
428
|
1697 internal_array_hash (Lisp_Object *arr, int size, int depth)
|
|
1698 {
|
|
1699 int i;
|
665
|
1700 Hashcode hash = 0;
|
442
|
1701 depth++;
|
428
|
1702
|
|
1703 if (size <= 5)
|
|
1704 {
|
|
1705 for (i = 0; i < size; i++)
|
442
|
1706 hash = HASH2 (hash, internal_hash (arr[i], depth));
|
428
|
1707 return hash;
|
|
1708 }
|
|
1709
|
|
1710 /* just pick five elements scattered throughout the array.
|
|
1711 A slightly better approach would be to offset by some
|
|
1712 noise factor from the points chosen below. */
|
|
1713 for (i = 0; i < 5; i++)
|
442
|
1714 hash = HASH2 (hash, internal_hash (arr[i*size/5], depth));
|
428
|
1715
|
|
1716 return hash;
|
|
1717 }
|
|
1718
|
|
1719 /* Return a hash value for a Lisp_Object. This is for use when hashing
|
|
1720 objects with the comparison being `equal' (for `eq', you can just
|
|
1721 use the Lisp_Object itself as the hash value). You need to make a
|
|
1722 tradeoff between the speed of the hash function and how good the
|
|
1723 hashing is. In particular, the hash function needs to be FAST,
|
|
1724 so you can't just traipse down the whole tree hashing everything
|
|
1725 together. Most of the time, objects will differ in the first
|
|
1726 few elements you hash. Thus, we only go to a short depth (5)
|
|
1727 and only hash at most 5 elements out of a vector. Theoretically
|
|
1728 we could still take 5^5 time (a big big number) to compute a
|
|
1729 hash, but practically this won't ever happen. */
|
|
1730
|
665
|
1731 Hashcode
|
428
|
1732 internal_hash (Lisp_Object obj, int depth)
|
|
1733 {
|
|
1734 if (depth > 5)
|
|
1735 return 0;
|
|
1736 if (CONSP (obj))
|
|
1737 {
|
|
1738 /* no point in worrying about tail recursion, since we're not
|
|
1739 going very deep */
|
|
1740 return HASH2 (internal_hash (XCAR (obj), depth + 1),
|
|
1741 internal_hash (XCDR (obj), depth + 1));
|
|
1742 }
|
|
1743 if (STRINGP (obj))
|
|
1744 {
|
|
1745 return hash_string (XSTRING_DATA (obj), XSTRING_LENGTH (obj));
|
|
1746 }
|
|
1747 if (LRECORDP (obj))
|
|
1748 {
|
442
|
1749 const struct lrecord_implementation
|
428
|
1750 *imp = XRECORD_LHEADER_IMPLEMENTATION (obj);
|
|
1751 if (imp->hash)
|
|
1752 return imp->hash (obj, depth);
|
|
1753 }
|
|
1754
|
|
1755 return LISP_HASH (obj);
|
|
1756 }
|
|
1757
|
|
1758 DEFUN ("sxhash", Fsxhash, 1, 1, 0, /*
|
|
1759 Return a hash value for OBJECT.
|
444
|
1760 \(equal obj1 obj2) implies (= (sxhash obj1) (sxhash obj2)).
|
428
|
1761 */
|
|
1762 (object))
|
|
1763 {
|
|
1764 return make_int (internal_hash (object, 0));
|
|
1765 }
|
|
1766
|
|
1767 #if 0
|
826
|
1768 DEFUN ("internal-hash-value", Finternal_hash_value, 1, 1, 0, /*
|
428
|
1769 Hash value of OBJECT. For debugging.
|
|
1770 The value is returned as (HIGH . LOW).
|
|
1771 */
|
|
1772 (object))
|
|
1773 {
|
|
1774 /* This function is pretty 32bit-centric. */
|
665
|
1775 Hashcode hash = internal_hash (object, 0);
|
428
|
1776 return Fcons (hash >> 16, hash & 0xffff);
|
|
1777 }
|
|
1778 #endif
|
|
1779
|
|
1780
|
|
1781 /************************************************************************/
|
|
1782 /* initialization */
|
|
1783 /************************************************************************/
|
|
1784
|
|
1785 void
|
|
1786 syms_of_elhash (void)
|
|
1787 {
|
|
1788 DEFSUBR (Fhash_table_p);
|
|
1789 DEFSUBR (Fmake_hash_table);
|
|
1790 DEFSUBR (Fcopy_hash_table);
|
|
1791 DEFSUBR (Fgethash);
|
|
1792 DEFSUBR (Fremhash);
|
|
1793 DEFSUBR (Fputhash);
|
|
1794 DEFSUBR (Fclrhash);
|
|
1795 DEFSUBR (Fmaphash);
|
|
1796 DEFSUBR (Fhash_table_count);
|
|
1797 DEFSUBR (Fhash_table_test);
|
|
1798 DEFSUBR (Fhash_table_size);
|
|
1799 DEFSUBR (Fhash_table_rehash_size);
|
|
1800 DEFSUBR (Fhash_table_rehash_threshold);
|
|
1801 DEFSUBR (Fhash_table_weakness);
|
|
1802 DEFSUBR (Fhash_table_type); /* obsolete */
|
|
1803 DEFSUBR (Fsxhash);
|
|
1804 #if 0
|
|
1805 DEFSUBR (Finternal_hash_value);
|
|
1806 #endif
|
|
1807
|
563
|
1808 DEFSYMBOL_MULTIWORD_PREDICATE (Qhash_tablep);
|
|
1809 DEFSYMBOL (Qhash_table);
|
|
1810 DEFSYMBOL (Qhashtable);
|
|
1811 DEFSYMBOL (Qweakness);
|
|
1812 DEFSYMBOL (Qvalue);
|
|
1813 DEFSYMBOL (Qkey_or_value);
|
|
1814 DEFSYMBOL (Qkey_and_value);
|
|
1815 DEFSYMBOL (Qrehash_size);
|
|
1816 DEFSYMBOL (Qrehash_threshold);
|
428
|
1817
|
563
|
1818 DEFSYMBOL (Qweak); /* obsolete */
|
|
1819 DEFSYMBOL (Qkey_weak); /* obsolete */
|
|
1820 DEFSYMBOL (Qkey_or_value_weak); /* obsolete */
|
|
1821 DEFSYMBOL (Qvalue_weak); /* obsolete */
|
|
1822 DEFSYMBOL (Qnon_weak); /* obsolete */
|
428
|
1823
|
563
|
1824 DEFKEYWORD (Q_test);
|
|
1825 DEFKEYWORD (Q_size);
|
|
1826 DEFKEYWORD (Q_rehash_size);
|
|
1827 DEFKEYWORD (Q_rehash_threshold);
|
|
1828 DEFKEYWORD (Q_weakness);
|
|
1829 DEFKEYWORD (Q_type); /* obsolete */
|
428
|
1830 }
|
|
1831
|
|
1832 void
|
771
|
1833 init_elhash_once_early (void)
|
428
|
1834 {
|
771
|
1835 INIT_LRECORD_IMPLEMENTATION (hash_table);
|
3092
|
1836 #ifdef NEW_GC
|
|
1837 INIT_LRECORD_IMPLEMENTATION (hash_table_entry);
|
|
1838 #endif /* NEW_GC */
|
771
|
1839
|
428
|
1840 /* This must NOT be staticpro'd */
|
|
1841 Vall_weak_hash_tables = Qnil;
|
452
|
1842 dump_add_weak_object_chain (&Vall_weak_hash_tables);
|
428
|
1843 }
|