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 |