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 dot operator inline cache to reduce property lookup overhead

+67 -14
+67 -14
src/ant.c
··· 181 181 uint64_t generation; 182 182 } intern_prop_cache_entry_t; 183 183 184 + typedef struct { 185 + const char *code_ptr; 186 + jsoff_t code_off; 187 + jsoff_t cached_key_off; 188 + uint64_t generation; 189 + } dot_ic_entry_t; 190 + 184 191 static uint64_t intern_prop_cache_gen = 1; 192 + static dot_ic_entry_t dot_ic_table[ANT_LIMIT_SIZE_CACHE]; 185 193 static intern_prop_cache_entry_t intern_prop_cache[ANT_LIMIT_SIZE_CACHE]; 194 + 195 + static inline size_t dot_ic_slot(const char *code, jsoff_t off) { 196 + uint64_t h = (uintptr_t)code ^ (off * 0x9E3779B97F4A7C15ULL); 197 + return (size_t)((h ^ (h >> 32)) & (ANT_LIMIT_SIZE_CACHE - 1)); 198 + } 186 199 187 200 typedef struct promise_handler { 188 201 jsval_t onFulfilled; ··· 6267 6280 } 6268 6281 6269 6282 static jsval_t do_dot_op(struct js *js, jsval_t l, jsval_t r) { 6283 + if (vtype(r) == T_CODEREF && is_special_object(l) && !is_proxy(js, l)) { 6284 + dot_ic_entry_t *ic = &dot_ic_table[dot_ic_slot(js->code, coderefoff(r))]; 6285 + 6286 + if ( 6287 + ic->generation == intern_prop_cache_gen 6288 + && ic->code_ptr == js->code 6289 + && ic->code_off == coderefoff(r) 6290 + ) return mkpropref((jsoff_t)vdata(l), ic->cached_key_off); 6291 + } 6292 + 6270 6293 const char *raw_ptr = (char *) &js->code[coderefoff(r)]; 6271 6294 size_t raw_len = codereflen(r); 6272 6295 ··· 6380 6403 return err; 6381 6404 } 6382 6405 6406 + bool ic_eligible = !is_proxy(js, l); 6407 + jsoff_t ic_obj_off = (jsoff_t)vdata(l); 6408 + jsoff_t ic_key_off = 0; 6409 + 6383 6410 if ((streq(ptr, plen, "callee", 6) || streq(ptr, plen, "caller", 6)) && 6384 6411 vtype(get_slot(js, l, SLOT_STRICT_ARGS)) != T_UNDEF) { 6385 6412 return js_mkerr_typed(js, JS_ERR_TYPE, "'%.*s' not allowed on strict arguments", (int)plen, ptr); ··· 6394 6421 jsoff_t obj_off = (jsoff_t)vdata(l); 6395 6422 descriptor_entry_t *desc = lookup_descriptor(js, obj_off, ptr, plen); 6396 6423 if (desc) { 6424 + if (desc->has_getter || desc->has_setter) ic_eligible = false; 6397 6425 jsval_t key = js_mkstr(js, ptr, plen); 6398 - return mkpropref(obj_off, (jsoff_t)vdata(key)); 6426 + ic_key_off = (jsoff_t)vdata(key); 6427 + if (ic_eligible) goto ic_populate; 6428 + return mkpropref(obj_off, ic_key_off); 6399 6429 } 6400 6430 jsval_t result = try_dynamic_getter(js, l, ptr, plen); 6401 6431 if (vtype(result) != T_UNDEF) { ··· 6403 6433 if (own_off != 0) return mkval(T_PROP, own_off); 6404 6434 } 6405 6435 jsval_t key = js_mkstr(js, ptr, plen); 6406 - return mkpropref((jsoff_t)vdata(l), (jsoff_t)vdata(key)); 6436 + ic_key_off = (jsoff_t)vdata(key); 6437 + if (ic_eligible) goto ic_populate; 6438 + return mkpropref((jsoff_t)vdata(l), ic_key_off); 6407 6439 } 6408 6440 6409 - jsoff_t own_off = lkp(js, l, ptr, plen); 6410 - if (own_off != 0) { 6411 - jsval_t key = js_mkstr(js, ptr, plen); 6412 - return mkpropref((jsoff_t)vdata(l), (jsoff_t)vdata(key)); 6413 - } 6414 - 6415 - jsval_t result = try_dynamic_getter(js, l, ptr, plen); 6416 - if (vtype(result) != T_UNDEF) { 6417 - own_off = lkp(js, l, ptr, plen); 6441 + { 6442 + jsoff_t own_off = lkp(js, l, ptr, plen); 6418 6443 if (own_off != 0) { 6444 + if (ic_eligible) { 6445 + descriptor_entry_t *desc = lookup_descriptor(js, ic_obj_off, ptr, plen); 6446 + if (desc && (desc->has_getter || desc->has_setter)) ic_eligible = false; 6447 + } 6419 6448 jsval_t key = js_mkstr(js, ptr, plen); 6420 - return mkpropref((jsoff_t)vdata(l), (jsoff_t)vdata(key)); 6449 + ic_key_off = (jsoff_t)vdata(key); 6450 + if (ic_eligible) goto ic_populate; 6451 + return mkpropref((jsoff_t)vdata(l), ic_key_off); 6421 6452 } 6453 + 6454 + jsval_t result = try_dynamic_getter(js, l, ptr, plen); 6455 + if (vtype(result) != T_UNDEF) { 6456 + own_off = lkp(js, l, ptr, plen); 6457 + if (own_off != 0) { 6458 + jsval_t key = js_mkstr(js, ptr, plen); 6459 + ic_key_off = (jsoff_t)vdata(key); 6460 + if (ic_eligible) goto ic_populate; 6461 + return mkpropref((jsoff_t)vdata(l), ic_key_off); 6462 + } 6463 + } 6464 + 6465 + jsval_t key = js_mkstr(js, ptr, plen); 6466 + ic_key_off = (jsoff_t)vdata(key); 6467 + if (ic_eligible) goto ic_populate; 6468 + return mkpropref((jsoff_t)vdata(l), ic_key_off); 6422 6469 } 6423 6470 6424 - jsval_t key = js_mkstr(js, ptr, plen); 6425 - return mkpropref((jsoff_t)vdata(l), (jsoff_t)vdata(key)); 6471 + ic_populate: { 6472 + dot_ic_entry_t *ic = &dot_ic_table[dot_ic_slot(js->code, coderefoff(r))]; 6473 + ic->code_ptr = js->code; 6474 + ic->code_off = coderefoff(r); 6475 + ic->generation = intern_prop_cache_gen; 6476 + ic->cached_key_off = ic_key_off; 6477 + return mkpropref(ic_obj_off, ic_key_off); 6478 + } 6426 6479 } 6427 6480 6428 6481 static jsval_t do_optional_chain_op(struct js *js, jsval_t l, jsval_t r) {