From 8e97f24044102b5793524ab22b037ca75f536319 Mon Sep 17 00:00:00 2001 From: Fabrice Bellard Date: Wed, 3 Jun 2026 17:25:16 +0200 Subject: [PATCH] faster add, sub and mul for mixed integer floating point operands --- quickjs.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 55 insertions(+), 8 deletions(-) diff --git a/quickjs.c b/quickjs.c index f694fdf..2e8b3da 100644 --- a/quickjs.c +++ b/quickjs.c @@ -19733,9 +19733,24 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, sp[-2] = JS_NewInt32(ctx, r); } sp--; - } else if (JS_VALUE_IS_BOTH_FLOAT(op1, op2)) { - sp[-2] = __JS_NewFloat64(ctx, JS_VALUE_GET_FLOAT64(op1) + - JS_VALUE_GET_FLOAT64(op2)); + } else if (JS_TAG_IS_FLOAT64(JS_VALUE_GET_TAG(op1)) || + JS_TAG_IS_FLOAT64(JS_VALUE_GET_TAG(op2))) { + double d1, d2; + if (JS_TAG_IS_FLOAT64(JS_VALUE_GET_TAG(op1))) { + d1 = JS_VALUE_GET_FLOAT64(op1); + } else if (JS_VALUE_GET_TAG(op1) == JS_TAG_INT) { + d1 = JS_VALUE_GET_INT(op1); + } else { + goto add_slow_case; + } + if (JS_TAG_IS_FLOAT64(JS_VALUE_GET_TAG(op2))) { + d2 = JS_VALUE_GET_FLOAT64(op2); + } else if (JS_VALUE_GET_TAG(op2) == JS_TAG_INT) { + d2 = JS_VALUE_GET_INT(op2); + } else { + goto add_slow_case; + } + sp[-2] = __JS_NewFloat64(ctx, d1 + d2); sp--; } else if (JS_IsString(op1) && JS_IsString(op2)) { sp[-2] = JS_ConcatString(ctx, op1, op2); @@ -19743,6 +19758,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, if (JS_IsException(sp[-1])) goto exception; } else { + add_slow_case: sf->cur_pc = pc; if (js_add_slow(ctx, sp)) goto exception; @@ -19813,9 +19829,24 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, sp[-2] = JS_NewInt32(ctx, r); } sp--; - } else if (JS_VALUE_IS_BOTH_FLOAT(op1, op2)) { - sp[-2] = __JS_NewFloat64(ctx, JS_VALUE_GET_FLOAT64(op1) - - JS_VALUE_GET_FLOAT64(op2)); + } else if (JS_TAG_IS_FLOAT64(JS_VALUE_GET_TAG(op1)) || + JS_TAG_IS_FLOAT64(JS_VALUE_GET_TAG(op2))) { + double d1, d2; + if (JS_TAG_IS_FLOAT64(JS_VALUE_GET_TAG(op1))) { + d1 = JS_VALUE_GET_FLOAT64(op1); + } else if (JS_VALUE_GET_TAG(op1) == JS_TAG_INT) { + d1 = JS_VALUE_GET_INT(op1); + } else { + goto binary_arith_slow; + } + if (JS_TAG_IS_FLOAT64(JS_VALUE_GET_TAG(op2))) { + d2 = JS_VALUE_GET_FLOAT64(op2); + } else if (JS_VALUE_GET_TAG(op2) == JS_TAG_INT) { + d2 = JS_VALUE_GET_INT(op2); + } else { + goto binary_arith_slow; + } + sp[-2] = __JS_NewFloat64(ctx, d1 - d2); sp--; } else { goto binary_arith_slow; @@ -19845,8 +19876,24 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj, } sp[-2] = JS_NewInt32(ctx, r); sp--; - } else if (JS_VALUE_IS_BOTH_FLOAT(op1, op2)) { - d = JS_VALUE_GET_FLOAT64(op1) * JS_VALUE_GET_FLOAT64(op2); + } else if (JS_TAG_IS_FLOAT64(JS_VALUE_GET_TAG(op1)) || + JS_TAG_IS_FLOAT64(JS_VALUE_GET_TAG(op2))) { + double d1, d2; + if (JS_TAG_IS_FLOAT64(JS_VALUE_GET_TAG(op1))) { + d1 = JS_VALUE_GET_FLOAT64(op1); + } else if (JS_VALUE_GET_TAG(op1) == JS_TAG_INT) { + d1 = JS_VALUE_GET_INT(op1); + } else { + goto binary_arith_slow; + } + if (JS_TAG_IS_FLOAT64(JS_VALUE_GET_TAG(op2))) { + d2 = JS_VALUE_GET_FLOAT64(op2); + } else if (JS_VALUE_GET_TAG(op2) == JS_TAG_INT) { + d2 = JS_VALUE_GET_INT(op2); + } else { + goto binary_arith_slow; + } + d = d1 * d2; mul_fp_res: sp[-2] = __JS_NewFloat64(ctx, d); sp--;