comparison src/opaque.c @ 0:376386a54a3c r19-14

Import from CVS: tag r19-14
author cvs
date Mon, 13 Aug 2007 08:45:50 +0200
parents
children 8eaf7971accc
comparison
equal deleted inserted replaced
-1:000000000000 0:376386a54a3c
1 /* Opaque Lisp objects.
2 Copyright (C) 1993, 1994, 1995 Sun Microsystems, Inc.
3 Copyright (C) 1995, 1996 Ben Wing.
4
5 This file is part of XEmacs.
6
7 XEmacs is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 2, or (at your option) any
10 later version.
11
12 XEmacs is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with XEmacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
21
22 /* Synched up with: Not in FSF. */
23
24 /* Written by Ben Wing, October 1993. */
25
26 /* "Opaque" is used internally to hold keep track of allocated memory
27 so it gets GC'd properly, and to store arbitrary data in places
28 where a Lisp_Object is required and which may get GC'd. (e.g. as
29 the argument to record_unwind_protect()). Once created in C,
30 opaque objects cannot be resized.
31
32 OPAQUE OBJECTS SHOULD NEVER ESCAPE TO THE LISP LEVEL. Some code
33 depends on this. As such, opaque objects are a generalization
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 */
41
42 #include <config.h>
43 #include "lisp.h"
44 #include "opaque.h"
45
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;
54
55 static Lisp_Object mark_opaque (Lisp_Object, void (*) (Lisp_Object));
56 static unsigned int sizeof_opaque (CONST void *header);
57 static void print_opaque (Lisp_Object obj, Lisp_Object printcharfun,
58 int escapeflag);
59 DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION ("opaque", opaque,
60 mark_opaque, print_opaque, 0, 0, 0,
61 sizeof_opaque, struct Lisp_Opaque);
62
63 static Lisp_Object
64 mark_opaque (Lisp_Object obj, void (*markobj) (Lisp_Object))
65 {
66 #ifdef ERROR_CHECK_GC
67 if (!in_opaque_list_marking)
68 /* size is non-int for objects on an opaque free list. We sure
69 as hell better not be marking any of these objects unless
70 we're marking an opaque list. */
71 assert (INTP (XOPAQUE (obj)->size_or_chain));
72 else
73 /* marking an opaque on the free list doesn't do any recursive
74 markings, so we better not have non-freed opaques on a free
75 list. */
76 assert (!INTP (XOPAQUE (obj)->size_or_chain));
77 #endif
78 if (INTP (XOPAQUE (obj)->size_or_chain) && XOPAQUE_MARKFUN (obj))
79 return (XOPAQUE_MARKFUN (obj)) (obj, markobj);
80 else
81 return XOPAQUE (obj)->size_or_chain;
82 }
83
84 /* Should never, ever be called. (except by an external debugger) */
85 static void
86 print_opaque (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
87 {
88 char buf[200];
89 if (INTP (XOPAQUE (obj)->size_or_chain))
90 sprintf (buf, "#<INTERNAL EMACS BUG (opaque, size=%d) 0x%x>",
91 (EMACS_INT) XOPAQUE_SIZE (obj),
92 (EMACS_INT) XPNTR (obj));
93 else
94 sprintf (buf, "#<INTERNAL EMACS BUG (opaque, freed) 0x%x>",
95 (EMACS_INT) XPNTR (obj));
96 write_c_string (buf, printcharfun);
97 }
98
99 static unsigned int
100 sizeof_opaque (CONST void *header)
101 {
102 CONST struct Lisp_Opaque *p = (CONST struct Lisp_Opaque *) header;
103 if (!INTP (p->size_or_chain))
104 return sizeof (*p);
105 return sizeof (*p) + XINT (p->size_or_chain) - sizeof (int);
106 }
107
108 Lisp_Object
109 make_opaque (int size, CONST void *data)
110 {
111 struct Lisp_Opaque *p = alloc_lcrecord (sizeof (*p) + size - sizeof (int),
112 lrecord_opaque);
113 Lisp_Object val;
114
115 p->markfun = 0;
116 p->size_or_chain = make_int (size);
117 if (data)
118 memcpy (p->data, data, size);
119 else
120 memset (p->data, 0, size);
121 XSETOPAQUE (val, p);
122 return val;
123 }
124
125 static Lisp_Object mark_opaque_list (Lisp_Object, void (*) (Lisp_Object));
126 DEFINE_LRECORD_IMPLEMENTATION ("opaque-list", opaque_list,
127 mark_opaque_list, internal_object_printer,
128 0, 0, 0, struct Lisp_Opaque_List);
129
130 static Lisp_Object
131 mark_opaque_list (Lisp_Object obj, void (*markobj) (Lisp_Object))
132 {
133 in_opaque_list_marking++;
134 (markobj) (XOPAQUE_LIST (obj)->free);
135 in_opaque_list_marking--;
136 return Qnil;
137 }
138
139 Lisp_Object
140 make_opaque_list (int size,
141 Lisp_Object (*markfun) (Lisp_Object obj,
142 void (*markobj) (Lisp_Object)))
143 {
144 struct Lisp_Opaque_List *p = alloc_lcrecord (sizeof (*p),
145 lrecord_opaque_list);
146 Lisp_Object val = Qnil;
147
148 p->markfun = markfun;
149 p->size = size;
150 p->free = Qnil;
151 XSETOPAQUE_LIST (val, p);
152 return val;
153 }
154
155 Lisp_Object
156 allocate_managed_opaque (Lisp_Object opaque_list, CONST void *data)
157 {
158 struct Lisp_Opaque_List *li = XOPAQUE_LIST (opaque_list);
159 Lisp_Object val;
160
161 if (!NILP (li->free))
162 {
163 val = li->free;
164 li->free = XOPAQUE (val)->size_or_chain;
165 #ifdef ERROR_CHECK_GC
166 assert (NILP (li->free) || OPAQUEP (li->free));
167 #endif
168 XOPAQUE (val)->size_or_chain = make_int (li->size);
169 if (data)
170 memcpy (XOPAQUE (val)->data, data, li->size);
171 else
172 memset (XOPAQUE (val)->data, 0, li->size);
173 }
174 else
175 val = make_opaque (li->size, data);
176 XOPAQUE (val)->markfun = li->markfun;
177 return val;
178 }
179
180 void
181 free_managed_opaque (Lisp_Object opaque_list, Lisp_Object opaque)
182 {
183 struct Lisp_Opaque_List *li = XOPAQUE_LIST (opaque_list);
184
185 #ifdef ERROR_CHECK_GC
186 assert (INTP (XOPAQUE (opaque)->size_or_chain));
187 #endif
188 XOPAQUE (opaque)->size_or_chain = li->free;
189 li->free = opaque;
190 }
191
192 /* stuff to handle opaque pointers */
193
194 Lisp_Object
195 make_opaque_ptr (CONST void *val)
196 {
197 return allocate_managed_opaque (Vopaque_ptr_free_list,
198 (CONST void *) &val);
199 }
200
201 /* Be wery wery careful with this. Same admonitions as with
202 free_cons() apply. */
203
204 void
205 free_opaque_ptr (Lisp_Object ptr)
206 {
207 free_managed_opaque (Vopaque_ptr_free_list, ptr);
208 }
209
210 Lisp_Object
211 make_opaque_long (long val)
212 {
213 return make_opaque (sizeof (val), (void *) &val);
214 }
215
216 void
217 init_opaque_once_early (void)
218 {
219 Vopaque_ptr_free_list = make_opaque_list (sizeof (void *), 0);
220 staticpro (&Vopaque_ptr_free_list);
221 }