optimize frames; remove trampoline

This commit is contained in:
2026-02-18 22:37:48 -06:00
parent 27ca008f18
commit e004b2c472
14 changed files with 318 additions and 91 deletions

View File

@@ -10514,15 +10514,46 @@ JSValue JS_CellCall (JSContext *ctx, JSValue fn, JSValue this_val, JSValue args)
return js_cell_call (ctx, JS_NULL, argc, argv);
}
static int js_cell_read_number_strict (JSValue val, double *out) {
uint32_t tag = JS_VALUE_GET_TAG (val);
if (tag == JS_TAG_INT) {
*out = (double)JS_VALUE_GET_INT (val);
return 0;
}
if (JS_TAG_IS_FLOAT64 (tag)) {
*out = JS_VALUE_GET_FLOAT64 (val);
return 0;
}
return -1;
}
static JSValue js_cell_number_from_double (JSContext *ctx, double d) {
if (d >= INT32_MIN && d <= INT32_MAX) {
int32_t i = (int32_t)d;
if ((double)i == d)
return JS_NewInt32 (ctx, i);
}
return JS_NewFloat64 (ctx, d);
}
/* C API: modulo(a, b) - modulo operation */
JSValue JS_CellModulo (JSContext *ctx, JSValue a, JSValue b) {
JSValue argv[2] = { a, b };
return js_cell_modulo (ctx, JS_NULL, 2, argv);
double dividend, divisor;
if (js_cell_read_number_strict (a, &dividend) < 0) return JS_NULL;
if (js_cell_read_number_strict (b, &divisor) < 0) return JS_NULL;
if (isnan (dividend) || isnan (divisor)) return JS_NULL;
if (divisor == 0.0) return JS_NULL;
if (dividend == 0.0) return JS_NewFloat64 (ctx, 0.0);
return js_cell_number_from_double (ctx,
dividend - (divisor * floor (dividend / divisor)));
}
/* C API: neg(val) - negate number */
JSValue JS_CellNeg (JSContext *ctx, JSValue val) {
return js_cell_neg (ctx, JS_NULL, 1, &val);
double d;
if (js_cell_read_number_strict (val, &d) < 0) return JS_NULL;
if (isnan (d)) return JS_NULL;
return js_cell_number_from_double (ctx, -d);
}
/* C API: not(val) - logical not */
@@ -10647,60 +10678,86 @@ JSValue JS_CellNumber (JSContext *ctx, JSValue val) {
/* C API: abs(num) - absolute value */
JSValue JS_CellAbs (JSContext *ctx, JSValue num) {
return js_cell_number_abs (ctx, JS_NULL, 1, &num);
double d;
if (js_cell_read_number_strict (num, &d) < 0) return JS_NULL;
return js_cell_number_from_double (ctx, fabs (d));
}
/* C API: sign(num) - sign of number (-1, 0, 1) */
JSValue JS_CellSign (JSContext *ctx, JSValue num) {
return js_cell_number_sign (ctx, JS_NULL, 1, &num);
double d;
if (js_cell_read_number_strict (num, &d) < 0) return JS_NULL;
if (d < 0) return JS_NewInt32 (ctx, -1);
if (d > 0) return JS_NewInt32 (ctx, 1);
return JS_NewInt32 (ctx, 0);
}
/* C API: floor(num) - floor */
JSValue JS_CellFloor (JSContext *ctx, JSValue num) {
return js_cell_number_floor (ctx, JS_NULL, 1, &num);
double d;
if (js_cell_read_number_strict (num, &d) < 0) return JS_NULL;
return js_cell_number_from_double (ctx, floor (d));
}
/* C API: ceiling(num) - ceiling */
JSValue JS_CellCeiling (JSContext *ctx, JSValue num) {
return js_cell_number_ceiling (ctx, JS_NULL, 1, &num);
double d;
if (js_cell_read_number_strict (num, &d) < 0) return JS_NULL;
return js_cell_number_from_double (ctx, ceil (d));
}
/* C API: round(num) - round to nearest integer */
JSValue JS_CellRound (JSContext *ctx, JSValue num) {
return js_cell_number_round (ctx, JS_NULL, 1, &num);
double d;
if (js_cell_read_number_strict (num, &d) < 0) return JS_NULL;
return js_cell_number_from_double (ctx, round (d));
}
/* C API: trunc(num) - truncate towards zero */
JSValue JS_CellTrunc (JSContext *ctx, JSValue num) {
return js_cell_number_trunc (ctx, JS_NULL, 1, &num);
double d;
if (js_cell_read_number_strict (num, &d) < 0) return JS_NULL;
return js_cell_number_from_double (ctx, trunc (d));
}
/* C API: whole(num) - integer part */
JSValue JS_CellWhole (JSContext *ctx, JSValue num) {
return js_cell_number_whole (ctx, JS_NULL, 1, &num);
double d;
if (js_cell_read_number_strict (num, &d) < 0) return JS_NULL;
return js_cell_number_from_double (ctx, trunc (d));
}
/* C API: fraction(num) - fractional part */
JSValue JS_CellFraction (JSContext *ctx, JSValue num) {
return js_cell_number_fraction (ctx, JS_NULL, 1, &num);
double d;
if (js_cell_read_number_strict (num, &d) < 0) return JS_NULL;
return js_cell_number_from_double (ctx, d - trunc (d));
}
/* C API: min(a, b) - minimum of two numbers */
JSValue JS_CellMin (JSContext *ctx, JSValue a, JSValue b) {
JSValue argv[2] = { a, b };
return js_cell_number_min (ctx, JS_NULL, 2, argv);
double da, db;
if (js_cell_read_number_strict (a, &da) < 0) return JS_NULL;
if (js_cell_read_number_strict (b, &db) < 0) return JS_NULL;
return js_cell_number_from_double (ctx, da < db ? da : db);
}
/* C API: max(a, b) - maximum of two numbers */
JSValue JS_CellMax (JSContext *ctx, JSValue a, JSValue b) {
JSValue argv[2] = { a, b };
return js_cell_number_max (ctx, JS_NULL, 2, argv);
double da, db;
if (js_cell_read_number_strict (a, &da) < 0) return JS_NULL;
if (js_cell_read_number_strict (b, &db) < 0) return JS_NULL;
return js_cell_number_from_double (ctx, da > db ? da : db);
}
/* C API: remainder(a, b) - remainder after division */
JSValue JS_CellRemainder (JSContext *ctx, JSValue a, JSValue b) {
JSValue argv[2] = { a, b };
return js_cell_number_remainder (ctx, JS_NULL, 2, argv);
double dividend, divisor;
if (js_cell_read_number_strict (a, &dividend) < 0) return JS_NULL;
if (js_cell_read_number_strict (b, &divisor) < 0) return JS_NULL;
if (divisor == 0.0) return JS_NULL;
return js_cell_number_from_double (ctx,
dividend - (trunc (dividend / divisor) * divisor));
}
/* Object functions */
@@ -11374,7 +11431,7 @@ static void JS_AddIntrinsicBaseObjects (JSContext *ctx) {
js_set_global_cfunc(ctx, "filter", js_cell_array_filter, 2);
js_set_global_cfunc(ctx, "sort", js_cell_array_sort, 2);
/* Number utility functions */
/* Number intrinsics: direct calls lower to mcode; globals remain for first-class use. */
js_set_global_cfunc(ctx, "whole", js_cell_number_whole, 1);
js_set_global_cfunc(ctx, "fraction", js_cell_number_fraction, 1);
js_set_global_cfunc(ctx, "floor", js_cell_number_floor, 2);