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.

add arena shrinking and decommit

+35 -14
+27
include/arena.h
··· 52 52 if (base) VirtualFree(base, 0, MEM_RELEASE); 53 53 } 54 54 55 + static inline int ant_arena_decommit(void *base, size_t old_size, size_t new_size) { 56 + if (new_size >= old_size) return 0; 57 + void *decommit_start = (char *)base + new_size; 58 + size_t decommit_size = old_size - new_size; 59 + return VirtualFree(decommit_start, decommit_size, MEM_DECOMMIT) ? 0 : -1; 60 + } 61 + 55 62 #else 56 63 57 64 static inline void *ant_arena_reserve(size_t max_size) { ··· 79 86 80 87 static inline void ant_arena_free(void *base, size_t reserved_size) { 81 88 if (base) munmap(base, reserved_size); 89 + } 90 + 91 + static inline int ant_arena_decommit(void *base, size_t old_size, size_t new_size) { 92 + if (new_size >= old_size) return 0; 93 + 94 + long page_size_long = sysconf(_SC_PAGESIZE); 95 + if (page_size_long <= 0) return -1; 96 + 97 + size_t page_size = (size_t)page_size_long; 98 + size_t new_pages = ((new_size + page_size - 1) / page_size) * page_size; 99 + size_t old_pages = ((old_size + page_size - 1) / page_size) * page_size; 100 + 101 + if (new_pages >= old_pages) return 0; 102 + 103 + void *decommit_start = (char *)base + new_pages; 104 + size_t decommit_size = old_pages - new_pages; 105 + 106 + if (mprotect(decommit_start, decommit_size, PROT_NONE) == 0) return 0; 107 + madvise(decommit_start, decommit_size, MADV_DONTNEED); 108 + return 0; 82 109 } 83 110 84 111 #endif
+7 -14
src/gc.c
··· 605 605 gc_scratch_size = 0; 606 606 } 607 607 608 - size_t page_size = 4096; 609 - size_t used_pages = (ctx.new_brk + page_size - 1) & ~(page_size - 1); 608 + size_t new_brk = ctx.new_brk; 609 + size_t old_size = js->size; 610 610 611 - if (js->size > used_pages) { 612 - size_t release_size = js->size - used_pages; 613 - void *release_start = js->mem + used_pages; 614 - 615 - #ifdef _WIN32 616 - VirtualFree(release_start, release_size, MEM_DECOMMIT); 617 - VirtualAlloc(release_start, release_size, MEM_COMMIT, PAGE_READWRITE); 618 - #else 619 - void *p = mmap(release_start, release_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0); 620 - if (p == MAP_FAILED) madvise(release_start, release_size, MADV_DONTNEED); 621 - #endif 611 + if (new_brk < old_size / 2 && old_size > ARENA_GROW_INCREMENT) { 612 + size_t target = ((new_brk * 2 + ARENA_GROW_INCREMENT - 1) / ARENA_GROW_INCREMENT) * ARENA_GROW_INCREMENT; 613 + if (target < ARENA_GROW_INCREMENT) target = ARENA_GROW_INCREMENT; 614 + if (target < old_size) { ant_arena_decommit(js->mem, old_size, target); js->size = (jsoff_t)target; } 622 615 } 623 616 624 - return (old_brk > ctx.new_brk ? old_brk - ctx.new_brk : 0); 617 + return (old_brk > new_brk ? old_brk - new_brk : 0); 625 618 } 626 619 627 620 void js_maybe_gc(ant_t *js) {
+1
tests/bench_gc.js
··· 92 92 let final = Ant.stats(); 93 93 console.log('Final state:'); 94 94 console.log(' arenaUsed:', fmt(final.arenaUsed)); 95 + console.log(' arenaSize:', fmt(final.arenaSize)); 95 96 console.log(' rss:', fmt(final.rss)); 96 97 console.log(''); 97 98 console.log('Note: GC runs automatically at safe points.');