1 /*
2 * Copyright (c) 2005
3 * David Leonard. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of David Leonard nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
20 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
21 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
23 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
27 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #if HAVE_CONFIG_H
32 # include <config.h>
33 #endif
34
35 #if STDC_HEADERS
36 # include <stdio.h>
37 # include <stdlib.h>
38 #endif
39
40 #if HAVE_TIME
41 # if TIME_WITH_SYS_TIME
42 # include <sys/time.h>
43 # include <time.h>
44 # else
45 # if HAVE_SYS_TIME_H
46 # include <sys/time.h>
47 # else
48 # include <time.h>
49 # endif
50 # endif
51 #endif
52
53 #if WITH_BOEHM_GC
54 # include <gc/gc.h>
55 #endif
56
57 #include <see/interpreter.h>
58 #include <see/system.h>
59
60 #include "dprint.h"
61 #include "platform.h"
62 #include "code.h"
63 #include "regex.h"
64
65 /* Prototypes */
66 static unsigned int simple_random_seed(void);
67 #if WITH_BOEHM_GC
68 static void *simple_gc_malloc(struct SEE_interpreter *, SEE_size_t,
69 const char *, int);
70 static void *simple_gc_malloc_string(struct SEE_interpreter *, SEE_size_t,
71 const char *, int);
72 static void *simple_gc_malloc_finalize(struct SEE_interpreter *, SEE_size_t,
73 void (*)(struct SEE_interpreter *, void *, void *), void *,
74 const char *, int);
75 static void simple_gc_free(struct SEE_interpreter *, void *,
76 const char *, int);
77 static void simple_gc_finalizer(void *, void *);
78 static void simple_gc_gcollect(struct SEE_interpreter *);
79 #else
80 static void *simple_malloc(struct SEE_interpreter *, SEE_size_t,
81 const char *, int);
82 static void *simple_malloc_finalize(struct SEE_interpreter *, SEE_size_t,
83 void (*)(struct SEE_interpreter *, void *, void *), void *,
84 const char *, int);
85 static void simple_free(struct SEE_interpreter *, void *,
86 const char *, int);
87 static void simple_finalize_all(void);
88 #endif
89 static void simple_mem_exhausted(struct SEE_interpreter *) SEE_dead;
90
91 /*
92 * System defaults. This structure should be not be modified after
93 * interpreters are created.
94 */
95 struct SEE_system SEE_system = {
96 NULL, /* default_locale */
97 -1, /* default_recursion_limit */
98 NULL, /* default_trace */
99
100 SEE_COMPAT_262_3B, /* default_compat_flags */
101
102 simple_random_seed, /* random_seed */
103
104 _SEE_platform_abort, /* abort */
105 NULL, /* periodic */
106
107 #if WITH_BOEHM_GC
108 simple_gc_malloc, /* malloc */
109 simple_gc_malloc_finalize, /* malloc_finalize */
110 simple_gc_malloc_string, /* malloc_string */
111 simple_gc_free, /* free */
112 simple_mem_exhausted, /* mem_exhausted */
113 simple_gc_gcollect, /* gcollect */
114 #else
115 simple_malloc, /* malloc */
116 simple_malloc_finalize, /* malloc_finalize */
117 simple_malloc, /* malloc_string */
118 simple_free, /* free */
119 simple_mem_exhausted, /* mem_exhausted */
120 NULL, /* gcollect */
121 #endif
122 NULL, /* transit_sec_domain */
123 #if WITH_PARSER_CODEGEN
124 _SEE_code1_alloc, /* code_alloc */
125 #else
126 NULL, /* code_alloc */
127 #endif
128 NULL, /* object_construct */
129 &_SEE_ecma_regex_engine /* default_regex_engine */
130 };
131
132 /*
133 * A simple random number seed generator. It is not thread safe.
134 */
135 static unsigned int
simple_random_seed()136 simple_random_seed()
137 {
138 static unsigned int counter = 0;
139 unsigned int r;
140
141 r = counter++;
142 #if HAVE_TIME
143 r += (unsigned int)time(0);
144 #endif
145 return r;
146 }
147
148 /*
149 * A simple memory exhausted handler.
150 */
151 static void
simple_mem_exhausted(interp)152 simple_mem_exhausted(interp)
153 struct SEE_interpreter *interp;
154 {
155 SEE_ABORT(interp, "memory exhausted");
156 }
157
158
159 #if WITH_BOEHM_GC
160
161 /* Redefine GC_EXTRAS as a quick, happy way to pass through the file,line */
162 #undef GC_EXTRAS
163 #ifdef GC_ADD_CALLER
164 # define GC_EXTRAS GC_RETURN_ADDR, file, line
165 #else
166 # define GC_EXTRAS file, line
167 #endif
168
169 /*
170 * Memory allocator using Boehm GC
171 */
172 static void *
simple_gc_malloc(interp,size,file,line)173 simple_gc_malloc(interp, size, file, line)
174 struct SEE_interpreter *interp;
175 SEE_size_t size;
176 const char *file;
177 int line;
178 {
179 return GC_MALLOC(size);
180 }
181
182 /*
183 * A private structure to hold finalization info. This is appended onto
184 * objects that are allocated with finalization requirements.
185 */
186 struct finalize_info {
187 struct SEE_interpreter *interp;
188 void (*finalizefn)(struct SEE_interpreter *, void *, void *);
189 void *closure;
190 };
191
192 static void
simple_gc_finalizer(p,cd)193 simple_gc_finalizer(p, cd)
194 void *p;
195 void *cd;
196 {
197 struct finalize_info *info =
198 (struct finalize_info *)((char *)p + (SEE_size_t)cd);
199
200 (*info->finalizefn)(info->interp, (void *)p, info->closure);
201 }
202
203 static void *
simple_gc_malloc_finalize(interp,size,finalizefn,closure,file,line)204 simple_gc_malloc_finalize(interp, size, finalizefn, closure, file, line)
205 struct SEE_interpreter *interp;
206 SEE_size_t size;
207 void (*finalizefn)(struct SEE_interpreter *, void *, void *);
208 void *closure;
209 const char *file;
210 int line;
211 {
212 SEE_size_t padsz;
213 void *data;
214 struct finalize_info *info;
215
216 /* Round up to align the finalize_info */
217 padsz = size;
218 padsz += sizeof (struct finalize_info) - 1;
219 padsz -= padsz % sizeof (struct finalize_info);
220
221 /* Allocate, with space for the finalize_info */
222 data = GC_MALLOC(padsz + sizeof (struct finalize_info));
223
224 /* Fill in the finalize_info now */
225 info = (struct finalize_info *)((char *)data + padsz);
226 info->interp = interp;
227 info->finalizefn = finalizefn;
228 info->closure = closure;
229
230 /* Ask the GC to call the finalizer when data is unreachable */
231 GC_REGISTER_FINALIZER(data, simple_gc_finalizer, (void *)padsz, NULL, NULL);
232
233 return data;
234 }
235
236 /*
237 * Non-pointer memory allocator using Boehm GC
238 */
239 static void *
simple_gc_malloc_string(interp,size,file,line)240 simple_gc_malloc_string(interp, size, file, line)
241 struct SEE_interpreter *interp;
242 SEE_size_t size;
243 const char *file;
244 int line;
245 {
246 return GC_MALLOC_ATOMIC(size);
247 }
248
249 /*
250 * Non-pointer memory allocator using Boehm GC
251 */
252 static void
simple_gc_free(interp,ptr,file,line)253 simple_gc_free(interp, ptr, file, line)
254 struct SEE_interpreter *interp;
255 void *ptr;
256 const char *file;
257 int line;
258 {
259 GC_FREE(ptr);
260 }
261
262 static void
simple_gc_gcollect(interp)263 simple_gc_gcollect(interp)
264 struct SEE_interpreter *interp;
265 {
266 GC_gcollect();
267 }
268
269 #else /* !WITH_BOEHM_GC */
270
271
272 /*
273 * Memory allocator using system malloc().
274 * Note: most mallocs do not get freed!
275 * System strongly assumes a garbage collector.
276 * This is a stub function.
277 */
278 static void *
simple_malloc(interp,size,file,line)279 simple_malloc(interp, size, file, line)
280 struct SEE_interpreter *interp;
281 SEE_size_t size;
282 const char *file;
283 int line;
284 {
285 #ifndef NDEBUG
286 static int warning_printed = 0;
287
288 if (!warning_printed) {
289 warning_printed++;
290 dprintf("WARNING: SEE is using non-release malloc\n");
291 }
292
293 #endif
294 return malloc(size);
295 }
296
297 /* Linked list of all finalizers to run on exit */
298 static struct finalize_entry {
299 struct SEE_interpreter *interp;
300 void *ptr;
301 void (*finalizefn)(struct SEE_interpreter *, void *, void *);
302 void *closure;
303 struct finalize_entry *next;
304 } *simple_finalize_list;
305
306 /* Runs all the finalizers */
307 static void
simple_finalize_all()308 simple_finalize_all()
309 {
310 struct finalize_entry *entry;
311 #ifndef NDEBUG
312 extern int SEE_mem_debug;
313 #endif
314
315 #ifndef NDEBUG
316 if (SEE_mem_debug)
317 dprintf("Running finalizers\n");
318 #endif
319
320 while (simple_finalize_list) {
321 entry = simple_finalize_list;
322 simple_finalize_list = entry->next;
323 (*entry->finalizefn)(entry->interp, entry->ptr, entry->closure);
324 free(entry);
325 }
326 }
327
328 static void *
simple_malloc_finalize(interp,size,finalizefn,closure,file,line)329 simple_malloc_finalize(interp, size, finalizefn, closure, file, line)
330 struct SEE_interpreter *interp;
331 SEE_size_t size;
332 void (*finalizefn)(struct SEE_interpreter *, void *, void *);
333 void *closure;
334 const char *file;
335 int line;
336 {
337 static int called = 0;
338 struct finalize_entry *entry;
339 void *ptr;
340
341 ptr = malloc(size);
342 if (!ptr)
343 return NULL;
344
345 /* Record the finalization function to call at exit */
346 entry = (struct finalize_entry *)malloc(sizeof *entry);
347 if (entry) {
348 entry->interp = interp;
349 entry->ptr = ptr;
350 entry->finalizefn = finalizefn;
351 entry->closure = closure;
352 /* Insert at head of list */
353 entry->next = simple_finalize_list;
354 simple_finalize_list = entry;
355 /* Set up finalizers to be run during exit() */
356 if (!called) {
357 called = 1;
358 atexit(simple_finalize_all);
359 }
360 }
361
362 return ptr;
363 }
364
365 /*
366 * Memory deallocator using system free().
367 */
368 static void
simple_free(interp,ptr,file,line)369 simple_free(interp, ptr, file, line)
370 struct SEE_interpreter *interp;
371 void *ptr;
372 const char *file;
373 int line;
374 {
375 free(ptr);
376 }
377
378 #endif /* !WITH_BOEHM_GC */
379
380
381 /* Reserved for future use */
382 void
SEE_init()383 SEE_init()
384 {
385 static int initialised = 0;
386
387 if (initialised)
388 return;
389 initialised = 1;
390
391 SEE_regex_init();
392 }
393