comparison src/opaque.c @ 398:74fd4e045ea6 r21-2-29

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