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.

proper T_CFUNC promotion support

+111 -25
+18
include/internal.h
··· 221 221 size_t cap; 222 222 } pending_rejections; 223 223 224 + struct { 225 + uintptr_t *cfunc_ptr; 226 + ant_value_t *promoted; 227 + uint8_t len; 228 + uint8_t cap; 229 + } cfunc_promote_cache; 230 + 224 231 bool owns_mem; 225 232 bool fatal_error; 226 233 bool thrown_exists; ··· 483 490 js_set(js, lib, "default", ctor_fn); 484 491 js_set(js, ctor_fn, "default", ctor_fn); 485 492 js_set_slot_wb(js, lib, SLOT_DEFAULT, ctor_fn); 493 + } 494 + 495 + ant_value_t js_cfunc_promote(ant_t *js, ant_value_t cfunc); 496 + 497 + static inline ant_value_t js_cfunc_lookup_promoted(ant_t *js, ant_value_t cfunc) { 498 + uintptr_t ptr = vdata(cfunc); 499 + for (uint8_t i = 0; i < js->cfunc_promote_cache.len; i++) { 500 + if (js->cfunc_promote_cache.cfunc_ptr[i] == ptr) 501 + return js->cfunc_promote_cache.promoted[i]; 502 + } 503 + return cfunc; 486 504 } 487 505 488 506 static inline ant_value_t js_make_ctor(ant_t *js, ant_cfunc_t fn, ant_value_t proto, const char *name, size_t nlen) {
+74 -20
src/ant.c
··· 3163 3163 ant_value_t js_setprop(ant_t *js, ant_value_t obj, ant_value_t k, ant_value_t v) { 3164 3164 uint8_t ot = vtype(obj); 3165 3165 3166 - if (ot == T_STR || ot == T_NUM || ot == T_BOOL || ot == T_CFUNC) { 3166 + if (ot == T_CFUNC) { 3167 + ant_value_t promoted = js_cfunc_promote(js, obj); 3168 + return js_setprop(js, promoted, k, v); 3169 + } 3170 + 3171 + if (ot == T_STR || ot == T_NUM || ot == T_BOOL) { 3167 3172 ant_offset_t klen; ant_offset_t koff = vstr(js, k, &klen); 3168 3173 const char *key = (char *)(uintptr_t)(koff); 3169 3174 3170 - if (ot != T_CFUNC) { 3171 - ant_value_t proto = get_prototype_for_type(js, ot); 3172 - if (is_object_type(proto)) { 3173 - ant_value_t setter = js_mkundef(); 3174 - bool has_setter = false; 3175 - lkp_with_setter(js, proto, key, klen, &setter, &has_setter); 3176 - if (has_setter && (vtype(setter) == T_FUNC || vtype(setter) == T_CFUNC)) { 3177 - call_proto_accessor(js, obj, setter, true, &v, 1, true); 3178 - return v; 3179 - } 3180 - } 3181 - } 3175 + ant_value_t proto = get_prototype_for_type(js, ot); 3176 + if (is_object_type(proto)) { 3177 + ant_value_t setter = js_mkundef(); 3178 + bool has_setter = false; 3179 + 3180 + lkp_with_setter(js, proto, key, klen, &setter, &has_setter); 3181 + if (has_setter && (vtype(setter) == T_FUNC || vtype(setter) == T_CFUNC)) { 3182 + call_proto_accessor(js, obj, setter, true, &v, 1, true); 3183 + return v; 3184 + }} 3182 3185 3183 - if (sv_is_strict_context(js)) 3184 - return js_mkerr_typed(js, JS_ERR_TYPE, 3185 - "Cannot create property '%.*s' on %s", 3186 - (int)klen, key, typestr(ot)); 3186 + if (sv_is_strict_context(js)) return js_mkerr_typed(js, JS_ERR_TYPE, 3187 + "Cannot create property '%.*s' on %s", 3188 + (int)klen, key, typestr(ot) 3189 + ); 3190 + 3187 3191 return v; 3188 3192 } 3189 3193 ··· 5773 5777 uint8_t t = vtype(obj); 5774 5778 5775 5779 if (t == T_CFUNC) { 5776 - ant_value_t fn_obj = mkobj(js, 0); 5777 - set_slot(fn_obj, SLOT_CFUNC, obj); 5778 - obj = js_obj_to_func(fn_obj); 5780 + obj = js_cfunc_promote(js, obj); 5779 5781 args[0] = obj; 5780 5782 t = T_FUNC; 5781 5783 } ··· 12888 12890 js->pending_rejections.items = NULL; 12889 12891 js->pending_rejections.len = js->pending_rejections.cap = 0; 12890 12892 12893 + free(js->cfunc_promote_cache.cfunc_ptr); 12894 + free(js->cfunc_promote_cache.promoted); 12895 + js->cfunc_promote_cache.cfunc_ptr = NULL; 12896 + js->cfunc_promote_cache.promoted = NULL; 12897 + js->cfunc_promote_cache.len = js->cfunc_promote_cache.cap = 0; 12898 + 12891 12899 js_pool_destroy(&js->pool.rope); 12892 12900 js_pool_destroy(&js->pool.symbol); 12893 12901 js_pool_destroy(&js->pool.permanent); ··· 12914 12922 inline ant_value_t js_getthis(ant_t *js) { return js->this_val; } 12915 12923 inline void js_setthis(ant_t *js, ant_value_t val) { js->this_val = val; } 12916 12924 inline ant_value_t js_getcurrentfunc(ant_t *js) { return js->current_func; } 12925 + 12926 + ant_value_t js_cfunc_promote(ant_t *js, ant_value_t cfunc) { 12927 + uintptr_t ptr = vdata(cfunc); 12928 + 12929 + for (uint8_t i = 0; i < js->cfunc_promote_cache.len; i++) { 12930 + if (js->cfunc_promote_cache.cfunc_ptr[i] == ptr) 12931 + return js->cfunc_promote_cache.promoted[i]; 12932 + } 12933 + 12934 + ant_value_t fn_obj = mkobj(js, 0); 12935 + set_slot(fn_obj, SLOT_CFUNC, cfunc); 12936 + 12937 + ant_value_t proto = get_prototype_for_type(js, T_CFUNC); 12938 + if (is_object_type(proto)) { 12939 + ant_object_t *obj_ptr = js_obj_ptr(js_as_obj(fn_obj)); 12940 + if (obj_ptr) obj_ptr->proto = proto; 12941 + } 12942 + 12943 + ant_value_t promoted = js_obj_to_func(fn_obj); 12944 + 12945 + if (js->cfunc_promote_cache.len >= js->cfunc_promote_cache.cap) { 12946 + uint8_t new_cap = js->cfunc_promote_cache.cap ? js->cfunc_promote_cache.cap * 2 : 4; 12947 + uintptr_t *new_ptrs = realloc(js->cfunc_promote_cache.cfunc_ptr, new_cap * sizeof(uintptr_t)); 12948 + ant_value_t *new_vals = realloc(js->cfunc_promote_cache.promoted, new_cap * sizeof(ant_value_t)); 12949 + 12950 + if (new_ptrs && new_vals) { 12951 + js->cfunc_promote_cache.cfunc_ptr = new_ptrs; 12952 + js->cfunc_promote_cache.promoted = new_vals; 12953 + js->cfunc_promote_cache.cap = new_cap; 12954 + } 12955 + } 12956 + 12957 + if (js->cfunc_promote_cache.len < js->cfunc_promote_cache.cap) { 12958 + uint8_t idx = js->cfunc_promote_cache.len++; 12959 + js->cfunc_promote_cache.cfunc_ptr[idx] = ptr; 12960 + js->cfunc_promote_cache.promoted[idx] = promoted; 12961 + } 12962 + 12963 + return promoted; 12964 + } 12917 12965 12918 12966 ant_value_t js_heavy_mkfun(ant_t *js, ant_value_t (*fn)(ant_t *, ant_value_t *, int), ant_value_t data) { 12919 12967 ant_value_t cfunc = js_mkfun(fn); ··· 13185 13233 } 13186 13234 13187 13235 ant_value_t js_getprop_fallback(ant_t *js, ant_value_t obj, const char *name) { 13236 + if (vtype(obj) == T_CFUNC && js->cfunc_promote_cache.len > 0) { 13237 + ant_value_t promoted = js_cfunc_lookup_promoted(js, obj); 13238 + if (vtype(promoted) != T_CFUNC) return js_getprop_fallback(js, promoted, name); 13239 + } 13240 + 13188 13241 ant_value_t val; 13189 13242 if (js_try_get(js, obj, name, &val)) return val; 13243 + 13190 13244 return js_getprop_proto(js, obj, name); 13191 13245 } 13192 13246
+3
src/gc/objects.c
··· 472 472 for (size_t i = 0; i < js->pending_rejections.len; i++) 473 473 gc_mark_value(js, js->pending_rejections.items[i]); 474 474 475 + for (uint8_t i = 0; i < js->cfunc_promote_cache.len; i++) 476 + gc_mark_value(js, js->cfunc_promote_cache.promoted[i]); 477 + 475 478 gc_visit_roots(js, gc_mark_value); 476 479 gc_mark_timers(js, gc_mark_value); 477 480 gc_mark_ffi(js, gc_mark_value);
+16 -5
src/silver/ops/property.h
··· 70 70 } 71 71 72 72 *out = (idx < ptr->prop_count) ? ant_object_prop_get_unchecked(ptr, idx) : js_mkundef(); 73 + if (vtype(*out) == T_CFUNC && js->cfunc_promote_cache.len > 0) { 74 + ant_value_t promoted = js_cfunc_lookup_promoted(js, *out); 75 + if (vtype(promoted) != T_CFUNC) { 76 + ant_object_prop_set_unchecked(ptr, idx, promoted); 77 + gc_write_barrier(js, ptr, promoted); 78 + *out = promoted; 79 + }} 80 + 73 81 return true; 74 82 } 75 83 ··· 236 244 ) { 237 245 uint8_t t = vtype(obj); 238 246 247 + if (t == T_CFUNC && js->cfunc_promote_cache.len > 0) { 248 + ant_value_t promoted = js_cfunc_lookup_promoted(js, obj); 249 + if (vtype(promoted) != T_CFUNC) return sv_prop_get_at(js, promoted, str, len, func, ip); 250 + } 251 + 239 252 if (t == T_NULL || t == T_UNDEF) { 240 253 if (func && ip) js_set_error_site_from_bc(js, func, (int)(ip - func->code), func->filename); 241 254 return js_mkerr_typed(js, JS_ERR_TYPE, ··· 246 259 ant_value_t str_prim = js_mkundef(); 247 260 ant_value_t sym_prim = js_mkundef(); 248 261 249 - if (t == T_STR) { 250 - str_prim = obj; 251 - } else if (t == T_SYMBOL) { 252 - sym_prim = obj; 253 - } else if (t == T_OBJ) { 262 + if (t == T_STR) str_prim = obj; 263 + else if (t == T_SYMBOL) sym_prim = obj; 264 + else if (t == T_OBJ) { 254 265 ant_value_t prim = js_get_slot(obj, SLOT_PRIMITIVE); 255 266 if (vtype(prim) == T_STR) str_prim = prim; 256 267 else if (vtype(prim) == T_SYMBOL) sym_prim = prim;