| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /* | ||
| 2 | Copyright 2023, 2024, 2025 Joel Svensson svenssonjoel@yahoo.se | ||
| 3 | 2023 Benjamin Vedder | ||
| 4 | |||
| 5 | This program is free software: you can redistribute it and/or modify | ||
| 6 | it under the terms of the GNU General Public License as published by | ||
| 7 | the Free Software Foundation, either version 3 of the License, or | ||
| 8 | (at your option) any later version. | ||
| 9 | |||
| 10 | This program is distributed in the hope that it will be useful, | ||
| 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | GNU General Public License for more details. | ||
| 14 | |||
| 15 | You should have received a copy of the GNU General Public License | ||
| 16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 17 | */ | ||
| 18 | |||
| 19 | #include <lbm_flat_value.h> | ||
| 20 | #include <eval_cps.h> | ||
| 21 | #include <stack.h> | ||
| 22 | |||
| 23 | #include <setjmp.h> | ||
| 24 | |||
| 25 | // ------------------------------------------------------------ | ||
| 26 | // Access to GC from eval_cps | ||
| 27 | int lbm_perform_gc(void); | ||
| 28 | |||
| 29 | |||
| 30 | // ------------------------------------------------------------ | ||
| 31 | // Flatteners | ||
| 32 | 84406 | bool lbm_start_flatten(lbm_flat_value_t *v, size_t buffer_size) { | |
| 33 | 84406 | bool res = false; | |
| 34 | 84406 | uint8_t *data = lbm_malloc_reserve(buffer_size); | |
| 35 |
1/2✓ Branch 0 taken 84406 times.
✗ Branch 1 not taken.
|
84406 | if (data) { |
| 36 | 84406 | v->buf = data; | |
| 37 | 84406 | v->buf_size = buffer_size; | |
| 38 | 84406 | v->buf_pos = 0; | |
| 39 | 84406 | res = true; | |
| 40 | } | ||
| 41 | 84406 | return res; | |
| 42 | } | ||
| 43 | |||
| 44 | 15273 | bool lbm_finish_flatten(lbm_flat_value_t *v) { | |
| 45 | lbm_uint size_words; | ||
| 46 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 15271 times.
|
15273 | if (v->buf_pos % sizeof(lbm_uint) == 0) { |
| 47 | 2 | size_words = v->buf_pos / sizeof(lbm_uint); | |
| 48 | } else { | ||
| 49 | 15271 | size_words = (v->buf_pos / sizeof(lbm_uint)) + 1; | |
| 50 | } | ||
| 51 |
2/2✓ Branch 0 taken 56 times.
✓ Branch 1 taken 15217 times.
|
15273 | if (v->buf_size <= size_words * sizeof(lbm_uint)) return true; |
| 52 | 15217 | v->buf_size = size_words * sizeof(lbm_uint); | |
| 53 | 15217 | return (lbm_memory_shrink((lbm_uint*)v->buf, size_words) >= 0); | |
| 54 | } | ||
| 55 | |||
| 56 | 845836 | static bool write_byte(lbm_flat_value_t *v, uint8_t b) { | |
| 57 | 845836 | bool res = false; | |
| 58 |
1/2✓ Branch 0 taken 845836 times.
✗ Branch 1 not taken.
|
845836 | if (v->buf_size >= v->buf_pos + 1) { |
| 59 | 845836 | v->buf[v->buf_pos++] = b; | |
| 60 | 845836 | res = true; | |
| 61 | } | ||
| 62 | 845836 | return res; | |
| 63 | } | ||
| 64 | |||
| 65 | 363721 | static bool write_bytes(lbm_flat_value_t *v, uint8_t *data,lbm_uint num_bytes) { | |
| 66 | 363721 | bool res = false; | |
| 67 |
1/2✓ Branch 0 taken 363721 times.
✗ Branch 1 not taken.
|
363721 | if (v->buf_size >= v->buf_pos + num_bytes) { |
| 68 | 363721 | memcpy(v->buf + v->buf_pos, data, num_bytes); | |
| 69 | 363721 | v->buf_pos += num_bytes; | |
| 70 | 363721 | res = true; | |
| 71 | } | ||
| 72 | 363721 | return res; | |
| 73 | } | ||
| 74 | |||
| 75 | 424594 | static bool write_word(lbm_flat_value_t *v, uint32_t w) { | |
| 76 | 424594 | bool res = false; | |
| 77 |
1/2✓ Branch 0 taken 424594 times.
✗ Branch 1 not taken.
|
424594 | if (v->buf_size >= v->buf_pos + 4) { |
| 78 | 424594 | v->buf[v->buf_pos++] = (uint8_t)(w >> 24); | |
| 79 | 424594 | v->buf[v->buf_pos++] = (uint8_t)(w >> 16); | |
| 80 | 424594 | v->buf[v->buf_pos++] = (uint8_t)(w >> 8); | |
| 81 | 424594 | v->buf[v->buf_pos++] = (uint8_t)w; | |
| 82 | 424594 | res = true; | |
| 83 | } | ||
| 84 | 424594 | return res; | |
| 85 | } | ||
| 86 | |||
| 87 | 52425 | static bool write_dword(lbm_flat_value_t *v, uint64_t w) { | |
| 88 | 52425 | bool res = false; | |
| 89 |
1/2✓ Branch 0 taken 52425 times.
✗ Branch 1 not taken.
|
52425 | if (v->buf_size >= v->buf_pos + 8) { |
| 90 | 52425 | v->buf[v->buf_pos++] = (uint8_t)(w >> 56); | |
| 91 | 52425 | v->buf[v->buf_pos++] = (uint8_t)(w >> 48); | |
| 92 | 52425 | v->buf[v->buf_pos++] = (uint8_t)(w >> 40); | |
| 93 | 52425 | v->buf[v->buf_pos++] = (uint8_t)(w >> 32); | |
| 94 | 52425 | v->buf[v->buf_pos++] = (uint8_t)(w >> 24); | |
| 95 | 52425 | v->buf[v->buf_pos++] = (uint8_t)(w >> 16); | |
| 96 | 52425 | v->buf[v->buf_pos++] = (uint8_t)(w >> 8); | |
| 97 | 52425 | v->buf[v->buf_pos++] = (uint8_t)w; | |
| 98 | 52425 | res = true; | |
| 99 | } | ||
| 100 | 52425 | return res; | |
| 101 | } | ||
| 102 | |||
| 103 | 639408 | bool f_cons(lbm_flat_value_t *v) { | |
| 104 | 639408 | bool res = false; | |
| 105 |
1/2✓ Branch 0 taken 639408 times.
✗ Branch 1 not taken.
|
639408 | if (v->buf_size >= v->buf_pos + 1) { |
| 106 | 639408 | v->buf[v->buf_pos++] = S_CONS; | |
| 107 | 639408 | res = true; | |
| 108 | } | ||
| 109 | 639408 | return res; | |
| 110 | } | ||
| 111 | |||
| 112 | 224 | bool f_lisp_array(lbm_flat_value_t *v, uint32_t size) { | |
| 113 | // arrays are smaller than 2^32 elements long | ||
| 114 | 224 | bool res = true; | |
| 115 |
2/4✓ Branch 0 taken 224 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 224 times.
✗ Branch 3 not taken.
|
224 | res = res && write_byte(v, S_LBM_LISP_ARRAY); |
| 116 |
2/4✓ Branch 0 taken 224 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 224 times.
✗ Branch 3 not taken.
|
224 | res = res && write_word(v, size); // number of elements. |
| 117 | 224 | return res; | |
| 118 | } | ||
| 119 | |||
| 120 | 11633 | bool f_sym(lbm_flat_value_t *v, lbm_uint sym_id) { | |
| 121 | 11633 | bool res = true; | |
| 122 |
2/4✓ Branch 0 taken 11633 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11633 times.
✗ Branch 3 not taken.
|
11633 | res = res && write_byte(v,S_SYM_VALUE); |
| 123 | #ifndef LBM64 | ||
| 124 |
2/4✓ Branch 0 taken 5030 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 5030 times.
✗ Branch 3 not taken.
|
5030 | res = res && write_word(v,sym_id); |
| 125 | #else | ||
| 126 |
2/4✓ Branch 0 taken 6603 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6603 times.
✗ Branch 3 not taken.
|
6603 | res = res && write_dword(v,sym_id); |
| 127 | #endif | ||
| 128 | 11633 | return res; | |
| 129 | } | ||
| 130 | |||
| 131 | 126225 | bool f_sym_string(lbm_flat_value_t *v, char *str) { | |
| 132 | 126225 | bool res = false; | |
| 133 |
1/2✓ Branch 0 taken 126225 times.
✗ Branch 1 not taken.
|
126225 | if (str) { |
| 134 | 126225 | lbm_uint sym_bytes = strlen(str) + 1; | |
| 135 |
2/4✓ Branch 0 taken 126225 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 126225 times.
✗ Branch 3 not taken.
|
252450 | if (write_byte(v, S_SYM_STRING) && |
| 136 | 126225 | write_bytes(v, (uint8_t*)str, sym_bytes)) { | |
| 137 | 126225 | res = true; | |
| 138 | } | ||
| 139 | } | ||
| 140 | 126225 | return res; | |
| 141 | } | ||
| 142 | |||
| 143 | // Potentially a difference between 32/64 bit version. | ||
| 144 | // strlen returns size_t which is different on 32/64 bit platforms. | ||
| 145 | 126145 | int f_sym_string_bytes(lbm_value sym) { | |
| 146 | 126145 | int res = FLATTEN_VALUE_ERROR_FATAL; | |
| 147 |
1/2✓ Branch 0 taken 126145 times.
✗ Branch 1 not taken.
|
126145 | if (lbm_is_symbol(sym)) { |
| 148 | 126145 | lbm_uint s = lbm_dec_sym(sym); | |
| 149 | 126145 | char *sym_str = (char*)lbm_get_name_by_symbol(s); | |
| 150 |
1/2✓ Branch 0 taken 126145 times.
✗ Branch 1 not taken.
|
126145 | if (sym_str) { |
| 151 | 126145 | lbm_uint sym_bytes = strlen(sym_str) + 1; | |
| 152 | 126145 | res = (int)sym_bytes; | |
| 153 | } | ||
| 154 | } | ||
| 155 | 126145 | return res; | |
| 156 | } | ||
| 157 | |||
| 158 | 91252 | bool f_i(lbm_flat_value_t *v, lbm_int i) { | |
| 159 | 91252 | bool res = true; | |
| 160 | #ifndef LBM64 | ||
| 161 |
2/4✓ Branch 0 taken 45626 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 45626 times.
✗ Branch 3 not taken.
|
45626 | res = res && write_byte(v,S_I28_VALUE); |
| 162 |
2/4✓ Branch 0 taken 45626 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 45626 times.
✗ Branch 3 not taken.
|
45626 | res = res && write_word(v,(uint32_t)i); |
| 163 | #else | ||
| 164 |
2/4✓ Branch 0 taken 45626 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 45626 times.
✗ Branch 3 not taken.
|
45626 | res = res && write_byte(v,S_I56_VALUE); |
| 165 |
2/4✓ Branch 0 taken 45626 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 45626 times.
✗ Branch 3 not taken.
|
45626 | res = res && write_dword(v, (uint64_t)i); |
| 166 | #endif | ||
| 167 | 91252 | return res; | |
| 168 | } | ||
| 169 | |||
| 170 | 56 | bool f_u(lbm_flat_value_t *v, lbm_uint u) { | |
| 171 | 56 | bool res = true; | |
| 172 | #ifndef LBM64 | ||
| 173 |
2/4✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 28 times.
✗ Branch 3 not taken.
|
28 | res = res && write_byte(v,S_U28_VALUE); |
| 174 |
2/4✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 28 times.
✗ Branch 3 not taken.
|
28 | res = res && write_word(v,(uint32_t)u); |
| 175 | #else | ||
| 176 |
2/4✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 28 times.
✗ Branch 3 not taken.
|
28 | res = res && write_byte(v,S_U56_VALUE); |
| 177 |
2/4✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 28 times.
✗ Branch 3 not taken.
|
28 | res = res && write_dword(v,(uint64_t)u); |
| 178 | #endif | ||
| 179 | 56 | return res; | |
| 180 | } | ||
| 181 | |||
| 182 | 121296 | bool f_b(lbm_flat_value_t *v, uint8_t b) { | |
| 183 | 121296 | bool res = true; | |
| 184 |
2/4✓ Branch 0 taken 121296 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 121296 times.
✗ Branch 3 not taken.
|
121296 | res = res && write_byte(v,S_BYTE_VALUE); |
| 185 |
2/4✓ Branch 0 taken 121296 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 121296 times.
✗ Branch 3 not taken.
|
121296 | res = res && write_byte(v,b); |
| 186 | 121296 | return res; | |
| 187 | } | ||
| 188 | |||
| 189 | 58548 | bool f_i32(lbm_flat_value_t *v, int32_t w) { | |
| 190 | 58548 | bool res = true; | |
| 191 |
2/4✓ Branch 0 taken 58548 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 58548 times.
✗ Branch 3 not taken.
|
58548 | res = res && write_byte(v, S_I32_VALUE); |
| 192 |
2/4✓ Branch 0 taken 58548 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 58548 times.
✗ Branch 3 not taken.
|
58548 | res = res && write_word(v, (uint32_t)w); |
| 193 | 58548 | return res; | |
| 194 | } | ||
| 195 | |||
| 196 | 62244 | bool f_u32(lbm_flat_value_t *v, uint32_t w) { | |
| 197 | 62244 | bool res = true; | |
| 198 |
2/4✓ Branch 0 taken 62244 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 62244 times.
✗ Branch 3 not taken.
|
62244 | res = res && write_byte(v, S_U32_VALUE); |
| 199 |
2/4✓ Branch 0 taken 62244 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 62244 times.
✗ Branch 3 not taken.
|
62244 | res = res && write_word(v, w); |
| 200 | 62244 | return res; | |
| 201 | } | ||
| 202 | |||
| 203 | 15398 | bool f_float(lbm_flat_value_t *v, float f) { | |
| 204 | 15398 | bool res = true; | |
| 205 |
2/4✓ Branch 0 taken 15398 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15398 times.
✗ Branch 3 not taken.
|
15398 | res = res && write_byte(v, S_FLOAT_VALUE); |
| 206 | uint32_t u; | ||
| 207 | 15398 | memcpy(&u, &f, sizeof(uint32_t)); | |
| 208 |
2/4✓ Branch 0 taken 15398 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15398 times.
✗ Branch 3 not taken.
|
15398 | res = res && write_word(v, (uint32_t)u); |
| 209 | 15398 | return res; | |
| 210 | } | ||
| 211 | |||
| 212 | 56 | bool f_double(lbm_flat_value_t *v, double d) { | |
| 213 | 56 | bool res = true; | |
| 214 |
2/4✓ Branch 0 taken 56 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 56 times.
✗ Branch 3 not taken.
|
56 | res = res && write_byte(v, S_DOUBLE_VALUE); |
| 215 | uint64_t u; | ||
| 216 | 56 | memcpy(&u, &d, sizeof(uint64_t)); | |
| 217 |
2/4✓ Branch 0 taken 56 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 56 times.
✗ Branch 3 not taken.
|
56 | res = res && write_dword(v, u); |
| 218 | 56 | return res; | |
| 219 | } | ||
| 220 | |||
| 221 | 56 | bool f_i64(lbm_flat_value_t *v, int64_t w) { | |
| 222 | 56 | bool res = true; | |
| 223 |
2/4✓ Branch 0 taken 56 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 56 times.
✗ Branch 3 not taken.
|
56 | res = res && write_byte(v, S_I64_VALUE); |
| 224 |
2/4✓ Branch 0 taken 56 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 56 times.
✗ Branch 3 not taken.
|
56 | res = res && write_dword(v, (uint64_t)w); |
| 225 | 56 | return res; | |
| 226 | } | ||
| 227 | |||
| 228 | 56 | bool f_u64(lbm_flat_value_t *v, uint64_t w) { | |
| 229 | 56 | bool res = true; | |
| 230 |
2/4✓ Branch 0 taken 56 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 56 times.
✗ Branch 3 not taken.
|
56 | res = res && write_byte(v, S_U64_VALUE); |
| 231 |
2/4✓ Branch 0 taken 56 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 56 times.
✗ Branch 3 not taken.
|
56 | res = res && write_dword(v, w); |
| 232 | 56 | return res; | |
| 233 | } | ||
| 234 | |||
| 235 | // num_bytes is specifically an uint32_t | ||
| 236 | 237496 | bool f_lbm_array(lbm_flat_value_t *v, uint32_t num_bytes, uint8_t *data) { | |
| 237 | 237496 | bool res = write_byte(v, S_LBM_ARRAY); | |
| 238 |
2/4✓ Branch 0 taken 237496 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 237496 times.
✗ Branch 3 not taken.
|
237496 | res = res && write_word(v, num_bytes); |
| 239 |
2/4✓ Branch 0 taken 237496 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 237496 times.
✗ Branch 3 not taken.
|
237496 | res = res && write_bytes(v, data, num_bytes); |
| 240 | 237496 | return res; | |
| 241 | } | ||
| 242 | |||
| 243 | static int flatten_maximum_depth = FLATTEN_VALUE_MAXIMUM_DEPTH; | ||
| 244 | |||
| 245 | 56 | void lbm_set_max_flatten_depth(int depth) { | |
| 246 | 56 | flatten_maximum_depth = depth; | |
| 247 | 56 | } | |
| 248 | |||
| 249 | ✗ | int lbm_get_max_flatten_depth(void) { | |
| 250 | ✗ | return flatten_maximum_depth; | |
| 251 | } | ||
| 252 | |||
| 253 | 56 | void flatten_error(jmp_buf jb, int val) { | |
| 254 | 56 | longjmp(jb, val); | |
| 255 | } | ||
| 256 | |||
| 257 | 1325493 | int flatten_value_size_internal(jmp_buf jb, lbm_value v, int depth, bool image) { | |
| 258 |
2/2✓ Branch 0 taken 56 times.
✓ Branch 1 taken 1325437 times.
|
1325493 | if (depth > flatten_maximum_depth) { |
| 259 | 56 | flatten_error(jb, FLATTEN_VALUE_ERROR_MAXIMUM_DEPTH); | |
| 260 | } | ||
| 261 | |||
| 262 | 1325437 | lbm_uint t = lbm_type_of(v); | |
| 263 |
3/4✓ Branch 0 taken 926172 times.
✓ Branch 1 taken 399265 times.
✓ Branch 2 taken 926172 times.
✗ Branch 3 not taken.
|
1325437 | if (t >= LBM_POINTER_TYPE_FIRST && t < LBM_POINTER_TYPE_LAST) { |
| 264 | // Clear constant bit, it is irrelevant to flattening | ||
| 265 | 926172 | t = t & ~(LBM_PTR_TO_CONSTANT_BIT); | |
| 266 | } | ||
| 267 | |||
| 268 |
1/6✗ Branch 0 not taken.
✓ Branch 1 taken 1325437 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
1325437 | if (image && lbm_is_ptr(v) && (v & LBM_PTR_TO_CONSTANT_BIT)) { |
| 269 | // If flattening to image, constants can be stored by reference. | ||
| 270 | ✗ | return (sizeof(lbm_uint) + 1); // one byte tag, one word ptr | |
| 271 | } | ||
| 272 | |||
| 273 |
8/9✓ Branch 0 taken 627864 times.
✓ Branch 1 taken 224 times.
✓ Branch 2 taken 121328 times.
✓ Branch 3 taken 91324 times.
✓ Branch 4 taken 120936 times.
✓ Branch 5 taken 168 times.
✓ Branch 6 taken 126145 times.
✓ Branch 7 taken 237448 times.
✗ Branch 8 not taken.
|
1325437 | switch (t) { |
| 274 | 627864 | case LBM_TYPE_CONS: { | |
| 275 | 627864 | int res = 0; | |
| 276 | 627864 | int s1 = flatten_value_size_internal(jb,lbm_car(v), depth + 1, image); | |
| 277 |
1/2✓ Branch 0 taken 627696 times.
✗ Branch 1 not taken.
|
627696 | if (s1 > 0) { |
| 278 | 627696 | int s2 = flatten_value_size_internal(jb,lbm_cdr(v), depth + 1, image); | |
| 279 |
1/2✓ Branch 0 taken 627696 times.
✗ Branch 1 not taken.
|
627696 | if (s2 > 0) { |
| 280 | 627696 | res = (1 + s1 + s2); | |
| 281 | } | ||
| 282 | } | ||
| 283 | 627696 | return res; | |
| 284 | } | ||
| 285 | 224 | case LBM_TYPE_LISPARRAY: { | |
| 286 | 224 | int sum = 4 + 1; // sizeof(uint32_t) + 1; | |
| 287 | 224 | lbm_array_header_t *header = (lbm_array_header_t*)lbm_car(v); | |
| 288 |
1/2✓ Branch 0 taken 224 times.
✗ Branch 1 not taken.
|
224 | if (header) { |
| 289 | 224 | lbm_value *arrdata = (lbm_value*)header->data; | |
| 290 | 224 | lbm_uint size = header->size / sizeof(lbm_value); | |
| 291 |
2/2✓ Branch 0 taken 728 times.
✓ Branch 1 taken 224 times.
|
952 | for (lbm_uint i = 0; i < size; i ++ ) { |
| 292 | 728 | sum += flatten_value_size_internal(jb, arrdata[i], depth + 1, image); | |
| 293 | } | ||
| 294 | } else { | ||
| 295 | ✗ | flatten_error(jb, FLATTEN_VALUE_ERROR_ARRAY); | |
| 296 | } | ||
| 297 | 224 | return sum; | |
| 298 | } | ||
| 299 | 121328 | case LBM_TYPE_BYTE: | |
| 300 | 121328 | return 1 + 1; | |
| 301 | 91324 | case LBM_TYPE_U: /* fall through */ | |
| 302 | case LBM_TYPE_I: | ||
| 303 | #ifndef LBM64 | ||
| 304 | 45662 | return 1 + 4; | |
| 305 | #else | ||
| 306 | 45662 | return 1 + 8; | |
| 307 | #endif | ||
| 308 | 120936 | case LBM_TYPE_U32: /* fall through */ | |
| 309 | case LBM_TYPE_I32: | ||
| 310 | case LBM_TYPE_FLOAT: | ||
| 311 | 120936 | return 1 + 4; | |
| 312 | 168 | case LBM_TYPE_U64: /* fall through */ | |
| 313 | case LBM_TYPE_I64: | ||
| 314 | case LBM_TYPE_DOUBLE: | ||
| 315 | 168 | return 1 + 8; | |
| 316 | 126145 | case LBM_TYPE_SYMBOL: { | |
| 317 |
1/2✓ Branch 0 taken 126145 times.
✗ Branch 1 not taken.
|
126145 | if (!image) { |
| 318 | 126145 | int s = f_sym_string_bytes(v); | |
| 319 |
1/2✓ Branch 0 taken 126145 times.
✗ Branch 1 not taken.
|
126145 | if (s > 0) return 1 + s; |
| 320 | ✗ | flatten_error(jb, (int)s); | |
| 321 | } else { | ||
| 322 | ✗ | return 1 + sizeof(lbm_uint); | |
| 323 | } | ||
| 324 | ✗ | } return 0; // already terminated with error | |
| 325 | 237448 | case LBM_TYPE_ARRAY: { | |
| 326 | // Platform dependent size. | ||
| 327 | // TODO: Something needs to be done to these inconsistencies. | ||
| 328 | 237448 | lbm_int s = lbm_heap_array_get_size(v); | |
| 329 |
1/2✓ Branch 0 taken 237448 times.
✗ Branch 1 not taken.
|
237448 | if (s > 0) |
| 330 | 237448 | return 1 + 4 + (int)s; | |
| 331 | ✗ | flatten_error(jb, (int)s); | |
| 332 | ✗ | } return 0; // already terminated with error | |
| 333 | ✗ | default: | |
| 334 | ✗ | return FLATTEN_VALUE_ERROR_CANNOT_BE_FLATTENED; | |
| 335 | } | ||
| 336 | } | ||
| 337 | |||
| 338 | 69205 | int flatten_value_size(lbm_value v, bool image) { | |
| 339 | jmp_buf jb; | ||
| 340 | 69205 | int r = setjmp(jb); | |
| 341 |
2/2✓ Branch 0 taken 56 times.
✓ Branch 1 taken 69205 times.
|
69261 | if (r != 0) { |
| 342 | 56 | return r; | |
| 343 | } | ||
| 344 | 69205 | return flatten_value_size_internal(jb, v, 0, image); | |
| 345 | } | ||
| 346 | |||
| 347 | 1324933 | int flatten_value_c(lbm_flat_value_t *fv, lbm_value v) { | |
| 348 | |||
| 349 | 1324933 | lbm_uint t = lbm_type_of(v); | |
| 350 |
3/4✓ Branch 0 taken 925764 times.
✓ Branch 1 taken 399169 times.
✓ Branch 2 taken 925764 times.
✗ Branch 3 not taken.
|
1324933 | if (t >= LBM_POINTER_TYPE_FIRST && t < LBM_POINTER_TYPE_LAST) { |
| 351 | // Clear constant bit, it is irrelevant to flattening | ||
| 352 | 925764 | t = t & ~(LBM_PTR_TO_CONSTANT_BIT); | |
| 353 | } | ||
| 354 | |||
| 355 |
13/14✓ Branch 0 taken 627536 times.
✓ Branch 1 taken 224 times.
✓ Branch 2 taken 121296 times.
✓ Branch 3 taken 56 times.
✓ Branch 4 taken 91252 times.
✓ Branch 5 taken 62244 times.
✓ Branch 6 taken 58548 times.
✓ Branch 7 taken 56 times.
✓ Branch 8 taken 56 times.
✓ Branch 9 taken 112 times.
✓ Branch 10 taken 56 times.
✓ Branch 11 taken 126113 times.
✓ Branch 12 taken 237384 times.
✗ Branch 13 not taken.
|
1324933 | switch (t) { |
| 356 | 627536 | case LBM_TYPE_CONS: { | |
| 357 | 627536 | bool res = true; | |
| 358 |
2/4✓ Branch 0 taken 627536 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 627536 times.
✗ Branch 3 not taken.
|
627536 | res = res && f_cons(fv); |
| 359 |
1/2✓ Branch 0 taken 627536 times.
✗ Branch 1 not taken.
|
627536 | if (res) { |
| 360 | 627536 | int fv_r = flatten_value_c(fv, lbm_car(v)); | |
| 361 |
1/2✓ Branch 0 taken 627536 times.
✗ Branch 1 not taken.
|
627536 | if (fv_r == FLATTEN_VALUE_OK) { |
| 362 | 627536 | fv_r = flatten_value_c(fv, lbm_cdr(v)); | |
| 363 | } | ||
| 364 | 627536 | return fv_r; | |
| 365 | } | ||
| 366 | ✗ | }break; | |
| 367 | 224 | case LBM_TYPE_LISPARRAY: { | |
| 368 | 224 | lbm_array_header_t *header = (lbm_array_header_t*)lbm_car(v); | |
| 369 |
1/2✓ Branch 0 taken 224 times.
✗ Branch 1 not taken.
|
224 | if (header) { |
| 370 | 224 | lbm_value *arrdata = (lbm_value*)header->data; | |
| 371 | // always exact multiple of sizeof(lbm_value) | ||
| 372 | 224 | uint32_t size = (uint32_t)(header->size / sizeof(lbm_value)); | |
| 373 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 224 times.
|
224 | if (!f_lisp_array(fv, size)) return FLATTEN_VALUE_ERROR_NOT_ENOUGH_MEMORY; |
| 374 | 224 | int fv_r = FLATTEN_VALUE_OK; | |
| 375 |
2/2✓ Branch 0 taken 728 times.
✓ Branch 1 taken 224 times.
|
952 | for (lbm_uint i = 0; i < size; i ++ ) { |
| 376 | 728 | fv_r = flatten_value_c(fv, arrdata[i]); | |
| 377 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 728 times.
|
728 | if (fv_r != FLATTEN_VALUE_OK) { |
| 378 | ✗ | break; | |
| 379 | } | ||
| 380 | } | ||
| 381 | 224 | return fv_r; | |
| 382 | } else { | ||
| 383 | ✗ | return FLATTEN_VALUE_ERROR_ARRAY; | |
| 384 | } | ||
| 385 | } break; | ||
| 386 | 121296 | case LBM_TYPE_BYTE: | |
| 387 |
1/2✓ Branch 0 taken 121296 times.
✗ Branch 1 not taken.
|
121296 | if (f_b(fv, (uint8_t)lbm_dec_as_char(v))) { |
| 388 | 121296 | return FLATTEN_VALUE_OK; | |
| 389 | } | ||
| 390 | ✗ | break; | |
| 391 | 56 | case LBM_TYPE_U: | |
| 392 |
1/2✓ Branch 0 taken 56 times.
✗ Branch 1 not taken.
|
56 | if (f_u(fv, lbm_dec_u(v))) { |
| 393 | 56 | return FLATTEN_VALUE_OK; | |
| 394 | } | ||
| 395 | ✗ | break; | |
| 396 | 91252 | case LBM_TYPE_I: | |
| 397 |
1/2✓ Branch 0 taken 91252 times.
✗ Branch 1 not taken.
|
91252 | if (f_i(fv, lbm_dec_i(v))) { |
| 398 | 91252 | return FLATTEN_VALUE_OK; | |
| 399 | } | ||
| 400 | ✗ | break; | |
| 401 | 62244 | case LBM_TYPE_U32: | |
| 402 |
1/2✓ Branch 0 taken 62244 times.
✗ Branch 1 not taken.
|
62244 | if (f_u32(fv, lbm_dec_as_u32(v))) { |
| 403 | 62244 | return FLATTEN_VALUE_OK; | |
| 404 | } | ||
| 405 | ✗ | break; | |
| 406 | 58548 | case LBM_TYPE_I32: | |
| 407 |
1/2✓ Branch 0 taken 58548 times.
✗ Branch 1 not taken.
|
58548 | if (f_i32(fv, lbm_dec_as_i32(v))) { |
| 408 | 58548 | return FLATTEN_VALUE_OK; | |
| 409 | } | ||
| 410 | ✗ | break; | |
| 411 | 56 | case LBM_TYPE_U64: | |
| 412 |
1/2✓ Branch 0 taken 56 times.
✗ Branch 1 not taken.
|
56 | if (f_u64(fv, lbm_dec_as_u64(v))) { |
| 413 | 56 | return FLATTEN_VALUE_OK; | |
| 414 | } | ||
| 415 | ✗ | break; | |
| 416 | 56 | case LBM_TYPE_I64: | |
| 417 |
1/2✓ Branch 0 taken 56 times.
✗ Branch 1 not taken.
|
56 | if (f_i64(fv, lbm_dec_as_i64(v))) { |
| 418 | 56 | return FLATTEN_VALUE_OK; | |
| 419 | } | ||
| 420 | ✗ | break; | |
| 421 | 112 | case LBM_TYPE_FLOAT: | |
| 422 |
1/2✓ Branch 0 taken 112 times.
✗ Branch 1 not taken.
|
112 | if (f_float(fv, lbm_dec_as_float(v))) { |
| 423 | 112 | return FLATTEN_VALUE_OK; | |
| 424 | } | ||
| 425 | ✗ | break; | |
| 426 | 56 | case LBM_TYPE_DOUBLE: | |
| 427 |
1/2✓ Branch 0 taken 56 times.
✗ Branch 1 not taken.
|
56 | if (f_double(fv, lbm_dec_as_double(v))) { |
| 428 | 56 | return FLATTEN_VALUE_OK; | |
| 429 | } | ||
| 430 | ✗ | break; | |
| 431 | 126113 | case LBM_TYPE_SYMBOL: { | |
| 432 | 126113 | char *sym_str = (char*)lbm_get_name_by_symbol(lbm_dec_sym(v)); | |
| 433 |
1/2✓ Branch 0 taken 126113 times.
✗ Branch 1 not taken.
|
126113 | if (f_sym_string(fv, sym_str)) { |
| 434 | 126113 | return FLATTEN_VALUE_OK; | |
| 435 | } | ||
| 436 | ✗ | } break; | |
| 437 | 237384 | case LBM_TYPE_ARRAY: { | |
| 438 | 237384 | lbm_int s = lbm_heap_array_get_size(v); | |
| 439 | 237384 | const uint8_t *d = lbm_heap_array_get_data_ro(v); | |
| 440 |
2/4✓ Branch 0 taken 237384 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 237384 times.
✗ Branch 3 not taken.
|
237384 | if (s > 0 && d != NULL) { |
| 441 |
1/2✓ Branch 0 taken 237384 times.
✗ Branch 1 not taken.
|
237384 | if (f_lbm_array(fv, (uint32_t)s, (uint8_t*)d)) { |
| 442 | 237384 | return FLATTEN_VALUE_OK; | |
| 443 | } | ||
| 444 | } else { | ||
| 445 | ✗ | return FLATTEN_VALUE_ERROR_ARRAY; | |
| 446 | } | ||
| 447 | ✗ | }break; | |
| 448 | ✗ | default: | |
| 449 | ✗ | return FLATTEN_VALUE_ERROR_CANNOT_BE_FLATTENED; | |
| 450 | } | ||
| 451 | ✗ | return FLATTEN_VALUE_ERROR_BUFFER_TOO_SMALL; | |
| 452 | } | ||
| 453 | |||
| 454 | 56 | lbm_value handle_flatten_error(int err_val) { | |
| 455 |
1/5✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 56 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
56 | switch (err_val) { |
| 456 | ✗ | case FLATTEN_VALUE_ERROR_CANNOT_BE_FLATTENED: | |
| 457 | ✗ | return ENC_SYM_EERROR; | |
| 458 | ✗ | case FLATTEN_VALUE_ERROR_BUFFER_TOO_SMALL: /* fall through */ | |
| 459 | case FLATTEN_VALUE_ERROR_FATAL: | ||
| 460 | ✗ | return ENC_SYM_FATAL_ERROR; | |
| 461 | 56 | case FLATTEN_VALUE_ERROR_CIRCULAR: /* fall through */ | |
| 462 | case FLATTEN_VALUE_ERROR_MAXIMUM_DEPTH: | ||
| 463 | 56 | return ENC_SYM_EERROR; | |
| 464 | ✗ | case FLATTEN_VALUE_ERROR_ARRAY: /* fall through */ | |
| 465 | case FLATTEN_VALUE_ERROR_NOT_ENOUGH_MEMORY: | ||
| 466 | ✗ | return ENC_SYM_MERROR; | |
| 467 | } | ||
| 468 | ✗ | return ENC_SYM_NIL; | |
| 469 | } | ||
| 470 | |||
| 471 | 69221 | lbm_value flatten_value(lbm_value v) { | |
| 472 | |||
| 473 | 69221 | lbm_value array_cell = lbm_heap_allocate_cell(LBM_TYPE_CONS, ENC_SYM_NIL, ENC_SYM_ARRAY_TYPE); | |
| 474 | |||
| 475 |
2/2✓ Branch 0 taken 16 times.
✓ Branch 1 taken 69205 times.
|
69221 | if (array_cell == ENC_SYM_MERROR) { |
| 476 | 16 | return array_cell; | |
| 477 | } | ||
| 478 | |||
| 479 | lbm_flat_value_t fv; | ||
| 480 | |||
| 481 | 69205 | lbm_array_header_t *array = NULL; | |
| 482 | 69205 | int required_mem = flatten_value_size(v, false); | |
| 483 |
2/2✓ Branch 0 taken 69149 times.
✓ Branch 1 taken 56 times.
|
69205 | if (required_mem > 0) { |
| 484 | 69149 | array = (lbm_array_header_t *)lbm_malloc(sizeof(lbm_array_header_t)); | |
| 485 |
2/2✓ Branch 0 taken 16 times.
✓ Branch 1 taken 69133 times.
|
69149 | if (array == NULL) { |
| 486 | 16 | lbm_set_car_and_cdr(array_cell, ENC_SYM_NIL, ENC_SYM_NIL); | |
| 487 | 16 | return ENC_SYM_MERROR; | |
| 488 | } | ||
| 489 | |||
| 490 | 69133 | bool r = lbm_start_flatten(&fv, (lbm_uint)required_mem); | |
| 491 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 69133 times.
|
69133 | if (!r) { |
| 492 | ✗ | lbm_free(array); | |
| 493 | ✗ | lbm_set_car_and_cdr(array_cell, ENC_SYM_NIL, ENC_SYM_NIL); | |
| 494 | ✗ | return ENC_SYM_MERROR; | |
| 495 | } | ||
| 496 | |||
| 497 |
1/2✓ Branch 0 taken 69133 times.
✗ Branch 1 not taken.
|
69133 | if (flatten_value_c(&fv, v) == FLATTEN_VALUE_OK) { |
| 498 | // it would be wasteful to run finish_flatten here. | ||
| 499 | 69133 | r = true; | |
| 500 | } else { | ||
| 501 | ✗ | r = false; | |
| 502 | } | ||
| 503 | |||
| 504 |
1/2✓ Branch 0 taken 69133 times.
✗ Branch 1 not taken.
|
69133 | if (r) { |
| 505 | // lift flat_value | ||
| 506 | 69133 | array->data = (lbm_uint*)fv.buf; | |
| 507 | 69133 | array->size = fv.buf_size; | |
| 508 | 69133 | lbm_set_car(array_cell, (lbm_uint)array); | |
| 509 | 69133 | array_cell = lbm_set_ptr_type(array_cell, LBM_TYPE_ARRAY); | |
| 510 | 69133 | return array_cell; | |
| 511 | } | ||
| 512 | } | ||
| 513 | 56 | lbm_set_car_and_cdr(array_cell, ENC_SYM_NIL, ENC_SYM_NIL); | |
| 514 | 56 | return handle_flatten_error(required_mem); | |
| 515 | } | ||
| 516 | |||
| 517 | // ------------------------------------------------------------ | ||
| 518 | // Unflattening | ||
| 519 | 122658 | static bool extract_byte(lbm_flat_value_t *v, uint8_t *r) { | |
| 520 |
1/2✓ Branch 0 taken 122658 times.
✗ Branch 1 not taken.
|
122658 | if (v->buf_size >= v->buf_pos + 1) { |
| 521 | 122658 | *r = v->buf[v->buf_pos++]; | |
| 522 | 122658 | return true; | |
| 523 | } | ||
| 524 | ✗ | return false; | |
| 525 | } | ||
| 526 | |||
| 527 | 426811 | static bool extract_word(lbm_flat_value_t *v, uint32_t *r) { | |
| 528 | 426811 | bool res = false; | |
| 529 |
1/2✓ Branch 0 taken 426811 times.
✗ Branch 1 not taken.
|
426811 | if (v->buf_size >= v->buf_pos + 4) { |
| 530 | 426811 | uint32_t tmp = 0; | |
| 531 | 426811 | tmp |= (lbm_value)v->buf[v->buf_pos++]; | |
| 532 | 426811 | tmp = tmp << 8 | (uint32_t)v->buf[v->buf_pos++]; | |
| 533 | 426811 | tmp = tmp << 8 | (uint32_t)v->buf[v->buf_pos++]; | |
| 534 | 426811 | tmp = tmp << 8 | (uint32_t)v->buf[v->buf_pos++]; | |
| 535 | 426811 | *r = tmp; | |
| 536 | 426811 | res = true; | |
| 537 | } | ||
| 538 | 426811 | return res; | |
| 539 | } | ||
| 540 | |||
| 541 | 48998 | static bool extract_dword(lbm_flat_value_t *v, uint64_t *r) { | |
| 542 | 48998 | bool res = false; | |
| 543 |
1/2✓ Branch 0 taken 48998 times.
✗ Branch 1 not taken.
|
48998 | if (v->buf_size >= v->buf_pos + 8) { |
| 544 | 48998 | uint64_t tmp = 0; | |
| 545 | 48998 | tmp |= (lbm_value)v->buf[v->buf_pos++]; | |
| 546 | 48998 | tmp = tmp << 8 | (uint64_t)v->buf[v->buf_pos++]; | |
| 547 | 48998 | tmp = tmp << 8 | (uint64_t)v->buf[v->buf_pos++]; | |
| 548 | 48998 | tmp = tmp << 8 | (uint64_t)v->buf[v->buf_pos++]; | |
| 549 | 48998 | tmp = tmp << 8 | (uint64_t)v->buf[v->buf_pos++]; | |
| 550 | 48998 | tmp = tmp << 8 | (uint64_t)v->buf[v->buf_pos++]; | |
| 551 | 48998 | tmp = tmp << 8 | (uint64_t)v->buf[v->buf_pos++]; | |
| 552 | 48998 | tmp = tmp << 8 | (uint64_t)v->buf[v->buf_pos++]; | |
| 553 | 48998 | *r = tmp; | |
| 554 | 48998 | res = true;; | |
| 555 | } | ||
| 556 | 48998 | return res; | |
| 557 | } | ||
| 558 | |||
| 559 | 724526 | static int lbm_unflatten_value_atom(lbm_flat_value_t *v, lbm_value *res) { | |
| 560 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 724526 times.
|
724526 | if (v->buf_size == v->buf_pos) return UNFLATTEN_MALFORMED; |
| 561 | |||
| 562 | 724526 | uint8_t curr = v->buf[v->buf_pos++]; | |
| 563 | |||
| 564 |
15/17✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 8305 times.
✓ Branch 3 taken 122658 times.
✓ Branch 4 taken 47323 times.
✓ Branch 5 taken 32 times.
✓ Branch 6 taken 45744 times.
✓ Branch 7 taken 28 times.
✓ Branch 8 taken 12498 times.
✓ Branch 9 taken 58 times.
✓ Branch 10 taken 58804 times.
✓ Branch 11 taken 63258 times.
✓ Branch 12 taken 58 times.
✓ Branch 13 taken 58 times.
✓ Branch 14 taken 239387 times.
✓ Branch 15 taken 126314 times.
✗ Branch 16 not taken.
|
724526 | switch(curr) { |
| 565 | ✗ | case S_CONS: { | |
| 566 | ✗ | return UNFLATTEN_MALFORMED; | |
| 567 | } | ||
| 568 | 1 | case S_CONSTANT_REF: { | |
| 569 | lbm_uint tmp; | ||
| 570 | bool b; | ||
| 571 | #ifndef LBM64 | ||
| 572 | 1 | b = extract_word(v, &tmp); | |
| 573 | #else | ||
| 574 | ✗ | b = extract_dword(v, &tmp); | |
| 575 | #endif | ||
| 576 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (b) { |
| 577 | 1 | *res = tmp; | |
| 578 | 1 | return UNFLATTEN_OK; | |
| 579 | } | ||
| 580 | ✗ | return UNFLATTEN_MALFORMED; | |
| 581 | } | ||
| 582 | 8305 | case S_SYM_VALUE: { | |
| 583 | lbm_uint tmp; | ||
| 584 | bool b; | ||
| 585 | #ifndef LBM64 | ||
| 586 | 5253 | b = extract_word(v, &tmp); | |
| 587 | #else | ||
| 588 | 3052 | b = extract_dword(v, &tmp); | |
| 589 | #endif | ||
| 590 |
1/2✓ Branch 0 taken 8305 times.
✗ Branch 1 not taken.
|
8305 | if (b) { |
| 591 | 8305 | *res = lbm_enc_sym(tmp); | |
| 592 | 8305 | return UNFLATTEN_OK; | |
| 593 | } | ||
| 594 | ✗ | return UNFLATTEN_MALFORMED; | |
| 595 | } | ||
| 596 | 122658 | case S_BYTE_VALUE: { | |
| 597 | uint8_t tmp; | ||
| 598 | 122658 | bool b = extract_byte(v, &tmp); | |
| 599 |
1/2✓ Branch 0 taken 122658 times.
✗ Branch 1 not taken.
|
122658 | if (b) { |
| 600 | 122658 | *res = lbm_enc_char((uint8_t)tmp); | |
| 601 | 122658 | return UNFLATTEN_OK; | |
| 602 | } | ||
| 603 | ✗ | return UNFLATTEN_MALFORMED; | |
| 604 | } | ||
| 605 | 47323 | case S_I28_VALUE: { | |
| 606 | uint32_t tmp; | ||
| 607 | bool b; | ||
| 608 | 47323 | b = extract_word(v, &tmp); | |
| 609 |
1/2✓ Branch 0 taken 47323 times.
✗ Branch 1 not taken.
|
47323 | if (b) { |
| 610 | 47323 | *res = lbm_enc_i((int32_t)tmp); | |
| 611 | 47323 | return UNFLATTEN_OK; | |
| 612 | } | ||
| 613 | ✗ | return UNFLATTEN_MALFORMED; | |
| 614 | } | ||
| 615 | 32 | case S_U28_VALUE: { | |
| 616 | uint32_t tmp; | ||
| 617 | bool b; | ||
| 618 | 32 | b = extract_word(v, &tmp); | |
| 619 |
1/2✓ Branch 0 taken 32 times.
✗ Branch 1 not taken.
|
32 | if (b) { |
| 620 | 32 | *res = lbm_enc_u((uint32_t)tmp); | |
| 621 | 32 | return UNFLATTEN_OK; | |
| 622 | } | ||
| 623 | ✗ | return UNFLATTEN_MALFORMED; | |
| 624 | } | ||
| 625 | 45744 | case S_I56_VALUE: { | |
| 626 | uint64_t tmp; | ||
| 627 | bool b; | ||
| 628 | 45744 | b = extract_dword(v, &tmp); | |
| 629 |
1/2✓ Branch 0 taken 45744 times.
✗ Branch 1 not taken.
|
45744 | if (b) { |
| 630 | #ifndef LBM64 | ||
| 631 | ✗ | *res = lbm_enc_i64((int64_t)tmp); | |
| 632 | #else | ||
| 633 | 45744 | *res = lbm_enc_i((int64_t)tmp); | |
| 634 | #endif | ||
| 635 | 45744 | return UNFLATTEN_OK; | |
| 636 | } | ||
| 637 | ✗ | return UNFLATTEN_MALFORMED; | |
| 638 | } | ||
| 639 | 28 | case S_U56_VALUE: { | |
| 640 | uint64_t tmp; | ||
| 641 | bool b; | ||
| 642 | 28 | b = extract_dword(v, &tmp); | |
| 643 |
1/2✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
|
28 | if (b) { |
| 644 | #ifndef LBM64 | ||
| 645 | ✗ | *res = lbm_enc_u64(tmp); | |
| 646 | #else | ||
| 647 | 28 | *res = lbm_enc_u(tmp); | |
| 648 | #endif | ||
| 649 | 28 | return UNFLATTEN_OK; | |
| 650 | } | ||
| 651 | ✗ | return UNFLATTEN_MALFORMED; | |
| 652 | } | ||
| 653 | 12498 | case S_FLOAT_VALUE: { | |
| 654 | uint32_t tmp; | ||
| 655 | bool b; | ||
| 656 | 12498 | b = extract_word(v, &tmp); | |
| 657 |
1/2✓ Branch 0 taken 12498 times.
✗ Branch 1 not taken.
|
12498 | if (b) { |
| 658 | lbm_float f; | ||
| 659 | 12498 | memcpy(&f, &tmp, sizeof(lbm_float)); | |
| 660 | 12498 | lbm_value im = lbm_enc_float(f); | |
| 661 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12498 times.
|
12498 | if (lbm_is_symbol_merror(im)) { |
| 662 | ✗ | return UNFLATTEN_GC_RETRY; | |
| 663 | } | ||
| 664 | 12498 | *res = im; | |
| 665 | 12498 | return UNFLATTEN_OK; | |
| 666 | } | ||
| 667 | ✗ | return UNFLATTEN_MALFORMED; | |
| 668 | } | ||
| 669 | 58 | case S_DOUBLE_VALUE: { | |
| 670 | uint64_t tmp; | ||
| 671 | bool b; | ||
| 672 | 58 | b = extract_dword(v, &tmp); | |
| 673 |
1/2✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
|
58 | if (b) { |
| 674 | double f; | ||
| 675 | 58 | memcpy(&f, &tmp, sizeof(uint64_t)); | |
| 676 | 58 | lbm_value im = lbm_enc_double(f); | |
| 677 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
|
58 | if (lbm_is_symbol_merror(im)) { |
| 678 | ✗ | return UNFLATTEN_GC_RETRY; | |
| 679 | } | ||
| 680 | 58 | *res = im; | |
| 681 | 58 | return UNFLATTEN_OK; | |
| 682 | } | ||
| 683 | ✗ | return UNFLATTEN_MALFORMED; | |
| 684 | } | ||
| 685 | 58804 | case S_I32_VALUE: { | |
| 686 | uint32_t tmp; | ||
| 687 |
1/2✓ Branch 0 taken 58804 times.
✗ Branch 1 not taken.
|
58804 | if (extract_word(v, &tmp)) { |
| 688 | 58804 | lbm_value im = lbm_enc_i32((int32_t)tmp); | |
| 689 |
2/2✓ Branch 0 taken 74 times.
✓ Branch 1 taken 58730 times.
|
58804 | if (lbm_is_symbol_merror(im)) { |
| 690 | 74 | return UNFLATTEN_GC_RETRY; | |
| 691 | } | ||
| 692 | 58730 | *res = im; | |
| 693 | 58730 | return UNFLATTEN_OK; | |
| 694 | } | ||
| 695 | ✗ | return UNFLATTEN_MALFORMED; | |
| 696 | } | ||
| 697 | 63258 | case S_U32_VALUE: { | |
| 698 | uint32_t tmp; | ||
| 699 |
1/2✓ Branch 0 taken 63258 times.
✗ Branch 1 not taken.
|
63258 | if (extract_word(v, &tmp)) { |
| 700 | 63258 | lbm_value im = lbm_enc_u32(tmp); | |
| 701 |
2/2✓ Branch 0 taken 24 times.
✓ Branch 1 taken 63234 times.
|
63258 | if (lbm_is_symbol_merror(im)) { |
| 702 | 24 | return UNFLATTEN_GC_RETRY; | |
| 703 | } | ||
| 704 | 63234 | *res = im; | |
| 705 | 63234 | return UNFLATTEN_OK; | |
| 706 | } | ||
| 707 | ✗ | return UNFLATTEN_MALFORMED; | |
| 708 | } | ||
| 709 | 58 | case S_I64_VALUE: { | |
| 710 | 58 | uint64_t tmp = 0; | |
| 711 |
1/2✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
|
58 | if (extract_dword(v, &tmp)) { |
| 712 | 58 | lbm_value im = lbm_enc_i64((int64_t)tmp); | |
| 713 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
|
58 | if (lbm_is_symbol_merror(im)) { |
| 714 | ✗ | return UNFLATTEN_GC_RETRY; | |
| 715 | } | ||
| 716 | 58 | *res = im; | |
| 717 | 58 | return UNFLATTEN_OK; | |
| 718 | } | ||
| 719 | ✗ | return UNFLATTEN_MALFORMED; | |
| 720 | } | ||
| 721 | 58 | case S_U64_VALUE: { | |
| 722 | 58 | uint64_t tmp = 0; | |
| 723 |
1/2✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
|
58 | if (extract_dword(v, &tmp)) { |
| 724 | 58 | lbm_value im = lbm_enc_u64(tmp); | |
| 725 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 58 times.
|
58 | if (lbm_is_symbol_merror(im)) { |
| 726 | ✗ | return UNFLATTEN_GC_RETRY; | |
| 727 | } | ||
| 728 | 58 | *res = im; | |
| 729 | 58 | return UNFLATTEN_OK; | |
| 730 | } | ||
| 731 | ✗ | return UNFLATTEN_MALFORMED; | |
| 732 | } | ||
| 733 | 239387 | case S_LBM_ARRAY: { | |
| 734 | uint32_t num_elt; | ||
| 735 |
1/2✓ Branch 0 taken 239387 times.
✗ Branch 1 not taken.
|
239387 | if (extract_word(v, &num_elt)) { |
| 736 |
2/2✓ Branch 0 taken 238921 times.
✓ Branch 1 taken 466 times.
|
239387 | if (lbm_heap_allocate_array(res, num_elt)) { |
| 737 | 238921 | lbm_array_header_t *arr = (lbm_array_header_t*)lbm_car(*res); | |
| 738 | 238921 | lbm_uint num_bytes = num_elt; | |
| 739 | 238921 | memcpy(arr->data, v->buf + v->buf_pos, num_bytes); | |
| 740 | 238921 | v->buf_pos += num_bytes; | |
| 741 | } else { | ||
| 742 | 466 | return UNFLATTEN_GC_RETRY; | |
| 743 | } | ||
| 744 | 238921 | return UNFLATTEN_OK; | |
| 745 | } | ||
| 746 | ✗ | return UNFLATTEN_MALFORMED; | |
| 747 | } | ||
| 748 | 126314 | case S_SYM_STRING: { | |
| 749 | lbm_uint sym_id; | ||
| 750 |
1/2✓ Branch 0 taken 126314 times.
✗ Branch 1 not taken.
|
126314 | if (lbm_add_symbol((char *)(v->buf + v->buf_pos), &sym_id)) { |
| 751 | 126314 | lbm_uint num_bytes = strlen((char*)(v->buf + v->buf_pos)) + 1; | |
| 752 | 126314 | v->buf_pos += num_bytes; | |
| 753 | 126314 | *res = lbm_enc_sym(sym_id); | |
| 754 | 126314 | return UNFLATTEN_OK; | |
| 755 | } | ||
| 756 | ✗ | return UNFLATTEN_GC_RETRY; | |
| 757 | } | ||
| 758 | ✗ | default: | |
| 759 | ✗ | return UNFLATTEN_MALFORMED; | |
| 760 | } | ||
| 761 | } | ||
| 762 | |||
| 763 | // //////////////////////////////////////////////////////////// | ||
| 764 | // Pointer-reversal-esque "stackless" deserialization of | ||
| 765 | // flattened (serialized) trees. | ||
| 766 | // | ||
| 767 | // Initially: | ||
| 768 | // curr = LBM_NULL; v->buf = { ... } | ||
| 769 | // | ||
| 770 | // FORWARDS PHASE: | ||
| 771 | // Cons case: | ||
| 772 | // Reading conses from the buffer builds a backpointing list. | ||
| 773 | // Placeholder element acts as a 1 bit "visited" field. | ||
| 774 | // | ||
| 775 | // curr = p; v->buf = {S_CONS, ... } | ||
| 776 | // => | ||
| 777 | // curr = [p, placeholder]; v->buf = { ... } | ||
| 778 | // | ||
| 779 | // Lisp array case: | ||
| 780 | // An Array tag in the buffer leads to the creation of an array | ||
| 781 | // with a backptr in the last element position. Placeholder element | ||
| 782 | // is not needed as LBM-Arrays have a built in index field (used by GC) | ||
| 783 | // that can keep a count of how far along the array we have progressed. | ||
| 784 | // | ||
| 785 | // curr = p; v->buf = {S_LBM_LISP_ARRAY, ... } | ||
| 786 | // => | ||
| 787 | // curr = [| nil ... p |]; v->buf = { ... } | ||
| 788 | // | ||
| 789 | // Atom case: | ||
| 790 | // Reading an atom triggers a backwards traversal along the backpointer | ||
| 791 | // structure. | ||
| 792 | // | ||
| 793 | // curr = X; v->buf = {any_atom, ... } example integer, string. | ||
| 794 | // => | ||
| 795 | // val = unflatten_atom(v->buf); v->buf = { ... } | ||
| 796 | // | ||
| 797 | // BACKWARDS PHASE: Start the backwards traversal: | ||
| 798 | // | ||
| 799 | // Case on X | ||
| 800 | // LBM_NULL; | ||
| 801 | // => Done! result = val | ||
| 802 | // | ||
| 803 | // [p, placeholder]; | ||
| 804 | // => | ||
| 805 | // [p, val] Base case. Finishes back traversal. | ||
| 806 | // Go back to FORWARDS PHASE. | ||
| 807 | // | ||
| 808 | // | ||
| 809 | // [p, val0]; | ||
| 810 | // => | ||
| 811 | // tmp = [val0, val]; val = tmp; curr = p; continue backwards with value pointing to recently constructed final subresult. | ||
| 812 | // | ||
| 813 | // | ||
| 814 | // [| a b nil ... p |] | ||
| 815 | // => | ||
| 816 | // [| a b val ... p |] Base case. Finishes back traversal. | ||
| 817 | // Array internal index field keeps track of write position. | ||
| 818 | // Go back to FORWARDS PHASE. | ||
| 819 | // | ||
| 820 | // | ||
| 821 | // [| a0 a1 ... an p |] | ||
| 822 | // => | ||
| 823 | // tmp = [| a0 a1 ... an val |]; val = tmp; curr = p; continue backwards | ||
| 824 | // | ||
| 825 | |||
| 826 | 77122 | static int lbm_unflatten_value_nostack(sharing_table *st, lbm_uint *target_map, lbm_flat_value_t *v, lbm_value *res) { | |
| 827 | 77122 | bool done = false; | |
| 828 | lbm_value val0; | ||
| 829 | 77122 | lbm_value curr = lbm_enc_cons_ptr(LBM_PTR_NULL); | |
| 830 |
1/2✓ Branch 0 taken 1373120 times.
✗ Branch 1 not taken.
|
1373120 | while (!done) { |
| 831 | 1373120 | int32_t set_ix = -1; | |
| 832 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 1373111 times.
|
1373120 | if (v->buf[v->buf_pos] == S_SHARED) { |
| 833 | 9 | v->buf_pos++; | |
| 834 |
2/4✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
|
18 | if (st && target_map) { |
| 835 | 9 | bool b = false; | |
| 836 | lbm_uint tmp; | ||
| 837 | #ifndef LBM64 | ||
| 838 | 9 | b = extract_word(v, &tmp); | |
| 839 | #else | ||
| 840 | ✗ | b = extract_dword(v, &tmp); | |
| 841 | #endif | ||
| 842 |
1/2✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
|
9 | if (b) { |
| 843 | 9 | int32_t ix = sharing_table_contains(st, tmp); | |
| 844 |
1/2✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
|
9 | if (ix >= 0) { |
| 845 | 9 | set_ix = ix; | |
| 846 | } else { | ||
| 847 | ✗ | return UNFLATTEN_SHARING_TABLE_ERROR; | |
| 848 | } | ||
| 849 | } else { | ||
| 850 | ✗ | return UNFLATTEN_MALFORMED; | |
| 851 | } | ||
| 852 | } else { | ||
| 853 | ✗ | return UNFLATTEN_SHARING_TABLE_REQUIRED; | |
| 854 | } | ||
| 855 | } | ||
| 856 | |||
| 857 | 1373120 | bool is_leaf = true; | |
| 858 | 1373120 | lbm_value unflattened = ENC_SYM_NIL; | |
| 859 | |||
| 860 |
2/2✓ Branch 0 taken 648348 times.
✓ Branch 1 taken 724772 times.
|
1373120 | if (v->buf[v->buf_pos] == S_CONS) { |
| 861 | 648348 | lbm_value tmp = curr; | |
| 862 | 648348 | curr = lbm_cons(tmp, ENC_SYM_PLACEHOLDER); | |
| 863 |
2/2✓ Branch 0 taken 498 times.
✓ Branch 1 taken 647850 times.
|
648348 | if (lbm_is_symbol_merror(curr)) return UNFLATTEN_GC_RETRY; |
| 864 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 647841 times.
|
647850 | if (set_ix >= 0) target_map[set_ix] = curr; |
| 865 | 647850 | v->buf_pos ++; | |
| 866 | 647850 | is_leaf = false; | |
| 867 |
2/2✓ Branch 0 taken 237 times.
✓ Branch 1 taken 724535 times.
|
724772 | } else if (v->buf[v->buf_pos] == S_LBM_LISP_ARRAY) { |
| 868 | uint32_t size; | ||
| 869 | 237 | v->buf_pos ++; | |
| 870 | 237 | bool b = extract_word(v, &size); | |
| 871 |
1/2✓ Branch 0 taken 237 times.
✗ Branch 1 not taken.
|
237 | if (b) { |
| 872 | lbm_value array; | ||
| 873 | 237 | lbm_heap_allocate_lisp_array(&array, size); | |
| 874 | 237 | lbm_array_header_extended_t *header = (lbm_array_header_extended_t*)lbm_car(array); | |
| 875 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 235 times.
|
237 | if (size == 0) { |
| 876 | 2 | unflattened = array; | |
| 877 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if (set_ix >= 0) target_map[set_ix] = array; |
| 878 | } else { | ||
| 879 | 235 | is_leaf = false; | |
| 880 | 235 | lbm_value *arrdata = (lbm_value*)header->data; | |
| 881 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 235 times.
|
235 | if (lbm_is_symbol_merror(array)) return UNFLATTEN_GC_RETRY; |
| 882 | 235 | header->index = 0; | |
| 883 | 235 | arrdata[size-1] = curr; // backptr | |
| 884 | 235 | curr = array; | |
| 885 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 235 times.
|
235 | if (set_ix >= 0) target_map[set_ix] = curr; |
| 886 | } | ||
| 887 | } else { | ||
| 888 | ✗ | return UNFLATTEN_MALFORMED; | |
| 889 | } | ||
| 890 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 724535 times.
|
724535 | } else if (v->buf[v->buf_pos] == 0) { |
| 891 | ✗ | return UNFLATTEN_MALFORMED; | |
| 892 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 724526 times.
|
724535 | } else if (v->buf[v->buf_pos] == S_REF) { |
| 893 | 9 | v->buf_pos++; | |
| 894 |
2/4✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
|
18 | if (st && target_map) { |
| 895 | 9 | bool b = false; | |
| 896 | lbm_uint tmp; | ||
| 897 | #ifndef LBM64 | ||
| 898 | 9 | b = extract_word(v, &tmp); | |
| 899 | #else | ||
| 900 | ✗ | b = extract_dword(v, &tmp); | |
| 901 | #endif | ||
| 902 |
1/2✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
|
9 | if (b) { |
| 903 | // Shared should have been hit before S_REF. So just look up index and copy from | ||
| 904 | // the target_map. | ||
| 905 | 9 | int32_t ix = sharing_table_contains(st, tmp); | |
| 906 |
1/2✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
|
9 | if (ix >= 0) { |
| 907 | //curr = target_map[ix]; | ||
| 908 | 9 | unflattened = target_map[ix]; | |
| 909 | } else { | ||
| 910 | ✗ | return UNFLATTEN_SHARING_TABLE_ERROR; | |
| 911 | } | ||
| 912 | } else { | ||
| 913 | ✗ | return UNFLATTEN_MALFORMED; | |
| 914 | } | ||
| 915 | } else { | ||
| 916 | ✗ | return UNFLATTEN_SHARING_TABLE_REQUIRED; | |
| 917 | } | ||
| 918 | } else { | ||
| 919 | 724526 | int e_val = lbm_unflatten_value_atom(v, &unflattened); | |
| 920 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 724526 times.
|
724526 | if (set_ix >= 0) { |
| 921 | ✗ | target_map[set_ix] = unflattened; | |
| 922 | } | ||
| 923 |
2/2✓ Branch 0 taken 564 times.
✓ Branch 1 taken 723962 times.
|
724526 | if (e_val != UNFLATTEN_OK) { |
| 924 | 564 | return e_val; | |
| 925 | } | ||
| 926 | } | ||
| 927 | |||
| 928 |
2/2✓ Branch 0 taken 723973 times.
✓ Branch 1 taken 648085 times.
|
1372058 | if (is_leaf) { |
| 929 | 723973 | val0 = unflattened; | |
| 930 |
4/4✓ Branch 0 taken 1291180 times.
✓ Branch 1 taken 76060 times.
✓ Branch 2 taken 643894 times.
✓ Branch 3 taken 647286 times.
|
2658420 | while (lbm_dec_ptr(curr) != LBM_PTR_NULL && |
| 931 | 1291180 | lbm_cdr(curr) != ENC_SYM_PLACEHOLDER) { // has done left | |
| 932 |
2/2✓ Branch 0 taken 862 times.
✓ Branch 1 taken 643032 times.
|
643894 | if ( lbm_type_of(curr) == LBM_TYPE_LISPARRAY) { |
| 933 | 862 | lbm_array_header_extended_t *header = (lbm_array_header_extended_t*)lbm_car(curr); | |
| 934 | 862 | lbm_value *arrdata = (lbm_value*)header->data; | |
| 935 | 862 | uint32_t arrlen = header->size / sizeof(lbm_value); | |
| 936 |
2/2✓ Branch 0 taken 235 times.
✓ Branch 1 taken 627 times.
|
862 | if (header->index == arrlen - 1) { |
| 937 | 235 | lbm_value prev = arrdata[arrlen-1]; | |
| 938 | 235 | header->index = 0; | |
| 939 | 235 | arrdata[arrlen-1] = val0; | |
| 940 | 235 | val0 = curr; | |
| 941 | 235 | curr = prev; | |
| 942 | } else { | ||
| 943 | 627 | arrdata[header->index++] = val0; | |
| 944 | 627 | break; | |
| 945 | } | ||
| 946 | } else { | ||
| 947 | 643032 | lbm_value prev = lbm_car(curr); | |
| 948 | 643032 | lbm_value r0 = lbm_cdr(curr); | |
| 949 | 643032 | lbm_set_cdr(curr, val0); | |
| 950 | 643032 | lbm_set_car(curr, r0); | |
| 951 | 643032 | val0 = curr; | |
| 952 | 643032 | curr = prev; | |
| 953 | } | ||
| 954 | } | ||
| 955 |
2/2✓ Branch 0 taken 76060 times.
✓ Branch 1 taken 647913 times.
|
723973 | if (lbm_dec_ptr(curr) == LBM_PTR_NULL) { |
| 956 | 76060 | *res = val0; // done | |
| 957 | 76060 | break; | |
| 958 |
2/2✓ Branch 0 taken 647286 times.
✓ Branch 1 taken 627 times.
|
647913 | } else if (lbm_type_of(curr) == LBM_TYPE_LISPARRAY) { |
| 959 | // Do nothing in this case. It has been arranged.. | ||
| 960 |
1/2✓ Branch 0 taken 647286 times.
✗ Branch 1 not taken.
|
647286 | } else if (lbm_cdr(curr) == ENC_SYM_PLACEHOLDER) { |
| 961 | 647286 | lbm_set_cdr(curr, val0); | |
| 962 | } else { | ||
| 963 | ✗ | return UNFLATTEN_MALFORMED; | |
| 964 | } | ||
| 965 | } | ||
| 966 | } | ||
| 967 | 76060 | return UNFLATTEN_OK; | |
| 968 | } | ||
| 969 | |||
| 970 | /* lbm_unflatten_value_nostack, does not backtrack | ||
| 971 | upon error to swap pointer to the correct direction | ||
| 972 | and to remove the LBM_PTR_NULL tag. | ||
| 973 | |||
| 974 | unflatten_value_nostack does not alter the GC_FLAG or the GC_MARK, | ||
| 975 | So really only reverse pointers and the NIL tag could be | ||
| 976 | potential problems. | ||
| 977 | */ | ||
| 978 | 76034 | bool lbm_unflatten_value(lbm_flat_value_t *v, lbm_value *res) { | |
| 979 | 76034 | bool b = false; | |
| 980 | #ifdef LBM_ALWAYS_GC | ||
| 981 | lbm_perform_gc(); | ||
| 982 | #endif | ||
| 983 | 76034 | int r = lbm_unflatten_value_nostack(NULL,NULL, v,res); | |
| 984 |
2/2✓ Branch 0 taken 1062 times.
✓ Branch 1 taken 74972 times.
|
76034 | if (r == UNFLATTEN_GC_RETRY) { |
| 985 | 1062 | lbm_perform_gc(); | |
| 986 | 1062 | v->buf_pos = 0; | |
| 987 | 1062 | r = lbm_unflatten_value_nostack(NULL,NULL,v,res); | |
| 988 | } | ||
| 989 |
1/3✓ Branch 0 taken 76034 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
|
76034 | switch(r) { |
| 990 | 76034 | case UNFLATTEN_OK: | |
| 991 | 76034 | b = true; | |
| 992 | 76034 | break; | |
| 993 | ✗ | case UNFLATTEN_GC_RETRY: | |
| 994 | ✗ | *res = ENC_SYM_MERROR; | |
| 995 | ✗ | break; | |
| 996 | ✗ | default: | |
| 997 | ✗ | *res = ENC_SYM_EERROR; | |
| 998 | ✗ | break; | |
| 999 | } | ||
| 1000 | // Do not free the flat value buffer here. | ||
| 1001 | // there are 2 cases: | ||
| 1002 | // 1: unflatten was called from lisp code -> GC removes the buffer. | ||
| 1003 | // 2: unflatten called from event processing -> event processor frees buffer. | ||
| 1004 | 76034 | return b; | |
| 1005 | } | ||
| 1006 | |||
| 1007 | 26 | bool lbm_unflatten_value_sharing(sharing_table *st, lbm_uint *target_map, lbm_flat_value_t *v, lbm_value *res) { | |
| 1008 | 26 | bool b = false; | |
| 1009 | #ifdef LBM_ALWAYS_GC | ||
| 1010 | lbm_perform_gc(); | ||
| 1011 | #endif | ||
| 1012 | 26 | int r = lbm_unflatten_value_nostack(st,target_map, v,res); | |
| 1013 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 26 times.
|
26 | if (r == UNFLATTEN_GC_RETRY) { |
| 1014 | ✗ | lbm_perform_gc(); | |
| 1015 | ✗ | v->buf_pos = 0; | |
| 1016 | ✗ | r = lbm_unflatten_value_nostack(st,target_map,v,res); | |
| 1017 | } | ||
| 1018 |
1/3✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
|
26 | switch(r) { |
| 1019 | 26 | case UNFLATTEN_OK: | |
| 1020 | 26 | b = true; | |
| 1021 | 26 | break; | |
| 1022 | ✗ | case UNFLATTEN_GC_RETRY: | |
| 1023 | ✗ | *res = ENC_SYM_MERROR; | |
| 1024 | ✗ | break; | |
| 1025 | ✗ | default: | |
| 1026 | ✗ | *res = ENC_SYM_EERROR; | |
| 1027 | ✗ | break; | |
| 1028 | } | ||
| 1029 | // Do not free the flat value buffer here. | ||
| 1030 | // there are 2 cases: | ||
| 1031 | // 1: unflatten was called from lisp code -> GC removes the buffer. | ||
| 1032 | // 2: unflatten called from event processing -> event processor frees buffer. | ||
| 1033 | 26 | return b; | |
| 1034 | } | ||
| 1035 |