binary logic only works on ints; returns null otherwise

This commit is contained in:
2025-06-17 12:54:20 -05:00
parent 9ecdaae7a7
commit 3459d85a82

View File

@@ -12904,6 +12904,19 @@ static no_inline __exception int js_binary_arith_slow(JSContext *ctx, JSValue *s
d2 = JS_VALUE_GET_FLOAT64(op2); d2 = JS_VALUE_GET_FLOAT64(op2);
goto handle_float64; goto handle_float64;
} }
if ((tag1 == JS_TAG_INT && tag2 == JS_TAG_FLOAT64) || (tag1 == JS_TAG_FLOAT64 && tag2 == JS_TAG_INT)) {
if(tag1 == JS_TAG_INT)
d1 = (double)JS_VALUE_GET_INT(op1);
else
d1 = JS_VALUE_GET_FLOAT64(op1);
if(tag2 == JS_TAG_INT)
d2 = (double)JS_VALUE_GET_INT(op2);
else
d2 = JS_VALUE_GET_FLOAT64(op2);
goto handle_float64;
}
/* fast path for short big int operations */ /* fast path for short big int operations */
if (tag1 == JS_TAG_SHORT_BIG_INT && tag2 == JS_TAG_SHORT_BIG_INT) { if (tag1 == JS_TAG_SHORT_BIG_INT && tag2 == JS_TAG_SHORT_BIG_INT) {
js_slimb_t v1, v2; js_slimb_t v1, v2;
@@ -12948,6 +12961,9 @@ static no_inline __exception int js_binary_arith_slow(JSContext *ctx, JSValue *s
} }
return 0; return 0;
} }
op1 = JS_ToNumericFree(ctx, op1); op1 = JS_ToNumericFree(ctx, op1);
if (JS_IsException(op1)) { if (JS_IsException(op1)) {
JS_FreeValue(ctx, op2); JS_FreeValue(ctx, op2);
@@ -13195,167 +13211,6 @@ static no_inline __exception int js_add_slow(JSContext *ctx, JSValue *sp)
return -1; return -1;
} }
static no_inline __exception int js_binary_logic_slow(JSContext *ctx,
JSValue *sp,
OPCodeEnum op)
{
JSValue op1, op2;
uint32_t tag1, tag2;
uint32_t v1, v2, r;
op1 = sp[-2];
op2 = sp[-1];
tag1 = JS_VALUE_GET_NORM_TAG(op1);
tag2 = JS_VALUE_GET_NORM_TAG(op2);
if (tag1 == JS_TAG_SHORT_BIG_INT && tag2 == JS_TAG_SHORT_BIG_INT) {
js_slimb_t v1, v2, v;
js_sdlimb_t vd;
v1 = JS_VALUE_GET_SHORT_BIG_INT(op1);
v2 = JS_VALUE_GET_SHORT_BIG_INT(op2);
/* bigint fast path */
switch(op) {
case OP_and:
v = v1 & v2;
break;
case OP_or:
v = v1 | v2;
break;
case OP_xor:
v = v1 ^ v2;
break;
case OP_sar:
if (v2 > (JS_LIMB_BITS - 1)) {
goto slow_big_int;
} else if (v2 < 0) {
if (v2 < -(JS_LIMB_BITS - 1))
goto slow_big_int;
v2 = -v2;
goto bigint_shl;
}
bigint_sar:
v = v1 >> v2;
break;
case OP_shl:
if (v2 > (JS_LIMB_BITS - 1)) {
goto slow_big_int;
} else if (v2 < 0) {
if (v2 < -(JS_LIMB_BITS - 1))
goto slow_big_int;
v2 = -v2;
goto bigint_sar;
}
bigint_shl:
vd = (js_dlimb_t)v1 << v2;
if (likely(vd >= JS_SHORT_BIG_INT_MIN &&
vd <= JS_SHORT_BIG_INT_MAX)) {
v = vd;
} else {
JSBigInt *r = js_bigint_new_di(ctx, vd);
if (!r)
goto exception;
sp[-2] = JS_MKPTR(JS_TAG_BIG_INT, r);
return 0;
}
break;
default:
abort();
}
sp[-2] = __JS_NewShortBigInt(ctx, v);
return 0;
}
op1 = JS_ToNumericFree(ctx, op1);
if (JS_IsException(op1)) {
JS_FreeValue(ctx, op2);
goto exception;
}
op2 = JS_ToNumericFree(ctx, op2);
if (JS_IsException(op2)) {
JS_FreeValue(ctx, op1);
goto exception;
}
tag1 = JS_VALUE_GET_TAG(op1);
tag2 = JS_VALUE_GET_TAG(op2);
if ((tag1 == JS_TAG_BIG_INT || tag1 == JS_TAG_SHORT_BIG_INT) &&
(tag2 == JS_TAG_BIG_INT || tag2 == JS_TAG_SHORT_BIG_INT)) {
JSBigInt *p1, *p2, *r;
JSBigIntBuf buf1, buf2;
slow_big_int:
if (JS_VALUE_GET_TAG(op1) == JS_TAG_SHORT_BIG_INT)
p1 = js_bigint_set_short(&buf1, op1);
else
p1 = JS_VALUE_GET_PTR(op1);
if (JS_VALUE_GET_TAG(op2) == JS_TAG_SHORT_BIG_INT)
p2 = js_bigint_set_short(&buf2, op2);
else
p2 = JS_VALUE_GET_PTR(op2);
switch(op) {
case OP_and:
case OP_or:
case OP_xor:
r = js_bigint_logic(ctx, p1, p2, op);
break;
case OP_shl:
case OP_sar:
{
js_slimb_t shift;
shift = js_bigint_get_si_sat(p2);
if (shift > INT32_MAX)
shift = INT32_MAX;
else if (shift < -INT32_MAX)
shift = -INT32_MAX;
if (op == OP_sar)
shift = -shift;
if (shift >= 0)
r = js_bigint_shl(ctx, p1, shift);
else
r = js_bigint_shr(ctx, p1, -shift);
}
break;
default:
abort();
}
JS_FreeValue(ctx, op1);
JS_FreeValue(ctx, op2);
if (!r)
goto exception;
sp[-2] = JS_CompactBigInt(ctx, r);
} else {
if (unlikely(JS_ToInt32Free(ctx, (int32_t *)&v1, op1))) {
JS_FreeValue(ctx, op2);
goto exception;
}
if (unlikely(JS_ToInt32Free(ctx, (int32_t *)&v2, op2)))
goto exception;
switch(op) {
case OP_shl:
r = v1 << (v2 & 0x1f);
break;
case OP_sar:
r = (int)v1 >> (v2 & 0x1f);
break;
case OP_and:
r = v1 & v2;
break;
case OP_or:
r = v1 | v2;
break;
case OP_xor:
r = v1 ^ v2;
break;
default:
abort();
}
sp[-2] = JS_NewInt32(ctx, r);
}
return 0;
exception:
sp[-2] = JS_UNDEFINED;
sp[-1] = JS_UNDEFINED;
return -1;
}
/* op1 must be a bigint or int. */ /* op1 must be a bigint or int. */
static JSBigInt *JS_ToBigIntBuf(JSContext *ctx, JSBigIntBuf *buf1, static JSBigInt *JS_ToBigIntBuf(JSContext *ctx, JSBigIntBuf *buf1,
JSValue op1) JSValue op1)
@@ -17309,9 +17164,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
sp[-2] = JS_NewInt32(ctx, v1 << v2); sp[-2] = JS_NewInt32(ctx, v1 << v2);
sp--; sp--;
} else { } else {
sf->cur_pc = pc; sp[-2] = JS_NULL;
if (js_binary_logic_slow(ctx, sp, opcode))
goto exception;
sp--; sp--;
} }
} }
@@ -17330,9 +17183,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
v2); v2);
sp--; sp--;
} else { } else {
sf->cur_pc = pc; sp[-2] = JS_NULL;
if (js_shr_slow(ctx, sp))
goto exception;
sp--; sp--;
} }
} }
@@ -17350,9 +17201,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
(int)JS_VALUE_GET_INT(op1) >> v2); (int)JS_VALUE_GET_INT(op1) >> v2);
sp--; sp--;
} else { } else {
sf->cur_pc = pc; sp[-2] = JS_NULL;
if (js_binary_logic_slow(ctx, sp, opcode))
goto exception;
sp--; sp--;
} }
} }
@@ -17368,9 +17217,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
JS_VALUE_GET_INT(op2)); JS_VALUE_GET_INT(op2));
sp--; sp--;
} else { } else {
sf->cur_pc = pc; sp[-2] = JS_NULL;
if (js_binary_logic_slow(ctx, sp, opcode))
goto exception;
sp--; sp--;
} }
} }
@@ -17386,9 +17233,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
JS_VALUE_GET_INT(op2)); JS_VALUE_GET_INT(op2));
sp--; sp--;
} else { } else {
sf->cur_pc = pc; sp[-2] = JS_NULL;
if (js_binary_logic_slow(ctx, sp, opcode))
goto exception;
sp--; sp--;
} }
} }
@@ -17404,9 +17249,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
JS_VALUE_GET_INT(op2)); JS_VALUE_GET_INT(op2));
sp--; sp--;
} else { } else {
sf->cur_pc = pc; sp[-2] = JS_NULL;
if (js_binary_logic_slow(ctx, sp, opcode))
goto exception;
sp--; sp--;
} }
} }