comparison src/opaque.c @ 424:11054d720c21 r21-2-20

Import from CVS: tag r21-2-20
author cvs
date Mon, 13 Aug 2007 11:26:11 +0200
parents 41dbb7a9d5f2
children
comparison
equal deleted inserted replaced
423:28d9c139be4c 424:11054d720c21
30 opaque objects cannot be resized. 30 opaque objects cannot be resized.
31 31
32 OPAQUE OBJECTS SHOULD NEVER ESCAPE TO THE LISP LEVEL. Some code 32 OPAQUE OBJECTS SHOULD NEVER ESCAPE TO THE LISP LEVEL. Some code
33 depends on this. As such, opaque objects are a generalization 33 depends on this. As such, opaque objects are a generalization
34 of the Qunbound marker. 34 of the Qunbound marker.
35
36 "Opaque lists" are used to keep track of lots of opaque objects
37 of a particular size so that they can be efficiently "freed" and
38 re-used again without actually entering the Lisp allocation system
39 (and consequently doing a malloc()).
40 */ 35 */
41 36
42 #include <config.h> 37 #include <config.h>
43 #include "lisp.h" 38 #include "lisp.h"
44 #include "opaque.h" 39 #include "opaque.h"
45 40
46 Lisp_Object Qopaquep;
47
48 static int in_opaque_list_marking;
49
50 /* Holds freed opaque objects created with make_opaque_ptr().
51 We do this quite often so it's a noticeable win if we don't
52 create GC junk. */
53 Lisp_Object Vopaque_ptr_free_list; 41 Lisp_Object Vopaque_ptr_free_list;
54
55 static Lisp_Object
56 mark_opaque (Lisp_Object obj, void (*markobj) (Lisp_Object))
57 {
58 Lisp_Opaque *p = XOPAQUE (obj);
59 /* Egcs 1.1.1 sometimes crashes on INTP (p->size_or_chain) */
60 Lisp_Object size_or_chain = p->size_or_chain;
61 #ifdef ERROR_CHECK_GC
62 if (!in_opaque_list_marking)
63 /* size is non-int for objects on an opaque free list. We sure
64 as hell better not be marking any of these objects unless
65 we're marking an opaque list. */
66 assert (GC_INTP (size_or_chain));
67 else
68 /* marking an opaque on the free list doesn't do any recursive
69 markings, so we better not have non-freed opaques on a free
70 list. */
71 assert (!GC_INTP (size_or_chain));
72 #endif
73 if (GC_INTP (size_or_chain) && OPAQUE_MARKFUN (p))
74 return OPAQUE_MARKFUN (p) (obj, markobj);
75 else
76 return size_or_chain;
77 }
78 42
79 /* Should never, ever be called. (except by an external debugger) */ 43 /* Should never, ever be called. (except by an external debugger) */
80 static void 44 static void
81 print_opaque (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag) 45 print_opaque (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
82 { 46 {
83 CONST Lisp_Opaque *p = XOPAQUE (obj); 47 CONST Lisp_Opaque *p = XOPAQUE (obj);
84 /* Egcs 1.1.1 sometimes crashes on INTP (p->size_or_chain) */
85 Lisp_Object size_or_chain = p->size_or_chain;
86 char buf[200]; 48 char buf[200];
87 char size_buf[50];
88 49
89 if (INTP (size_or_chain)) 50 sprintf (buf, "#<INTERNAL OBJECT (XEmacs bug?) (opaque, size=%lu) 0x%lx>",
90 sprintf (size_buf, "size=%lu", (unsigned long) OPAQUE_SIZE (p)); 51 (long)(p->size), (unsigned long) p);
91 else
92 sprintf (size_buf, "freed");
93
94 sprintf (buf, "#<INTERNAL OBJECT (XEmacs bug?) (opaque, %s) 0x%lx>",
95 size_buf, (unsigned long) p);
96 write_c_string (buf, printcharfun); 52 write_c_string (buf, printcharfun);
97 } 53 }
98 54
99 static size_t 55 static size_t
100 sizeof_opaque (CONST void *header) 56 sizeof_opaque (CONST void *header)
101 { 57 {
102 CONST Lisp_Opaque *p = (CONST Lisp_Opaque *) header; 58 CONST Lisp_Opaque *p = (CONST Lisp_Opaque *) header;
103 /* Egcs 1.1.1 sometimes crashes on INTP (p->size_or_chain) */ 59 return offsetof (Lisp_Opaque, data) + p->size;
104 Lisp_Object size_or_chain = p->size_or_chain;
105 return offsetof (Lisp_Opaque, data)
106 + (GC_INTP (size_or_chain) ? XINT (size_or_chain) : 0);
107 } 60 }
108 61
109 /* Return an opaque object of size SIZE. 62 /* Return an opaque object of size SIZE.
110 If DATA is OPAQUE_CLEAR, the object's data is memset to '\0' bytes. 63 If DATA is OPAQUE_CLEAR, the object's data is memset to '\0' bytes.
111 If DATA is OPAQUE_UNINIT, the object's data is uninitialized. 64 If DATA is OPAQUE_UNINIT, the object's data is uninitialized.
113 Lisp_Object 66 Lisp_Object
114 make_opaque (size_t size, CONST void *data) 67 make_opaque (size_t size, CONST void *data)
115 { 68 {
116 Lisp_Opaque *p = (Lisp_Opaque *) 69 Lisp_Opaque *p = (Lisp_Opaque *)
117 alloc_lcrecord (offsetof (Lisp_Opaque, data) + size, &lrecord_opaque); 70 alloc_lcrecord (offsetof (Lisp_Opaque, data) + size, &lrecord_opaque);
118 p->markfun = 0; 71 p->size = size;
119 p->size_or_chain = make_int (size);
120 72
121 if (data == OPAQUE_CLEAR) 73 if (data == OPAQUE_CLEAR)
122 memset (p->data, '\0', size); 74 memset (p->data, '\0', size);
123 else if (data == OPAQUE_UNINIT) 75 else if (data == OPAQUE_UNINIT)
124 DO_NOTHING; 76 DO_NOTHING;
135 /* This will not work correctly for opaques with subobjects! */ 87 /* This will not work correctly for opaques with subobjects! */
136 88
137 static int 89 static int
138 equal_opaque (Lisp_Object obj1, Lisp_Object obj2, int depth) 90 equal_opaque (Lisp_Object obj1, Lisp_Object obj2, int depth)
139 { 91 {
140 #ifdef DEBUG_XEMACS 92 size_t size;
141 { 93 return ((size = XOPAQUE_SIZE (obj1)) == XOPAQUE_SIZE (obj2) &&
142 /* Egcs 1.1.1 sometimes crashes on INTP (p->size_or_chain) */ 94 !memcmp (XOPAQUE_DATA (obj1), XOPAQUE_DATA (obj2), size));
143 Lisp_Object size_or_chain_1 = XOPAQUE (obj1)->size_or_chain;
144 Lisp_Object size_or_chain_2 = XOPAQUE (obj2)->size_or_chain;
145 assert (INTP (size_or_chain_1));
146 assert (INTP (size_or_chain_2));
147 assert (!XOPAQUE_MARKFUN (obj1) && !XOPAQUE_MARKFUN (obj2));
148 }
149 #endif
150 {
151 size_t size;
152 return ((size = XOPAQUE_SIZE (obj1)) == XOPAQUE_SIZE (obj2) &&
153 !memcmp (XOPAQUE_DATA (obj1), XOPAQUE_DATA (obj2), size));
154 }
155 } 95 }
156 96
157 /* This will not work correctly for opaques with subobjects! */ 97 /* This will not work correctly for opaques with subobjects! */
158 98
159 static unsigned long 99 static unsigned long
160 hash_opaque (Lisp_Object obj, int depth) 100 hash_opaque (Lisp_Object obj, int depth)
161 { 101 {
162 #ifdef DEBUG_XEMACS
163 {
164 /* Egcs 1.1.1 sometimes crashes on INTP (p->size_or_chain) */
165 Lisp_Object size_or_chain = XOPAQUE (obj)->size_or_chain;
166 assert (INTP (size_or_chain));
167 assert (!XOPAQUE_MARKFUN (obj));
168 }
169 #endif
170 if (XOPAQUE_SIZE (obj) == sizeof (unsigned long)) 102 if (XOPAQUE_SIZE (obj) == sizeof (unsigned long))
171 return *((unsigned long *) XOPAQUE_DATA (obj)); 103 return *((unsigned long *) XOPAQUE_DATA (obj));
172 else 104 else
173 return memory_hash (XOPAQUE_DATA (obj), XOPAQUE_SIZE (obj)); 105 return memory_hash (XOPAQUE_DATA (obj), XOPAQUE_SIZE (obj));
174 } 106 }
175 107
108 static const struct lrecord_description opaque_description[] = {
109 { XD_END }
110 };
111
176 DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION ("opaque", opaque, 112 DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION ("opaque", opaque,
177 mark_opaque, print_opaque, 0, 113 0, print_opaque, 0,
178 equal_opaque, hash_opaque, 0, 114 equal_opaque, hash_opaque,
115 opaque_description,
179 sizeof_opaque, Lisp_Opaque); 116 sizeof_opaque, Lisp_Opaque);
180
181 static Lisp_Object
182 mark_opaque_list (Lisp_Object obj, void (*markobj) (Lisp_Object))
183 {
184 in_opaque_list_marking++;
185 markobj (XOPAQUE_LIST (obj)->free);
186 in_opaque_list_marking--;
187 return Qnil;
188 }
189
190 Lisp_Object
191 make_opaque_list (size_t size,
192 Lisp_Object (*markfun) (Lisp_Object obj,
193 void (*markobj) (Lisp_Object)))
194 {
195 Lisp_Object val;
196 Lisp_Opaque_List *p =
197 alloc_lcrecord_type (Lisp_Opaque_List, &lrecord_opaque_list);
198
199 p->markfun = markfun;
200 p->size = size;
201 p->free = Qnil;
202 XSETOPAQUE_LIST (val, p);
203 return val;
204 }
205
206 DEFINE_LRECORD_IMPLEMENTATION ("opaque-list", opaque_list,
207 mark_opaque_list, internal_object_printer,
208 0, 0, 0, 0, Lisp_Opaque_List);
209
210 Lisp_Object
211 allocate_managed_opaque (Lisp_Object opaque_list, CONST void *data)
212 {
213 Lisp_Opaque_List *li = XOPAQUE_LIST (opaque_list);
214 Lisp_Object val;
215
216 if (!NILP (li->free))
217 {
218 val = li->free;
219 li->free = XOPAQUE (val)->size_or_chain;
220 #ifdef ERROR_CHECK_GC
221 assert (NILP (li->free) || OPAQUEP (li->free));
222 #endif
223 XOPAQUE (val)->size_or_chain = make_int (li->size);
224 if (data)
225 memcpy (XOPAQUE (val)->data, data, li->size);
226 else
227 memset (XOPAQUE (val)->data, 0, li->size);
228 }
229 else
230 val = make_opaque (li->size, data);
231 XOPAQUE (val)->markfun = li->markfun;
232 return val;
233 }
234
235 void
236 free_managed_opaque (Lisp_Object opaque_list, Lisp_Object opaque)
237 {
238 Lisp_Opaque_List *li = XOPAQUE_LIST (opaque_list);
239
240 #ifdef ERROR_CHECK_GC
241 {
242 /* Egcs 1.1.1 sometimes crashes on INTP (p->size_or_chain) */
243 Lisp_Object size_or_chain = XOPAQUE (opaque)->size_or_chain;
244 assert (INTP (size_or_chain));
245 }
246 #endif
247 XOPAQUE (opaque)->size_or_chain = li->free;
248 li->free = opaque;
249 }
250 117
251 /* stuff to handle opaque pointers */ 118 /* stuff to handle opaque pointers */
252 119
120 /* Should never, ever be called. (except by an external debugger) */
121 static void
122 print_opaque_ptr (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
123 {
124 CONST Lisp_Opaque_Ptr *p = XOPAQUE_PTR (obj);
125 char buf[200];
126
127 sprintf (buf, "#<INTERNAL OBJECT (XEmacs bug?) (opaque_ptr, adr=0x%lx) 0x%lx>",
128 (long)(p->ptr), (unsigned long) p);
129 write_c_string (buf, printcharfun);
130 }
131
132 static int
133 equal_opaque_ptr (Lisp_Object obj1, Lisp_Object obj2, int depth)
134 {
135 return (XOPAQUE_PTR (obj1)->ptr == XOPAQUE_PTR (obj2)->ptr);
136 }
137
138 static unsigned long
139 hash_opaque_ptr (Lisp_Object obj, int depth)
140 {
141 return (unsigned long) XOPAQUE_PTR (obj)->ptr;
142 }
143
144 DEFINE_LRECORD_IMPLEMENTATION ("opaque_ptr", opaque_ptr,
145 0, print_opaque_ptr, 0,
146 equal_opaque_ptr, hash_opaque_ptr, 0,
147 Lisp_Opaque_Ptr);
148
253 Lisp_Object 149 Lisp_Object
254 make_opaque_ptr (CONST void *val) 150 make_opaque_ptr (void *val)
255 { 151 {
256 return allocate_managed_opaque (Vopaque_ptr_free_list, 152 Lisp_Object res = allocate_managed_lcrecord(Vopaque_ptr_free_list);
257 (CONST void *) &val); 153 set_opaque_ptr (res, val);
154 return res;
258 } 155 }
259 156
260 /* Be very very careful with this. Same admonitions as with 157 /* Be very very careful with this. Same admonitions as with
261 free_cons() apply. */ 158 free_cons() apply. */
262 159
263 void 160 void
264 free_opaque_ptr (Lisp_Object ptr) 161 free_opaque_ptr (Lisp_Object ptr)
265 { 162 {
266 free_managed_opaque (Vopaque_ptr_free_list, ptr); 163 free_managed_lcrecord (Vopaque_ptr_free_list, ptr);
267 } 164 }
268 165
269 Lisp_Object 166 void
270 make_opaque_long (long val) 167 reinit_opaque_once_early (void)
271 { 168 {
272 return make_opaque (sizeof (val), (void *) &val); 169 Vopaque_ptr_free_list = make_lcrecord_list (sizeof (Lisp_Opaque_Ptr), &lrecord_opaque_ptr);
170 staticpro_nodump (&Vopaque_ptr_free_list);
273 } 171 }
274 172
275 void 173 void
276 init_opaque_once_early (void) 174 init_opaque_once_early (void)
277 { 175 {
278 Vopaque_ptr_free_list = make_opaque_list (sizeof (void *), 0); 176 reinit_opaque_once_early ();
279 staticpro (&Vopaque_ptr_free_list);
280 } 177 }