Merge branch 'fix_aot'
This commit is contained in:
82
mcode.cm
82
mcode.cm
@@ -1008,7 +1008,7 @@ var mcode = function(ast) {
|
||||
var inline_reduce = true
|
||||
|
||||
// --- Helper: emit a reduce loop body ---
|
||||
// r = {acc, i, arr, fn, len}; emits loop updating acc in-place.
|
||||
// r = {acc, i, arr, fn, len, fn_arity}; emits loop updating acc in-place.
|
||||
// Caller must emit the done_label after calling this.
|
||||
var emit_reduce_loop = function(r, forward, done_label) {
|
||||
var acc = r.acc
|
||||
@@ -1016,29 +1016,51 @@ var mcode = function(ast) {
|
||||
var arr_slot = r.arr
|
||||
var fn_slot = r.fn
|
||||
var len = r.len
|
||||
var fn_arity = r.fn_arity
|
||||
var check = alloc_slot()
|
||||
var item = alloc_slot()
|
||||
var null_s = alloc_slot()
|
||||
var one = alloc_slot()
|
||||
var zero = alloc_slot()
|
||||
var arity_is_zero = alloc_slot()
|
||||
var arity_is_one = alloc_slot()
|
||||
var f = alloc_slot()
|
||||
var loop_label = gen_label("reduce_loop")
|
||||
var call_one_label = gen_label("reduce_call_one")
|
||||
var call_two_label = gen_label("reduce_call_two")
|
||||
var call_done_label = gen_label("reduce_call_done")
|
||||
emit_2("int", one, 1)
|
||||
emit_2("int", zero, 0)
|
||||
emit_1("null", null_s)
|
||||
emit_label(loop_label)
|
||||
if (forward) {
|
||||
emit_3("lt_int", check, i, len)
|
||||
} else {
|
||||
emit_2("int", zero, 0)
|
||||
emit_3("ge_int", check, i, zero)
|
||||
}
|
||||
emit_jump_cond("jump_false", check, done_label)
|
||||
emit_3("load_index", item, arr_slot, i)
|
||||
emit_3("eq_int", arity_is_zero, fn_arity, zero)
|
||||
emit_jump_cond("jump_false", arity_is_zero, call_one_label)
|
||||
emit_3("frame", f, fn_slot, 0)
|
||||
emit_3("setarg", f, 0, null_s)
|
||||
emit_2("invoke", f, acc)
|
||||
emit_jump(call_done_label)
|
||||
emit_label(call_one_label)
|
||||
emit_3("eq_int", arity_is_one, fn_arity, one)
|
||||
emit_jump_cond("jump_false", arity_is_one, call_two_label)
|
||||
emit_3("frame", f, fn_slot, 1)
|
||||
emit_3("setarg", f, 0, null_s)
|
||||
emit_3("setarg", f, 1, acc)
|
||||
emit_2("invoke", f, acc)
|
||||
emit_jump(call_done_label)
|
||||
emit_label(call_two_label)
|
||||
emit_3("frame", f, fn_slot, 2)
|
||||
emit_3("setarg", f, 0, null_s)
|
||||
emit_3("setarg", f, 1, acc)
|
||||
emit_3("setarg", f, 2, item)
|
||||
emit_2("invoke", f, acc)
|
||||
emit_label(call_done_label)
|
||||
if (forward) {
|
||||
emit_3("add", i, i, one)
|
||||
} else {
|
||||
@@ -1054,17 +1076,21 @@ var mcode = function(ast) {
|
||||
var check = alloc_slot()
|
||||
var item = alloc_slot()
|
||||
var fn_arity = alloc_slot()
|
||||
var arity_is_zero = alloc_slot()
|
||||
var arity_is_one = alloc_slot()
|
||||
var null_s = alloc_slot()
|
||||
var zero = alloc_slot()
|
||||
var one = alloc_slot()
|
||||
var f = alloc_slot()
|
||||
var discard = alloc_slot()
|
||||
var loop_label = gen_label("arrfor_loop")
|
||||
var done_label = gen_label("arrfor_done")
|
||||
var call_one_label = gen_label("arrfor_call_one")
|
||||
var call_two_label = gen_label("arrfor_call_two")
|
||||
var call_done_label = gen_label("arrfor_call_done")
|
||||
emit_2("length", len, arr_slot)
|
||||
emit_2("int", i, 0)
|
||||
emit_2("int", zero, 0)
|
||||
emit_2("int", one, 1)
|
||||
emit_1("null", null_s)
|
||||
emit_2("length", fn_arity, fn_slot)
|
||||
@@ -1072,6 +1098,13 @@ var mcode = function(ast) {
|
||||
emit_3("lt_int", check, i, len)
|
||||
emit_jump_cond("jump_false", check, done_label)
|
||||
emit_3("load_index", item, arr_slot, i)
|
||||
emit_3("eq_int", arity_is_zero, fn_arity, zero)
|
||||
emit_jump_cond("jump_false", arity_is_zero, call_one_label)
|
||||
emit_3("frame", f, fn_slot, 0)
|
||||
emit_3("setarg", f, 0, null_s)
|
||||
emit_2("invoke", f, discard)
|
||||
emit_jump(call_done_label)
|
||||
emit_label(call_one_label)
|
||||
emit_3("eq_int", arity_is_one, fn_arity, one)
|
||||
emit_jump_cond("jump_false", arity_is_one, call_two_label)
|
||||
emit_3("frame", f, fn_slot, 1)
|
||||
@@ -1099,26 +1132,41 @@ var mcode = function(ast) {
|
||||
var i = alloc_slot()
|
||||
var check = alloc_slot()
|
||||
var item = alloc_slot()
|
||||
var fn_arity = alloc_slot()
|
||||
var arity_is_zero = alloc_slot()
|
||||
var null_s = alloc_slot()
|
||||
var zero = alloc_slot()
|
||||
var one = alloc_slot()
|
||||
var f = alloc_slot()
|
||||
var val = alloc_slot()
|
||||
var loop_label = gen_label("every_loop")
|
||||
var call_one_label = gen_label("every_call_one")
|
||||
var call_done_label = gen_label("every_call_done")
|
||||
var ret_true = gen_label("every_true")
|
||||
var ret_false = gen_label("every_false")
|
||||
var done_label = gen_label("every_done")
|
||||
emit_2("length", len, arr_slot)
|
||||
emit_2("int", i, 0)
|
||||
emit_2("int", zero, 0)
|
||||
emit_2("int", one, 1)
|
||||
emit_1("null", null_s)
|
||||
emit_2("length", fn_arity, fn_slot)
|
||||
emit_label(loop_label)
|
||||
emit_3("lt_int", check, i, len)
|
||||
emit_jump_cond("jump_false", check, ret_true)
|
||||
emit_3("load_index", item, arr_slot, i)
|
||||
emit_3("eq_int", arity_is_zero, fn_arity, zero)
|
||||
emit_jump_cond("jump_false", arity_is_zero, call_one_label)
|
||||
emit_3("frame", f, fn_slot, 0)
|
||||
emit_3("setarg", f, 0, null_s)
|
||||
emit_2("invoke", f, val)
|
||||
emit_jump(call_done_label)
|
||||
emit_label(call_one_label)
|
||||
emit_3("frame", f, fn_slot, 1)
|
||||
emit_3("setarg", f, 0, null_s)
|
||||
emit_3("setarg", f, 1, item)
|
||||
emit_2("invoke", f, val)
|
||||
emit_label(call_done_label)
|
||||
emit_jump_cond("jump_false", val, ret_false)
|
||||
emit_3("add", i, i, one)
|
||||
emit_jump(loop_label)
|
||||
@@ -1137,26 +1185,41 @@ var mcode = function(ast) {
|
||||
var i = alloc_slot()
|
||||
var check = alloc_slot()
|
||||
var item = alloc_slot()
|
||||
var fn_arity = alloc_slot()
|
||||
var arity_is_zero = alloc_slot()
|
||||
var null_s = alloc_slot()
|
||||
var zero = alloc_slot()
|
||||
var one = alloc_slot()
|
||||
var f = alloc_slot()
|
||||
var val = alloc_slot()
|
||||
var loop_label = gen_label("some_loop")
|
||||
var call_one_label = gen_label("some_call_one")
|
||||
var call_done_label = gen_label("some_call_done")
|
||||
var ret_true = gen_label("some_true")
|
||||
var ret_false = gen_label("some_false")
|
||||
var done_label = gen_label("some_done")
|
||||
emit_2("length", len, arr_slot)
|
||||
emit_2("int", i, 0)
|
||||
emit_2("int", zero, 0)
|
||||
emit_2("int", one, 1)
|
||||
emit_1("null", null_s)
|
||||
emit_2("length", fn_arity, fn_slot)
|
||||
emit_label(loop_label)
|
||||
emit_3("lt_int", check, i, len)
|
||||
emit_jump_cond("jump_false", check, ret_false)
|
||||
emit_3("load_index", item, arr_slot, i)
|
||||
emit_3("eq_int", arity_is_zero, fn_arity, zero)
|
||||
emit_jump_cond("jump_false", arity_is_zero, call_one_label)
|
||||
emit_3("frame", f, fn_slot, 0)
|
||||
emit_3("setarg", f, 0, null_s)
|
||||
emit_2("invoke", f, val)
|
||||
emit_jump(call_done_label)
|
||||
emit_label(call_one_label)
|
||||
emit_3("frame", f, fn_slot, 1)
|
||||
emit_3("setarg", f, 0, null_s)
|
||||
emit_3("setarg", f, 1, item)
|
||||
emit_2("invoke", f, val)
|
||||
emit_label(call_done_label)
|
||||
emit_jump_cond("jump_true", val, ret_true)
|
||||
emit_3("add", i, i, one)
|
||||
emit_jump(loop_label)
|
||||
@@ -1177,12 +1240,15 @@ var mcode = function(ast) {
|
||||
var check = alloc_slot()
|
||||
var item = alloc_slot()
|
||||
var fn_arity = alloc_slot()
|
||||
var arity_is_zero = alloc_slot()
|
||||
var arity_is_one = alloc_slot()
|
||||
var null_s = alloc_slot()
|
||||
var zero = alloc_slot()
|
||||
var one = alloc_slot()
|
||||
var f = alloc_slot()
|
||||
var val = alloc_slot()
|
||||
var loop_label = gen_label("filter_loop")
|
||||
var call_one_label = gen_label("filter_call_one")
|
||||
var call_two_label = gen_label("filter_call_two")
|
||||
var call_done_label = gen_label("filter_call_done")
|
||||
var skip_label = gen_label("filter_skip")
|
||||
@@ -1190,6 +1256,7 @@ var mcode = function(ast) {
|
||||
add_instr(["array", result, 0])
|
||||
emit_2("length", len, arr_slot)
|
||||
emit_2("int", i, 0)
|
||||
emit_2("int", zero, 0)
|
||||
emit_2("int", one, 1)
|
||||
emit_1("null", null_s)
|
||||
emit_2("length", fn_arity, fn_slot)
|
||||
@@ -1197,6 +1264,13 @@ var mcode = function(ast) {
|
||||
emit_3("lt_int", check, i, len)
|
||||
emit_jump_cond("jump_false", check, done_label)
|
||||
emit_3("load_index", item, arr_slot, i)
|
||||
emit_3("eq_int", arity_is_zero, fn_arity, zero)
|
||||
emit_jump_cond("jump_false", arity_is_zero, call_one_label)
|
||||
emit_3("frame", f, fn_slot, 0)
|
||||
emit_3("setarg", f, 0, null_s)
|
||||
emit_2("invoke", f, val)
|
||||
emit_jump(call_done_label)
|
||||
emit_label(call_one_label)
|
||||
emit_3("eq_int", arity_is_one, fn_arity, one)
|
||||
emit_jump_cond("jump_false", arity_is_one, call_two_label)
|
||||
emit_3("frame", f, fn_slot, 1)
|
||||
@@ -1227,6 +1301,7 @@ var mcode = function(ast) {
|
||||
var fn_slot = args.fn
|
||||
var init_slot = args.init
|
||||
var rev_slot = args.rev
|
||||
var fn_arity = alloc_slot()
|
||||
var len = alloc_slot()
|
||||
var acc = alloc_slot()
|
||||
var i = alloc_slot()
|
||||
@@ -1244,9 +1319,10 @@ var mcode = function(ast) {
|
||||
var d4 = null
|
||||
var r = null
|
||||
emit_2("length", len, arr_slot)
|
||||
emit_2("length", fn_arity, fn_slot)
|
||||
emit_2("int", zero, 0)
|
||||
emit_2("int", one, 1)
|
||||
r = {acc: acc, i: i, arr: arr_slot, fn: fn_slot, len: len}
|
||||
r = {acc: acc, i: i, arr: arr_slot, fn: fn_slot, len: len, fn_arity: fn_arity}
|
||||
if (nargs == 2) {
|
||||
null_label = gen_label("reduce_null")
|
||||
d1 = gen_label("reduce_d1")
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
|
||||
#define BOOTSTRAP_MCODE "boot/bootstrap.cm.mcode"
|
||||
#define ENGINE_SRC "internal/engine.cm"
|
||||
#define ENGINE_CACHE_VERSION "engine-cache-v2"
|
||||
#define CELL_SHOP_DIR ".cell"
|
||||
#define CELL_CORE_DIR "packages/core"
|
||||
|
||||
@@ -223,18 +222,7 @@ static char *try_engine_cache(size_t *out_size) {
|
||||
char *src = load_core_file(ENGINE_SRC, &src_size);
|
||||
if (!src) return NULL;
|
||||
|
||||
size_t ver_len = strlen(ENGINE_CACHE_VERSION);
|
||||
size_t salted_size = src_size + 1 + ver_len;
|
||||
char *salted = malloc(salted_size);
|
||||
if (!salted) {
|
||||
free(src);
|
||||
return NULL;
|
||||
}
|
||||
memcpy(salted, src, src_size);
|
||||
salted[src_size] = '\n';
|
||||
memcpy(salted + src_size + 1, ENGINE_CACHE_VERSION, ver_len);
|
||||
char *hex = compute_blake2_hex(salted, salted_size);
|
||||
free(salted);
|
||||
char *hex = compute_blake2_hex(src, src_size);
|
||||
free(src);
|
||||
if (!hex) return NULL;
|
||||
char *cpath = build_cache_path(hex);
|
||||
|
||||
@@ -85,9 +85,6 @@ static JSValue *mach_materialize_cpool(JSContext *ctx, MachCPoolEntry *entries,
|
||||
static int mach_check_call_arity(JSContext *ctx, JSFunction *fn, int argc) {
|
||||
if (unlikely(fn->length >= 0 && argc > fn->length)) {
|
||||
char buf[KEY_GET_STR_BUF_SIZE];
|
||||
fprintf(stderr, "[arity-mach] callee=%s expected=%d got=%d\n",
|
||||
JS_KeyGetStr(ctx, buf, KEY_GET_STR_BUF_SIZE, fn->name),
|
||||
fn->length, argc);
|
||||
JS_RaiseDisrupt(ctx, "too many arguments for %s: expected %d, got %d",
|
||||
JS_KeyGetStr(ctx, buf, KEY_GET_STR_BUF_SIZE, fn->name), fn->length, argc);
|
||||
return 0;
|
||||
@@ -2183,13 +2180,8 @@ vm_dispatch:
|
||||
int c_argc = (nr >= 2) ? nr - 2 : 0;
|
||||
JSValue fn_val = fr->function;
|
||||
JSFunction *fn = JS_VALUE_GET_FUNCTION(fn_val);
|
||||
if (!mach_check_call_arity(ctx, fn, c_argc)) {
|
||||
fprintf(stderr, "[arity-mach] caller=%s file=%s pc=%u op=invoke argc=%d\n",
|
||||
code->name_cstr ? code->name_cstr : "?",
|
||||
code->filename_cstr ? code->filename_cstr : "?",
|
||||
(unsigned)(pc > 0 ? pc - 1 : 0), c_argc);
|
||||
if (!mach_check_call_arity(ctx, fn, c_argc))
|
||||
goto disrupt;
|
||||
}
|
||||
|
||||
if (fn->kind == JS_FUNC_KIND_REGISTER) {
|
||||
/* Register function: switch frames inline (fast path) */
|
||||
@@ -2261,13 +2253,8 @@ vm_dispatch:
|
||||
int c_argc = (nr >= 2) ? nr - 2 : 0;
|
||||
JSValue fn_val = fr->function;
|
||||
JSFunction *fn = JS_VALUE_GET_FUNCTION(fn_val);
|
||||
if (!mach_check_call_arity(ctx, fn, c_argc)) {
|
||||
fprintf(stderr, "[arity-mach] caller=%s file=%s pc=%u op=goinvoke argc=%d\n",
|
||||
code->name_cstr ? code->name_cstr : "?",
|
||||
code->filename_cstr ? code->filename_cstr : "?",
|
||||
(unsigned)(pc > 0 ? pc - 1 : 0), c_argc);
|
||||
if (!mach_check_call_arity(ctx, fn, c_argc))
|
||||
goto disrupt;
|
||||
}
|
||||
|
||||
if (fn->kind == JS_FUNC_KIND_REGISTER) {
|
||||
JSCodeRegister *fn_code = JS_VALUE_GET_CODE(fn->u.cell.code)->u.reg.code;
|
||||
|
||||
@@ -771,9 +771,6 @@ void cell_rt_signal_tail_call(JSContext *ctx, void *fp, int64_t frame_slot) {
|
||||
static int cell_check_call_arity(JSContext *ctx, JSFunction *fn, int argc) {
|
||||
if (unlikely(fn->length >= 0 && argc > fn->length)) {
|
||||
char buf[KEY_GET_STR_BUF_SIZE];
|
||||
fprintf(stderr, "[arity-qbe] callee=%s expected=%d got=%d\n",
|
||||
JS_KeyGetStr(ctx, buf, KEY_GET_STR_BUF_SIZE, fn->name),
|
||||
fn->length, argc);
|
||||
JS_RaiseDisrupt(ctx, "too many arguments for %s: expected %d, got %d",
|
||||
JS_KeyGetStr(ctx, buf, KEY_GET_STR_BUF_SIZE, fn->name),
|
||||
fn->length, argc);
|
||||
|
||||
135
source/runtime.c
135
source/runtime.c
@@ -4736,6 +4736,11 @@ JSValue JS_CallInternal (JSContext *ctx, JSValue func_obj, JSValue this_obj,
|
||||
if (!JS_IsFunction (func_obj))
|
||||
return JS_RaiseDisrupt (ctx, "not a function");
|
||||
JSFunction *f = JS_VALUE_GET_FUNCTION (func_obj);
|
||||
if (unlikely (f->length >= 0 && argc > f->length)) {
|
||||
char buf[KEY_GET_STR_BUF_SIZE];
|
||||
return JS_RaiseDisrupt (ctx, "too many arguments for %s: expected %d, got %d",
|
||||
JS_KeyGetStr (ctx, buf, KEY_GET_STR_BUF_SIZE, f->name), f->length, argc);
|
||||
}
|
||||
switch (f->kind) {
|
||||
case JS_FUNC_KIND_C:
|
||||
case JS_FUNC_KIND_C_DATA:
|
||||
@@ -4750,6 +4755,16 @@ JSValue JS_CallInternal (JSContext *ctx, JSValue func_obj, JSValue this_obj,
|
||||
}
|
||||
}
|
||||
|
||||
/* Call helper used by runtime callback intrinsics.
|
||||
Caps argc to function arity so helper callbacks never rely on over-arity calls. */
|
||||
static inline JSValue js_call_internal_capped (JSContext *ctx, JSValue func_obj, JSValue this_obj,
|
||||
int argc, JSValue *argv) {
|
||||
JSFunction *f = JS_VALUE_GET_FUNCTION (func_obj);
|
||||
if (f->length >= 0 && argc > f->length)
|
||||
argc = f->length;
|
||||
return JS_CallInternal (ctx, func_obj, this_obj, argc, argc > 0 ? argv : NULL, 0);
|
||||
}
|
||||
|
||||
JSValue JS_Call (JSContext *ctx, JSValue func_obj, JSValue this_obj, int argc, JSValue *argv) {
|
||||
if (js_poll_interrupts (ctx)) return JS_EXCEPTION;
|
||||
if (unlikely (!JS_IsFunction (func_obj)))
|
||||
@@ -8245,7 +8260,7 @@ static JSValue js_cell_array (JSContext *ctx, JSValue this_val, int argc, JSValu
|
||||
MAP_STORE (val);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
} else if (arity == 1) {
|
||||
if (reverse) {
|
||||
for (int i = len - 1; i >= 0; i--) {
|
||||
arr = JS_VALUE_GET_ARRAY (arg0_ref.val);
|
||||
@@ -8267,6 +8282,26 @@ static JSValue js_cell_array (JSContext *ctx, JSValue this_val, int argc, JSValu
|
||||
MAP_STORE (val);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (reverse) {
|
||||
for (int i = len - 1; i >= 0; i--) {
|
||||
arr = JS_VALUE_GET_ARRAY (arg0_ref.val);
|
||||
if (i >= (int)arr->len) continue;
|
||||
JSValue val = JS_CallInternal (ctx, arg1_ref.val, JS_NULL, 0, NULL, 0);
|
||||
if (JS_IsException (val)) { MAP_ERR (); }
|
||||
if (!JS_IsNull (exit_val) && js_strict_eq (ctx, val, exit_val)) break;
|
||||
MAP_STORE (val);
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < len; i++) {
|
||||
arr = JS_VALUE_GET_ARRAY (arg0_ref.val);
|
||||
if (i >= (int)arr->len) break;
|
||||
JSValue val = JS_CallInternal (ctx, arg1_ref.val, JS_NULL, 0, NULL, 0);
|
||||
if (JS_IsException (val)) { MAP_ERR (); }
|
||||
if (!JS_IsNull (exit_val) && js_strict_eq (ctx, val, exit_val)) break;
|
||||
MAP_STORE (val);
|
||||
}
|
||||
}
|
||||
}
|
||||
#undef MAP_STORE
|
||||
#undef MAP_ERR
|
||||
@@ -8626,6 +8661,7 @@ static JSValue js_cell_array_reduce (JSContext *ctx, JSValue this_val, int argc,
|
||||
|
||||
JSArray *arr = JS_VALUE_GET_ARRAY (argv[0]);
|
||||
word_t len = arr->len;
|
||||
JSValue fn = argv[1];
|
||||
|
||||
int reverse = argc > 3 && JS_ToBool (ctx, argv[3]);
|
||||
JSGCRef acc_ref;
|
||||
@@ -8642,7 +8678,7 @@ static JSValue js_cell_array_reduce (JSContext *ctx, JSValue this_val, int argc,
|
||||
if (i - 1 >= arr->len) continue;
|
||||
JSValue args[2] = { acc, arr->values[i - 1] };
|
||||
JS_PUSH_VALUE (ctx, acc);
|
||||
JSValue new_acc = JS_CallInternal (ctx, argv[1], JS_NULL, 2, args, 0);
|
||||
JSValue new_acc = js_call_internal_capped (ctx, fn, JS_NULL, 2, args);
|
||||
JS_POP_VALUE (ctx, acc);
|
||||
if (JS_IsException (new_acc)) return JS_EXCEPTION;
|
||||
acc = new_acc;
|
||||
@@ -8654,7 +8690,7 @@ static JSValue js_cell_array_reduce (JSContext *ctx, JSValue this_val, int argc,
|
||||
if (i >= arr->len) break;
|
||||
JSValue args[2] = { acc, arr->values[i] };
|
||||
JS_PUSH_VALUE (ctx, acc);
|
||||
JSValue new_acc = JS_CallInternal (ctx, argv[1], JS_NULL, 2, args, 0);
|
||||
JSValue new_acc = js_call_internal_capped (ctx, fn, JS_NULL, 2, args);
|
||||
JS_POP_VALUE (ctx, acc);
|
||||
if (JS_IsException (new_acc)) return JS_EXCEPTION;
|
||||
acc = new_acc;
|
||||
@@ -8670,7 +8706,7 @@ static JSValue js_cell_array_reduce (JSContext *ctx, JSValue this_val, int argc,
|
||||
if (i - 1 >= arr->len) continue;
|
||||
JSValue args[2] = { acc, arr->values[i - 1] };
|
||||
JS_PUSH_VALUE (ctx, acc);
|
||||
JSValue new_acc = JS_CallInternal (ctx, argv[1], JS_NULL, 2, args, 0);
|
||||
JSValue new_acc = js_call_internal_capped (ctx, fn, JS_NULL, 2, args);
|
||||
JS_POP_VALUE (ctx, acc);
|
||||
if (JS_IsException (new_acc)) return JS_EXCEPTION;
|
||||
acc = new_acc;
|
||||
@@ -8681,7 +8717,7 @@ static JSValue js_cell_array_reduce (JSContext *ctx, JSValue this_val, int argc,
|
||||
if (i >= arr->len) break;
|
||||
JSValue args[2] = { acc, arr->values[i] };
|
||||
JS_PUSH_VALUE (ctx, acc);
|
||||
JSValue new_acc = JS_CallInternal (ctx, argv[1], JS_NULL, 2, args, 0);
|
||||
JSValue new_acc = js_call_internal_capped (ctx, fn, JS_NULL, 2, args);
|
||||
JS_POP_VALUE (ctx, acc);
|
||||
if (JS_IsException (new_acc)) return JS_EXCEPTION;
|
||||
acc = new_acc;
|
||||
@@ -8706,23 +8742,14 @@ static JSValue js_cell_array_for (JSContext *ctx, JSValue this_val, int argc, JS
|
||||
int reverse = argc > 2 && JS_ToBool (ctx, argv[2]);
|
||||
JSValue exit_val = argc > 3 ? argv[3] : JS_NULL;
|
||||
|
||||
/* Determine function arity */
|
||||
int arity = ((JSFunction *)JS_VALUE_GET_FUNCTION (argv[1]))->length;
|
||||
|
||||
if (reverse) {
|
||||
for (word_t i = len; i > 0; i--) {
|
||||
arr = JS_VALUE_GET_ARRAY (argv[0]);
|
||||
if (i - 1 >= arr->len) continue;
|
||||
JSValue result;
|
||||
if (arity == 1) {
|
||||
JSValue item = arr->values[i - 1];
|
||||
result = JS_CallInternal (ctx, argv[1], JS_NULL, 1, &item, 0);
|
||||
} else {
|
||||
JSValue args[2];
|
||||
args[0] = arr->values[i - 1];
|
||||
args[1] = JS_NewInt32 (ctx, (int32_t)(i - 1));
|
||||
result = JS_CallInternal (ctx, argv[1], JS_NULL, 2, args, 0);
|
||||
}
|
||||
JSValue args[2];
|
||||
args[0] = arr->values[i - 1];
|
||||
args[1] = JS_NewInt32 (ctx, (int32_t)(i - 1));
|
||||
JSValue result = js_call_internal_capped (ctx, argv[1], JS_NULL, 2, args);
|
||||
if (JS_IsException (result)) return JS_EXCEPTION;
|
||||
if (!JS_IsNull (exit_val) && js_strict_eq (ctx, result, exit_val))
|
||||
return result;
|
||||
@@ -8731,16 +8758,10 @@ static JSValue js_cell_array_for (JSContext *ctx, JSValue this_val, int argc, JS
|
||||
for (word_t i = 0; i < len; i++) {
|
||||
arr = JS_VALUE_GET_ARRAY (argv[0]);
|
||||
if (i >= arr->len) break;
|
||||
JSValue result;
|
||||
if (arity == 1) {
|
||||
JSValue item = arr->values[i];
|
||||
result = JS_CallInternal (ctx, argv[1], JS_NULL, 1, &item, 0);
|
||||
} else {
|
||||
JSValue args[2];
|
||||
args[0] = arr->values[i];
|
||||
args[1] = JS_NewInt32 (ctx, (int32_t)i);
|
||||
result = JS_CallInternal (ctx, argv[1], JS_NULL, 2, args, 0);
|
||||
}
|
||||
JSValue args[2];
|
||||
args[0] = arr->values[i];
|
||||
args[1] = JS_NewInt32 (ctx, (int32_t)i);
|
||||
JSValue result = js_call_internal_capped (ctx, argv[1], JS_NULL, 2, args);
|
||||
if (JS_IsException (result)) return JS_EXCEPTION;
|
||||
if (!JS_IsNull (exit_val) && js_strict_eq (ctx, result, exit_val))
|
||||
return result;
|
||||
@@ -8787,47 +8808,23 @@ static JSValue js_cell_array_find (JSContext *ctx, JSValue this_val, int argc, J
|
||||
}
|
||||
|
||||
/* Use function predicate — re-chase after each call */
|
||||
int arity = ((JSFunction *)JS_VALUE_GET_FUNCTION (argv[1]))->length;
|
||||
|
||||
if (arity == 2) {
|
||||
if (reverse) {
|
||||
for (int32_t i = from; i >= 0; i--) {
|
||||
arr = JS_VALUE_GET_ARRAY (argv[0]);
|
||||
if ((word_t)i >= arr->len) continue;
|
||||
JSValue args[2] = { arr->values[i], JS_NewInt32 (ctx, i) };
|
||||
JSValue result = JS_CallInternal (ctx, argv[1], JS_NULL, 2, args, 0);
|
||||
if (JS_IsException (result)) return JS_EXCEPTION;
|
||||
if (JS_ToBool (ctx, result)) return JS_NewInt32 (ctx, i);
|
||||
}
|
||||
} else {
|
||||
for (word_t i = (word_t)from; i < len; i++) {
|
||||
arr = JS_VALUE_GET_ARRAY (argv[0]);
|
||||
if (i >= arr->len) break;
|
||||
JSValue args[2] = { arr->values[i], JS_NewInt32 (ctx, (int32_t)i) };
|
||||
JSValue result = JS_CallInternal (ctx, argv[1], JS_NULL, 2, args, 0);
|
||||
if (JS_IsException (result)) return JS_EXCEPTION;
|
||||
if (JS_ToBool (ctx, result)) return JS_NewInt32 (ctx, (int32_t)i);
|
||||
}
|
||||
if (reverse) {
|
||||
for (int32_t i = from; i >= 0; i--) {
|
||||
arr = JS_VALUE_GET_ARRAY (argv[0]);
|
||||
if ((word_t)i >= arr->len) continue;
|
||||
JSValue args[2] = { arr->values[i], JS_NewInt32 (ctx, i) };
|
||||
JSValue result = js_call_internal_capped (ctx, argv[1], JS_NULL, 2, args);
|
||||
if (JS_IsException (result)) return JS_EXCEPTION;
|
||||
if (JS_ToBool (ctx, result)) return JS_NewInt32 (ctx, i);
|
||||
}
|
||||
} else {
|
||||
if (reverse) {
|
||||
for (int32_t i = from; i >= 0; i--) {
|
||||
arr = JS_VALUE_GET_ARRAY (argv[0]);
|
||||
if ((word_t)i >= arr->len) continue;
|
||||
JSValue item = arr->values[i];
|
||||
JSValue result = JS_CallInternal (ctx, argv[1], JS_NULL, 1, &item, 0);
|
||||
if (JS_IsException (result)) return JS_EXCEPTION;
|
||||
if (JS_ToBool (ctx, result)) return JS_NewInt32 (ctx, i);
|
||||
}
|
||||
} else {
|
||||
for (word_t i = (word_t)from; i < len; i++) {
|
||||
arr = JS_VALUE_GET_ARRAY (argv[0]);
|
||||
if (i >= arr->len) break;
|
||||
JSValue item = arr->values[i];
|
||||
JSValue result = JS_CallInternal (ctx, argv[1], JS_NULL, 1, &item, 0);
|
||||
if (JS_IsException (result)) return JS_EXCEPTION;
|
||||
if (JS_ToBool (ctx, result)) return JS_NewInt32 (ctx, (int32_t)i);
|
||||
}
|
||||
for (word_t i = (word_t)from; i < len; i++) {
|
||||
arr = JS_VALUE_GET_ARRAY (argv[0]);
|
||||
if (i >= arr->len) break;
|
||||
JSValue args[2] = { arr->values[i], JS_NewInt32 (ctx, (int32_t)i) };
|
||||
JSValue result = js_call_internal_capped (ctx, argv[1], JS_NULL, 2, args);
|
||||
if (JS_IsException (result)) return JS_EXCEPTION;
|
||||
if (JS_ToBool (ctx, result)) return JS_NewInt32 (ctx, (int32_t)i);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9264,7 +9261,7 @@ static JSValue js_cell_object (JSContext *ctx, JSValue this_val, int argc, JSVal
|
||||
val = JS_TRUE;
|
||||
} else if (is_func) {
|
||||
JSValue arg_key = key;
|
||||
val = JS_CallInternal (ctx, func_ref.val, JS_NULL, 1, &arg_key, 0);
|
||||
val = js_call_internal_capped (ctx, func_ref.val, JS_NULL, 1, &arg_key);
|
||||
if (JS_IsException (val)) {
|
||||
JS_PopGCRef (ctx, &result_ref);
|
||||
JS_PopGCRef (ctx, &func_ref);
|
||||
@@ -11317,7 +11314,7 @@ static JSValue js_cell_every (JSContext *ctx, JSValue this_val, int argc, JSValu
|
||||
JSArray *arr = JS_VALUE_GET_ARRAY (argv[0]);
|
||||
for (int i = 0; i < arr->len; i++) {
|
||||
JSValue elem = arr->values[i];
|
||||
JSValue r = JS_CallInternal (ctx, argv[1], JS_NULL, 1, &elem, 0);
|
||||
JSValue r = js_call_internal_capped (ctx, argv[1], JS_NULL, 1, &elem);
|
||||
arr = JS_VALUE_GET_ARRAY (argv[0]);
|
||||
if (JS_IsException (r)) return r;
|
||||
if (!JS_ToBool (ctx, r)) return JS_FALSE;
|
||||
|
||||
Reference in New Issue
Block a user