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.

optimize dense array includes fast path

+102 -19
+102 -19
src/ant.c
··· 8340 8340 free(result); return ret; 8341 8341 } 8342 8342 8343 - static inline bool array_includes_same_value_zero(ant_t *js, ant_value_t val, ant_value_t search) { 8344 - return ( 8345 - vtype(val) == T_NUM && 8346 - vtype(search) == T_NUM && 8347 - isnan(tod(val)) && 8348 - isnan(tod(search)) 8349 - ) || strict_eq_values(js, val, search); 8343 + typedef struct { 8344 + ant_value_t search; 8345 + double search_num; 8346 + uint8_t search_type; 8347 + uint8_t mode; 8348 + } array_includes_query_t; 8349 + 8350 + enum { 8351 + ARRAY_INCLUDES_MATCH_GENERIC = 0, 8352 + ARRAY_INCLUDES_MATCH_NUM = 1, 8353 + ARRAY_INCLUDES_MATCH_NAN = 2, 8354 + ARRAY_INCLUDES_MATCH_ID = 3, 8355 + }; 8356 + 8357 + static inline array_includes_query_t array_includes_prepare_query(ant_value_t search) { 8358 + array_includes_query_t q = { 8359 + .search = search, 8360 + .search_num = 0.0, 8361 + .search_type = vtype(search), 8362 + .mode = ARRAY_INCLUDES_MATCH_GENERIC, 8363 + }; 8364 + 8365 + if (q.search_type == T_NUM) { 8366 + q.search_num = tod(search); 8367 + q.mode = isnan(q.search_num) 8368 + ? ARRAY_INCLUDES_MATCH_NAN 8369 + : ARRAY_INCLUDES_MATCH_NUM; 8370 + } else if ( 8371 + q.search_type != T_STR && 8372 + q.search_type != T_BIGINT 8373 + ) q.mode = ARRAY_INCLUDES_MATCH_ID; 8374 + 8375 + return q; 8350 8376 } 8351 8377 8378 + static inline bool array_includes_matches(ant_t *js, const array_includes_query_t *q, ant_value_t val) { 8379 + switch (q->mode) { 8380 + case ARRAY_INCLUDES_MATCH_NUM: return vtype(val) == T_NUM && tod(val) == q->search_num; 8381 + case ARRAY_INCLUDES_MATCH_NAN: return vtype(val) == T_NUM && isnan(tod(val)); 8382 + case ARRAY_INCLUDES_MATCH_ID: return vtype(val) == q->search_type && vdata(val) == vdata(q->search); 8383 + default: return strict_eq_values(js, val, q->search); 8384 + }} 8385 + 8352 8386 static inline ant_offset_t array_includes_length_from_number(double len_num) { 8353 8387 if (isnan(len_num) || len_num <= 0) return 0; 8354 8388 if (len_num >= (double)UINT32_MAX) return UINT32_MAX; ··· 8370 8404 return (ant_offset_t)start; 8371 8405 } 8372 8406 8407 + static ant_value_t array_includes_length_value(ant_t *js, ant_value_t arr) { 8408 + if (array_obj_ptr(arr) && !is_proxy(arr)) return tov((double)get_array_length(js, arr)); 8409 + if (is_proxy(arr)) return proxy_get(js, arr, "length", 6); 8410 + 8411 + ant_offset_t off = lkp(js, arr, "length", 6); 8412 + if (off != 0) { 8413 + const ant_shape_prop_t *prop_meta = prop_shape_meta(js, off); 8414 + if (prop_meta && prop_meta->has_getter) { 8415 + ant_value_t accessor_result; 8416 + if (try_accessor_getter(js, arr, "length", 6, &accessor_result)) return accessor_result; 8417 + } 8418 + return propref_load(js, off); 8419 + } 8420 + 8421 + if (lkp_proto(js, arr, "length", 6) == 0) return js_mkundef(); 8422 + return js_getprop_super(js, get_proto(js, arr), arr, "length"); 8423 + } 8424 + 8425 + static ant_value_t array_includes_get_index_value( 8426 + ant_t *js, ant_value_t arr, ant_offset_t idx, char *idxstr, size_t idxlen 8427 + ) { 8428 + if (is_proxy(arr)) return proxy_get(js, arr, idxstr, idxlen); 8429 + 8430 + if (array_obj_ptr(arr)) { 8431 + if (arr_has(js, arr, idx)) return arr_get(js, arr, idx); 8432 + if (lkp_proto(js, arr, idxstr, idxlen) == 0) return js_mkundef(); 8433 + idxstr[idxlen] = '\0'; 8434 + return js_getprop_super(js, get_proto(js, arr), arr, idxstr); 8435 + } 8436 + 8437 + ant_offset_t off = lkp(js, arr, idxstr, idxlen); 8438 + if (off != 0) { 8439 + const ant_shape_prop_t *prop_meta = prop_shape_meta(js, off); 8440 + if (prop_meta && prop_meta->has_getter) { 8441 + ant_value_t accessor_result; 8442 + if (try_accessor_getter(js, arr, idxstr, idxlen, &accessor_result)) return accessor_result; 8443 + } 8444 + return propref_load(js, off); 8445 + } 8446 + 8447 + if (lkp_proto(js, arr, idxstr, idxlen) == 0) return js_mkundef(); 8448 + idxstr[idxlen] = '\0'; 8449 + return js_getprop_super(js, get_proto(js, arr), arr, idxstr); 8450 + } 8451 + 8373 8452 static ant_value_t array_includes_dense_fast( 8374 - ant_t *js, ant_value_t arr, ant_value_t search, ant_value_t *args, int nargs 8453 + ant_t *js, ant_value_t arr, const array_includes_query_t *query, ant_value_t *args, int nargs 8375 8454 ) { 8376 8455 if (!array_obj_ptr(arr) || is_proxy(arr)) return js_mkundef(); 8377 8456 ··· 8380 8459 8381 8460 ant_offset_t doff = get_dense_buf(arr); 8382 8461 if (!doff) return js_mkundef(); 8462 + 8463 + ant_value_t *dense = dense_data(doff); 8464 + if (!dense) return js_mkundef(); 8383 8465 8384 8466 ant_offset_t dense_len = dense_iterable_length(js, arr); 8385 8467 if (dense_len != len) return js_mkundef(); ··· 8388 8470 if (start >= len) return mkval(T_BOOL, 0); 8389 8471 8390 8472 for (ant_offset_t i = start; i < len; i++) { 8391 - ant_value_t val = dense_get(doff, i); 8473 + ant_value_t val = dense[i]; 8392 8474 if (is_empty_slot(val)) return js_mkundef(); 8393 - if (array_includes_same_value_zero(js, val, search)) return mkval(T_BOOL, 1); 8475 + if (array_includes_matches(js, query, val)) return mkval(T_BOOL, 1); 8394 8476 } 8395 8477 8396 8478 return mkval(T_BOOL, 0); 8397 8479 } 8398 8480 8399 8481 static ant_value_t array_includes_generic( 8400 - ant_t *js, ant_value_t arr, ant_value_t search, ant_value_t *args, int nargs 8482 + ant_t *js, ant_value_t arr, const array_includes_query_t *query, ant_value_t *args, int nargs 8401 8483 ) { 8402 - ant_value_t len_val = js_getprop_fallback(js, arr, "length"); 8484 + ant_value_t len_val = array_includes_length_value(js, arr); 8403 8485 if (is_err(len_val)) return len_val; 8404 8486 8405 8487 ant_offset_t len = array_includes_length_from_number(js_to_number(js, len_val)); ··· 8409 8491 if (start >= len) return mkval(T_BOOL, 0); 8410 8492 8411 8493 for (ant_offset_t i = start; i < len; i++) { 8412 - char idxstr[24]; 8494 + char idxstr[16]; 8413 8495 size_t idxlen = uint_to_str(idxstr, sizeof(idxstr), (uint64_t)i); 8414 - idxstr[idxlen] = '\0'; 8415 8496 8416 - ant_value_t val = js_getprop_fallback(js, arr, idxstr); 8497 + ant_value_t val = array_includes_get_index_value(js, arr, i, idxstr, idxlen); 8417 8498 if (is_err(val)) return val; 8418 - if (array_includes_same_value_zero(js, val, search)) return mkval(T_BOOL, 1); 8499 + if (array_includes_matches(js, query, val)) return mkval(T_BOOL, 1); 8419 8500 } 8420 8501 8421 8502 return mkval(T_BOOL, 0); ··· 8427 8508 if (vtype(arr) != T_ARR && vtype(arr) != T_OBJ) 8428 8509 return js_mkerr(js, "includes called on non-array"); 8429 8510 8430 - ant_value_t search = (nargs > 0) ? args[0] : js_mkundef(); 8511 + array_includes_query_t query = array_includes_prepare_query( 8512 + (nargs > 0) ? args[0] : js_mkundef() 8513 + ); 8431 8514 8432 - ant_value_t fast = array_includes_dense_fast(js, arr, search, args, nargs); 8515 + ant_value_t fast = array_includes_dense_fast(js, arr, &query, args, nargs); 8433 8516 if (vtype(fast) != T_UNDEF) return fast; 8434 8517 8435 - return array_includes_generic(js, arr, search, args, nargs); 8518 + return array_includes_generic(js, arr, &query, args, nargs); 8436 8519 } 8437 8520 8438 8521 static ant_value_t builtin_array_every(ant_t *js, ant_value_t *args, int nargs) {