binary logic only works on ints; returns null otherwise
This commit is contained in:
201
source/quickjs.c
201
source/quickjs.c
@@ -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--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user