clang -cc1 -triple i386-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name heap.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mthread-model posix -mframe-pointer=none -fmath-errno -fno-rounding-math -masm-verbose -mconstructor-aliases -target-cpu i686 -dwarf-column-info -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib/llvm-10/lib/clang/10.0.0 -I ./include -I ./include/extensions -I platform/linux/include -D _PRELUDE -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-10/lib/clang/10.0.0/include -internal-externc-isystem /usr/include/i386-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -std=c99 -fdebug-compilation-dir /home/joels/Current/lispbm -ferror-limit 19 -fmessage-length 0 -fgnuc-version=4.2.1 -fobjc-runtime=gcc -fdiagnostics-show-option -vectorize-loops -vectorize-slp -analyzer-output=html -faddrsig -o /home/joels/Current/lispbm/test_reports/version_0.25.0/scan-build/2024-07-23-152344-239046-1 -x c src/heap.c
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | #include <stdio.h> |
20 | #include <stdlib.h> |
21 | #include <stdint.h> |
22 | #include <stdarg.h> |
23 | #include <inttypes.h> |
24 | #include <lbm_memory.h> |
25 | #include <lbm_custom_type.h> |
26 | |
27 | #include "heap.h" |
28 | #include "symrepr.h" |
29 | #include "stack.h" |
30 | #include "lbm_channel.h" |
31 | #include "platform_mutex.h" |
32 | #include "eval_cps.h" |
33 | #ifdef VISUALIZE_HEAP |
34 | #include "heap_vis.h" |
35 | #endif |
36 | |
37 | |
38 | static inline lbm_value lbm_set_gc_mark(lbm_value x) { |
39 | return x | LBM_GC_MARKED; |
40 | } |
41 | |
42 | static inline lbm_value lbm_clr_gc_mark(lbm_value x) { |
43 | return x & ~LBM_GC_MASK; |
44 | } |
45 | |
46 | static inline bool lbm_get_gc_mark(lbm_value x) { |
47 | return x & LBM_GC_MASK; |
48 | } |
49 | |
50 | |
51 | static inline bool lbm_get_gc_flag(lbm_value x) { |
52 | return x & LBM_GC_MARKED; |
53 | } |
54 | |
55 | static inline lbm_value lbm_set_gc_flag(lbm_value x) { |
56 | return x | LBM_GC_MARKED; |
57 | } |
58 | |
59 | static inline lbm_value lbm_clr_gc_flag(lbm_value x) { |
60 | return x & ~LBM_GC_MASK; |
61 | } |
62 | |
63 | |
64 | lbm_heap_state_t lbm_heap_state; |
65 | |
66 | lbm_const_heap_t *lbm_const_heap_state; |
67 | |
68 | lbm_cons_t *lbm_heaps[2] = {NULL, NULL}; |
69 | |
70 | static mutex_t lbm_const_heap_mutex; |
71 | static bool lbm_const_heap_mutex_initialized = false; |
72 | |
73 | static mutex_t lbm_mark_mutex; |
74 | static bool lbm_mark_mutex_initialized = false; |
75 | |
76 | #ifdef USE_GC_PTR_REV |
77 | void lbm_gc_lock(void) { |
78 | mutex_lock(&lbm_mark_mutex); |
79 | } |
80 | void lbm_gc_unlock(void) { |
81 | mutex_unlock(&lbm_mark_mutex); |
82 | } |
83 | #else |
84 | void lbm_gc_lock(void) { |
85 | } |
86 | void lbm_gc_unlock(void) { |
87 | } |
88 | #endif |
89 | |
90 | |
91 | |
92 | |
93 | lbm_value lbm_enc_i32(int32_t x) { |
94 | #ifndef LBM64 |
95 | lbm_value i = lbm_cons((lbm_uint)x, ENC_SYM_RAW_I_TYPE); |
96 | if (lbm_type_of(i) == LBM_TYPE_SYMBOL) return i; |
97 | return lbm_set_ptr_type(i, LBM_TYPE_I32); |
98 | #else |
99 | return (((lbm_uint)x) << LBM_VAL_SHIFT) | LBM_TYPE_I32; |
100 | #endif |
101 | } |
102 | |
103 | lbm_value lbm_enc_u32(uint32_t x) { |
104 | #ifndef LBM64 |
105 | lbm_value u = lbm_cons(x, ENC_SYM_RAW_U_TYPE); |
106 | if (lbm_type_of(u) == LBM_TYPE_SYMBOL) return u; |
107 | return lbm_set_ptr_type(u, LBM_TYPE_U32); |
108 | #else |
109 | return (((lbm_uint)x) << LBM_VAL_SHIFT) | LBM_TYPE_U32; |
110 | #endif |
111 | } |
112 | |
113 | lbm_value lbm_enc_float(float x) { |
114 | #ifndef LBM64 |
115 | lbm_uint t; |
116 | memcpy(&t, &x, sizeof(lbm_float)); |
117 | lbm_value f = lbm_cons(t, ENC_SYM_RAW_F_TYPE); |
118 | if (lbm_type_of(f) == LBM_TYPE_SYMBOL) return f; |
119 | return lbm_set_ptr_type(f, LBM_TYPE_FLOAT); |
120 | #else |
121 | lbm_uint t = 0; |
122 | memcpy(&t, &x, sizeof(float)); |
123 | return (((lbm_uint)t) << LBM_VAL_SHIFT) | LBM_TYPE_FLOAT; |
124 | #endif |
125 | } |
126 | |
127 | static lbm_value enc_64_on_32(uint8_t *source, lbm_uint type_qual, lbm_uint type) { |
128 | lbm_value res = ENC_SYM_MERROR; |
129 | res = lbm_cons(ENC_SYM_NIL,ENC_SYM_NIL); |
130 | if (lbm_type_of(res) != LBM_TYPE_SYMBOL) { |
131 | uint8_t* storage = lbm_malloc(sizeof(uint64_t)); |
132 | if (storage) { |
133 | memcpy(storage,source, sizeof(uint64_t)); |
134 | lbm_set_car_and_cdr(res, (lbm_uint)storage, type_qual); |
135 | res = lbm_set_ptr_type(res, type); |
136 | } else { |
137 | res = ENC_SYM_MERROR; |
138 | } |
139 | } |
140 | return res; |
141 | } |
142 | |
143 | lbm_value lbm_enc_i64(int64_t x) { |
144 | #ifndef LBM64 |
145 | return enc_64_on_32((uint8_t *)&x, ENC_SYM_IND_I_TYPE, LBM_TYPE_I64); |
146 | #else |
147 | lbm_value u = lbm_cons((uint64_t)x, ENC_SYM_RAW_I_TYPE); |
148 | if (lbm_type_of(u) == LBM_TYPE_SYMBOL) return u; |
149 | return lbm_set_ptr_type(u, LBM_TYPE_I64); |
150 | #endif |
151 | } |
152 | |
153 | lbm_value lbm_enc_u64(uint64_t x) { |
154 | #ifndef LBM64 |
155 | return enc_64_on_32((uint8_t *)&x, ENC_SYM_IND_U_TYPE, LBM_TYPE_U64); |
156 | #else |
157 | lbm_value u = lbm_cons(x, ENC_SYM_RAW_U_TYPE); |
158 | if (lbm_type_of(u) == LBM_TYPE_SYMBOL) return u; |
159 | return lbm_set_ptr_type(u, LBM_TYPE_U64); |
160 | #endif |
161 | } |
162 | |
163 | lbm_value lbm_enc_double(double x) { |
164 | #ifndef LBM64 |
165 | return enc_64_on_32((uint8_t *)&x, ENC_SYM_IND_F_TYPE, LBM_TYPE_DOUBLE); |
166 | #else |
167 | lbm_uint t; |
168 | memcpy(&t, &x, sizeof(double)); |
169 | lbm_value f = lbm_cons(t, ENC_SYM_RAW_F_TYPE); |
170 | if (lbm_type_of(f) == LBM_TYPE_SYMBOL) return f; |
171 | return lbm_set_ptr_type(f, LBM_TYPE_DOUBLE); |
172 | #endif |
173 | } |
174 | |
175 | |
176 | |
177 | |
178 | |
179 | float lbm_dec_float(lbm_value x) { |
180 | #ifndef LBM64 |
181 | float f_tmp; |
182 | lbm_uint tmp = lbm_car(x); |
183 | memcpy(&f_tmp, &tmp, sizeof(float)); |
184 | return f_tmp; |
185 | #else |
186 | uint32_t tmp = (uint32_t)(x >> LBM_VAL_SHIFT); |
187 | float f_tmp; |
188 | memcpy(&f_tmp, &tmp, sizeof(float)); |
189 | return f_tmp; |
190 | #endif |
191 | } |
192 | |
193 | double lbm_dec_double(lbm_value x) { |
194 | #ifndef LBM64 |
195 | double d; |
196 | uint32_t *data = (uint32_t*)lbm_car(x); |
197 | memcpy(&d, data, sizeof(double)); |
198 | return d; |
199 | #else |
200 | double f_tmp; |
201 | lbm_uint tmp = lbm_car(x); |
202 | memcpy(&f_tmp, &tmp, sizeof(double)); |
203 | return f_tmp; |
204 | #endif |
205 | } |
206 | |
207 | uint64_t lbm_dec_u64(lbm_value x) { |
208 | #ifndef LBM64 |
209 | uint64_t u; |
210 | uint32_t *data = (uint32_t*)lbm_car(x); |
211 | memcpy(&u, data, 8); |
212 | return u; |
213 | #else |
214 | return (uint64_t)lbm_car(x); |
215 | #endif |
216 | } |
217 | |
218 | int64_t lbm_dec_i64(lbm_value x) { |
219 | #ifndef LBM64 |
220 | int64_t i; |
221 | uint32_t *data = (uint32_t*)lbm_car(x); |
222 | memcpy(&i, data, 8); |
223 | return i; |
224 | #else |
225 | return (int64_t)lbm_car(x); |
226 | #endif |
227 | } |
228 | |
229 | char *lbm_dec_str(lbm_value val) { |
230 | char *res = 0; |
231 | |
232 | if (lbm_is_array_r(val)) { |
| 1 | Calling 'lbm_is_array_r' | |
|
| 4 | | Returning from 'lbm_is_array_r' | |
|
| |
233 | lbm_array_header_t *array = (lbm_array_header_t *)lbm_car(val); |
| |
| 12 | | Returning from 'lbm_car' | |
|
| 13 | | 'array' initialized to a null pointer value | |
|
234 | res = (char *)array->data; |
| 14 | | Access to field 'data' results in a dereference of a null pointer (loaded from variable 'array') |
|
235 | } |
236 | return res; |
237 | } |
238 | |
239 | lbm_char_channel_t *lbm_dec_channel(lbm_value val) { |
240 | lbm_char_channel_t *res = NULL; |
241 | |
242 | if (lbm_type_of(val) == LBM_TYPE_CHANNEL) { |
243 | res = (lbm_char_channel_t *)lbm_car(val); |
244 | } |
245 | return res; |
246 | } |
247 | |
248 | lbm_uint lbm_dec_custom(lbm_value val) { |
249 | lbm_uint res = 0; |
250 | if (lbm_type_of(val) == LBM_TYPE_CUSTOM) { |
251 | res = (lbm_uint)lbm_car(val); |
252 | } |
253 | return res; |
254 | } |
255 | |
256 | uint8_t lbm_dec_as_char(lbm_value a) { |
257 | switch (lbm_type_of_functional(a)) { |
258 | case LBM_TYPE_CHAR: |
259 | return (uint8_t) lbm_dec_char(a); |
260 | case LBM_TYPE_I: |
261 | return (uint8_t) lbm_dec_i(a); |
262 | case LBM_TYPE_U: |
263 | return (uint8_t) lbm_dec_u(a); |
264 | case LBM_TYPE_I32: |
265 | return (uint8_t) lbm_dec_i32(a); |
266 | case LBM_TYPE_U32: |
267 | return (uint8_t) lbm_dec_u32(a); |
268 | case LBM_TYPE_FLOAT: |
269 | return (uint8_t)lbm_dec_float(a); |
270 | case LBM_TYPE_I64: |
271 | return (uint8_t) lbm_dec_i64(a); |
272 | case LBM_TYPE_U64: |
273 | return (uint8_t) lbm_dec_u64(a); |
274 | case LBM_TYPE_DOUBLE: |
275 | return (uint8_t) lbm_dec_double(a); |
276 | } |
277 | return 0; |
278 | } |
279 | |
280 | uint32_t lbm_dec_as_u32(lbm_value a) { |
281 | switch (lbm_type_of_functional(a)) { |
282 | case LBM_TYPE_CHAR: |
283 | return (uint32_t) lbm_dec_char(a); |
284 | case LBM_TYPE_I: |
285 | return (uint32_t) lbm_dec_i(a); |
286 | case LBM_TYPE_U: |
287 | return (uint32_t) lbm_dec_u(a); |
288 | case LBM_TYPE_I32: |
289 | case LBM_TYPE_U32: |
290 | return (uint32_t) lbm_dec_u32(a); |
291 | case LBM_TYPE_FLOAT: |
292 | return (uint32_t)lbm_dec_float(a); |
293 | case LBM_TYPE_I64: |
294 | return (uint32_t) lbm_dec_i64(a); |
295 | case LBM_TYPE_U64: |
296 | return (uint32_t) lbm_dec_u64(a); |
297 | case LBM_TYPE_DOUBLE: |
298 | return (uint32_t) lbm_dec_double(a); |
299 | } |
300 | return 0; |
301 | } |
302 | |
303 | int32_t lbm_dec_as_i32(lbm_value a) { |
304 | switch (lbm_type_of_functional(a)) { |
305 | case LBM_TYPE_CHAR: |
306 | return (int32_t) lbm_dec_char(a); |
307 | case LBM_TYPE_I: |
308 | return (int32_t) lbm_dec_i(a); |
309 | case LBM_TYPE_U: |
310 | return (int32_t) lbm_dec_u(a); |
311 | case LBM_TYPE_I32: |
312 | return (int32_t) lbm_dec_i32(a); |
313 | case LBM_TYPE_U32: |
314 | return (int32_t) lbm_dec_u32(a); |
315 | case LBM_TYPE_FLOAT: |
316 | return (int32_t) lbm_dec_float(a); |
317 | case LBM_TYPE_I64: |
318 | return (int32_t) lbm_dec_i64(a); |
319 | case LBM_TYPE_U64: |
320 | return (int32_t) lbm_dec_u64(a); |
321 | case LBM_TYPE_DOUBLE: |
322 | return (int32_t) lbm_dec_double(a); |
323 | |
324 | } |
325 | return 0; |
326 | } |
327 | |
328 | int64_t lbm_dec_as_i64(lbm_value a) { |
329 | switch (lbm_type_of_functional(a)) { |
330 | case LBM_TYPE_CHAR: |
331 | return (int64_t) lbm_dec_char(a); |
332 | case LBM_TYPE_I: |
333 | return lbm_dec_i(a); |
334 | case LBM_TYPE_U: |
335 | return (int64_t) lbm_dec_u(a); |
336 | case LBM_TYPE_I32: |
337 | return (int64_t) lbm_dec_i32(a); |
338 | case LBM_TYPE_U32: |
339 | return (int64_t) lbm_dec_u32(a); |
340 | case LBM_TYPE_FLOAT: |
341 | return (int64_t) lbm_dec_float(a); |
342 | case LBM_TYPE_I64: |
343 | return (int64_t) lbm_dec_i64(a); |
344 | case LBM_TYPE_U64: |
345 | return (int64_t) lbm_dec_u64(a); |
346 | case LBM_TYPE_DOUBLE: |
347 | return (int64_t) lbm_dec_double(a); |
348 | } |
349 | return 0; |
350 | } |
351 | |
352 | uint64_t lbm_dec_as_u64(lbm_value a) { |
353 | switch (lbm_type_of_functional(a)) { |
354 | case LBM_TYPE_CHAR: |
355 | return (uint64_t) lbm_dec_char(a); |
356 | case LBM_TYPE_I: |
357 | return (uint64_t) lbm_dec_i(a); |
358 | case LBM_TYPE_U: |
359 | return lbm_dec_u(a); |
360 | case LBM_TYPE_I32: |
361 | return (uint64_t) lbm_dec_i32(a); |
362 | case LBM_TYPE_U32: |
363 | return (uint64_t) lbm_dec_u32(a); |
364 | case LBM_TYPE_FLOAT: |
365 | return (uint64_t)lbm_dec_float(a); |
366 | case LBM_TYPE_I64: |
367 | return (uint64_t) lbm_dec_i64(a); |
368 | case LBM_TYPE_U64: |
369 | return (uint64_t) lbm_dec_u64(a); |
370 | case LBM_TYPE_DOUBLE: |
371 | return (uint64_t) lbm_dec_double(a); |
372 | } |
373 | return 0; |
374 | } |
375 | |
376 | lbm_uint lbm_dec_as_uint(lbm_value a) { |
377 | switch (lbm_type_of_functional(a)) { |
378 | case LBM_TYPE_CHAR: |
379 | return (lbm_uint) lbm_dec_char(a); |
380 | case LBM_TYPE_I: |
381 | return (lbm_uint) lbm_dec_i(a); |
382 | case LBM_TYPE_U: |
383 | return (lbm_uint) lbm_dec_u(a); |
384 | case LBM_TYPE_I32: |
385 | return (lbm_uint) lbm_dec_i32(a); |
386 | case LBM_TYPE_U32: |
387 | return (lbm_uint) lbm_dec_u32(a); |
388 | case LBM_TYPE_FLOAT: |
389 | return (lbm_uint) lbm_dec_float(a); |
390 | case LBM_TYPE_I64: |
391 | return (lbm_uint) lbm_dec_i64(a); |
392 | case LBM_TYPE_U64: |
393 | return (lbm_uint) lbm_dec_u64(a); |
394 | case LBM_TYPE_DOUBLE: |
395 | return (lbm_uint) lbm_dec_double(a); |
396 | } |
397 | return 0; |
398 | } |
399 | |
400 | lbm_int lbm_dec_as_int(lbm_value a) { |
401 | switch (lbm_type_of_functional(a)) { |
402 | case LBM_TYPE_CHAR: |
403 | return (lbm_int) lbm_dec_char(a); |
404 | case LBM_TYPE_I: |
405 | return (lbm_int) lbm_dec_i(a); |
406 | case LBM_TYPE_U: |
407 | return (lbm_int) lbm_dec_u(a); |
408 | case LBM_TYPE_I32: |
409 | return (lbm_int) lbm_dec_i32(a); |
410 | case LBM_TYPE_U32: |
411 | return (lbm_int) lbm_dec_u32(a); |
412 | case LBM_TYPE_FLOAT: |
413 | return (lbm_int)lbm_dec_float(a); |
414 | case LBM_TYPE_I64: |
415 | return (lbm_int) lbm_dec_i64(a); |
416 | case LBM_TYPE_U64: |
417 | return (lbm_int) lbm_dec_u64(a); |
418 | case LBM_TYPE_DOUBLE: |
419 | return (lbm_int) lbm_dec_double(a); |
420 | } |
421 | return 0; |
422 | } |
423 | |
424 | float lbm_dec_as_float(lbm_value a) { |
425 | |
426 | switch (lbm_type_of_functional(a)) { |
427 | case LBM_TYPE_CHAR: |
428 | return (float) lbm_dec_char(a); |
429 | case LBM_TYPE_I: |
430 | return (float) lbm_dec_i(a); |
431 | case LBM_TYPE_U: |
432 | return (float) lbm_dec_u(a); |
433 | case LBM_TYPE_I32: |
434 | return (float) lbm_dec_i32(a); |
435 | case LBM_TYPE_U32: |
436 | return (float) lbm_dec_u32(a); |
437 | case LBM_TYPE_FLOAT: |
438 | return (float) lbm_dec_float(a); |
439 | case LBM_TYPE_I64: |
440 | return (float) lbm_dec_i64(a); |
441 | case LBM_TYPE_U64: |
442 | return (float) lbm_dec_u64(a); |
443 | case LBM_TYPE_DOUBLE: |
444 | return (float) lbm_dec_double(a); |
445 | } |
446 | return 0; |
447 | } |
448 | |
449 | double lbm_dec_as_double(lbm_value a) { |
450 | |
451 | switch (lbm_type_of_functional(a)) { |
452 | case LBM_TYPE_CHAR: |
453 | return (double) lbm_dec_char(a); |
454 | case LBM_TYPE_I: |
455 | return (double) lbm_dec_i(a); |
456 | case LBM_TYPE_U: |
457 | return (double) lbm_dec_u(a); |
458 | case LBM_TYPE_I32: |
459 | return (double) lbm_dec_i32(a); |
460 | case LBM_TYPE_U32: |
461 | return (double) lbm_dec_u32(a); |
462 | case LBM_TYPE_FLOAT: |
463 | return (double) lbm_dec_float(a); |
464 | case LBM_TYPE_I64: |
465 | return (double) lbm_dec_i64(a); |
466 | case LBM_TYPE_U64: |
467 | return (double) lbm_dec_u64(a); |
468 | case LBM_TYPE_DOUBLE: |
469 | return (double) lbm_dec_double(a); |
470 | } |
471 | return 0; |
472 | } |
473 | |
474 | |
475 | |
476 | |
477 | static int generate_freelist(size_t num_cells) { |
478 | size_t i = 0; |
479 | |
480 | if (!lbm_heap_state.heap) return 0; |
481 | |
482 | lbm_heap_state.freelist = lbm_enc_cons_ptr(0); |
483 | |
484 | lbm_cons_t *t; |
485 | |
486 | |
487 | for (i = 1; i < num_cells; i ++) { |
488 | t = lbm_ref_cell(lbm_enc_cons_ptr(i-1)); |
489 | t->car = ENC_SYM_RECOVERED; |
490 | t->cdr = lbm_enc_cons_ptr(i); |
491 | } |
492 | |
493 | |
494 | t = lbm_ref_cell(lbm_enc_cons_ptr(num_cells-1)); |
495 | t->cdr = ENC_SYM_NIL; |
496 | |
497 | return 1; |
498 | } |
499 | |
500 | void lbm_nil_freelist(void) { |
501 | lbm_heap_state.freelist = ENC_SYM_NIL; |
502 | lbm_heap_state.num_alloc = lbm_heap_state.heap_size; |
503 | } |
504 | |
505 | static void heap_init_state(lbm_cons_t *addr, lbm_uint num_cells, |
506 | lbm_uint* gc_stack_storage, lbm_uint gc_stack_size) { |
507 | lbm_heap_state.heap = addr; |
508 | lbm_heap_state.heap_bytes = (unsigned int)(num_cells * sizeof(lbm_cons_t)); |
509 | lbm_heap_state.heap_size = num_cells; |
510 | |
511 | lbm_stack_create(&lbm_heap_state.gc_stack, gc_stack_storage, gc_stack_size); |
512 | |
513 | lbm_heap_state.num_alloc = 0; |
514 | lbm_heap_state.num_alloc_arrays = 0; |
515 | lbm_heap_state.gc_num = 0; |
516 | lbm_heap_state.gc_marked = 0; |
517 | lbm_heap_state.gc_recovered = 0; |
518 | lbm_heap_state.gc_recovered_arrays = 0; |
519 | lbm_heap_state.gc_least_free = num_cells; |
520 | lbm_heap_state.gc_last_free = num_cells; |
521 | } |
522 | |
523 | void lbm_heap_new_freelist_length(void) { |
524 | lbm_uint l = lbm_heap_state.heap_size - lbm_heap_state.num_alloc; |
525 | lbm_heap_state.gc_last_free = l; |
526 | if (l < lbm_heap_state.gc_least_free) |
527 | lbm_heap_state.gc_least_free = l; |
528 | } |
529 | |
530 | int lbm_heap_init(lbm_cons_t *addr, lbm_uint num_cells, |
531 | lbm_uint gc_stack_size) { |
532 | |
533 | if (((uintptr_t)addr % 8) != 0) return 0; |
534 | |
535 | memset(addr,0, sizeof(lbm_cons_t) * num_cells); |
536 | |
537 | lbm_uint *gc_stack_storage = (lbm_uint*)lbm_malloc(gc_stack_size * sizeof(lbm_uint)); |
538 | if (gc_stack_storage == NULL) return 0; |
539 | |
540 | heap_init_state(addr, num_cells, |
541 | gc_stack_storage, gc_stack_size); |
542 | |
543 | lbm_heaps[0] = addr; |
544 | |
545 | return generate_freelist(num_cells); |
546 | } |
547 | |
548 | lbm_uint lbm_heap_num_free(void) { |
549 | return lbm_heap_state.heap_size - lbm_heap_state.num_alloc; |
550 | } |
551 | |
552 | lbm_value lbm_heap_allocate_cell(lbm_type ptr_type, lbm_value car, lbm_value cdr) { |
553 | lbm_value res; |
554 | |
555 | res = lbm_heap_state.freelist; |
556 | if (lbm_type_of(res) == LBM_TYPE_CONS) { |
557 | lbm_uint heap_ix = lbm_dec_ptr(res); |
558 | lbm_heap_state.freelist = lbm_heap_state.heap[heap_ix].cdr; |
559 | lbm_heap_state.num_alloc++; |
560 | lbm_heap_state.heap[heap_ix].car = car; |
561 | lbm_heap_state.heap[heap_ix].cdr = cdr; |
562 | res = lbm_set_ptr_type(res, ptr_type); |
563 | return res; |
564 | } |
565 | return ENC_SYM_MERROR; |
566 | } |
567 | |
568 | lbm_value lbm_heap_allocate_list(lbm_uint n) { |
569 | if (n == 0) return ENC_SYM_NIL; |
570 | if (lbm_heap_num_free() < n) return ENC_SYM_MERROR; |
571 | |
572 | lbm_value curr = lbm_heap_state.freelist; |
573 | lbm_value res = curr; |
574 | if (lbm_type_of(curr) == LBM_TYPE_CONS) { |
575 | |
576 | lbm_cons_t *c_cell = NULL; |
577 | lbm_uint count = 0; |
578 | do { |
579 | c_cell = lbm_ref_cell(curr); |
580 | c_cell->car = ENC_SYM_NIL; |
581 | curr = c_cell->cdr; |
582 | count ++; |
583 | } while (count < n); |
584 | lbm_heap_state.freelist = curr; |
585 | c_cell->cdr = ENC_SYM_NIL; |
586 | lbm_heap_state.num_alloc+=count; |
587 | return res; |
588 | } |
589 | return ENC_SYM_FATAL_ERROR; |
590 | } |
591 | |
592 | lbm_value lbm_heap_allocate_list_init_va(unsigned int n, va_list valist) { |
593 | if (n == 0) return ENC_SYM_NIL; |
594 | if (lbm_heap_num_free() < n) return ENC_SYM_MERROR; |
595 | |
596 | lbm_value curr = lbm_heap_state.freelist; |
597 | lbm_value res = curr; |
598 | if (lbm_type_of(curr) == LBM_TYPE_CONS) { |
599 | |
600 | lbm_cons_t *c_cell = NULL; |
601 | unsigned int count = 0; |
602 | do { |
603 | c_cell = lbm_ref_cell(curr); |
604 | c_cell->car = va_arg(valist, lbm_value); |
605 | curr = c_cell->cdr; |
606 | count ++; |
607 | } while (count < n); |
608 | lbm_heap_state.freelist = curr; |
609 | c_cell->cdr = ENC_SYM_NIL; |
610 | lbm_heap_state.num_alloc+=count; |
611 | return res; |
612 | } |
613 | return ENC_SYM_FATAL_ERROR; |
614 | } |
615 | |
616 | lbm_value lbm_heap_allocate_list_init(unsigned int n, ...) { |
617 | va_list valist; |
618 | va_start(valist, n); |
619 | lbm_value r = lbm_heap_allocate_list_init_va(n, valist); |
620 | va_end(valist); |
621 | return r; |
622 | } |
623 | |
624 | lbm_uint lbm_heap_num_allocated(void) { |
625 | return lbm_heap_state.num_alloc; |
626 | } |
627 | lbm_uint lbm_heap_size(void) { |
628 | return lbm_heap_state.heap_size; |
629 | } |
630 | |
631 | lbm_uint lbm_heap_size_bytes(void) { |
632 | return lbm_heap_state.heap_bytes; |
633 | } |
634 | |
635 | void lbm_get_heap_state(lbm_heap_state_t *res) { |
636 | *res = lbm_heap_state; |
637 | } |
638 | |
639 | lbm_uint lbm_get_gc_stack_max(void) { |
640 | return lbm_heap_state.gc_stack.max_sp; |
641 | } |
642 | |
643 | lbm_uint lbm_get_gc_stack_size(void) { |
644 | return lbm_heap_state.gc_stack.size; |
645 | } |
646 | |
647 | #ifdef USE_GC_PTR_REV |
648 | static inline void value_assign(lbm_value *a, lbm_value b) { |
649 | lbm_value a_old = *a & LBM_GC_MASK; |
650 | *a = a_old | (b & ~LBM_GC_MASK); |
651 | } |
652 | |
653 | void lbm_gc_mark_phase(lbm_value root) { |
654 | bool work_to_do = true; |
655 | |
656 | if (!lbm_is_ptr(root)) return; |
657 | |
658 | mutex_lock(&lbm_const_heap_mutex); |
659 | lbm_value curr = root; |
660 | lbm_value prev = lbm_enc_cons_ptr(LBM_PTR_NULL); |
661 | |
662 | while (work_to_do) { |
663 | |
664 | while (lbm_is_ptr(curr) && |
665 | (lbm_dec_ptr(curr) != LBM_PTR_NULL) && |
666 | ((curr & LBM_PTR_TO_CONSTANT_BIT) == 0) && |
667 | !lbm_get_gc_mark(lbm_cdr(curr))) { |
668 | |
669 | lbm_cons_t *cell = lbm_ref_cell(curr); |
670 | cell->cdr = lbm_set_gc_mark(cell->cdr); |
671 | if (lbm_is_cons_rw(curr)) { |
672 | lbm_value next = 0; |
673 | value_assign(&next, cell->car); |
674 | value_assign(&cell->car, prev); |
675 | value_assign(&prev,curr); |
676 | value_assign(&curr, next); |
677 | } |
678 | |
679 | } |
680 | while (lbm_is_ptr(prev) && |
681 | (lbm_dec_ptr(prev) != LBM_PTR_NULL) && |
682 | lbm_get_gc_flag(lbm_car(prev)) ) { |
683 | |
684 | lbm_cons_t *cell = lbm_ref_cell(prev); |
685 | cell->car = lbm_clr_gc_flag(cell->car); |
686 | lbm_value next = 0; |
687 | value_assign(&next, cell->cdr); |
688 | value_assign(&cell->cdr, curr); |
689 | value_assign(&curr, prev); |
690 | value_assign(&prev, next); |
691 | } |
692 | if (lbm_is_ptr(prev) && |
693 | lbm_dec_ptr(prev) == LBM_PTR_NULL) { |
694 | work_to_do = false; |
695 | } else if (lbm_is_ptr(prev)) { |
696 | |
697 | lbm_cons_t *cell = lbm_ref_cell(prev); |
698 | cell->car = lbm_set_gc_flag(cell->car); |
699 | lbm_value next = 0; |
700 | value_assign(&next, cell->car); |
701 | value_assign(&cell->car, curr); |
702 | value_assign(&curr, cell->cdr); |
703 | value_assign(&cell->cdr, next); |
704 | } |
705 | } |
706 | mutex_unlock(&lbm_const_heap_mutex); |
707 | } |
708 | |
709 | #else |
710 | extern eval_context_t *ctx_running; |
711 | void lbm_gc_mark_phase(lbm_value root) { |
712 | lbm_value t_ptr; |
713 | lbm_stack_t *s = &lbm_heap_state.gc_stack; |
714 | s->data[s->sp++] = root; |
715 | |
716 | while (!lbm_stack_is_empty(s)) { |
717 | lbm_value curr; |
718 | lbm_pop(s, &curr); |
719 | |
720 | mark_shortcut: |
721 | |
722 | if (!lbm_is_ptr(curr) || |
723 | (curr & LBM_PTR_TO_CONSTANT_BIT)) { |
724 | continue; |
725 | } |
726 | |
727 | lbm_cons_t *cell = &lbm_heap_state.heap[lbm_dec_ptr(curr)]; |
728 | |
729 | if (lbm_get_gc_mark(cell->cdr)) { |
730 | continue; |
731 | } |
732 | |
733 | t_ptr = lbm_type_of(curr); |
734 | |
735 | |
736 | |
737 | |
738 | if (t_ptr == LBM_TYPE_LISPARRAY) { |
739 | lbm_push(s, curr); |
740 | lbm_array_header_extended_t *arr = (lbm_array_header_extended_t*)cell->car; |
741 | lbm_value *arrdata = (lbm_value *)arr->data; |
742 | uint32_t index = arr->index; |
743 | |
744 | |
745 | |
746 | |
747 | if (lbm_is_ptr(arrdata[index]) && ((arrdata[index] & LBM_PTR_TO_CONSTANT_BIT) == 0) && |
748 | !((arrdata[index] & LBM_CONTINUATION_INTERNAL) == LBM_CONTINUATION_INTERNAL)) { |
749 | lbm_cons_t *elt = &lbm_heap_state.heap[lbm_dec_ptr(arrdata[index])]; |
750 | if (!lbm_get_gc_mark(elt->cdr)) { |
751 | curr = arrdata[index]; |
752 | goto mark_shortcut; |
753 | } |
754 | } |
755 | if (index < ((arr->size/(sizeof(lbm_value))) - 1)) { |
756 | arr->index++; |
757 | continue; |
758 | } |
759 | |
760 | arr->index = 0; |
761 | cell->cdr = lbm_set_gc_mark(cell->cdr); |
762 | lbm_heap_state.gc_marked ++; |
763 | lbm_pop(s, &curr); |
764 | continue; |
765 | } |
766 | |
767 | cell->cdr = lbm_set_gc_mark(cell->cdr); |
768 | lbm_heap_state.gc_marked ++; |
769 | |
770 | if (t_ptr == LBM_TYPE_CONS) { |
771 | if (lbm_is_ptr(cell->cdr)) { |
772 | if (!lbm_push(s, cell->cdr)) { |
773 | lbm_critical_error(); |
774 | break; |
775 | } |
776 | } |
777 | curr = cell->car; |
778 | goto mark_shortcut; |
779 | } |
780 | } |
781 | } |
782 | #endif |
783 | |
784 | |
785 | void lbm_gc_mark_env(lbm_value env) { |
786 | lbm_value curr = env; |
787 | lbm_cons_t *c; |
788 | |
789 | while (lbm_is_ptr(curr)) { |
790 | c = lbm_ref_cell(curr); |
791 | c->cdr = lbm_set_gc_mark(c->cdr); |
792 | lbm_cons_t *b = lbm_ref_cell(c->car); |
793 | b->cdr = lbm_set_gc_mark(b->cdr); |
794 | lbm_gc_mark_phase(b->cdr); |
795 | lbm_heap_state.gc_marked +=2; |
796 | curr = c->cdr; |
797 | } |
798 | } |
799 | |
800 | |
801 | void lbm_gc_mark_aux(lbm_uint *aux_data, lbm_uint aux_size) { |
802 | for (lbm_uint i = 0; i < aux_size; i ++) { |
803 | if (lbm_is_ptr(aux_data[i])) { |
804 | lbm_type pt_t = lbm_type_of(aux_data[i]); |
805 | lbm_uint pt_v = lbm_dec_ptr(aux_data[i]); |
806 | if( pt_t >= LBM_POINTER_TYPE_FIRST && |
807 | pt_t <= LBM_POINTER_TYPE_LAST && |
808 | pt_v < lbm_heap_state.heap_size) { |
809 | lbm_gc_mark_phase(aux_data[i]); |
810 | } |
811 | } |
812 | } |
813 | } |
814 | |
815 | void lbm_gc_mark_roots(lbm_uint *roots, lbm_uint num_roots) { |
816 | for (lbm_uint i = 0; i < num_roots; i ++) { |
817 | lbm_gc_mark_phase(roots[i]); |
818 | } |
819 | } |
820 | |
821 | |
822 | int lbm_gc_sweep_phase(void) { |
823 | unsigned int i = 0; |
824 | lbm_cons_t *heap = (lbm_cons_t *)lbm_heap_state.heap; |
825 | |
826 | for (i = 0; i < lbm_heap_state.heap_size; i ++) { |
827 | if ( lbm_get_gc_mark(heap[i].cdr)) { |
828 | heap[i].cdr = lbm_clr_gc_mark(heap[i].cdr); |
829 | } else { |
830 | |
831 | |
832 | if (lbm_type_of(heap[i].cdr) == LBM_TYPE_SYMBOL) { |
833 | switch(heap[i].cdr) { |
834 | |
835 | case ENC_SYM_IND_I_TYPE: |
836 | case ENC_SYM_IND_U_TYPE: |
837 | case ENC_SYM_IND_F_TYPE: |
838 | lbm_memory_free((lbm_uint*)heap[i].car); |
839 | break; |
840 | case ENC_SYM_LISPARRAY_TYPE: |
841 | case ENC_SYM_ARRAY_TYPE:{ |
842 | lbm_array_header_t *arr = (lbm_array_header_t*)heap[i].car; |
843 | if (lbm_memory_ptr_inside((lbm_uint*)arr->data)) { |
844 | lbm_memory_free((lbm_uint *)arr->data); |
845 | lbm_heap_state.gc_recovered_arrays++; |
846 | } |
847 | lbm_memory_free((lbm_uint *)arr); |
848 | } break; |
849 | case ENC_SYM_CHANNEL_TYPE:{ |
850 | lbm_char_channel_t *chan = (lbm_char_channel_t*)heap[i].car; |
851 | if (lbm_memory_ptr_inside((lbm_uint*)chan)) { |
852 | lbm_memory_free((lbm_uint*)chan->state); |
853 | lbm_memory_free((lbm_uint*)chan); |
854 | } |
855 | } break; |
856 | case ENC_SYM_CUSTOM_TYPE: { |
857 | lbm_uint *t = (lbm_uint*)heap[i].car; |
858 | lbm_custom_type_destroy(t); |
859 | lbm_memory_free(t); |
860 | } break; |
861 | default: |
862 | break; |
863 | } |
864 | } |
865 | |
866 | lbm_uint addr = lbm_enc_cons_ptr(i); |
867 | |
868 | |
869 | heap[i].car = ENC_SYM_RECOVERED; |
870 | heap[i].cdr = lbm_heap_state.freelist; |
871 | lbm_heap_state.freelist = addr; |
872 | lbm_heap_state.num_alloc --; |
873 | lbm_heap_state.gc_recovered ++; |
874 | } |
875 | } |
876 | return 1; |
877 | } |
878 | |
879 | void lbm_gc_state_inc(void) { |
880 | lbm_heap_state.gc_num ++; |
881 | lbm_heap_state.gc_recovered = 0; |
882 | lbm_heap_state.gc_marked = 0; |
883 | } |
884 | |
885 | |
886 | lbm_value lbm_cons(lbm_value car, lbm_value cdr) { |
887 | return lbm_heap_allocate_cell(LBM_TYPE_CONS, car, cdr); |
888 | } |
889 | |
890 | lbm_value lbm_car(lbm_value c){ |
891 | |
892 | if (lbm_is_ptr(c) ){ |
| |
893 | lbm_cons_t *cell = lbm_ref_cell(c); |
894 | return cell->car; |
895 | } |
896 | |
897 | if (lbm_type_of(c) == LBM_TYPE_SYMBOL && |
| 8 | | Assuming the condition is true | |
|
| |
898 | c == ENC_SYM_NIL) { |
| 9 | | Assuming the condition is true | |
|
899 | return ENC_SYM_NIL; |
| |
900 | } |
901 | |
902 | return ENC_SYM_TERROR; |
903 | } |
904 | |
905 | |
906 | |
907 | |
908 | |
909 | lbm_value lbm_caar(lbm_value c) { |
910 | |
911 | lbm_value tmp; |
912 | |
913 | if (lbm_is_ptr(c)) { |
914 | tmp = lbm_ref_cell(c)->car; |
915 | |
916 | if (lbm_is_ptr(tmp)) { |
917 | return lbm_ref_cell(tmp)->car; |
918 | } else if (lbm_is_symbol(tmp) && tmp == ENC_SYM_NIL) { |
919 | return tmp; |
920 | } |
921 | } else if (lbm_is_symbol(c) && c == ENC_SYM_NIL) { |
922 | return c; |
923 | } |
924 | return ENC_SYM_TERROR; |
925 | } |
926 | |
927 | |
928 | lbm_value lbm_cadr(lbm_value c) { |
929 | |
930 | lbm_value tmp; |
931 | |
932 | if (lbm_is_ptr(c)) { |
933 | tmp = lbm_ref_cell(c)->cdr; |
934 | |
935 | if (lbm_is_ptr(tmp)) { |
936 | return lbm_ref_cell(tmp)->car; |
937 | } else if (lbm_is_symbol(tmp) && tmp == ENC_SYM_NIL) { |
938 | return tmp; |
939 | } |
940 | } else if (lbm_is_symbol(c) && c == ENC_SYM_NIL) { |
941 | return c; |
942 | } |
943 | return ENC_SYM_TERROR; |
944 | } |
945 | |
946 | lbm_value lbm_cdr(lbm_value c){ |
947 | |
948 | if (lbm_type_of(c) == LBM_TYPE_SYMBOL && |
949 | c == ENC_SYM_NIL) { |
950 | return ENC_SYM_NIL; |
951 | } |
952 | |
953 | if (lbm_is_ptr(c)) { |
954 | lbm_cons_t *cell = lbm_ref_cell(c); |
955 | return cell->cdr; |
956 | } |
957 | return ENC_SYM_TERROR; |
958 | } |
959 | |
960 | lbm_value lbm_cddr(lbm_value c) { |
961 | |
962 | if (lbm_is_ptr(c)) { |
963 | lbm_value tmp = lbm_ref_cell(c)->cdr; |
964 | if (lbm_is_ptr(tmp)) { |
965 | return lbm_ref_cell(tmp)->cdr; |
966 | } |
967 | } |
968 | if (lbm_is_symbol(c) && c == ENC_SYM_NIL) { |
969 | return ENC_SYM_NIL; |
970 | } |
971 | return ENC_SYM_TERROR; |
972 | } |
973 | |
974 | int lbm_set_car(lbm_value c, lbm_value v) { |
975 | int r = 0; |
976 | |
977 | if (lbm_type_of(c) == LBM_TYPE_CONS) { |
978 | lbm_cons_t *cell = lbm_ref_cell(c); |
979 | cell->car = v; |
980 | r = 1; |
981 | } |
982 | return r; |
983 | } |
984 | |
985 | int lbm_set_cdr(lbm_value c, lbm_value v) { |
986 | int r = 0; |
987 | if (lbm_is_cons_rw(c)){ |
988 | lbm_cons_t *cell = lbm_ref_cell(c); |
989 | cell->cdr = v; |
990 | r = 1; |
991 | } |
992 | return r; |
993 | } |
994 | |
995 | int lbm_set_car_and_cdr(lbm_value c, lbm_value car_val, lbm_value cdr_val) { |
996 | int r = 0; |
997 | if (lbm_is_cons_rw(c)) { |
998 | lbm_cons_t *cell = lbm_ref_cell(c); |
999 | cell->car = car_val; |
1000 | cell->cdr = cdr_val; |
1001 | r = 1; |
1002 | } |
1003 | return r; |
1004 | } |
1005 | |
1006 | |
1007 | lbm_uint lbm_list_length(lbm_value c) { |
1008 | lbm_uint len = 0; |
1009 | |
1010 | while (lbm_is_cons(c)){ |
1011 | len ++; |
1012 | c = lbm_cdr(c); |
1013 | } |
1014 | return len; |
1015 | } |
1016 | |
1017 | |
1018 | |
1019 | unsigned int lbm_list_length_pred(lbm_value c, bool *pres, bool (*pred)(lbm_value)) { |
1020 | bool res = true; |
1021 | unsigned int len = 0; |
1022 | |
1023 | while (lbm_is_cons(c)){ |
1024 | len ++; |
1025 | res = res && pred(lbm_car(c)); |
1026 | c = lbm_cdr(c); |
1027 | } |
1028 | *pres = res; |
1029 | return len; |
1030 | } |
1031 | |
1032 | |
1033 | lbm_value lbm_list_reverse(lbm_value list) { |
1034 | if (lbm_type_of(list) == LBM_TYPE_SYMBOL) { |
1035 | return list; |
1036 | } |
1037 | |
1038 | lbm_value curr = list; |
1039 | |
1040 | lbm_value new_list = ENC_SYM_NIL; |
1041 | while (lbm_is_cons(curr)) { |
1042 | |
1043 | new_list = lbm_cons(lbm_car(curr), new_list); |
1044 | if (lbm_type_of(new_list) == LBM_TYPE_SYMBOL) { |
1045 | return ENC_SYM_MERROR; |
1046 | } |
1047 | curr = lbm_cdr(curr); |
1048 | } |
1049 | return new_list; |
1050 | } |
1051 | |
1052 | lbm_value lbm_list_destructive_reverse(lbm_value list) { |
1053 | if (lbm_type_of(list) == LBM_TYPE_SYMBOL) { |
1054 | return list; |
1055 | } |
1056 | lbm_value curr = list; |
1057 | lbm_value last_cell = ENC_SYM_NIL; |
1058 | |
1059 | while (lbm_is_cons_rw(curr)) { |
1060 | lbm_value next = lbm_cdr(curr); |
1061 | lbm_set_cdr(curr, last_cell); |
1062 | last_cell = curr; |
1063 | curr = next; |
1064 | } |
1065 | return last_cell; |
1066 | } |
1067 | |
1068 | |
1069 | lbm_value lbm_list_copy(int *m, lbm_value list) { |
1070 | lbm_value curr = list; |
1071 | lbm_uint n = lbm_list_length(list); |
1072 | lbm_uint copy_n = n; |
1073 | if (*m >= 0 && (lbm_uint)*m < n) { |
1074 | copy_n = (lbm_uint)*m; |
1075 | } else if (*m == -1) { |
1076 | *m = (int)n; |
1077 | } |
1078 | if (copy_n == 0) return ENC_SYM_NIL; |
1079 | lbm_uint new_list = lbm_heap_allocate_list(copy_n); |
1080 | if (lbm_is_symbol(new_list)) return new_list; |
1081 | lbm_value curr_targ = new_list; |
1082 | |
1083 | while (lbm_is_cons(curr) && copy_n > 0) { |
1084 | lbm_value v = lbm_car(curr); |
1085 | lbm_set_car(curr_targ, v); |
1086 | curr_targ = lbm_cdr(curr_targ); |
1087 | curr = lbm_cdr(curr); |
1088 | copy_n --; |
1089 | } |
1090 | |
1091 | return new_list; |
1092 | } |
1093 | |
1094 | |
1095 | |
1096 | lbm_value lbm_list_append(lbm_value list1, lbm_value list2) { |
1097 | |
1098 | if(lbm_is_list_rw(list1) && |
1099 | lbm_is_list(list2)) { |
1100 | |
1101 | lbm_value curr = list1; |
1102 | while(lbm_type_of(lbm_cdr(curr)) == LBM_TYPE_CONS) { |
1103 | curr = lbm_cdr(curr); |
1104 | } |
1105 | if (lbm_is_symbol_nil(curr)) return list2; |
1106 | lbm_set_cdr(curr, list2); |
1107 | return list1; |
1108 | } |
1109 | return ENC_SYM_EERROR; |
1110 | } |
1111 | |
1112 | lbm_value lbm_list_drop(unsigned int n, lbm_value ls) { |
1113 | lbm_value curr = ls; |
1114 | while (lbm_type_of_functional(curr) == LBM_TYPE_CONS && |
1115 | n > 0) { |
1116 | curr = lbm_cdr(curr); |
1117 | n --; |
1118 | } |
1119 | return curr; |
1120 | } |
1121 | |
1122 | lbm_value lbm_index_list(lbm_value l, int32_t n) { |
1123 | lbm_value curr = l; |
1124 | |
1125 | if (n < 0) { |
1126 | int32_t len = (int32_t)lbm_list_length(l); |
1127 | n = len + n; |
1128 | if (n < 0) return ENC_SYM_NIL; |
1129 | } |
1130 | |
1131 | while (lbm_is_cons(curr) && |
1132 | n > 0) { |
1133 | curr = lbm_cdr(curr); |
1134 | n --; |
1135 | } |
1136 | if (lbm_is_cons(curr)) { |
1137 | return lbm_car(curr); |
1138 | } else { |
1139 | return ENC_SYM_NIL; |
1140 | } |
1141 | } |
1142 | |
1143 | |
1144 | |
1145 | |
1146 | |
1147 | |
1148 | |
1149 | int lbm_heap_allocate_array_base(lbm_value *res, bool byte_array, lbm_uint size){ |
1150 | |
1151 | lbm_array_header_t *array = NULL; |
1152 | |
1153 | if (byte_array) { |
1154 | array = (lbm_array_header_t*)lbm_malloc(sizeof(lbm_array_header_t)); |
1155 | } else { |
1156 | |
1157 | array = (lbm_array_header_t*)lbm_malloc(sizeof(lbm_array_header_extended_t)); |
1158 | } |
1159 | |
1160 | if (array == NULL) { |
1161 | *res = ENC_SYM_MERROR; |
1162 | return 0; |
1163 | } |
1164 | |
1165 | lbm_uint tag = ENC_SYM_ARRAY_TYPE; |
1166 | lbm_uint type = LBM_TYPE_ARRAY; |
1167 | if (!byte_array) { |
1168 | tag = ENC_SYM_LISPARRAY_TYPE; |
1169 | type = LBM_TYPE_LISPARRAY; |
1170 | size = sizeof(lbm_value) * size; |
1171 | lbm_array_header_extended_t *ext_array = (lbm_array_header_extended_t*)array; |
1172 | ext_array->index = 0; |
1173 | } |
1174 | |
1175 | array->data = (lbm_uint*)lbm_malloc(size); |
1176 | |
1177 | if (array->data == NULL) { |
1178 | lbm_memory_free((lbm_uint*)array); |
1179 | *res = ENC_SYM_MERROR; |
1180 | return 0; |
1181 | } |
1182 | |
1183 | |
1184 | memset(array->data, 0, size); |
1185 | array->size = size; |
1186 | |
1187 | |
1188 | lbm_value cell = lbm_heap_allocate_cell(type, (lbm_uint) array, tag); |
1189 | |
1190 | *res = cell; |
1191 | |
1192 | if (lbm_type_of(cell) == LBM_TYPE_SYMBOL) { |
1193 | lbm_memory_free((lbm_uint*)array->data); |
1194 | lbm_memory_free((lbm_uint*)array); |
1195 | *res = ENC_SYM_MERROR; |
1196 | return 0; |
1197 | } |
1198 | |
1199 | lbm_heap_state.num_alloc_arrays ++; |
1200 | |
1201 | return 1; |
1202 | } |
1203 | |
1204 | int lbm_heap_allocate_array(lbm_value *res, lbm_uint size){ |
1205 | return lbm_heap_allocate_array_base(res, true, size); |
1206 | } |
1207 | |
1208 | int lbm_heap_allocate_lisp_array(lbm_value *res, lbm_uint size) { |
1209 | return lbm_heap_allocate_array_base(res, false, size); |
1210 | } |
1211 | |
1212 | |
1213 | |
1214 | int lbm_lift_array(lbm_value *value, char *data, lbm_uint num_elt) { |
1215 | |
1216 | lbm_array_header_t *array = NULL; |
1217 | lbm_value cell = lbm_heap_allocate_cell(LBM_TYPE_CONS, ENC_SYM_NIL, ENC_SYM_ARRAY_TYPE); |
1218 | |
1219 | if (lbm_type_of(cell) == LBM_TYPE_SYMBOL) { |
1220 | *value = cell; |
1221 | return 0; |
1222 | } |
1223 | |
1224 | array = (lbm_array_header_t*)lbm_malloc(sizeof(lbm_array_header_t)); |
1225 | |
1226 | if (array == NULL) { |
1227 | lbm_set_car_and_cdr(cell, ENC_SYM_NIL, ENC_SYM_NIL); |
1228 | *value = ENC_SYM_MERROR; |
1229 | return 0; |
1230 | } |
1231 | |
1232 | array->data = (lbm_uint*)data; |
1233 | array->size = num_elt; |
1234 | |
1235 | lbm_set_car(cell, (lbm_uint)array); |
1236 | |
1237 | cell = lbm_set_ptr_type(cell, LBM_TYPE_ARRAY); |
1238 | *value = cell; |
1239 | return 1; |
1240 | } |
1241 | |
1242 | lbm_int lbm_heap_array_get_size(lbm_value arr) { |
1243 | |
1244 | lbm_int r = -1; |
1245 | if (lbm_is_array_r(arr)) { |
1246 | lbm_array_header_t *header = (lbm_array_header_t*)lbm_car(arr); |
1247 | if (header == NULL) { |
1248 | return r; |
1249 | } |
1250 | r = (lbm_int)header->size; |
1251 | } |
1252 | return r; |
1253 | } |
1254 | |
1255 | const uint8_t *lbm_heap_array_get_data_ro(lbm_value arr) { |
1256 | uint8_t *r = NULL; |
1257 | if (lbm_is_array_r(arr)) { |
1258 | lbm_array_header_t *header = (lbm_array_header_t*)lbm_car(arr); |
1259 | r = (uint8_t*)header->data; |
1260 | } |
1261 | return r; |
1262 | } |
1263 | |
1264 | uint8_t *lbm_heap_array_get_data_rw(lbm_value arr) { |
1265 | uint8_t *r = NULL; |
1266 | if (lbm_is_array_rw(arr)) { |
1267 | lbm_array_header_t *header = (lbm_array_header_t*)lbm_car(arr); |
1268 | r = (uint8_t*)header->data; |
1269 | } |
1270 | return r; |
1271 | } |
1272 | |
1273 | |
1274 | |
1275 | |
1276 | |
1277 | |
1278 | |
1279 | |
1280 | |
1281 | |
1282 | |
1283 | |
1284 | |
1285 | |
1286 | |
1287 | |
1288 | |
1289 | |
1290 | |
1291 | int lbm_heap_explicit_free_array(lbm_value arr) { |
1292 | |
1293 | int r = 0; |
1294 | if (lbm_is_array_rw(arr)) { |
1295 | |
1296 | lbm_array_header_t *header = (lbm_array_header_t*)lbm_car(arr); |
1297 | if (header == NULL) { |
1298 | return 0; |
1299 | } |
1300 | lbm_memory_free((lbm_uint*)header->data); |
1301 | lbm_memory_free((lbm_uint*)header); |
1302 | |
1303 | arr = lbm_set_ptr_type(arr, LBM_TYPE_CONS); |
1304 | lbm_set_car(arr, ENC_SYM_NIL); |
1305 | lbm_set_cdr(arr, ENC_SYM_NIL); |
1306 | r = 1; |
1307 | } |
1308 | |
1309 | return r; |
1310 | } |
1311 | |
1312 | lbm_uint lbm_size_of(lbm_type t) { |
1313 | lbm_uint s = 0; |
1314 | switch(t) { |
1315 | case LBM_TYPE_BYTE: |
1316 | s = 1; |
1317 | break; |
1318 | case LBM_TYPE_I: |
1319 | case LBM_TYPE_U: |
1320 | case LBM_TYPE_SYMBOL: |
1321 | s = sizeof(lbm_uint); |
1322 | break; |
1323 | case LBM_TYPE_I32: |
1324 | case LBM_TYPE_U32: |
1325 | case LBM_TYPE_FLOAT: |
1326 | s = 4; |
1327 | break; |
1328 | case LBM_TYPE_I64: |
1329 | case LBM_TYPE_U64: |
1330 | case LBM_TYPE_DOUBLE: |
1331 | s = 8; |
1332 | break; |
1333 | } |
1334 | return s; |
1335 | } |
1336 | |
1337 | static bool dummy_flash_write(lbm_uint ix, lbm_uint val) { |
1338 | (void)ix; |
1339 | (void)val; |
1340 | return false; |
1341 | } |
1342 | |
1343 | static const_heap_write_fun const_heap_write = dummy_flash_write; |
1344 | |
1345 | int lbm_const_heap_init(const_heap_write_fun w_fun, |
1346 | lbm_const_heap_t *heap, |
1347 | lbm_uint *addr, |
1348 | lbm_uint num_words) { |
1349 | if (((uintptr_t)addr % 4) != 0) return 0; |
1350 | if ((num_words % 2) != 0) return 0; |
1351 | |
1352 | if (!lbm_const_heap_mutex_initialized) { |
1353 | mutex_init(&lbm_const_heap_mutex); |
1354 | lbm_const_heap_mutex_initialized = true; |
1355 | } |
1356 | |
1357 | if (!lbm_mark_mutex_initialized) { |
1358 | mutex_init(&lbm_mark_mutex); |
1359 | lbm_mark_mutex_initialized = true; |
1360 | } |
1361 | |
1362 | const_heap_write = w_fun; |
1363 | |
1364 | heap->heap = addr; |
1365 | heap->size = num_words; |
1366 | heap->next = 0; |
1367 | |
1368 | lbm_const_heap_state = heap; |
1369 | |
1370 | lbm_heaps[1] = (lbm_cons_t*)addr; |
1371 | return 1; |
1372 | } |
1373 | |
1374 | lbm_flash_status lbm_allocate_const_cell(lbm_value *res) { |
1375 | lbm_flash_status r = LBM_FLASH_FULL; |
1376 | |
1377 | mutex_lock(&lbm_const_heap_mutex); |
1378 | |
1379 | if (lbm_const_heap_state->next % 2 == 1) { |
1380 | lbm_const_heap_state->next++; |
1381 | } |
1382 | |
1383 | if (lbm_const_heap_state && |
1384 | (lbm_const_heap_state->next+1) < lbm_const_heap_state->size) { |
1385 | |
1386 | lbm_value cell = lbm_const_heap_state->next; |
1387 | lbm_const_heap_state->next += 2; |
1388 | *res = (cell << LBM_ADDRESS_SHIFT) | LBM_PTR_BIT | LBM_TYPE_CONS | LBM_PTR_TO_CONSTANT_BIT; |
1389 | r = LBM_FLASH_WRITE_OK; |
1390 | } |
1391 | mutex_unlock(&lbm_const_heap_mutex); |
1392 | return r; |
1393 | } |
1394 | |
1395 | lbm_flash_status lbm_allocate_const_raw(lbm_uint nwords, lbm_uint *res) { |
1396 | lbm_flash_status r = LBM_FLASH_FULL; |
1397 | |
1398 | if (lbm_const_heap_state && |
1399 | (lbm_const_heap_state->next + nwords) < lbm_const_heap_state->size) { |
1400 | lbm_uint ix = lbm_const_heap_state->next; |
1401 | *res = (lbm_uint)&lbm_const_heap_state->heap[ix]; |
1402 | lbm_const_heap_state->next += nwords; |
1403 | r = LBM_FLASH_WRITE_OK; |
1404 | } |
1405 | return r; |
1406 | } |
1407 | |
1408 | lbm_flash_status lbm_write_const_raw(lbm_uint *data, lbm_uint n, lbm_uint *res) { |
1409 | |
1410 | lbm_flash_status r = LBM_FLASH_FULL; |
1411 | |
1412 | if (lbm_const_heap_state && |
1413 | (lbm_const_heap_state->next + n) < lbm_const_heap_state->size) { |
1414 | lbm_uint ix = lbm_const_heap_state->next; |
1415 | |
1416 | for (unsigned int i = 0; i < n; i ++) { |
1417 | if (!const_heap_write(ix + i, ((lbm_uint*)data)[i])) |
1418 | return LBM_FLASH_WRITE_ERROR; |
1419 | } |
1420 | lbm_const_heap_state->next += n; |
1421 | *res = (lbm_uint)&lbm_const_heap_state->heap[ix]; |
1422 | r = LBM_FLASH_WRITE_OK; |
1423 | } |
1424 | return r; |
1425 | } |
1426 | |
1427 | lbm_flash_status lbm_const_write(lbm_uint *tgt, lbm_uint val) { |
1428 | |
1429 | if (lbm_const_heap_state) { |
1430 | lbm_uint flash = (lbm_uint)lbm_const_heap_state->heap; |
1431 | lbm_uint ix = (((lbm_uint)tgt - flash) / 4); |
1432 | if (const_heap_write(ix, val)) { |
1433 | return LBM_FLASH_WRITE_OK; |
1434 | } |
1435 | return LBM_FLASH_WRITE_ERROR; |
1436 | } |
1437 | return LBM_FLASH_FULL; |
1438 | } |
1439 | |
1440 | lbm_flash_status write_const_cdr(lbm_value cell, lbm_value val) { |
1441 | lbm_uint addr = lbm_dec_ptr(cell); |
1442 | if (const_heap_write(addr+1, val)) |
1443 | return LBM_FLASH_WRITE_OK; |
1444 | return LBM_FLASH_WRITE_ERROR; |
1445 | } |
1446 | |
1447 | lbm_flash_status write_const_car(lbm_value cell, lbm_value val) { |
1448 | lbm_uint addr = lbm_dec_ptr(cell); |
1449 | if (const_heap_write(addr, val)) |
1450 | return LBM_FLASH_WRITE_OK; |
1451 | return LBM_FLASH_WRITE_ERROR; |
1452 | } |
1453 | |
1454 | lbm_uint lbm_flash_memory_usage(void) { |
1455 | return lbm_const_heap_state->next; |
1456 | } |
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | #ifndef HEAP_H_ |
21 | #define HEAP_H_ |
22 | |
23 | #include <string.h> |
24 | #include <stdarg.h> |
25 | |
26 | #include "lbm_types.h" |
27 | #include "symrepr.h" |
28 | #include "stack.h" |
29 | #include "lbm_memory.h" |
30 | #include "lbm_defines.h" |
31 | #include "lbm_channel.h" |
32 | |
33 | #ifdef __cplusplus |
34 | extern "C" { |
35 | #endif |
36 | |
37 | |
38 | |
39 | |
40 | |
41 | |
42 | |
43 | |
44 | |
45 | |
46 | |
47 | |
48 | |
49 | |
50 | |
51 | |
52 | |
53 | |
54 | |
55 | |
56 | |
57 | |
58 | |
59 | |
60 | |
61 | |
62 | |
63 | |
64 | |
65 | |
66 | |
67 | |
68 | |
69 | |
70 | |
71 | |
72 | |
73 | |
74 | |
75 | |
76 | |
77 | |
78 | |
79 | |
80 | |
81 | |
82 | |
83 | |
84 | |
85 | |
86 | |
87 | |
88 | |
89 | |
90 | |
91 | |
92 | |
93 | |
94 | |
95 | |
96 | |
97 | |
98 | |
99 | |
100 | |
101 | |
102 | |
103 | |
104 | |
105 | |
106 | |
107 | |
108 | |
109 | |
110 | |
111 | |
112 | |
113 | |
114 | |
115 | |
116 | |
117 | |
118 | |
119 | |
120 | |
121 | |
122 | |
123 | |
124 | |
125 | |
126 | |
127 | |
128 | |
129 | |
130 | |
131 | |
132 | |
133 | |
134 | |
135 | |
136 | |
137 | |
138 | |
139 | |
140 | |
141 | |
142 | |
143 | |
144 | |
145 | |
146 | |
147 | |
148 | |
149 | |
150 | |
151 | |
152 | |
153 | |
154 | |
155 | |
156 | |
157 | |
158 | |
159 | |
160 | |
161 | |
162 | |
163 | |
164 | |
165 | |
166 | |
167 | |
168 | |
169 | |
170 | |
171 | |
172 | |
173 | |
174 | |
175 | |
176 | |
177 | |
178 | |
179 | |
180 | |
181 | |
182 | |
183 | |
184 | |
185 | |
186 | |
187 | |
188 | |
189 | |
190 | |
191 | |
192 | |
193 | |
194 | |
195 | typedef enum { |
196 | LBM_FLASH_WRITE_OK, |
197 | LBM_FLASH_FULL, |
198 | LBM_FLASH_WRITE_ERROR |
199 | } lbm_flash_status; |
200 | |
201 | |
202 | |
203 | |
204 | typedef struct { |
205 | lbm_value car; |
206 | lbm_value cdr; |
207 | } lbm_cons_t; |
208 | |
209 | |
210 | |
211 | |
212 | typedef struct { |
213 | lbm_cons_t *heap; |
214 | lbm_value freelist; |
215 | lbm_stack_t gc_stack; |
216 | |
217 | lbm_uint heap_size; |
218 | lbm_uint heap_bytes; |
219 | |
220 | lbm_uint num_alloc; |
221 | lbm_uint num_alloc_arrays; |
222 | |
223 | lbm_uint gc_num; |
224 | lbm_uint gc_marked; |
225 | lbm_uint gc_recovered; |
226 | lbm_uint gc_recovered_arrays; |
227 | lbm_uint gc_least_free; |
228 | lbm_uint gc_last_free; |
229 | |
230 | } lbm_heap_state_t; |
231 | |
232 | extern lbm_heap_state_t lbm_heap_state; |
233 | |
234 | typedef bool (*const_heap_write_fun)(lbm_uint ix, lbm_uint w); |
235 | |
236 | typedef struct { |
237 | lbm_uint *heap; |
238 | lbm_uint next; |
239 | lbm_uint size; |
240 | } lbm_const_heap_t; |
241 | |
242 | |
243 | |
244 | |
245 | |
246 | |
247 | typedef struct { |
248 | lbm_uint size; |
249 | lbm_uint *data; |
250 | } lbm_array_header_t; |
251 | |
252 | typedef struct { |
253 | lbm_uint size; |
254 | lbm_uint *data; |
255 | uint32_t index; |
256 | } lbm_array_header_extended_t; |
257 | |
258 | |
259 | |
260 | |
261 | |
262 | void lbm_gc_lock(void); |
263 | |
264 | |
265 | void lbm_gc_unlock(void); |
266 | |
267 | |
268 | |
269 | |
270 | |
271 | |
272 | |
273 | int lbm_heap_init(lbm_cons_t *addr, lbm_uint num_cells, |
274 | lbm_uint gc_stack_size); |
275 | |
276 | |
277 | |
278 | |
279 | |
280 | void lbm_heap_new_gc_time(lbm_uint dur); |
281 | |
282 | |
283 | |
284 | |
285 | void lbm_heap_new_freelist_length(void); |
286 | |
287 | |
288 | |
289 | |
290 | lbm_uint lbm_heap_num_free(void); |
291 | |
292 | |
293 | |
294 | |
295 | lbm_uint lbm_heap_num_allocated(void); |
296 | |
297 | |
298 | |
299 | |
300 | lbm_uint lbm_heap_size(void); |
301 | |
302 | |
303 | |
304 | |
305 | lbm_uint lbm_heap_size_bytes(void); |
306 | |
307 | |
308 | |
309 | |
310 | |
311 | |
312 | |
313 | lbm_value lbm_heap_allocate_cell(lbm_type type, lbm_value car, lbm_value cdr); |
314 | |
315 | |
316 | |
317 | |
318 | lbm_value lbm_heap_allocate_list(lbm_uint n); |
319 | |
320 | |
321 | |
322 | |
323 | |
324 | |
325 | lbm_value lbm_heap_allocate_list_init_va(unsigned int n, va_list valist); |
326 | |
327 | |
328 | |
329 | |
330 | |
331 | lbm_value lbm_heap_allocate_list_init(unsigned int n, ...); |
332 | |
333 | |
334 | |
335 | |
336 | |
337 | char *lbm_dec_str(lbm_value val); |
338 | |
339 | |
340 | |
341 | |
342 | |
343 | lbm_char_channel_t *lbm_dec_channel(lbm_value val); |
344 | |
345 | |
346 | |
347 | |
348 | |
349 | lbm_uint lbm_dec_custom(lbm_value val); |
350 | |
351 | |
352 | |
353 | |
354 | |
355 | uint8_t lbm_dec_as_char(lbm_value a); |
356 | |
357 | |
358 | |
359 | |
360 | |
361 | uint32_t lbm_dec_as_u32(lbm_value val); |
362 | |
363 | |
364 | |
365 | |
366 | |
367 | int32_t lbm_dec_as_i32(lbm_value val); |
368 | |
369 | |
370 | |
371 | |
372 | |
373 | float lbm_dec_as_float(lbm_value val); |
374 | |
375 | |
376 | |
377 | |
378 | |
379 | uint64_t lbm_dec_as_u64(lbm_value val); |
380 | |
381 | |
382 | |
383 | |
384 | |
385 | int64_t lbm_dec_as_i64(lbm_value val); |
386 | |
387 | |
388 | |
389 | |
390 | |
391 | double lbm_dec_as_double(lbm_value val); |
392 | |
393 | |
394 | |
395 | |
396 | |
397 | |
398 | lbm_uint lbm_dec_as_uint(lbm_value val); |
399 | |
400 | |
401 | |
402 | |
403 | |
404 | |
405 | lbm_int lbm_dec_as_int(lbm_value val); |
406 | |
407 | lbm_uint lbm_dec_raw(lbm_value v); |
408 | |
409 | |
410 | |
411 | |
412 | |
413 | |
414 | lbm_value lbm_cons(lbm_value car, lbm_value cdr); |
415 | |
416 | |
417 | |
418 | |
419 | |
420 | |
421 | |
422 | |
423 | lbm_value lbm_car(lbm_value cons); |
424 | |
425 | |
426 | |
427 | |
428 | |
429 | lbm_value lbm_caar(lbm_value c); |
430 | |
431 | |
432 | |
433 | |
434 | |
435 | lbm_value lbm_cadr(lbm_value c); |
436 | |
437 | |
438 | |
439 | |
440 | |
441 | |
442 | |
443 | lbm_value lbm_cdr(lbm_value cons); |
444 | |
445 | |
446 | |
447 | |
448 | |
449 | |
450 | |
451 | lbm_value lbm_cddr(lbm_value c); |
452 | |
453 | |
454 | |
455 | |
456 | |
457 | |
458 | int lbm_set_car(lbm_value c, lbm_value v); |
459 | |
460 | |
461 | |
462 | |
463 | |
464 | |
465 | int lbm_set_cdr(lbm_value c, lbm_value v); |
466 | |
467 | |
468 | |
469 | |
470 | |
471 | |
472 | |
473 | int lbm_set_car_and_cdr(lbm_value c, lbm_value car_val, lbm_value cdr_val); |
474 | |
475 | |
476 | |
477 | |
478 | |
479 | |
480 | |
481 | |
482 | lbm_uint lbm_list_length(lbm_value c); |
483 | |
484 | |
485 | |
486 | |
487 | |
488 | |
489 | |
490 | |
491 | |
492 | unsigned int lbm_list_length_pred(lbm_value c, bool *pres, bool (*pred)(lbm_value)); |
493 | |
494 | |
495 | |
496 | |
497 | |
498 | |
499 | |
500 | lbm_value lbm_list_reverse(lbm_value list); |
501 | |
502 | |
503 | |
504 | |
505 | |
506 | |
507 | |
508 | lbm_value lbm_list_destructive_reverse(lbm_value list); |
509 | |
510 | |
511 | |
512 | |
513 | |
514 | |
515 | |
516 | |
517 | lbm_value lbm_list_copy(int *m, lbm_value list); |
518 | |
519 | |
520 | |
521 | |
522 | |
523 | |
524 | |
525 | lbm_value lbm_list_append(lbm_value list1, lbm_value list2); |
526 | |
527 | |
528 | |
529 | |
530 | |
531 | |
532 | lbm_value lbm_list_drop(unsigned int n, lbm_value ls); |
533 | |
534 | |
535 | |
536 | |
537 | |
538 | lbm_value lbm_index_list(lbm_value l, int32_t n); |
539 | |
540 | |
541 | |
542 | |
543 | |
544 | |
545 | |
546 | void lbm_get_heap_state(lbm_heap_state_t *); |
547 | |
548 | |
549 | |
550 | lbm_uint lbm_get_gc_stack_max(void); |
551 | |
552 | |
553 | |
554 | lbm_uint lbm_get_gc_stack_size(void); |
555 | |
556 | |
557 | |
558 | |
559 | void lbm_gc_state_inc(void); |
560 | |
561 | |
562 | |
563 | void lbm_nil_freelist(void); |
564 | |
565 | |
566 | |
567 | void lbm_gc_mark_env(lbm_value); |
568 | |
569 | |
570 | |
571 | void lbm_gc_mark_phase(lbm_value root); |
572 | |
573 | |
574 | |
575 | |
576 | |
577 | |
578 | |
579 | void lbm_gc_mark_aux(lbm_uint *data, lbm_uint n); |
580 | |
581 | |
582 | |
583 | |
584 | void lbm_gc_mark_roots(lbm_uint *roots, lbm_uint num_roots); |
585 | |
586 | |
587 | |
588 | |
589 | int lbm_gc_sweep_phase(void); |
590 | |
591 | |
592 | |
593 | |
594 | |
595 | |
596 | |
597 | |
598 | int lbm_heap_allocate_array(lbm_value *res, lbm_uint size); |
599 | |
600 | |
601 | |
602 | |
603 | |
604 | |
605 | int lbm_heap_allocate_lisp_array(lbm_value *res, lbm_uint size); |
606 | |
607 | |
608 | |
609 | |
610 | |
611 | |
612 | |
613 | |
614 | int lbm_lift_array(lbm_value *value, char *data, lbm_uint num_elt); |
615 | |
616 | |
617 | |
618 | |
619 | lbm_int lbm_heap_array_get_size(lbm_value arr); |
620 | |
621 | |
622 | |
623 | |
624 | const uint8_t *lbm_heap_array_get_data_ro(lbm_value arr); |
625 | |
626 | |
627 | |
628 | |
629 | uint8_t *lbm_heap_array_get_data_rw(lbm_value arr); |
630 | |
631 | |
632 | |
633 | |
634 | int lbm_heap_explicit_free_array(lbm_value arr); |
635 | |
636 | |
637 | |
638 | |
639 | lbm_uint lbm_size_of(lbm_type t); |
640 | |
641 | int lbm_const_heap_init(const_heap_write_fun w_fun, |
642 | lbm_const_heap_t *heap, |
643 | lbm_uint *addr, |
644 | lbm_uint num_words); |
645 | |
646 | lbm_flash_status lbm_allocate_const_cell(lbm_value *res); |
647 | lbm_flash_status lbm_write_const_raw(lbm_uint *data, lbm_uint n, lbm_uint *res); |
648 | lbm_flash_status lbm_allocate_const_raw(lbm_uint nwords, lbm_uint *res); |
649 | lbm_flash_status write_const_cdr(lbm_value cell, lbm_value val); |
650 | lbm_flash_status write_const_car(lbm_value cell, lbm_value val); |
651 | lbm_flash_status lbm_const_write(lbm_uint *tgt, lbm_uint val); |
652 | lbm_uint lbm_flash_memory_usage(void); |
653 | |
654 | |
655 | |
656 | |
657 | |
658 | |
659 | static inline lbm_type lbm_type_of(lbm_value x) { |
660 | return (x & LBM_PTR_BIT) ? (x & LBM_PTR_TYPE_MASK) : (x & LBM_VAL_TYPE_MASK); |
661 | } |
662 | |
663 | |
664 | static inline lbm_type lbm_type_of_functional(lbm_value x) { |
665 | return (x & LBM_PTR_BIT) ? |
666 | (x & (LBM_PTR_TO_CONSTANT_MASK & LBM_PTR_TYPE_MASK)) : |
667 | (x & LBM_VAL_TYPE_MASK); |
668 | } |
669 | |
670 | static inline lbm_value lbm_enc_cons_ptr(lbm_uint x) { |
671 | return ((x << LBM_ADDRESS_SHIFT) | LBM_TYPE_CONS | LBM_PTR_BIT); |
672 | } |
673 | |
674 | static inline lbm_uint lbm_dec_ptr(lbm_value p) { |
675 | return ((LBM_PTR_VAL_MASK & p) >> LBM_ADDRESS_SHIFT); |
676 | } |
677 | |
678 | extern lbm_cons_t *lbm_heaps[2]; |
679 | |
680 | static inline lbm_uint lbm_dec_cons_cell_ptr(lbm_value p) { |
681 | lbm_uint h = (p & LBM_PTR_TO_CONSTANT_BIT) >> LBM_PTR_TO_CONSTANT_SHIFT; |
682 | return lbm_dec_ptr(p) >> h; |
683 | } |
684 | |
685 | static inline lbm_cons_t *lbm_dec_heap(lbm_value p) { |
686 | lbm_uint h = (p & LBM_PTR_TO_CONSTANT_BIT) >> LBM_PTR_TO_CONSTANT_SHIFT; |
687 | return lbm_heaps[h]; |
688 | } |
689 | |
690 | static inline lbm_value lbm_set_ptr_type(lbm_value p, lbm_type t) { |
691 | return ((LBM_PTR_VAL_MASK & p) | t | LBM_PTR_BIT); |
692 | } |
693 | |
694 | static inline lbm_value lbm_enc_sym(lbm_uint s) { |
695 | return (s << LBM_VAL_SHIFT) | LBM_TYPE_SYMBOL; |
696 | } |
697 | |
698 | static inline lbm_value lbm_enc_i(lbm_int x) { |
699 | return ((lbm_uint)x << LBM_VAL_SHIFT) | LBM_TYPE_I; |
700 | } |
701 | |
702 | static inline lbm_value lbm_enc_u(lbm_uint x) { |
703 | return (x << LBM_VAL_SHIFT) | LBM_TYPE_U; |
704 | } |
705 | |
706 | |
707 | |
708 | |
709 | |
710 | extern lbm_value lbm_enc_i32(int32_t x); |
711 | |
712 | |
713 | |
714 | |
715 | |
716 | extern lbm_value lbm_enc_u32(uint32_t x); |
717 | |
718 | |
719 | |
720 | |
721 | |
722 | extern lbm_value lbm_enc_float(float x); |
723 | |
724 | |
725 | |
726 | |
727 | |
728 | extern lbm_value lbm_enc_i64(int64_t x); |
729 | |
730 | |
731 | |
732 | |
733 | |
734 | extern lbm_value lbm_enc_u64(uint64_t x); |
735 | |
736 | |
737 | |
738 | |
739 | |
740 | extern lbm_value lbm_enc_double(double x); |
741 | |
742 | static inline lbm_value lbm_enc_char(uint8_t x) { |
743 | return ((lbm_uint)x << LBM_VAL_SHIFT) | LBM_TYPE_CHAR; |
744 | } |
745 | |
746 | static inline lbm_int lbm_dec_i(lbm_value x) { |
747 | return (lbm_int)x >> LBM_VAL_SHIFT; |
748 | } |
749 | |
750 | static inline lbm_uint lbm_dec_u(lbm_value x) { |
751 | return x >> LBM_VAL_SHIFT; |
752 | } |
753 | |
754 | static inline uint8_t lbm_dec_char(lbm_value x) { |
755 | return (uint8_t)(x >> LBM_VAL_SHIFT); |
756 | } |
757 | |
758 | static inline lbm_uint lbm_dec_sym(lbm_value x) { |
759 | return x >> LBM_VAL_SHIFT; |
760 | } |
761 | |
762 | |
763 | |
764 | |
765 | |
766 | extern float lbm_dec_float(lbm_value x); |
767 | |
768 | |
769 | |
770 | |
771 | |
772 | extern double lbm_dec_double(lbm_value x); |
773 | |
774 | |
775 | static inline uint32_t lbm_dec_u32(lbm_value x) { |
776 | #ifndef LBM64 |
777 | return (uint32_t)lbm_car(x); |
778 | #else |
779 | return (uint32_t)(x >> LBM_VAL_SHIFT); |
780 | #endif |
781 | } |
782 | |
783 | |
784 | |
785 | |
786 | |
787 | extern uint64_t lbm_dec_u64(lbm_value x); |
788 | |
789 | static inline int32_t lbm_dec_i32(lbm_value x) { |
790 | #ifndef LBM64 |
791 | return (int32_t)lbm_car(x); |
792 | #else |
793 | return (int32_t)(x >> LBM_VAL_SHIFT); |
794 | #endif |
795 | } |
796 | |
797 | |
798 | |
799 | |
800 | |
801 | extern int64_t lbm_dec_i64(lbm_value x); |
802 | |
803 | |
804 | |
805 | |
806 | |
807 | |
808 | static inline bool lbm_is_ptr(lbm_value x) { |
809 | return (x & LBM_PTR_BIT); |
810 | } |
811 | |
812 | |
813 | |
814 | |
815 | |
816 | |
817 | static inline bool lbm_is_cons_rw(lbm_value x) { |
818 | return (lbm_type_of(x) == LBM_TYPE_CONS); |
819 | } |
820 | |
821 | |
822 | |
823 | |
824 | |
825 | |
826 | static inline bool lbm_is_cons(lbm_value x) { |
827 | return lbm_is_ptr(x) && ((x & LBM_CONS_TYPE_MASK) == LBM_TYPE_CONS); |
828 | } |
829 | |
830 | |
831 | |
832 | |
833 | |
834 | static inline bool lbm_is_number(lbm_value x) { |
835 | return |
836 | (x & LBM_PTR_BIT) ? |
837 | ((x & LBM_NUMBER_MASK) == LBM_NUMBER_MASK) : |
838 | (x & LBM_VAL_TYPE_MASK); |
839 | } |
840 | |
841 | |
842 | |
843 | |
844 | |
845 | static inline bool lbm_is_array_r(lbm_value x) { |
846 | lbm_type t = lbm_type_of(x); |
847 | return ((t & LBM_PTR_TO_CONSTANT_MASK) == LBM_TYPE_ARRAY); |
| 2 | | Assuming the condition is true | |
|
| 3 | | Returning the value 1, which participates in a condition later | |
|
848 | } |
849 | |
850 | static inline bool lbm_is_array_rw(lbm_value x) { |
851 | return( (lbm_type_of(x) == LBM_TYPE_ARRAY) && !(x & LBM_PTR_TO_CONSTANT_BIT)); |
852 | } |
853 | |
854 | static inline bool lbm_is_lisp_array_r(lbm_value x) { |
855 | lbm_type t = lbm_type_of(x); |
856 | return ((t & LBM_PTR_TO_CONSTANT_MASK) == LBM_TYPE_LISPARRAY); |
857 | } |
858 | |
859 | static inline bool lbm_is_lisp_array_rw(lbm_value x) { |
860 | return( (lbm_type_of(x) == LBM_TYPE_LISPARRAY) && !(x & LBM_PTR_TO_CONSTANT_BIT)); |
861 | } |
862 | |
863 | |
864 | static inline bool lbm_is_channel(lbm_value x) { |
865 | return (lbm_type_of(x) == LBM_TYPE_CHANNEL && |
866 | lbm_type_of(lbm_cdr(x)) == LBM_TYPE_SYMBOL && |
867 | lbm_cdr(x) == ENC_SYM_CHANNEL_TYPE); |
868 | } |
869 | static inline bool lbm_is_char(lbm_value x) { |
870 | return (lbm_type_of(x) == LBM_TYPE_CHAR); |
871 | } |
872 | |
873 | static inline bool lbm_is_special(lbm_value symrep) { |
874 | return ((lbm_type_of(symrep) == LBM_TYPE_SYMBOL) && |
875 | (lbm_dec_sym(symrep) < SPECIAL_SYMBOLS_END)); |
876 | } |
877 | |
878 | static inline bool lbm_is_closure(lbm_value exp) { |
879 | return ((lbm_is_cons(exp)) && |
880 | (lbm_type_of(lbm_car(exp)) == LBM_TYPE_SYMBOL) && |
881 | (lbm_car(exp) == ENC_SYM_CLOSURE)); |
882 | } |
883 | |
884 | static inline bool lbm_is_continuation(lbm_value exp) { |
885 | return ((lbm_type_of(exp) == LBM_TYPE_CONS) && |
886 | (lbm_type_of(lbm_car(exp)) == LBM_TYPE_SYMBOL) && |
887 | (lbm_car(exp) == ENC_SYM_CONT)); |
888 | } |
889 | |
890 | static inline bool lbm_is_macro(lbm_value exp) { |
891 | return ((lbm_type_of(exp) == LBM_TYPE_CONS) && |
892 | (lbm_type_of(lbm_car(exp)) == LBM_TYPE_SYMBOL) && |
893 | (lbm_car(exp) == ENC_SYM_MACRO)); |
894 | } |
895 | |
896 | static inline bool lbm_is_match_binder(lbm_value exp) { |
897 | return (lbm_is_cons(exp) && |
898 | (lbm_type_of(lbm_car(exp)) == LBM_TYPE_SYMBOL) && |
899 | (lbm_car(exp) == ENC_SYM_MATCH_ANY)); |
900 | } |
901 | |
902 | static inline bool lbm_is_comma_qualified_symbol(lbm_value exp) { |
903 | return (lbm_is_cons(exp) && |
904 | (lbm_type_of(lbm_car(exp)) == LBM_TYPE_SYMBOL) && |
905 | (lbm_car(exp) == ENC_SYM_COMMA) && |
906 | (lbm_type_of(lbm_cadr(exp)) == LBM_TYPE_SYMBOL)); |
907 | } |
908 | |
909 | static inline bool lbm_is_symbol(lbm_value exp) { |
910 | return !(exp & LBM_LOW_RESERVED_BITS); |
911 | } |
912 | |
913 | static inline bool lbm_is_symbol_nil(lbm_value exp) { |
914 | return !exp; |
915 | } |
916 | |
917 | static inline bool lbm_is_symbol_true(lbm_value exp) { |
918 | return (lbm_is_symbol(exp) && exp == ENC_SYM_TRUE); |
919 | } |
920 | |
921 | static inline bool lbm_is_symbol_eval(lbm_value exp) { |
922 | return (lbm_is_symbol(exp) && exp == ENC_SYM_EVAL); |
923 | } |
924 | |
925 | static inline bool lbm_is_symbol_merror(lbm_value exp) { |
926 | return lbm_is_symbol(exp) && (exp == ENC_SYM_MERROR); |
927 | } |
928 | |
929 | static inline bool lbm_is_list(lbm_value x) { |
930 | return (lbm_is_cons(x) || lbm_is_symbol_nil(x)); |
931 | } |
932 | |
933 | static inline bool lbm_is_list_rw(lbm_value x) { |
934 | return (lbm_is_cons_rw(x) || lbm_is_symbol_nil(x)); |
935 | } |
936 | |
937 | static inline bool lbm_is_quoted_list(lbm_value x) { |
938 | return (lbm_is_cons(x) && |
939 | lbm_is_symbol(lbm_car(x)) && |
940 | (lbm_car(x) == ENC_SYM_QUOTE) && |
941 | lbm_is_cons(lbm_cdr(x)) && |
942 | lbm_is_cons(lbm_cadr(x))); |
943 | } |
944 | |
945 | #ifndef LBM64 |
946 | #define ERROR_SYMBOL_MASK 0xFFFFFFF0 |
947 | #else |
948 | #define ERROR_SYMBOL_MASK 0xFFFFFFFFFFFFFFF0 |
949 | #endif |
950 | |
951 | |
952 | static inline bool lbm_is_error(lbm_value v){ |
953 | return (lbm_is_symbol(v) && |
954 | ((lbm_dec_sym(v) & ERROR_SYMBOL_MASK) == 0x20)); |
955 | } |
956 | |
957 | |
958 | |
959 | static inline lbm_cons_t* lbm_ref_cell(lbm_value addr) { |
960 | return &lbm_dec_heap(addr)[lbm_dec_cons_cell_ptr(addr)]; |
961 | |
962 | } |
963 | |
964 | |
965 | |
966 | |
967 | |
968 | |
969 | |
970 | #ifdef __cplusplus |
971 | } |
972 | #endif |
973 | #endif |