comparison src/elhash.c @ 185:3d6bfa290dbd r20-3b19

Import from CVS: tag r20-3b19
author cvs
date Mon, 13 Aug 2007 09:55:28 +0200
parents 8eaf7971accc
children b405438285a2
comparison
equal deleted inserted replaced
184:bcd2674570bf 185:3d6bfa290dbd
29 29
30 Lisp_Object Qhashtablep; 30 Lisp_Object Qhashtablep;
31 31
32 #define LISP_OBJECTS_PER_HENTRY (sizeof (hentry) / sizeof (Lisp_Object))/* 2 */ 32 #define LISP_OBJECTS_PER_HENTRY (sizeof (hentry) / sizeof (Lisp_Object))/* 2 */
33 33
34 struct hashtable_struct 34 struct hashtable
35 { 35 {
36 struct lcrecord_header header; 36 struct lcrecord_header header;
37 unsigned int fullness; 37 unsigned int fullness;
38 unsigned long (*hash_function) (CONST void *); 38 unsigned long (*hash_function) (CONST void *);
39 int (*test_function) (CONST void *, CONST void *); 39 int (*test_function) (CONST void *, CONST void *);
48 48
49 static Lisp_Object mark_hashtable (Lisp_Object, void (*) (Lisp_Object)); 49 static Lisp_Object mark_hashtable (Lisp_Object, void (*) (Lisp_Object));
50 static void print_hashtable (Lisp_Object, Lisp_Object, int); 50 static void print_hashtable (Lisp_Object, Lisp_Object, int);
51 DEFINE_LRECORD_IMPLEMENTATION ("hashtable", hashtable, 51 DEFINE_LRECORD_IMPLEMENTATION ("hashtable", hashtable,
52 mark_hashtable, print_hashtable, 0, 0, 0, 52 mark_hashtable, print_hashtable, 0, 0, 0,
53 struct hashtable_struct); 53 struct hashtable);
54 54
55 static Lisp_Object 55 static Lisp_Object
56 mark_hashtable (Lisp_Object obj, void (*markobj) (Lisp_Object)) 56 mark_hashtable (Lisp_Object obj, void (*markobj) (Lisp_Object))
57 { 57 {
58 struct hashtable_struct *table = XHASHTABLE (obj); 58 struct hashtable *table = XHASHTABLE (obj);
59 59
60 if (table->type != HASHTABLE_NONWEAK) 60 if (table->type != HASHTABLE_NONWEAK)
61 { 61 {
62 /* If the table is weak, we don't want to mark the keys and values 62 /* If the table is weak, we don't want to mark the keys and values
63 (we scan over them after everything else has been marked, 63 (we scan over them after everything else has been marked,
67 return Qnil; 67 return Qnil;
68 } 68 }
69 ((markobj) (table->zero_entry)); 69 ((markobj) (table->zero_entry));
70 return table->harray; 70 return table->harray;
71 } 71 }
72 72
73 static void 73 static void
74 print_hashtable (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag) 74 print_hashtable (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
75 { 75 {
76 struct hashtable_struct *table = XHASHTABLE (obj); 76 struct hashtable *table = XHASHTABLE (obj);
77 char buf[200]; 77 char buf[200];
78 if (print_readably) 78 if (print_readably)
79 error ("printing unreadable object #<hashtable 0x%x>", 79 error ("printing unreadable object #<hashtable 0x%x>",
80 table->header.uid); 80 table->header.uid);
81 sprintf (buf, GETTEXT ("#<%shashtable %d/%ld 0x%x>"), 81 sprintf (buf, GETTEXT ("#<%shashtable %d/%ld 0x%x>"),
90 table->header.uid); 90 table->header.uid);
91 write_c_string (buf, printcharfun); 91 write_c_string (buf, printcharfun);
92 } 92 }
93 93
94 static void 94 static void
95 ht_copy_to_c (struct hashtable_struct *ht, 95 ht_copy_to_c (struct hashtable *ht, c_hashtable c_table)
96 c_hashtable c_table)
97 { 96 {
98 int len = XVECTOR_LENGTH (ht->harray); 97 int len = XVECTOR_LENGTH (ht->harray);
99 98
100 c_table->harray = (void *) XVECTOR_DATA (ht->harray); 99 c_table->harray = (hentry *) XVECTOR_DATA (ht->harray);
101 c_table->zero_set = (!GC_UNBOUNDP (ht->zero_entry)); 100 c_table->zero_set = (!GC_UNBOUNDP (ht->zero_entry));
102 c_table->zero_entry = LISP_TO_VOID (ht->zero_entry); 101 c_table->zero_entry = LISP_TO_VOID (ht->zero_entry);
103 if (len < 0) 102 if (len < 0)
104 { 103 {
105 /* #### if alloc.c mark_object() changes, this must change too. */ 104 /* #### if alloc.c mark_object() changes, this must change too. */
116 c_table->test_function = ht->test_function; 115 c_table->test_function = ht->test_function;
117 XSETHASHTABLE (c_table->elisp_table, ht); 116 XSETHASHTABLE (c_table->elisp_table, ht);
118 } 117 }
119 118
120 static void 119 static void
121 ht_copy_from_c (c_hashtable c_table, 120 ht_copy_from_c (c_hashtable c_table, struct hashtable *ht)
122 struct hashtable_struct *ht)
123 { 121 {
124 struct Lisp_Vector dummy; 122 struct Lisp_Vector dummy;
125 /* C is truly hateful */ 123 /* C is truly hateful */
126 void *vec_addr 124 void *vec_addr
127 = ((char *) c_table->harray 125 = ((char *) c_table->harray
128 - ((char *) &(dummy.contents[0]) - (char *) &dummy)); 126 - ((char *) &(dummy.contents[0]) - (char *) &dummy));
129 127
130 XSETVECTOR (ht->harray, vec_addr); 128 XSETVECTOR (ht->harray, vec_addr);
131 if (c_table->zero_set) 129 if (c_table->zero_set)
132 VOID_TO_LISP (ht->zero_entry, c_table->zero_entry); 130 VOID_TO_LISP (ht->zero_entry, c_table->zero_entry);
134 ht->zero_entry = Qunbound; 132 ht->zero_entry = Qunbound;
135 ht->fullness = c_table->fullness; 133 ht->fullness = c_table->fullness;
136 } 134 }
137 135
138 136
139 static struct hashtable_struct * 137 static struct hashtable *
140 allocate_hashtable (void) 138 allocate_hashtable (void)
141 { 139 {
142 struct hashtable_struct *table 140 struct hashtable *table =
143 = alloc_lcrecord (sizeof (struct hashtable_struct), lrecord_hashtable); 141 alloc_lcrecord_type (struct hashtable, lrecord_hashtable);
144 table->harray = Qnil; 142 table->harray = Qnil;
145 table->zero_entry = Qunbound; 143 table->zero_entry = Qunbound;
146 table->fullness = 0; 144 table->fullness = 0;
147 table->hash_function = 0; 145 table->hash_function = 0;
148 table->test_function = 0; 146 table->test_function = 0;
151 149
152 void * 150 void *
153 elisp_hvector_malloc (unsigned int bytes, Lisp_Object table) 151 elisp_hvector_malloc (unsigned int bytes, Lisp_Object table)
154 { 152 {
155 Lisp_Object new_vector; 153 Lisp_Object new_vector;
156 struct hashtable_struct *ht; 154 struct hashtable *ht = XHASHTABLE (table);
157 155
158 ht = XHASHTABLE (table);
159 assert (bytes > XVECTOR_LENGTH (ht->harray) * sizeof (Lisp_Object)); 156 assert (bytes > XVECTOR_LENGTH (ht->harray) * sizeof (Lisp_Object));
160 new_vector = make_vector ((bytes / sizeof (Lisp_Object)), Qzero); 157 new_vector = make_vector ((bytes / sizeof (Lisp_Object)), Qzero);
161 return (void *) XVECTOR_DATA (new_vector); 158 return (void *) XVECTOR_DATA (new_vector);
162 } 159 }
163 160
164 void 161 void
165 elisp_hvector_free (void *ptr, Lisp_Object table) 162 elisp_hvector_free (void *ptr, Lisp_Object table)
166 { 163 {
167 struct hashtable_struct *ht = XHASHTABLE (table); 164 struct hashtable *ht = XHASHTABLE (table);
168 #if defined (USE_ASSERTIONS) || defined (DEBUG_XEMACS) 165 #if defined (USE_ASSERTIONS) || defined (DEBUG_XEMACS)
169 Lisp_Object current_vector = ht->harray; 166 Lisp_Object current_vector = ht->harray;
170 #endif 167 #endif
171 168
172 assert (((void *) XVECTOR_DATA (current_vector)) == ptr); 169 assert (((void *) XVECTOR_DATA (current_vector)) == ptr);
250 make_lisp_hashtable (int size, 247 make_lisp_hashtable (int size,
251 enum hashtable_type type, 248 enum hashtable_type type,
252 enum hashtable_test_fun test) 249 enum hashtable_test_fun test)
253 { 250 {
254 Lisp_Object result; 251 Lisp_Object result;
255 struct hashtable_struct *table = allocate_hashtable (); 252 struct hashtable *table = allocate_hashtable ();
256 253
257 table->harray = make_vector ((compute_harray_size (size) 254 table->harray = make_vector ((compute_harray_size (size)
258 * LISP_OBJECTS_PER_HENTRY), 255 * LISP_OBJECTS_PER_HENTRY),
259 Qzero); 256 Qzero);
260 switch (test) 257 switch (test)
301 CHECK_SYMBOL (sym); 298 CHECK_SYMBOL (sym);
302 299
303 if (EQ (sym, Qeq)) return HASHTABLE_EQ; 300 if (EQ (sym, Qeq)) return HASHTABLE_EQ;
304 if (EQ (sym, Qequal)) return HASHTABLE_EQUAL; 301 if (EQ (sym, Qequal)) return HASHTABLE_EQUAL;
305 if (EQ (sym, Qeql)) return HASHTABLE_EQL; 302 if (EQ (sym, Qeql)) return HASHTABLE_EQL;
306 303
307 signal_simple_error ("Invalid hashtable test fun", sym); 304 signal_simple_error ("Invalid hashtable test fun", sym);
308 return HASHTABLE_EQ; /* not reached */ 305 return HASHTABLE_EQ; /* not reached */
309 } 306 }
310 307
311 DEFUN ("make-hashtable", Fmake_hashtable, 1, 2, 0, /* 308 DEFUN ("make-hashtable", Fmake_hashtable, 1, 2, 0, /*
331 */ 328 */
332 (old_table)) 329 (old_table))
333 { 330 {
334 struct _C_hashtable old_htbl; 331 struct _C_hashtable old_htbl;
335 struct _C_hashtable new_htbl; 332 struct _C_hashtable new_htbl;
336 struct hashtable_struct *old_ht; 333 struct hashtable *old_ht;
337 struct hashtable_struct *new_ht; 334 struct hashtable *new_ht;
338 Lisp_Object result; 335 Lisp_Object result;
339 336
340 CHECK_HASHTABLE (old_table); 337 CHECK_HASHTABLE (old_table);
341 old_ht = XHASHTABLE (old_table); 338 old_ht = XHASHTABLE (old_table);
342 ht_copy_to_c (old_ht, &old_htbl); 339 ht_copy_to_c (old_ht, &old_htbl);
383 { 380 {
384 Lisp_Object val; 381 Lisp_Object val;
385 CVOID_TO_LISP (val, vval); 382 CVOID_TO_LISP (val, vval);
386 return val; 383 return val;
387 } 384 }
388 else 385 else
389 return default_; 386 return default_;
390 } 387 }
391 388
392 389
393 DEFUN ("remhash", Fremhash, 2, 2, 0, /* 390 DEFUN ("remhash", Fremhash, 2, 2, 0, /*
408 DEFUN ("puthash", Fputhash, 3, 3, 0, /* 405 DEFUN ("puthash", Fputhash, 3, 3, 0, /*
409 Hash KEY to VAL in TABLE. 406 Hash KEY to VAL in TABLE.
410 */ 407 */
411 (key, val, table)) 408 (key, val, table))
412 { 409 {
413 struct hashtable_struct *ht; 410 struct hashtable *ht;
414 void *vkey = LISP_TO_VOID (key); 411 void *vkey = LISP_TO_VOID (key);
415 412
416 CHECK_HASHTABLE (table); 413 CHECK_HASHTABLE (table);
417 ht = XHASHTABLE (table); 414 ht = XHASHTABLE (table);
418 if (!vkey) 415 if (!vkey)
469 if (SUBRP (function) || COMPILED_FUNCTIONP (function)) 466 if (SUBRP (function) || COMPILED_FUNCTIONP (function))
470 return; 467 return;
471 else if (CONSP (function)) 468 else if (CONSP (function))
472 { 469 {
473 Lisp_Object funcar = Fcar (function); 470 Lisp_Object funcar = Fcar (function);
474 if ((SYMBOLP (funcar)) 471 if ((SYMBOLP (funcar))
475 && (EQ (funcar, Qlambda) 472 && (EQ (funcar, Qlambda)
476 || EQ (funcar, Qautoload))) 473 || EQ (funcar, Qautoload)))
477 return; 474 return;
478 } 475 }
479 signal_error (Qinvalid_function, list1 (function)); 476 signal_error (Qinvalid_function, list1 (function));
480 } 477 }
619 616
620 /* This function is called over each pair in the hashtable. 617 /* This function is called over each pair in the hashtable.
621 We complete the marking for semi-weak hashtables. */ 618 We complete the marking for semi-weak hashtables. */
622 CVOID_TO_LISP (keytem, key); 619 CVOID_TO_LISP (keytem, key);
623 CVOID_TO_LISP (valuetem, contents); 620 CVOID_TO_LISP (valuetem, contents);
624 621
625 switch (fmh->type) 622 switch (fmh->type)
626 { 623 {
627 case HASHTABLE_KEY_WEAK: 624 case HASHTABLE_KEY_WEAK:
628 if ((fmh->obj_marked_p) (keytem) && 625 if ((fmh->obj_marked_p) (keytem) &&
629 !(fmh->obj_marked_p) (valuetem)) 626 !(fmh->obj_marked_p) (valuetem))
675 break; 672 break;
676 673
677 default: 674 default:
678 abort (); /* Huh? */ 675 abort (); /* Huh? */
679 } 676 }
680 677
681 return; 678 return;
682 } 679 }
683 680
684 int 681 int
685 finish_marking_weak_hashtables (int (*obj_marked_p) (Lisp_Object), 682 finish_marking_weak_hashtables (int (*obj_marked_p) (Lisp_Object),
745 742
746 static int 743 static int
747 pruning_mapper (CONST void *key, CONST void *contents, void *closure) 744 pruning_mapper (CONST void *key, CONST void *contents, void *closure)
748 { 745 {
749 Lisp_Object keytem, valuetem; 746 Lisp_Object keytem, valuetem;
750 struct pruning_closure *fmh = 747 struct pruning_closure *fmh = (struct pruning_closure *) closure;
751 (struct pruning_closure *) closure;
752 748
753 /* This function is called over each pair in the hashtable. 749 /* This function is called over each pair in the hashtable.
754 We remove the pairs that aren't completely marked (everything 750 We remove the pairs that aren't completely marked (everything
755 that is going to stay ought to have been marked already 751 that is going to stay ought to have been marked already
756 by the finish_marking stage). */ 752 by the finish_marking stage). */
802 { 798 {
803 for (i = 0; i < size; i++) 799 for (i = 0; i < size; i++)
804 hash = HASH2 (hash, internal_hash (arr[i], depth + 1)); 800 hash = HASH2 (hash, internal_hash (arr[i], depth + 1));
805 return hash; 801 return hash;
806 } 802 }
807 803
808 /* just pick five elements scattered throughout the array. 804 /* just pick five elements scattered throughout the array.
809 A slightly better approach would be to offset by some 805 A slightly better approach would be to offset by some
810 noise factor from the points chosen below. */ 806 noise factor from the points chosen below. */
811 for (i = 0; i < 5; i++) 807 for (i = 0; i < 5; i++)
812 hash = HASH2 (hash, internal_hash (arr[i*size/5], depth + 1)); 808 hash = HASH2 (hash, internal_hash (arr[i*size/5], depth + 1));
813 809
814 return hash; 810 return hash;
815 } 811 }
816 812
817 /* Return a hash value for a Lisp_Object. This is for use when hashing 813 /* Return a hash value for a Lisp_Object. This is for use when hashing
818 objects with the comparison being `equal' (for `eq', you can just 814 objects with the comparison being `equal' (for `eq', you can just