From c18defd3e488e3eb77c90792eedea2829ae3e826 Mon Sep 17 00:00:00 2001 From: theMackabu Date: Tue, 5 May 2026 16:49:22 -0700 Subject: [PATCH] improve performance --- src/ant.c | 70 ++++++++++++++++++++++-------- src/silver/ops/coercion.h | 90 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 140 insertions(+), 20 deletions(-) diff --git a/src/ant.c b/src/ant.c index 47ad8e4..8a57178 100644 --- a/src/ant.c +++ b/src/ant.c @@ -5605,13 +5605,16 @@ static ant_value_t builtin_function_call(ant_t *js, ant_value_t *args, int nargs } int extract_array_args(ant_t *js, ant_value_t arr, ant_value_t **out_args) { - int len = (int) proxy_aware_length(js, arr); + int len = (int)(vtype(arr) == T_ARR ? get_array_length(js, arr) : proxy_aware_length(js, arr)); if (len <= 0) return 0; ant_value_t *args_out = (ant_value_t *)ant_calloc(sizeof(ant_value_t) * len); if (!args_out) return 0; - - for (int i = 0; i < len; i++) { + + if (vtype(arr) == T_ARR) { + for (int i = 0; i < len; i++) + args_out[i] = arr_get(js, arr, (ant_offset_t)i); + } else for (int i = 0; i < len; i++) { ant_value_t item = array_method_get_index(js, arr, (ant_offset_t)i); args_out[i] = is_err(item) ? js_mkundef() : item; } @@ -10265,18 +10268,25 @@ static ant_value_t builtin_array_reduce(ant_t *js, ant_value_t *args, int nargs) } static inline ant_value_t flat_helper(ant_t *js, ant_value_t arr, ant_value_t result, ant_offset_t *result_idx, int depth) { - ant_offset_t len = proxy_aware_length(js, arr); + bool input_is_array = vtype(arr) == T_ARR; + ant_offset_t len = input_is_array ? get_array_length(js, arr) : proxy_aware_length(js, arr); if (len == 0) return js_mkundef(); for (ant_offset_t i = 0; i < len; i++) { - if (!array_method_has_index(js, arr, i)) continue; - ant_value_t val = array_method_get_index(js, arr, i); + if (input_is_array) { + if (!arr_has(js, arr, i)) continue; + } else if (!array_method_has_index(js, arr, i)) continue; + + ant_value_t val = input_is_array ? arr_get(js, arr, i) : array_method_get_index(js, arr, i); if (is_err(val)) return val; bool val_is_array = false; if (depth > 0) { - ant_value_t is_array_res = js_is_array_value_checked(js, val, &val_is_array); - if (is_err(is_array_res)) return is_array_res; + val_is_array = vtype(val) == T_ARR; + if (!val_is_array && is_proxy(val)) { + ant_value_t is_array_res = js_is_array_value_checked(js, val, &val_is_array); + if (is_err(is_array_res)) return is_array_res; + } } if (val_is_array) { @@ -10491,22 +10501,28 @@ static ant_value_t builtin_array_flatMap(ant_t *js, ant_value_t *args, int nargs ant_value_t callback = args[0]; ant_value_t this_arg = (nargs >= 2) ? args[1] : js_mkundef(); - ant_offset_t len = proxy_aware_length(js, arr); + bool input_is_array = vtype(arr) == T_ARR; + ant_offset_t len = input_is_array ? get_array_length(js, arr) : proxy_aware_length(js, arr); ant_value_t result = mkarr(js); if (is_err(result)) return result; ant_offset_t result_idx = 0; for (ant_offset_t i = 0; i < len; i++) { - if (!array_method_has_index(js, arr, i)) continue; - ant_value_t elem = array_method_get_index(js, arr, i); + if (input_is_array) { + if (!arr_has(js, arr, i)) continue; + } else if (!array_method_has_index(js, arr, i)) continue; + + ant_value_t elem = input_is_array ? arr_get(js, arr, i) : array_method_get_index(js, arr, i); if (is_err(elem)) return elem; ant_value_t call_args[3] = { elem, tov((double)i), arr }; ant_value_t mapped = sv_vm_call(js->vm, js, callback, this_arg, call_args, 3, NULL, false); if (is_err(mapped)) return mapped; - bool mapped_is_array = false; - ant_value_t is_array_res = js_is_array_value_checked(js, mapped, &mapped_is_array); - if (is_err(is_array_res)) return is_array_res; + bool mapped_is_array = vtype(mapped) == T_ARR; + if (!mapped_is_array && is_proxy(mapped)) { + ant_value_t is_array_res = js_is_array_value_checked(js, mapped, &mapped_is_array); + if (is_err(is_array_res)) return is_array_res; + } if (mapped_is_array) { ant_value_t flat_res = flat_helper(js, mapped, result, &result_idx, 0); @@ -11396,7 +11412,8 @@ static ant_value_t builtin_array_toLocaleString(ant_t *js, ant_value_t *args, in if (vtype(arr) != T_ARR && vtype(arr) != T_OBJ) return js_mkerr(js, "toLocaleString called on non-array"); - ant_offset_t len = proxy_aware_length(js, arr); + bool input_is_array = vtype(arr) == T_ARR; + ant_offset_t len = input_is_array ? get_array_length(js, arr) : proxy_aware_length(js, arr); if (len == 0) return js_mkstr(js, "", 0); char *result = NULL; @@ -11417,8 +11434,11 @@ static ant_value_t builtin_array_toLocaleString(ant_t *js, ant_value_t *args, in result[result_len++] = ','; } - if (!array_method_has_index(js, arr, i)) continue; - ant_value_t elem = array_method_get_index(js, arr, i); + if (input_is_array) { + if (!arr_has(js, arr, i)) continue; + } else if (!array_method_has_index(js, arr, i)) continue; + + ant_value_t elem = input_is_array ? arr_get(js, arr, i) : array_method_get_index(js, arr, i); if (is_err(elem)) { free(result); return elem; } if (vtype(elem) == T_NULL || vtype(elem) == T_UNDEF) continue; @@ -11545,17 +11565,31 @@ static ant_value_t builtin_Array_from(ant_t *js, ant_value_t *args, int nargs) { } else { ant_value_t iter_method = js_mkundef(); ant_offset_t iter_prop = 0; + bool src_is_array = false; if (vtype(iter_sym) == T_SYMBOL) { if (is_proxy(src)) { iter_method = js_get_sym(js, src, iter_sym); if (is_err(iter_method)) return iter_method; + ant_value_t target = proxy_read_target(js, src); + src_is_array = vtype(target) == T_ARR; } else { iter_prop = lkp_sym_proto(js, src, (ant_offset_t)vdata(iter_sym)); if (iter_prop != 0) iter_method = propref_load(js, iter_prop); } } - if (vtype(iter_method) != T_UNDEF) { + if (src_is_array && vtype(iter_method) == T_CFUNC) { + array_from_iter_ctx_t ctx = { write_target, result, mapFn, mapThis, 0 }; + ant_offset_t len = proxy_aware_length(js, src); + for (ant_offset_t i = 0; i < len; i++) { + ant_value_t unused; + ant_value_t item = array_method_get_index(js, src, i); + if (is_err(item)) return item; + iter_action_t act = array_from_iter_cb(js, item, &ctx, &unused); + if (act == ITER_ERROR) return unused; + } + if (vtype(result) != T_ARR) js_setprop(js, result, js->length_str, tov((double)len)); + } else if (vtype(iter_method) != T_UNDEF) { array_from_iter_ctx_t ctx = { write_target, result, mapFn, mapThis, 0 }; ant_value_t iter_result = iter_foreach(js, src, array_from_iter_cb, &ctx); if (is_err(iter_result)) return iter_result; diff --git a/src/silver/ops/coercion.h b/src/silver/ops/coercion.h index eede0e5..3e9e501 100644 --- a/src/silver/ops/coercion.h +++ b/src/silver/ops/coercion.h @@ -236,7 +236,67 @@ static inline bool sv_with_binding_is_unscopable( ) { *abrupt = false; - ant_value_t unscopables = js_get_sym(js, with_obj, get_unscopables_sym()); + ant_value_t unscopables_sym = get_unscopables_sym(); + if (vtype(unscopables_sym) != T_SYMBOL) return false; + + bool is_proxy_obj = is_proxy(js_as_obj(with_obj)); + ant_value_t unscopables = js_mkundef(); + + if (!is_proxy_obj) { + ant_offset_t sym_off = (ant_offset_t)vdata(unscopables_sym); + ant_object_t *base_ptr = js_obj_ptr(js_as_obj(with_obj)); + ant_value_t base_proto = (base_ptr && is_object_type(base_ptr->proto)) ? base_ptr->proto : js_mknull(); + ant_object_t *proto_ptr = is_object_type(base_proto) ? js_obj_ptr(js_as_obj(base_proto)) : NULL; + + static ant_object_t *cached_no_base = NULL; + static void *cached_no_base_shape = NULL; + static ant_value_t cached_no_proto = 0; + static void *cached_no_proto_shape = NULL; + + if ( + base_ptr == cached_no_base && + (void *)(base_ptr ? base_ptr->shape : NULL) == cached_no_base_shape && + base_proto == cached_no_proto && + (void *)(proto_ptr ? proto_ptr->shape : NULL) == cached_no_proto_shape + ) return false; + + ant_offset_t unscopables_off = lkp_sym_proto(js, with_obj, sym_off); + bool has_unscopables = unscopables_off != 0; + bool saw_exotic = base_ptr && base_ptr->is_exotic; + + if (!has_unscopables) { + ant_value_t cur = with_obj; + while (is_object_type(cur)) { + ant_value_t cur_obj = js_as_obj(cur); + ant_object_t *cur_ptr = js_obj_ptr(cur_obj); + if (cur_ptr && cur_ptr->is_exotic) saw_exotic = true; + prop_meta_t meta; + if (cur_ptr && cur_ptr->is_exotic && lookup_symbol_prop_meta(cur_obj, sym_off, &meta)) { + has_unscopables = true; + break; + } + + ant_value_t proto = js_get_proto(js, cur_obj); + if (!is_object_type(proto)) break; + cur = proto; + } + } + + if (!has_unscopables) { + ant_value_t proto_proto = (proto_ptr && is_object_type(proto_ptr->proto)) ? proto_ptr->proto : js_mknull(); + if (!saw_exotic && !is_object_type(proto_proto)) { + cached_no_base = base_ptr; + cached_no_base_shape = (void *)(base_ptr ? base_ptr->shape : NULL); + cached_no_proto = base_proto; + cached_no_proto_shape = (void *)(proto_ptr ? proto_ptr->shape : NULL); + } + return false; + } + if (unscopables_off != 0) unscopables = js_propref_load(js, unscopables_off); + } + + if (is_proxy_obj || vtype(unscopables) == T_UNDEF) + unscopables = js_get_sym(js, with_obj, unscopables_sym); if (is_err(unscopables)) { *out = unscopables; *abrupt = true; @@ -245,7 +305,33 @@ static inline bool sv_with_binding_is_unscopable( if (!is_object_type(unscopables)) return false; - ant_value_t blocked = js_getprop_fallback(js, unscopables, a->str); + ant_value_t blocked = js_mkundef(); + bool got_blocked_fast = false; + + if (!is_proxy(js_as_obj(unscopables))) { + ant_value_t cur = unscopables; + while (is_object_type(cur)) { + ant_value_t cur_obj = js_as_obj(cur); + prop_meta_t meta; + if (lookup_string_prop_meta(js, cur_obj, a->str, a->len, &meta)) { + if (meta.has_getter || meta.has_setter) break; + ant_offset_t off = lkp(js, cur_obj, a->str, a->len); + blocked = off != 0 ? js_propref_load(js, off) : js_mkundef(); + got_blocked_fast = true; + break; + } + + ant_value_t proto = js_get_proto(js, cur_obj); + if (!is_object_type(proto)) { + got_blocked_fast = true; + break; + } + cur = proto; + } + } + + if (!got_blocked_fast) + blocked = js_getprop_fallback(js, unscopables, a->str); if (is_err(blocked)) { *out = blocked; *abrupt = true; -- 2.51.2