1 /* i/n/a.h 2 ** 3 ** This file is in the public domain. 4 */ 5 /** Options. 6 **/ 7 /* U3_MEMORY_DEBUG: add debugging information to heap. Breaks image. 8 */ 9 # undef U3_MEMORY_DEBUG 10 11 /** Constants. 12 **/ 13 /* u3a_bits: number of bits in word-addressed pointer. 29 == 2GB. 14 */ 15 # define u3a_bits U3_OS_LoomBits 16 17 /* u3a_page: number of bits in word-addressed page. 12 == 16Kbyte page. 18 */ 19 # define u3a_page 12 20 21 /* u3a_pages: number of pages in memory. 22 */ 23 # define u3a_pages (1 << (u3a_bits - u3a_page)) 24 25 /* u3a_words: number of words in memory. 26 */ 27 # define u3a_words (1 << u3a_bits) 28 29 /* u3a_bytes: number of bytes in memory. 30 */ 31 # define u3a_bytes (c3_w)((1 << (2 + u3a_bits))) 32 33 /* u3a_minimum: minimum number of words in a box. 34 */ 35 #ifdef U3_MEMORY_DEBUG 36 # define u3a_minimum 8 37 #else 38 # define u3a_minimum 6 39 #endif 40 41 /* u3a_fbox_no: number of free lists per size. 42 */ 43 # define u3a_fbox_no 27 44 45 46 /** Structures. 47 **/ 48 /* u3a_atom, u3a_cell: logical atom and cell structures. 49 */ 50 typedef struct { 51 c3_w mug_w; 52 } u3a_noun; 53 54 typedef struct { 55 c3_w mug_w; 56 c3_w len_w; 57 c3_w buf_w[0]; 58 } u3a_atom; 59 60 typedef struct { 61 c3_w mug_w; 62 u3_noun hed; 63 u3_noun tel; 64 } u3a_cell; 65 66 /* u3a_box: classic allocation box. 67 ** 68 ** The box size is also stored at the end of the box in classic 69 ** bad ass malloc style. Hence a box is: 70 ** 71 ** --- 72 ** siz_w 73 ** use_w 74 ** user data 75 ** siz_w 76 ** --- 77 ** 78 ** Do not attempt to adjust this structure! 79 */ 80 typedef struct _u3a_box { 81 c3_w siz_w; // size of this box 82 c3_w use_w; // reference count; free if 0 83 # ifdef U3_MEMORY_DEBUG 84 c3_w eus_w; // recomputed refcount 85 c3_w cod_w; // tracing code 86 # endif 87 } u3a_box; 88 89 /* u3a_fbox: free node in heap. Sets minimum node size. 90 */ 91 typedef struct _u3a_fbox { 92 u3a_box box_u; 93 u3p(struct _u3a_fbox) pre_p; 94 u3p(struct _u3a_fbox) nex_p; 95 } u3a_fbox; 96 97 /* u3a_road: contiguous allocation and execution context. 98 */ 99 typedef struct _u3a_road { 100 u3p(struct _u3a_road) par_p; // parent road 101 u3p(struct _u3a_road) kid_p; // child road list 102 u3p(struct _u3a_road) nex_p; // sibling road 103 104 u3p(c3_w) cap_p; // top of transient region 105 u3p(c3_w) hat_p; // top of durable region 106 u3p(c3_w) mat_p; // bottom of transient region 107 u3p(c3_w) rut_p; // bottom of durable region 108 u3p(c3_w) ear_p; // original cap if kid is live 109 110 c3_w fut_w[32]; // futureproof buffer 111 112 struct { // escape buffer 113 union { 114 jmp_buf buf; 115 c3_w buf_w[256]; // futureproofing 116 }; 117 } esc; 118 119 struct { // miscellaneous config 120 c3_w fag_w; // flag bits 121 } how; // 122 123 struct { // allocation pools 124 u3p(u3a_fbox) fre_p[u3a_fbox_no]; // heap by node size log 125 u3p(u3a_fbox) cel_p; // custom cell allocator 126 c3_w fre_w; // number of free words 127 c3_w max_w; // maximum allocated 128 } all; 129 130 struct { // jet dashboard 131 u3p(u3h_root) har_p; // warm state 132 u3_noun das; // cold state 133 } jed; 134 135 struct { // namespace 136 u3_noun gul; // (list $+(* (unit (unit)))) now 137 } ski; 138 139 struct { // trace stack 140 u3_noun tax; // (list ,*) 141 u3_noun mer; // emergency buffer to release 142 } bug; 143 144 struct { // profile stack 145 c3_d nox_d; // nock steps 146 c3_d cel_d; // cell allocations 147 u3_noun don; // (list batt) 148 u3_noun day; // doss, only in u3H (moveme) 149 } pro; 150 151 struct { // memoization 152 u3p(u3h_root) har_p; // (map (pair term noun) noun) 153 } cax; 154 } u3a_road; 155 typedef u3a_road u3_road; 156 157 /* u3a_flag: flags for how.fag_w. All arena related. 158 */ 159 enum u3a_flag { 160 u3a_flag_sand = 0x1, // bump allocation (XX not impl) 161 }; 162 163 164 /** Macros. Should be better commented. 165 **/ 166 /* In and out of the box. 167 */ 168 # define u3a_boxed(len_w) (len_w + c3_wiseof(u3a_box) + 1) 169 # define u3a_boxto(box_v) ( (void *) \ 170 ( ((c3_w *)(void*)(box_v)) + \ 171 c3_wiseof(u3a_box) ) ) 172 # define u3a_botox(tox_v) ( (struct _u3a_box *) \ 173 (void *) \ 174 ( ((c3_w *)(void*)(tox_v)) - \ 175 c3_wiseof(u3a_box) ) ) 176 /* Inside a noun. 177 */ 178 # define u3a_is_cat(som) (((som) >> 31) ? c3n : c3y) 179 # define u3a_is_dog(som) (((som) >> 31) ? c3y : c3n) 180 181 # define u3a_is_pug(som) ((2 == ((som) >> 30)) ? c3y : c3n) 182 # define u3a_is_pom(som) ((3 == ((som) >> 30)) ? c3y : c3n) 183 # define u3a_to_off(som) ((som) & 0x3fffffff) 184 # define u3a_to_ptr(som) (u3a_into(u3a_to_off(som))) 185 # define u3a_to_wtr(som) ((c3_w *)u3a_to_ptr(som)) 186 # define u3a_to_pug(off) (off | 0x80000000) 187 # define u3a_to_pom(off) (off | 0xc0000000) 188 189 # define u3a_is_atom(som) c3o(u3a_is_cat(som), \ 190 u3a_is_pug(som)) 191 # define u3a_is_cell(som) u3a_is_pom(som) 192 # define u3a_de_twin(dog, dog_w) ((dog & 0xc0000000) | u3a_outa(dog_w)) 193 194 # define u3a_h(som) \ 195 ( _(u3a_is_cell(som)) \ 196 ? ( ((u3a_cell *)u3a_to_ptr(som))->hed )\ 197 : u3m_bail(c3__exit) ) 198 199 # define u3a_t(som) \ 200 ( _(u3a_is_cell(som)) \ 201 ? ( ((u3a_cell *)u3a_to_ptr(som))->tel )\ 202 : u3m_bail(c3__exit) ) 203 204 # define u3a_into(x) ((void *)(u3_Loom + (x))) 205 # define u3a_outa(p) (((c3_w*)(void*)(p)) - u3_Loom) 206 207 # define u3a_is_north(r) __(r->cap_p > r->hat_p) 208 # define u3a_is_south(r) !u3a_is_north(r) 209 210 # define u3a_open(r) ( (c3y == u3a_is_north(r)) \ 211 ? (c3_w)(r->cap_p - r->hat_p) \ 212 : (c3_w)(r->hat_p - r->cap_p) ) 213 214 # define u3a_north_is_senior(r, dog) \ 215 __((u3a_to_off(dog) < r->rut_p) || \ 216 (u3a_to_off(dog) >= r->mat_p)) 217 218 # define u3a_north_is_junior(r, dog) \ 219 __((u3a_to_off(dog) >= r->cap_p) && \ 220 (u3a_to_off(dog) < r->mat_p)) 221 222 # define u3a_north_is_normal(r, dog) \ 223 c3a(!(u3a_north_is_senior(r, dog)), \ 224 !(u3a_north_is_junior(r, dog))) 225 226 # define u3a_south_is_senior(r, dog) \ 227 __((u3a_to_off(dog) < r->mat_p) || \ 228 (u3a_to_off(dog) >= r->rut_p)) 229 230 # define u3a_south_is_junior(r, dog) \ 231 __((u3a_to_off(dog) < r->cap_p) && \ 232 (u3a_to_off(dog) >= r->mat_p)) 233 234 # define u3a_south_is_normal(r, dog) \ 235 c3a(!(u3a_south_is_senior(r, dog)), \ 236 !(u3a_south_is_junior(r, dog))) 237 238 # define u3a_is_junior(r, som) \ 239 ( _(u3a_is_cat(som)) \ 240 ? c3n \ 241 : _(u3a_is_north(r)) \ 242 ? u3a_north_is_junior(r, som) \ 243 : u3a_south_is_junior(r, som) ) 244 245 # define u3a_is_senior(r, som) \ 246 ( _(u3a_is_cat(som)) \ 247 ? c3y \ 248 : _(u3a_is_north(r)) \ 249 ? u3a_north_is_senior(r, som) \ 250 : u3a_south_is_senior(r, som) ) 251 252 253 /** Globals. 254 **/ 255 /* u3_Road / u3R: current road (thread-local). 256 */ 257 c3_global u3_road* u3a_Road; 258 # define u3R u3a_Road 259 260 /* u3_Code: memory code. 261 */ 262 #ifdef U3_MEMORY_DEBUG 263 c3_global c3_w u3_Code; 264 #endif 265 266 # define u3_Loom ((c3_w *)(void *)U3_OS_LoomBase) 267 268 /** Functions. 269 **/ 270 /** Allocation. 271 **/ 272 /* Word-aligned allocation. 273 */ 274 /* u3a_walloc(): allocate storage measured in words. 275 */ 276 void* 277 u3a_walloc(c3_w len_w); 278 279 /* u3a_celloc(): allocate a cell. Faster, sometimes. 280 */ 281 c3_w* 282 u3a_celloc(void); 283 284 /* u3a_wfree(): free storage. 285 */ 286 void 287 u3a_wfree(void* lag_v); 288 289 /* u3a_wealloc(): word realloc. 290 */ 291 void* 292 u3a_wealloc(void* lag_v, c3_w len_w); 293 294 /* u3a_push(): allocate space on the road stack 295 */ 296 void* 297 u3a_push(c3_w len_w); 298 299 /* u3a_pop(): deallocate space on the road stack 300 */ 301 void 302 u3a_pop(c3_w len_w); 303 304 /* u3a_peek(): examine the top of the road stack 305 */ 306 void* 307 u3a_peek(c3_w len_w); 308 309 310 /* C-style aligned allocation - *not* compatible with above. 311 */ 312 /* u3a_malloc(): aligned storage measured in bytes. 313 */ 314 void* 315 u3a_malloc(size_t len_i); 316 317 /* u3a_calloc(): aligned storage measured in bytes. 318 */ 319 void* 320 u3a_calloc(size_t num_i, size_t len_i); 321 322 /* u3a_realloc(): aligned realloc in bytes. 323 */ 324 void* 325 u3a_realloc(void* lag_v, size_t len_i); 326 327 /* u3a_realloc2(): gmp-shaped realloc. 328 */ 329 void* 330 u3a_realloc2(void* lag_v, size_t old_i, size_t new_i); 331 332 /* u3a_free(): free for aligned malloc. 333 */ 334 void 335 u3a_free(void* tox_v); 336 337 /* u3a_free2(): gmp-shaped free. 338 */ 339 void 340 u3a_free2(void* tox_v, size_t siz_i); 341 342 /* Reference and arena control. 343 */ 344 /* u3a_gain(): gain a reference count in normal space. 345 */ 346 u3_weak 347 u3a_gain(u3_weak som); 348 349 /* u3a_take(): gain, copying juniors. 350 */ 351 u3_noun 352 u3a_take(u3_noun som); 353 354 /* u3a_left(): true of junior if preserved. 355 */ 356 c3_o 357 u3a_left(u3_noun som); 358 359 /* u3a_lose(): lose a reference. 360 */ 361 void 362 u3a_lose(u3_weak som); 363 364 /* u3a_wash(): wash all lazy mugs in subtree. RETAIN. 365 */ 366 void 367 u3a_wash(u3_noun som); 368 369 /* u3a_use(): reference count. 370 */ 371 c3_w 372 u3a_use(u3_noun som); 373 374 /* u3a_luse(): check refcount sanity. 375 */ 376 void 377 u3a_luse(u3_noun som); 378 379 /* u3a_mark_ptr(): mark a pointer for gc. Produce size. 380 */ 381 c3_w 382 u3a_mark_ptr(void* ptr_v); 383 384 /* u3a_mark_mptr(): mark a u3_malloc-allocated ptr for gc. 385 */ 386 c3_w 387 u3a_mark_mptr(void* ptr_v); 388 389 /* u3a_mark_noun(): mark a noun for gc. Produce size. 390 */ 391 c3_w 392 u3a_mark_noun(u3_noun som); 393 394 /* u3a_sweep(): sweep a fully marked road. 395 */ 396 c3_w 397 u3a_sweep(void); 398 399 /* u3a_sane(): check allocator sanity. 400 */ 401 void 402 u3a_sane(void); 403 404 /* u3a_lush(): leak push. 405 */ 406 c3_w 407 u3a_lush(c3_w lab_w); 408 409 /* u3a_lop(): leak pop. 410 */ 411 void 412 u3a_lop(c3_w lab_w); 413 414 /* u3a_print_memory: print memory amount. 415 */ 416 void 417 u3a_print_memory(c3_c* cap_c, c3_w wor_w); 418 419 /* u3a_deadbeef(): write 0xdeadbeef from hat to cap. 420 */ 421 void 422 u3a_deadbeef(void); 423 424 /* Atoms from proto-atoms. 425 */ 426 /* u3a_slab(): create a length-bounded proto-atom. 427 */ 428 c3_w* 429 u3a_slab(c3_w len_w); 430 431 /* u3a_slaq(): u3a_slab() with a defined blocksize. 432 */ 433 c3_w* 434 u3a_slaq(c3_g met_g, c3_w len_w); 435 436 /* u3a_malt(): measure and finish a proto-atom. 437 */ 438 u3_noun 439 u3a_malt(c3_w* sal_w); 440 441 /* u3a_moot(): finish a pre-measured proto-atom; dangerous. 442 */ 443 u3_noun 444 u3a_moot(c3_w* sal_w); 445 446 /* u3a_mint(): finish a measured proto-atom. 447 */ 448 u3_noun 449 u3a_mint(c3_w* sal_w, c3_w len_w); 450 451 452