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.

replace CSS stack limit with OS stack limit detection

+64 -36
+2 -1
include/ant.h
··· 73 73 void js_destroy(ant_t *); 74 74 void js_delscope(ant_t *); 75 75 bool js_truthy(ant_t *, jsval_t); 76 - void js_setmaxcss(ant_t *, size_t); 76 + void js_setstacklimit(ant_t *, size_t); 77 + void js_setstackbase(ant_t *, void *); 77 78 78 79 uint32_t js_to_uint32(double d); 79 80 int32_t js_to_int32(double d);
+1 -2
include/internal.h
··· 11 11 }; 12 12 13 13 struct js { 14 - jsoff_t css; // max observed C stack size 15 14 const char *code; // currently parsed code snippet 16 15 char *errmsg; // dynamic error message buffer 17 16 size_t errmsg_size; // size of error message buffer ··· 40 39 uint8_t *mem; // available JS memory 41 40 jsoff_t size; // memory size 42 41 jsoff_t brk; // current mem usage boundary 43 - jsoff_t maxcss; // maximum allowed C stack size usage 44 42 void *cstk; // C stack pointer at the beginning of js_eval() 43 + size_t stack_limit; // max stack bytes allowed (0 = no limit) 45 44 jsval_t current_func; // currently executing function (for native closures) 46 45 bool var_warning_shown; // flag to show var deprecation warning only once 47 46 bool owns_mem; // true if js owns the memory buffer (dynamic allocation)
+28 -3
src/ant.c
··· 31 31 #else 32 32 #include <sys/time.h> 33 33 #include <sys/stat.h> 34 + #include <sys/resource.h> 34 35 #endif 35 36 36 37 #define MCO_USE_VMEM_ALLOCATOR ··· 708 709 709 710 static inline bool is_contextual_keyword(uint8_t tok) { 710 711 return tok == TOK_FROM || tok == TOK_OF || tok == TOK_AS || tok == TOK_ASYNC; 712 + } 713 + 714 + static inline bool js_stack_overflow(struct js *js) { 715 + if (js->stack_limit == 0 || js->cstk == NULL) return false; 716 + volatile char marker; 717 + uintptr_t base = (uintptr_t)js->cstk; 718 + uintptr_t curr = (uintptr_t)&marker; 719 + size_t used = (base > curr) ? (base - curr) : (curr - base); 720 + return used > js->stack_limit; 711 721 } 712 722 713 723 static inline bool is_valid_param_name(uint8_t tok) { ··· 6971 6981 } 6972 6982 6973 6983 static jsval_t do_call_op(struct js *js, jsval_t func, jsval_t args) { 6984 + if (js_stack_overflow(js)) return js_mkerr_typed(js, JS_ERR_RANGE | JS_ERR_NO_STACK, "stack overflow"); 6985 + 6974 6986 if (vtype(args) != T_CODEREF) return js_mkerr(js, "bad call"); 6975 6987 if (vtype(func) != T_FUNC && vtype(func) != T_CFUNC && vtype(func) != T_FFI) return js_mkerr(js, "calling non-function"); 6976 6988 ··· 8670 8682 8671 8683 static jsval_t js_literal(struct js *js) { 8672 8684 next(js); 8673 - if (js->maxcss > 0 && js->css > js->maxcss) return js_mkerr(js, "C stack"); 8674 8685 js->consumed = 1; 8675 8686 8676 8687 switch (js->tok) { ··· 22162 22173 js->errmsg = (char *)malloc(js->errmsg_size); 22163 22174 if (js->errmsg) js->errmsg[0] = '\0'; 22164 22175 22176 + #ifdef _WIN32 22177 + js->stack_limit = 512 * 1024; 22178 + #else 22179 + struct rlimit rl; 22180 + if (getrlimit(RLIMIT_STACK, &rl) == 0 && rl.rlim_cur != RLIM_INFINITY) { 22181 + js->stack_limit = rl.rlim_cur / 2; 22182 + } else { 22183 + js->stack_limit = 512 * 1024; 22184 + } 22185 + #endif 22186 + 22165 22187 jsval_t glob = js->scope; 22166 22188 jsval_t object_proto = js_mkobj(js); 22167 22189 set_proto(js, object_proto, js_mknull()); ··· 22757 22779 js->owns_mem = true; 22758 22780 js->max_size = (jsoff_t) max_size; 22759 22781 22782 + volatile char stack_base; 22783 + js->cstk = (void *)&stack_base; 22784 + 22760 22785 return js; 22761 22786 } 22762 22787 ··· 22782 22807 inline double js_getnum(jsval_t value) { return tod(value); } 22783 22808 inline int js_getbool(jsval_t value) { return vdata(value) & 1 ? 1 : 0; } 22784 22809 22785 - inline void js_setmaxcss(struct js *js, size_t max) { js->maxcss = (jsoff_t) max; } 22810 + inline void js_setstacklimit(struct js *js, size_t max) { js->stack_limit = max; } 22811 + inline void js_setstackbase(struct js *js, void *base) { js->cstk = base; } 22786 22812 inline void js_set_filename(struct js *js, const char *filename) { js->filename = filename; } 22787 22813 22788 22814 inline jsval_t js_mktrue(void) { return mkval(T_BOOL, 1); } ··· 23268 23294 js->code = buf; 23269 23295 js->clen = (jsoff_t) len; 23270 23296 js->pos = 0; 23271 - js->cstk = &res; 23272 23297 23273 23298 uint8_t saved_tok = js->tok; 23274 23299 jsoff_t saved_pos = js->pos;
+33 -30
src/modules/builtin.c
··· 7 7 #include <time.h> 8 8 #include <errno.h> 9 9 10 + #ifdef __APPLE__ 11 + #include <mach/mach.h> 12 + #elif defined(__linux__) 13 + #include <sys/resource.h> 14 + #endif 10 15 11 16 #include "runtime.h" 12 17 #include "internal.h" ··· 46 51 return js_mkundef(); 47 52 } 48 53 49 - // Ant.gc() - no-op with bdwgc removed 54 + // Ant.gc() 50 55 static jsval_t js_gc_trigger(struct js *js, jsval_t *args, int nargs) { 51 56 (void) args; (void) nargs; 52 57 53 58 size_t arena_before = js_getbrk(js); 59 + size_t arena_freed = js_gc_compact(js); 60 + size_t arena_after = js_getbrk(js); 54 61 55 62 jsval_t result = js_newobj(js); 56 - js_set(js, result, "heapBefore", js_mknum(0)); 57 - js_set(js, result, "heapAfter", js_mknum(0)); 58 - js_set(js, result, "usedBefore", js_mknum(0)); 59 - js_set(js, result, "usedAfter", js_mknum(0)); 60 - js_set(js, result, "freed", js_mknum(0)); 61 63 js_set(js, result, "arenaBefore", js_mknum((double)arena_before)); 62 - js_set(js, result, "arenaAfter", js_mknum((double)arena_before)); 63 - js_set(js, result, "arenaFreed", js_mknum(0)); 64 + js_set(js, result, "arenaAfter", js_mknum((double)arena_after)); 65 + js_set(js, result, "arenaFreed", js_mknum((double)arena_freed)); 64 66 65 67 return result; 66 68 } 67 69 68 - // Ant.alloc() 69 - static jsval_t js_alloc(struct js *js, jsval_t *args, int nargs) { 70 - (void) args; (void) nargs; 71 - 72 - jsval_t result = js_newobj(js); 73 - size_t arena_size = js_getbrk(js); 74 - 75 - js_set(js, result, "arenaSize", js_mknum((double)arena_size)); 76 - js_set(js, result, "heapSize", js_mknum(0)); 77 - js_set(js, result, "freeBytes", js_mknum(0)); 78 - js_set(js, result, "usedBytes", js_mknum(0)); 79 - js_set(js, result, "totalBytes", js_mknum(0)); 80 - 81 - return result; 82 - } 83 - 84 70 // Ant.raw.typeof(jsval_t) 85 71 static jsval_t js_raw_typeof(struct js *js, jsval_t *args, int nargs) { 86 72 if (nargs < 1) return js_mkerr(js, "Ant.raw.typeof() requires 1 argument"); ··· 119 105 (void) args; (void) nargs; 120 106 jsval_t result = js_newobj(js); 121 107 122 - js_set(js, result, "arenaUsed", js_mknum((double)js->size)); 123 - js_set(js, result, "cstack", js_mknum((double)js->css)); 108 + js_set(js, result, "arenaUsed", js_mknum((double)js_getbrk(js))); 109 + js_set(js, result, "arenaSize", js_mknum((double)js->size)); 110 + 111 + if (js->cstk != NULL) { 112 + volatile char marker; 113 + uintptr_t base = (uintptr_t)js->cstk; 114 + uintptr_t curr = (uintptr_t)&marker; 115 + size_t used = (base > curr) ? (base - curr) : (curr - base); 116 + js_set(js, result, "cstack", js_mknum((double)used)); 117 + } else js_set(js, result, "cstack", js_mknum(0)); 124 118 125 - js_set(js, result, "gcHeapSize", js_mknum(0)); 126 - js_set(js, result, "gcFreeBytes", js_mknum(0)); 127 - js_set(js, result, "gcUsedBytes", js_mknum(0)); 119 + #ifdef __APPLE__ 120 + struct mach_task_basic_info info; 121 + mach_msg_type_number_t count = MACH_TASK_BASIC_INFO_COUNT; 122 + if (task_info(mach_task_self(), MACH_TASK_BASIC_INFO, (task_info_t)&info, &count) == KERN_SUCCESS) { 123 + js_set(js, result, "rss", js_mknum((double)info.resident_size)); 124 + js_set(js, result, "virtualSize", js_mknum((double)info.virtual_size)); 125 + } 126 + #elif defined(__linux__) 127 + struct rusage usage; 128 + if (getrusage(RUSAGE_SELF, &usage) == 0) { 129 + js_set(js, result, "rss", js_mknum((double)usage.ru_maxrss * 1024)); 130 + } 131 + #endif 128 132 129 133 return result; 130 134 } ··· 134 138 jsval_t ant_obj = rt->ant_obj; 135 139 136 140 js_set(js, ant_obj, "gc", js_mkfun(js_gc_trigger)); 137 - js_set(js, ant_obj, "alloc", js_mkfun(js_alloc)); 138 141 js_set(js, ant_obj, "stats", js_mkfun(js_stats_fn)); 139 142 js_set(js, ant_obj, "signal", js_mkfun(js_signal)); 140 143 js_set(js, ant_obj, "sleep", js_mkfun(js_sleep));