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);
|
||||
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 */
|
||||
if (tag1 == JS_TAG_SHORT_BIG_INT && tag2 == JS_TAG_SHORT_BIG_INT) {
|
||||
js_slimb_t v1, v2;
|
||||
@@ -12948,6 +12961,9 @@ static no_inline __exception int js_binary_arith_slow(JSContext *ctx, JSValue *s
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
op1 = JS_ToNumericFree(ctx, op1);
|
||||
if (JS_IsException(op1)) {
|
||||
JS_FreeValue(ctx, op2);
|
||||
@@ -13195,167 +13211,6 @@ static no_inline __exception int js_add_slow(JSContext *ctx, JSValue *sp)
|
||||
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. */
|
||||
static JSBigInt *JS_ToBigIntBuf(JSContext *ctx, JSBigIntBuf *buf1,
|
||||
JSValue op1)
|
||||
@@ -17309,9 +17164,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
|
||||
sp[-2] = JS_NewInt32(ctx, v1 << v2);
|
||||
sp--;
|
||||
} else {
|
||||
sf->cur_pc = pc;
|
||||
if (js_binary_logic_slow(ctx, sp, opcode))
|
||||
goto exception;
|
||||
sp[-2] = JS_NULL;
|
||||
sp--;
|
||||
}
|
||||
}
|
||||
@@ -17330,9 +17183,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
|
||||
v2);
|
||||
sp--;
|
||||
} else {
|
||||
sf->cur_pc = pc;
|
||||
if (js_shr_slow(ctx, sp))
|
||||
goto exception;
|
||||
sp[-2] = JS_NULL;
|
||||
sp--;
|
||||
}
|
||||
}
|
||||
@@ -17350,9 +17201,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
|
||||
(int)JS_VALUE_GET_INT(op1) >> v2);
|
||||
sp--;
|
||||
} else {
|
||||
sf->cur_pc = pc;
|
||||
if (js_binary_logic_slow(ctx, sp, opcode))
|
||||
goto exception;
|
||||
sp[-2] = JS_NULL;
|
||||
sp--;
|
||||
}
|
||||
}
|
||||
@@ -17368,9 +17217,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
|
||||
JS_VALUE_GET_INT(op2));
|
||||
sp--;
|
||||
} else {
|
||||
sf->cur_pc = pc;
|
||||
if (js_binary_logic_slow(ctx, sp, opcode))
|
||||
goto exception;
|
||||
sp[-2] = JS_NULL;
|
||||
sp--;
|
||||
}
|
||||
}
|
||||
@@ -17386,9 +17233,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
|
||||
JS_VALUE_GET_INT(op2));
|
||||
sp--;
|
||||
} else {
|
||||
sf->cur_pc = pc;
|
||||
if (js_binary_logic_slow(ctx, sp, opcode))
|
||||
goto exception;
|
||||
sp[-2] = JS_NULL;
|
||||
sp--;
|
||||
}
|
||||
}
|
||||
@@ -17404,9 +17249,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
|
||||
JS_VALUE_GET_INT(op2));
|
||||
sp--;
|
||||
} else {
|
||||
sf->cur_pc = pc;
|
||||
if (js_binary_logic_slow(ctx, sp, opcode))
|
||||
goto exception;
|
||||
sp[-2] = JS_NULL;
|
||||
sp--;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user