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 internal gc functions

+123 -3
+3
include/ant.h
··· 14 14 15 15 struct js *js_create(void *buf, size_t len); 16 16 struct js *js_create_dynamic(size_t initial_size, size_t max_size); 17 + 18 + void js_gc(struct js *); 17 19 void js_destroy(struct js *); 18 20 19 21 jsval_t js_glob(struct js *); ··· 29 31 bool js_chkargs(jsval_t *, int, const char *); 30 32 void js_set_filename(struct js *, const char *); 31 33 void js_stats(struct js *, size_t *total, size_t *min, size_t *cstacksize); 34 + size_t js_getbrk(struct js *); 32 35 33 36 jsval_t js_mkundef(void); 34 37 jsval_t js_mknull(void);
+1 -1
meson.build
··· 41 41 build_date = run_command('date', '+%Y-%m-%d', check: true).stdout().strip() 42 42 43 43 version_conf = configuration_data() 44 - version_conf.set('ANT_VERSION', '0.0.5.53') 44 + version_conf.set('ANT_VERSION', '0.0.5.54') 45 45 version_conf.set('ANT_GIT_HASH', git_hash) 46 46 version_conf.set('ANT_BUILD_DATE', build_date) 47 47
+3 -2
src/ant.c
··· 172 172 #define CHECKV(_v) do { if (is_err(_v)) { res = (_v); goto done; } } while (0) 173 173 #define EXPECT(_tok, _e) do { if (next(js) != _tok) { _e; return js_mkerr(js, "parse error"); }; js->consumed = 1; } while (0) 174 174 175 - static void js_gc(struct js *js); 176 175 static bool streq(const char *buf, size_t len, const char *p, size_t n); 177 176 static size_t tostr(struct js *js, jsval_t value, char *buf, size_t len); 178 177 static size_t strpromise(struct js *js, jsval_t value, char *buf, size_t len); ··· 896 895 if (js->nogc) js_unmark_entity(js, js->nogc); 897 896 } 898 897 899 - static void js_gc(struct js *js) { 898 + void js_gc(struct js *js) { 900 899 setlwm(js); 901 900 if (js->nogc == (jsoff_t) ~0) return; 902 901 js_mark_all_entities_for_deletion(js); ··· 6541 6540 if (lwm) *lwm = js->lwm; 6542 6541 if (css) *css = js->css; 6543 6542 } 6543 + 6544 + size_t js_getbrk(struct js *js) { return (size_t) js->brk; } 6544 6545 6545 6546 bool js_chkargs(jsval_t *args, int nargs, const char *spec) { 6546 6547 int i = 0, ok = 1;
+44
src/main.c
··· 31 31 jsval_t handler; 32 32 } signal_handlers[32] = {0}; 33 33 34 + static jsval_t js_gc_trigger(struct js *js, jsval_t *args, int nargs) { 35 + (void) args; (void) nargs; 36 + size_t before_brk = js_getbrk(js); 37 + 38 + js_gc(js); 39 + size_t after_brk = js_getbrk(js); 40 + 41 + jsval_t result = js_mkobj(js); 42 + js_set(js, result, "before", js_mknum((double)before_brk)); 43 + js_set(js, result, "after", js_mknum((double)after_brk)); 44 + 45 + return result; 46 + } 47 + 48 + static jsval_t js_alloc(struct js *js, jsval_t *args, int nargs) { 49 + (void) args; (void) nargs; 50 + 51 + size_t total = 0, min_free = 0, cstack = 0; 52 + js_stats(js, &total, &min_free, &cstack); 53 + 54 + jsval_t result = js_mkobj(js); 55 + js_set(js, result, "used", js_mknum((double)total)); 56 + js_set(js, result, "minFree", js_mknum((double)min_free)); 57 + 58 + return result; 59 + } 60 + 61 + static jsval_t js_stats_fn(struct js *js, jsval_t *args, int nargs) { 62 + (void) args; (void) nargs; 63 + 64 + size_t total = 0, min_free = 0, cstack = 0; 65 + js_stats(js, &total, &min_free, &cstack); 66 + 67 + jsval_t result = js_mkobj(js); 68 + js_set(js, result, "used", js_mknum((double)total)); 69 + js_set(js, result, "minFree", js_mknum((double)min_free)); 70 + js_set(js, result, "cstack", js_mknum((double)cstack)); 71 + 72 + return result; 73 + } 74 + 34 75 static void general_signal_handler(int signum) { 35 76 if (signum >= 0 && signum < 32 && signal_handlers[signum].js != NULL) { 36 77 struct js *js = signal_handlers[signum].js; ··· 264 305 js_set(js, rt->ant_obj, "serve", js_mkfun(js_serve)); 265 306 js_set(js, rt->ant_obj, "require", js_mkfun(js_require)); 266 307 js_set(js, rt->ant_obj, "signal", js_mkfun(js_signal)); 308 + js_set(js, rt->ant_obj, "gc", js_mkfun(js_gc_trigger)); 309 + js_set(js, rt->ant_obj, "alloc", js_mkfun(js_alloc)); 310 + js_set(js, rt->ant_obj, "stats", js_mkfun(js_stats_fn)); 267 311 268 312 jsval_t exports_obj = js_mkobj(js); 269 313 js_set(js, rt->ant_obj, "exports", exports_obj);
src/modules/ant.c

This is a binary file and will not be displayed.

+72
tests/test_gc.cjs
··· 1 + // Test Ant.gc(), Ant.alloc(), and Ant.stats() 2 + 3 + console.log("=== Testing Ant.alloc() ==="); 4 + let alloc1 = Ant.alloc(); 5 + console.log("Initial allocation:"); 6 + console.log(" used:", alloc1.used); 7 + console.log(" minFree:", alloc1.minFree); 8 + 9 + console.log("\n=== Creating objects to allocate memory ==="); 10 + let arr = []; 11 + for (let i = 0; i < 100; i = i + 1) { 12 + arr.push({ value: i, name: "item" + i }); 13 + } 14 + console.log("Created array with 100 objects"); 15 + 16 + let alloc2 = Ant.alloc(); 17 + console.log("After allocation:"); 18 + console.log(" used:", alloc2.used); 19 + console.log(" minFree:", alloc2.minFree); 20 + console.log(" increase:", alloc2.used - alloc1.used); 21 + 22 + console.log("\n=== Testing Ant.stats() ==="); 23 + let stats1 = Ant.stats(); 24 + console.log("Memory stats:"); 25 + console.log(" used:", stats1.used); 26 + console.log(" minFree:", stats1.minFree); 27 + console.log(" cstack:", stats1.cstack); 28 + 29 + console.log("\n=== Testing Ant.gc() ==="); 30 + // Clear reference to allow GC 31 + arr = null; 32 + 33 + let gcResult = Ant.gc(); 34 + console.log("GC result:"); 35 + console.log(" before:", gcResult.before); 36 + console.log(" after:", gcResult.after); 37 + console.log(" freed:", gcResult.before - gcResult.after); 38 + 39 + console.log("\n=== Verifying memory after GC ==="); 40 + let alloc3 = Ant.alloc(); 41 + console.log("After GC:"); 42 + console.log(" used:", alloc3.used); 43 + console.log(" minFree:", alloc3.minFree); 44 + 45 + console.log("\n=== Testing multiple GC cycles ==="); 46 + // Allocate and free multiple times 47 + for (let cycle = 0; cycle < 3; cycle = cycle + 1) { 48 + console.log("Cycle", cycle + 1); 49 + 50 + // Allocate 51 + let temp = []; 52 + for (let i = 0; i < 50; i = i + 1) { 53 + temp.push({ data: "test data " + i }); 54 + } 55 + let beforeGc = Ant.alloc(); 56 + console.log(" Before GC - used:", beforeGc.used); 57 + 58 + // Clear and collect 59 + temp = null; 60 + let gc = Ant.gc(); 61 + console.log(" After GC - used:", gc.after, "freed:", gc.before - gc.after); 62 + } 63 + 64 + console.log("\n=== Testing stats consistency ==="); 65 + let statsA = Ant.stats(); 66 + let allocA = Ant.alloc(); 67 + console.log("Stats and alloc should match:"); 68 + console.log(" stats.used:", statsA.used); 69 + console.log(" alloc.used:", allocA.used); 70 + console.log(" match:", statsA.used === allocA.used); 71 + 72 + console.log("\n=== Test complete ===");