ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/readobj.c
Revision: 2.30
Committed: Mon Jun 23 19:56:47 2025 UTC (14 hours, 24 minutes ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 2.29: +107 -7 lines
Log Message:
perf: Consolidate object block memory to reduce malloc() fragmentation/overhead

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: readobj.c,v 2.29 2025/06/07 05:09:45 greg Exp $";
3 #endif
4 /*
5 * readobj.c - routines for reading in object descriptions.
6 *
7 * External symbols declared in object.h
8 */
9
10 #include "copyright.h"
11
12 #include <ctype.h>
13 #include <string.h>
14 #include <stdio.h>
15
16 #include "platform.h"
17 #include "standard.h"
18 #include "object.h"
19 #include "otypes.h"
20
21 #ifndef OBJMEMOPT
22 #define OBJMEMOPT 1 /* optimize object block memory? */
23 #endif
24
25 OBJREC *objblock[MAXOBJBLK]; /* our objects */
26 OBJECT nobjects = 0; /* # of objects */
27
28
29 void
30 readobj( /* read in an object file or stream */
31 char *inpspec
32 )
33 {
34 OBJECT lastobj;
35 FILE *infp;
36 char buf[2048];
37 int c;
38
39 lastobj = nobjects;
40 if (inpspec == NULL) {
41 infp = stdin;
42 inpspec = "standard input";
43 } else if (inpspec[0] == '!') {
44 if ((infp = popen(inpspec+1, "r")) == NULL) {
45 sprintf(errmsg, "cannot execute \"%s\"", inpspec);
46 error(SYSTEM, errmsg);
47 }
48 } else if ((infp = fopen(inpspec, "r")) == NULL) {
49 sprintf(errmsg, "cannot open scene file \"%s\"", inpspec);
50 error(SYSTEM, errmsg);
51 }
52 #ifdef getc_unlocked /* avoid stupid semaphores */
53 flockfile(infp);
54 #endif
55 while ((c = getc(infp)) != EOF) {
56 if (isspace(c))
57 continue;
58 if (c == '#') { /* comment */
59 fgets(buf, sizeof(buf), infp);
60 } else if (c == '!') { /* command */
61 ungetc(c, infp);
62 fgetline(buf, sizeof(buf), infp);
63 readobj(buf);
64 } else { /* object */
65 ungetc(c, infp);
66 getobject(inpspec, infp);
67 }
68 }
69 if (inpspec[0] == '!') {
70 if (pclose(infp) != 0) {
71 sprintf(errmsg, "bad status from \"%s\"", inpspec);
72 error(WARNING, errmsg);
73 }
74 } else if (infp != stdin)
75 fclose(infp);
76 #ifdef getc_unlocked
77 else
78 funlockfile(infp);
79 #endif
80 if (nobjects == lastobj) {
81 sprintf(errmsg, "(%s): empty file", inpspec);
82 error(WARNING, errmsg);
83 }
84 }
85
86
87 void
88 getobject( /* read the next object */
89 char *name,
90 FILE *fp
91 )
92 {
93 #define OALIAS -2
94 OBJECT obj;
95 char sbuf[MAXSTR];
96 int rval;
97 OBJREC *objp;
98
99 if ((obj = newobject()) == OVOID)
100 error(SYSTEM, "out of object space");
101 objp = objptr(obj);
102 /* get modifier */
103 strcpy(sbuf, "EOF");
104 fgetword(sbuf, MAXSTR, fp);
105 if (strchr(sbuf, '\t')) {
106 sprintf(errmsg, "(%s): illegal tab in modifier \"%s\"",
107 name, sbuf);
108 error(USER, errmsg);
109 }
110 if (!strcmp(sbuf, VOIDID))
111 objp->omod = OVOID;
112 else if (!strcmp(sbuf, ALIASMOD))
113 objp->omod = OALIAS;
114 else if ((objp->omod = modifier(sbuf)) == OVOID) {
115 sprintf(errmsg, "(%s): undefined modifier \"%s\"", name, sbuf);
116 error(USER, errmsg);
117 }
118 /* get type */
119 strcpy(sbuf, "EOF");
120 fgetword(sbuf, MAXSTR, fp);
121 if ((objp->otype = otype(sbuf)) < 0) {
122 sprintf(errmsg, "(%s): unknown type \"%s\"", name, sbuf);
123 error(USER, errmsg);
124 }
125 /* get identifier */
126 sbuf[0] = '\0';
127 fgetword(sbuf, MAXSTR, fp);
128 if (strchr(sbuf, '\t')) {
129 sprintf(errmsg, "(%s): illegal tab in identifier \"%s\"",
130 name, sbuf);
131 error(USER, errmsg);
132 }
133 objp->oname = savqstr(sbuf);
134 /* get arguments */
135 if (objp->otype == MOD_ALIAS) {
136 OBJECT ref;
137 OBJREC *rfp;
138 strcpy(sbuf, "EOF");
139 fgetword(sbuf, MAXSTR, fp);
140 if ((ref = modifier(sbuf)) == OVOID) {
141 sprintf(errmsg, "(%s): bad reference \"%s\"",
142 name, sbuf);
143 objerror(objp, USER, errmsg);
144 } /* skip pass-thru aliases */
145 while ((rfp=objptr(ref))->otype == MOD_ALIAS &&
146 !rfp->oargs.nsargs & (rfp->omod != OVOID))
147 ref = rfp->omod;
148
149 if ((objp->omod == OALIAS) | (objp->omod == rfp->omod)) {
150 objp->omod = ref;
151 } else {
152 objp->oargs.sarg = (char **)malloc(sizeof(char *));
153 if (objp->oargs.sarg == NULL)
154 error(SYSTEM, "out of memory in getobject");
155 objp->oargs.nsargs = 1;
156 objp->oargs.sarg[0] = savestr(sbuf);
157 }
158 } else if ((rval = readfargs(&objp->oargs, fp)) == 0) {
159 sprintf(errmsg, "(%s): bad arguments", name);
160 objerror(objp, USER, errmsg);
161 } else if (rval < 0) {
162 sprintf(errmsg, "(%s): error reading scene", name);
163 error(SYSTEM, errmsg);
164 }
165 if (objp->omod == OALIAS) {
166 sprintf(errmsg, "(%s): inappropriate use of '%s' modifier",
167 name, ALIASMOD);
168 objerror(objp, USER, errmsg);
169 }
170 /* initialize */
171 objp->os = NULL;
172
173 insertobject(obj); /* add to global structure */
174 #undef OALIAS
175 }
176
177
178 static void
179 optimize_objblock(int i) /* consolidate memory in object block */
180 {
181 #if OBJMEMOPT
182 OBJREC *o, *co;
183 int n = 0;
184 unsigned long sargcnt = 0, iargcnt = 0, fargcnt = 0, namecnt = 0;
185
186 if (i < 0 || objblock[i] == NULL || objblock[i][OBJBLKSIZ].otype < 0)
187 return; /* invalid or already flagged */
188
189 for (o = objblock[i]+OBJBLKSIZ; o-- > objblock[i]; ) {
190 if (o->oname == NULL) /* too early to optimize? */
191 return;
192 if (o->os != NULL) /* too late to optimize? */
193 return;
194 n += (o->oargs.nsargs > 0) | (o->oargs.nfargs > 0);
195 sargcnt += o->oargs.nsargs;
196 fargcnt += o->oargs.nfargs;
197 #ifdef IARGS
198 iargcnt += o->oargs.niargs;
199 #endif
200 namecnt += strlen(o->oname)+1;
201 }
202 if (n < OBJBLKSIZ/10) /* never happens? */
203 return;
204 /* prep consolidation object */
205 co = objblock[i]+OBJBLKSIZ;
206 co->oargs.nsargs = sargcnt;
207 co->oargs.nfargs = fargcnt;
208 if ((co->oargs.nsargs != sargcnt) | (co->oargs.nfargs != fargcnt))
209 return; /* overrun condition */
210
211 co->oname = (char *)malloc(sizeof(char)*namecnt);
212 co->oargs.sarg = (char **)malloc(sizeof(char *)*sargcnt);
213 co->oargs.farg = (RREAL *)malloc(sizeof(RREAL)*fargcnt);
214 if ((co->oname == NULL) | (co->oargs.sarg == NULL) |
215 (co->oargs.farg == NULL)) {
216 free(co->oname);
217 free(co->oargs.sarg); free(co->oargs.farg);
218 return; /* insufficient memory */
219 }
220 #ifdef IARGS
221 co->oargs.niargs = iargcnt;
222 co->oargs.iarg = (long *)malloc(sizeof(long)*iargcnt);
223 if (co->oargs.iarg == NULL) {
224 free(co->oname);
225 free(co->oargs.sarg); free(co->oargs.farg);
226 return; /* insufficient memory */
227 }
228 iargcnt = 0;
229 #endif
230 namecnt = sargcnt = fargcnt = 0;
231 for (o = objblock[i]+OBJBLKSIZ; o-- > objblock[i]; ) {
232 n = strlen(o->oname)+1;
233 memcpy(co->oname + namecnt, o->oname, n);
234 freeqstr(o->oname);
235 o->oname = co->oname + namecnt;
236 namecnt += n;
237 if (o->oargs.nsargs) {
238 memcpy(co->oargs.sarg+sargcnt, o->oargs.sarg,
239 sizeof(char *)*o->oargs.nsargs);
240 free(o->oargs.sarg);
241 o->oargs.sarg = co->oargs.sarg + sargcnt;
242 sargcnt += o->oargs.nsargs;
243 }
244 if (o->oargs.nfargs) {
245 memcpy(co->oargs.farg+fargcnt, o->oargs.farg,
246 sizeof(RREAL)*o->oargs.nfargs);
247 free(o->oargs.farg);
248 o->oargs.farg = co->oargs.farg + fargcnt;
249 fargcnt += o->oargs.nfargs;
250 }
251 #ifdef IARGS
252 if (o->oargs.niargs) {
253 memcpy(co->oargs.iarg+iargcnt, o->oargs.iarg,
254 sizeof(long)*o->oargs.niargs);
255 free(o->oargs.iarg);
256 o->oargs.iarg = co->oargs.iarg + iargcnt;
257 iargcnt += o->oargs.niargs;
258 }
259 #endif
260 }
261 co->otype = -1; /* flag for optimized block */
262 #endif
263 }
264
265
266 OBJECT
267 newobject(void) /* get a new object */
268 {
269 int i;
270
271 if ((nobjects & (OBJBLKSIZ-1)) == 0) { /* new block */
272 i = nobjects >> OBJBLKSHFT;
273 optimize_objblock(i-1); /* optimize previous block */
274 errno = 0;
275 if (i >= MAXOBJBLK)
276 return(OVOID);
277 objblock[i] = (OBJREC *)calloc(OBJBLKSIZ+OBJMEMOPT,
278 sizeof(OBJREC));
279 if (objblock[i] == NULL)
280 return(OVOID);
281 }
282 return(nobjects++);
283 }
284
285 void
286 freeobjects( /* free a range of objects */
287 int firstobj,
288 int nobjs
289 )
290 {
291 int obj;
292 /* check bounds */
293 if (firstobj < 0)
294 return;
295 if (nobjs <= 0)
296 return;
297 if (firstobj + nobjs > nobjects)
298 return;
299 /* clear objects */
300 for (obj = firstobj+nobjs; obj-- > firstobj; ) {
301 OBJREC *o = objptr(obj);
302 free_os(o); /* free client memory */
303 if (!OBJMEMOPT || !objblock[obj>>OBJBLKSHFT][OBJBLKSIZ].otype) {
304 freeqstr(o->oname);
305 freefargs(&o->oargs);
306 }
307 memset(o, 0, sizeof(OBJREC));
308 }
309 /* free objects off end */
310 for (obj = nobjects; obj-- > 0; )
311 if (objptr(obj)->oname != NULL)
312 break;
313 if (++obj >= nobjects)
314 return;
315 while (nobjects > obj) /* free empty end blocks */
316 if ((--nobjects & (OBJBLKSIZ-1)) == 0) {
317 int i = nobjects >> OBJBLKSHFT;
318 /* consolidated block? */
319 if (OBJMEMOPT && objblock[i][OBJBLKSIZ].otype < 0) {
320 free(objblock[i][OBJBLKSIZ].oname);
321 freefargs(&objblock[i][OBJBLKSIZ].oargs);
322 }
323 free(objblock[i]);
324 objblock[i] = NULL;
325 }
326 truncobjndx(); /* truncate modifier look-up */
327 }