GCC Code Coverage Report


Directory: ../src/
File: /home/joels/Current/lispbm/src/extensions/runtime_extensions.c
Date: 2025-08-08 18:10:24
Exec Total Coverage
Lines: 159 159 100.0%
Functions: 24 24 100.0%
Branches: 55 56 98.2%

Line Branch Exec Source
1 /*
2 Copyright 2023, 2024, 2025 Joel Svensson svenssonjoel@yahoo.se
3
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 #include <lbm_memory.h>
19 #include <heap.h>
20 #include <eval_cps.h>
21 #include <extensions.h>
22 #include <lbm_utils.h>
23 #include <lbm_version.h>
24 #include <env.h>
25
26 #ifdef LBM_OPT_RUNTIME_EXTENSIONS_SIZE
27 #pragma GCC optimize ("-Os")
28 #endif
29 #ifdef LBM_OPT_RUNTIME_EXTENSIONS_SIZE_AGGRESSIVE
30 #pragma GCC optimize ("-Oz")
31 #endif
32
33
34 #ifdef FULL_RTS_LIB
35 static lbm_uint sym_heap_size;
36 static lbm_uint sym_heap_bytes;
37 static lbm_uint sym_num_alloc_cells;
38 static lbm_uint sym_num_alloc_arrays;
39 static lbm_uint sym_num_gc;
40 static lbm_uint sym_num_gc_marked;
41 static lbm_uint sym_num_gc_recovered_cells;
42 static lbm_uint sym_num_gc_recovered_arrays;
43 static lbm_uint sym_num_least_free;
44 static lbm_uint sym_num_last_free;
45 #endif
46
47 58 lbm_value ext_eval_set_quota(lbm_value *args, lbm_uint argn) {
48
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 57 times.
58 LBM_CHECK_ARGN_NUMBER(1);
49 57 uint32_t q = lbm_dec_as_u32(args[0]);
50 #ifdef LBM_USE_TIME_QUOTA
51 1 lbm_set_eval_time_quota(q);
52 #else
53 56 lbm_set_eval_step_quota(q);
54 #endif
55 57 return ENC_SYM_TRUE;
56 }
57
58 2 lbm_value ext_hide_trapped_error(lbm_value *args, lbm_uint argn) {
59 (void)args;
60 (void)argn;
61 2 lbm_set_hide_trapped_error(true);
62 2 return ENC_SYM_TRUE;
63 }
64
65 1 lbm_value ext_show_trapped_error(lbm_value *args, lbm_uint argn) {
66 (void)args;
67 (void)argn;
68 1 lbm_set_hide_trapped_error(false);
69 1 return ENC_SYM_TRUE;
70 }
71
72 #ifdef FULL_RTS_LIB
73 2129 lbm_value ext_memory_num_free(lbm_value *args, lbm_uint argn) {
74 (void)args;
75 (void)argn;
76 2129 lbm_uint n = lbm_memory_num_free();
77 2129 return lbm_enc_i((lbm_int)n);
78 }
79
80 224 lbm_value ext_memory_longest_free(lbm_value *args, lbm_uint argn) {
81 (void)args;
82 (void)argn;
83 224 lbm_uint n = lbm_memory_longest_free();
84 224 return lbm_enc_i((lbm_int)n);
85 }
86
87 56 lbm_value ext_memory_size(lbm_value *args, lbm_uint argn) {
88 (void)args;
89 (void)argn;
90 56 lbm_uint n = lbm_memory_num_words();
91 56 return lbm_enc_i((lbm_int)n);
92 }
93
94 644 lbm_value ext_memory_word_size(lbm_value *args, lbm_uint argn) {
95 (void)args;
96 (void)argn;
97 644 return lbm_enc_i((lbm_int)sizeof(lbm_uint));
98 }
99
100 57 lbm_value ext_lbm_version(lbm_value *args, lbm_uint argn) {
101 (void) args;
102 (void) argn;
103 57 lbm_value version = lbm_heap_allocate_list_init(3,
104 lbm_enc_i(LBM_MAJOR_VERSION),
105 lbm_enc_i(LBM_MINOR_VERSION),
106 lbm_enc_i(LBM_PATCH_VERSION));
107 57 return version;
108 }
109
110 513 lbm_value ext_lbm_heap_state(lbm_value *args, lbm_uint argn) {
111
112 513 lbm_value res = ENC_SYM_TERROR;
113
114 lbm_heap_state_t hs;
115 513 lbm_get_heap_state(&hs);
116
117
4/4
✓ Branch 0 taken 510 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 508 times.
✓ Branch 3 taken 2 times.
1023 if (argn == 1 &&
118 510 lbm_is_symbol(args[0])) {
119 508 lbm_uint s = lbm_dec_sym(args[0]);
120
2/2
✓ Branch 0 taken 57 times.
✓ Branch 1 taken 451 times.
508 if (s == sym_heap_size) {
121 57 res = lbm_enc_u(hs.heap_size);
122
2/2
✓ Branch 0 taken 57 times.
✓ Branch 1 taken 394 times.
451 } else if (s == sym_heap_bytes) {
123 57 res = lbm_enc_u(hs.heap_bytes);
124
2/2
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 338 times.
394 } else if (s == sym_num_alloc_cells) {
125 56 res = lbm_enc_u(hs.num_alloc);
126
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 337 times.
338 } else if (s == sym_num_alloc_arrays) {
127 1 res = lbm_enc_u(hs.num_alloc_arrays);
128
2/2
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 281 times.
337 } else if (s == sym_num_gc) {
129 56 res = lbm_enc_u(hs.gc_num);
130
2/2
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 225 times.
281 } else if (s == sym_num_gc_marked) {
131 56 res = lbm_enc_u(hs.gc_marked);
132
2/2
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 169 times.
225 } else if (s == sym_num_gc_recovered_cells) {
133 56 res = lbm_enc_u(hs.gc_recovered);
134
2/2
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 113 times.
169 } else if (s == sym_num_gc_recovered_arrays) {
135 56 res = lbm_enc_u(hs.gc_recovered_arrays);
136
2/2
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 57 times.
113 } else if (s == sym_num_least_free) {
137 56 res = lbm_enc_u(hs.gc_least_free);
138
2/2
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 1 times.
57 } else if (s == sym_num_last_free) {
139 56 res = lbm_enc_u(hs.gc_last_free);
140 } else {
141 1 res = ENC_SYM_NIL;
142 }
143 }
144 513 return res;
145 }
146
147 1346 lbm_value ext_env_get(lbm_value *args, lbm_uint argn) {
148
4/4
✓ Branch 0 taken 1345 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1344 times.
✓ Branch 3 taken 1 times.
1346 if (argn == 1 && lbm_is_number(args[0])) {
149 1344 lbm_uint ix = lbm_dec_as_u32(args[0]) & GLOBAL_ENV_MASK;
150 1344 return lbm_get_global_env()[ix];
151 }
152 2 return ENC_SYM_TERROR;
153 }
154
155 1 lbm_value ext_local_env_get(lbm_value *args, lbm_uint argn) {
156 (void) args;
157 (void) argn;
158 1 eval_context_t *ctx = lbm_get_current_context();
159 1 return ctx->curr_env;
160 }
161
162 114 lbm_value ext_env_set(lbm_value *args, lbm_uint argn) {
163
4/4
✓ Branch 0 taken 113 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 112 times.
✓ Branch 3 taken 1 times.
114 if (argn == 2 && lbm_is_number(args[0])) {
164 112 lbm_uint ix = lbm_dec_as_u32(args[0]) & GLOBAL_ENV_MASK;
165 112 lbm_value *glob_env = lbm_get_global_env();
166 112 glob_env[ix] = args[1];
167 112 return ENC_SYM_TRUE;
168 }
169 2 return ENC_SYM_NIL;
170 }
171
172 8 lbm_value ext_env_drop(lbm_value *args, lbm_uint argn) {
173 8 lbm_value r = ENC_SYM_TERROR;
174
4/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 1 times.
8 if (argn == 2 && lbm_is_symbol(args[0])) {
175 4 r = lbm_env_drop_binding(args[1], args[0]);
176 }
177 8 return r;
178 }
179
180 2 lbm_value ext_global_env_size(lbm_value *args, lbm_uint argn) {
181 (void) args;
182 (void) argn; // ignores any and all arguments.
183 2 return lbm_enc_u(lbm_get_global_env_size());
184 }
185
186 340 lbm_value ext_set_gc_stack_size(lbm_value *args, lbm_uint argn) {
187
2/2
✓ Branch 0 taken 339 times.
✓ Branch 1 taken 1 times.
340 if (argn == 1) {
188
2/2
✓ Branch 0 taken 338 times.
✓ Branch 1 taken 1 times.
339 if (lbm_is_number(args[0])) {
189 338 uint32_t n = lbm_dec_as_u32(args[0]);
190 338 lbm_uint *new_stack = lbm_malloc(n * sizeof(lbm_uint));
191
2/2
✓ Branch 0 taken 336 times.
✓ Branch 1 taken 2 times.
338 if (new_stack) {
192 336 lbm_free(lbm_heap_state.gc_stack.data);
193 336 lbm_heap_state.gc_stack.data = new_stack;
194 336 lbm_heap_state.gc_stack.size = n;
195 336 lbm_heap_state.gc_stack.sp = 0; // should already be 0
196 336 return ENC_SYM_TRUE;
197 }
198 2 return ENC_SYM_MERROR;
199 }
200 }
201 2 return ENC_SYM_TERROR;
202 }
203
204 560 lbm_value ext_is_64bit(lbm_value *args, lbm_uint argn) {
205 (void) args;
206 (void) argn;
207 #ifndef LBM64
208 280 return ENC_SYM_NIL;
209 #else
210 280 return ENC_SYM_TRUE;
211 #endif
212 }
213
214 56 lbm_value ext_symbol_table_size(lbm_uint *args, lbm_uint argn) {
215 (void) args;
216 (void) argn;
217 56 return lbm_enc_u(lbm_get_symbol_table_size());
218 }
219
220 56 lbm_value ext_symbol_table_size_flash(lbm_uint *args, lbm_uint argn) {
221 (void) args;
222 (void) argn;
223 56 return lbm_enc_u(lbm_get_symbol_table_size_flash());
224 }
225
226 56 lbm_value ext_symbol_table_size_names(lbm_uint *args, lbm_uint argn) {
227 (void) args;
228 (void) argn;
229 56 return lbm_enc_u(lbm_get_symbol_table_size_names());
230 }
231
232 56 lbm_value ext_symbol_table_size_names_flash(lbm_uint *args, lbm_uint argn) {
233 (void) args;
234 (void) argn;
235 56 return lbm_enc_u(lbm_get_symbol_table_size_names_flash());
236 }
237
238 276 lbm_value ext_is_always_gc(lbm_uint *args, lbm_uint argn) {
239 (void) args;
240 (void) argn;
241 #ifdef LBM_ALWAYS_GC
242 return ENC_SYM_TRUE;
243 #else
244 276 return ENC_SYM_NIL;
245 #endif
246 }
247
248 #endif
249
250 #if defined(LBM_USE_EXT_MAILBOX_GET) || defined(FULL_RTS_LIB)
251
252 3 void find_cid(eval_context_t *ctx, void *arg1, void *arg2) {
253 3 lbm_cid id = (lbm_cid)arg1;
254
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 if (ctx->id == id) {
255 1 *(eval_context_t**)arg2 = ctx;
256 }
257 3 }
258
259
260 4 lbm_value ext_mailbox_get(lbm_uint *args, lbm_uint argn) {
261 4 lbm_value res = ENC_SYM_TERROR;
262 4 eval_context_t *ctx = NULL;
263
264
4/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 1 times.
4 if (argn == 1 && lbm_is_number(args[0])) {
265 2 res = ENC_SYM_NIL;
266 2 lbm_cid cid = lbm_dec_as_i32(args[0]);
267 2 lbm_all_ctxs_iterator(find_cid, (void*)cid, (void*)&ctx);
268
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (ctx) {
269 1 uint32_t num_mail = ctx->num_mail;
270 1 lbm_value ls = (lbm_heap_allocate_list(num_mail));
271 1 res = ls;
272
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (lbm_is_ptr(ls)) {
273 1 lbm_value curr = ls;
274 1 int i = 0;
275
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
4 while (lbm_is_ptr(curr)) {
276 3 lbm_set_car(curr, ctx->mailbox[i++]);
277 3 curr = lbm_cdr(curr);
278 }
279 }
280 }
281 }
282 4 return res;
283 }
284 #endif
285
286
287 44260 void lbm_runtime_extensions_init(void) {
288
289 #ifdef FULL_RTS_LIB
290 44260 lbm_add_symbol_const("get-heap-size", &sym_heap_size);
291 44260 lbm_add_symbol_const("get-heap-bytes", &sym_heap_bytes);
292 44260 lbm_add_symbol_const("get-num-alloc-cells", &sym_num_alloc_cells);
293 44260 lbm_add_symbol_const("get-num-alloc-arrays", &sym_num_alloc_arrays);
294 44260 lbm_add_symbol_const("get-gc-num", &sym_num_gc);
295 44260 lbm_add_symbol_const("get-gc-num-marked", &sym_num_gc_marked);
296 44260 lbm_add_symbol_const("get-gc-num-recovered-cells", &sym_num_gc_recovered_cells);
297 44260 lbm_add_symbol_const("get-gc-num-recovered-arrays", &sym_num_gc_recovered_arrays);
298 44260 lbm_add_symbol_const("get-gc-num-least-free", &sym_num_least_free);
299 44260 lbm_add_symbol_const("get-gc-num-last-free", &sym_num_last_free);
300 #endif
301
302 #if defined(LBM_USE_EXT_MAILBOX_GET) || defined(FULL_RTS_LIB)
303 44260 lbm_add_extension("mailbox-get", ext_mailbox_get);
304 #endif
305 #ifndef FULL_RTS_LIB
306 lbm_add_extension("set-eval-quota", ext_eval_set_quota);
307 lbm_add_extension("hide-trapped-error", ext_hide_trapped_error);
308 lbm_add_extension("show-trapped-error", ext_show_trapped_error);
309 #else
310 44260 lbm_add_extension("is-always-gc",ext_is_always_gc);
311 44260 lbm_add_extension("set-eval-quota", ext_eval_set_quota);
312 44260 lbm_add_extension("hide-trapped-error", ext_hide_trapped_error);
313 44260 lbm_add_extension("show-trapped-error", ext_show_trapped_error);
314 44260 lbm_add_extension("mem-num-free", ext_memory_num_free);
315 44260 lbm_add_extension("mem-longest-free", ext_memory_longest_free);
316 44260 lbm_add_extension("mem-size", ext_memory_size);
317 44260 lbm_add_extension("word-size", ext_memory_word_size);
318 44260 lbm_add_extension("lbm-version", ext_lbm_version);
319 44260 lbm_add_extension("lbm-heap-state", ext_lbm_heap_state);
320 44260 lbm_add_extension("env-get", ext_env_get);
321 44260 lbm_add_extension("env-set", ext_env_set);
322 44260 lbm_add_extension("env-drop", ext_env_drop);
323 44260 lbm_add_extension("local-env-get", ext_local_env_get);
324 44260 lbm_add_extension("global-env-size", ext_global_env_size);
325 44260 lbm_add_extension("set-gc-stack-size", ext_set_gc_stack_size);
326 44260 lbm_add_extension("is-64bit", ext_is_64bit);
327 44260 lbm_add_extension("symtab-size", ext_symbol_table_size);
328 44260 lbm_add_extension("symtab-size-flash", ext_symbol_table_size_flash);
329 44260 lbm_add_extension("symtab-size-names", ext_symbol_table_size_names);
330 44260 lbm_add_extension("symtab-size-names-flash", ext_symbol_table_size_names_flash);
331 #endif
332 44260 }
333