MIRROR: javascript for ๐Ÿœ's, a tiny runtime with big ambitions
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

mmap release scratch buffer

+54 -23
+54 -23
src/gc.c
··· 38 38 #define FWD_EMPTY ((jsoff_t)~0) 39 39 #define FWD_TOMBSTONE ((jsoff_t)~1) 40 40 41 + #ifdef _WIN32 42 + #define RELEASE_PAGES(p, sz) VirtualAlloc(p, sz, MEM_RESET, PAGE_READWRITE) 43 + #else 44 + #define RELEASE_PAGES(p, sz) madvise(p, sz, MADV_DONTNEED) 45 + #endif 46 + 41 47 typedef struct { 42 48 jsoff_t *old_offs; 43 49 jsoff_t *new_offs; ··· 82 88 83 89 static bool fwd_init(gc_forward_table_t *fwd, size_t estimated) { 84 90 size_t cap = next_pow2(estimated < 64 ? 64 : estimated); 85 - fwd->old_offs = (jsoff_t *)ant_calloc(cap * sizeof(jsoff_t)); 86 - fwd->new_offs = (jsoff_t *)ant_calloc(cap * sizeof(jsoff_t)); 91 + size_t size = cap * sizeof(jsoff_t); 92 + 93 + fwd->old_offs = (jsoff_t *)gc_mmap(size); 94 + fwd->new_offs = (jsoff_t *)gc_mmap(size); 95 + 87 96 if (!fwd->old_offs || !fwd->new_offs) { 88 - if (fwd->old_offs) free(fwd->old_offs); 89 - if (fwd->new_offs) free(fwd->new_offs); 97 + if (fwd->old_offs) gc_munmap(fwd->old_offs, size); 98 + if (fwd->new_offs) gc_munmap(fwd->new_offs, size); 90 99 return false; 91 100 } 101 + 92 102 for (size_t i = 0; i < cap; i++) fwd->old_offs[i] = FWD_EMPTY; 103 + 93 104 fwd->count = 0; 94 105 fwd->capacity = cap; 95 106 fwd->mask = cap - 1; 107 + 96 108 return true; 97 109 } 98 110 99 111 static bool fwd_grow(gc_forward_table_t *fwd) { 100 112 size_t new_cap = fwd->capacity * 2; 101 113 size_t new_mask = new_cap - 1; 102 - jsoff_t *new_old = (jsoff_t *)ant_calloc(new_cap * sizeof(jsoff_t)); 103 - jsoff_t *new_new = (jsoff_t *)ant_calloc(new_cap * sizeof(jsoff_t)); 114 + size_t new_size = new_cap * sizeof(jsoff_t); 115 + size_t old_size = fwd->capacity * sizeof(jsoff_t); 116 + 117 + jsoff_t *new_old = (jsoff_t *)gc_mmap(new_size); 118 + jsoff_t *new_new = (jsoff_t *)gc_mmap(new_size); 119 + 104 120 if (!new_old || !new_new) { 105 - if (new_old) free(new_old); 106 - if (new_new) free(new_new); 121 + if (new_old) gc_munmap(new_old, new_size); 122 + if (new_new) gc_munmap(new_new, new_size); 107 123 return false; 108 124 } 125 + 109 126 for (size_t i = 0; i < new_cap; i++) new_old[i] = FWD_EMPTY; 110 127 111 128 for (size_t i = 0; i < fwd->capacity; i++) { ··· 117 134 new_new[h] = fwd->new_offs[i]; 118 135 } 119 136 120 - free(fwd->old_offs); 121 - free(fwd->new_offs); 137 + gc_munmap(fwd->old_offs, old_size); 138 + gc_munmap(fwd->new_offs, old_size); 139 + 122 140 fwd->old_offs = new_old; 123 141 fwd->new_offs = new_new; 124 142 fwd->capacity = new_cap; 125 143 fwd->mask = new_mask; 144 + 126 145 return true; 127 146 } 128 147 ··· 130 149 if (fwd->count * 100 >= fwd->capacity * GC_FWD_LOAD_FACTOR) { 131 150 if (!fwd_grow(fwd)) return false; 132 151 } 152 + 133 153 size_t h = (old_off >> 3) & fwd->mask; 134 154 while (fwd->old_offs[h] != FWD_EMPTY && fwd->old_offs[h] != FWD_TOMBSTONE) { 135 155 if (fwd->old_offs[h] == old_off) { ··· 138 158 } 139 159 h = (h + 1) & fwd->mask; 140 160 } 161 + 141 162 fwd->old_offs[h] = old_off; 142 163 fwd->new_offs[h] = new_off; 143 164 fwd->count++; 165 + 144 166 return true; 145 167 } 146 168 ··· 156 178 } 157 179 158 180 static void fwd_free(gc_forward_table_t *fwd) { 159 - if (fwd->old_offs) free(fwd->old_offs); 160 - if (fwd->new_offs) free(fwd->new_offs); 181 + size_t size = fwd->capacity * sizeof(jsoff_t); 182 + if (fwd->old_offs) gc_munmap(fwd->old_offs, size); 183 + if (fwd->new_offs) gc_munmap(fwd->new_offs, size); 184 + 161 185 fwd->old_offs = NULL; 162 186 fwd->new_offs = NULL; 163 187 fwd->count = 0; ··· 165 189 } 166 190 167 191 static bool work_init(gc_work_queue_t *work, size_t initial) { 168 - work->items = (jsoff_t *)ant_calloc(initial * sizeof(jsoff_t)); 192 + size_t size = initial * sizeof(jsoff_t); 193 + work->items = (jsoff_t *)gc_mmap(size); 169 194 if (!work->items) return false; 170 195 work->count = 0; 171 196 work->capacity = initial; ··· 175 200 static inline bool work_push(gc_work_queue_t *work, jsoff_t off) { 176 201 if (work->count >= work->capacity) { 177 202 size_t new_cap = work->capacity * 2; 178 - jsoff_t *new_items = (jsoff_t *)ant_calloc(new_cap * sizeof(jsoff_t)); 203 + size_t new_size = new_cap * sizeof(jsoff_t); 204 + size_t old_size = work->capacity * sizeof(jsoff_t); 205 + 206 + jsoff_t *new_items = (jsoff_t *)gc_mmap(new_size); 179 207 if (!new_items) return false; 208 + 180 209 memcpy(new_items, work->items, work->count * sizeof(jsoff_t)); 181 - free(work->items); 210 + gc_munmap(work->items, old_size); 211 + 182 212 work->items = new_items; 183 213 work->capacity = new_cap; 184 214 } 215 + 185 216 work->items[work->count++] = off; 186 217 return true; 187 218 } ··· 192 223 } 193 224 194 225 static void work_free(gc_work_queue_t *work) { 195 - if (work->items) free(work->items); 226 + size_t size = work->capacity * sizeof(jsoff_t); 227 + if (work->items) gc_munmap(work->items, size); 228 + 196 229 work->items = NULL; 197 230 work->count = 0; 198 231 work->capacity = 0; ··· 529 562 530 563 size_t js_gc_compact(ant_t *js) { 531 564 if (!js || js->brk == 0) return 0; 532 - if (js->brk < 512 * 1024) return 0; 565 + if (js->brk < 2 * 1024 * 1024) return 0; 533 566 534 567 time_t now = time(NULL); 535 568 if (now != (time_t)-1 && gc_last_run_time != 0) { ··· 561 594 gc_scratch_buf = (uint8_t *)gc_mmap(new_size); 562 595 gc_scratch_size = gc_scratch_buf ? new_size : 0; 563 596 } 597 + 564 598 if (!gc_scratch_buf) return 0; 565 599 uint8_t *new_mem = gc_scratch_buf; 566 - memset(new_mem, 0, new_size); 567 600 568 601 size_t bitmap_size = (js->brk / 8 + 7) / 8 + 1; 569 602 uint8_t *mark_bits = (uint8_t *)calloc(1, bitmap_size); ··· 625 658 work_free(&ctx.work); 626 659 fwd_free(&ctx.fwd); 627 660 628 - if (gc_scratch_buf) { 629 - gc_munmap(gc_scratch_buf, gc_scratch_size); 630 - gc_scratch_buf = NULL; 631 - gc_scratch_size = 0; 661 + if (gc_scratch_buf && gc_scratch_size > 0) { 662 + RELEASE_PAGES(gc_scratch_buf, gc_scratch_size); 632 663 } 633 664 634 665 size_t new_brk = ctx.new_brk; ··· 645 676 646 677 void js_maybe_gc(ant_t *js) { 647 678 jsoff_t thresh = js->brk / 4; 648 - if (thresh < 512 * 1024) thresh = 512 * 1024; 679 + if (thresh < 2 * 1024 * 1024) thresh = 2 * 1024 * 1024; 649 680 if (thresh > 16 * 1024 * 1024) thresh = 16 * 1024 * 1024; 650 681 651 682 if (js->gc_alloc_since > thresh || js->needs_gc) {