mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 05:57:45 +00:00
LibJS: Add fast paths for bitwise ops on 2x Int32 JS::Value
~9% speed-up on Kraken/stanford-crypto-aes.js :^)
This commit is contained in:
parent
1efe4b58aa
commit
0cb9c9e81e
2 changed files with 35 additions and 11 deletions
|
@ -1344,6 +1344,10 @@ ThrowCompletionOr<Value> less_than_equals(VM& vm, Value lhs, Value rhs)
|
|||
// BitwiseANDExpression : BitwiseANDExpression & EqualityExpression
|
||||
ThrowCompletionOr<Value> bitwise_and(VM& vm, Value lhs, Value rhs)
|
||||
{
|
||||
// OPTIMIZATION: Fast path when both values are Int32.
|
||||
if (lhs.is_int32() && rhs.is_int32())
|
||||
return Value(lhs.as_i32() & rhs.as_i32());
|
||||
|
||||
// 13.15.3 ApplyStringOrNumericBinaryOperator ( lval, opText, rval ), https://tc39.es/ecma262/#sec-applystringornumericbinaryoperator
|
||||
// 1-2, 6. N/A.
|
||||
|
||||
|
@ -1377,6 +1381,10 @@ ThrowCompletionOr<Value> bitwise_and(VM& vm, Value lhs, Value rhs)
|
|||
// BitwiseORExpression : BitwiseORExpression | BitwiseXORExpression
|
||||
ThrowCompletionOr<Value> bitwise_or(VM& vm, Value lhs, Value rhs)
|
||||
{
|
||||
// OPTIMIZATION: Fast path when both values are Int32.
|
||||
if (lhs.is_int32() && rhs.is_int32())
|
||||
return Value(lhs.as_i32() | rhs.as_i32());
|
||||
|
||||
// 13.15.3 ApplyStringOrNumericBinaryOperator ( lval, opText, rval ), https://tc39.es/ecma262/#sec-applystringornumericbinaryoperator
|
||||
// 1-2, 6. N/A.
|
||||
|
||||
|
@ -1414,6 +1422,10 @@ ThrowCompletionOr<Value> bitwise_or(VM& vm, Value lhs, Value rhs)
|
|||
// BitwiseXORExpression : BitwiseXORExpression ^ BitwiseANDExpression
|
||||
ThrowCompletionOr<Value> bitwise_xor(VM& vm, Value lhs, Value rhs)
|
||||
{
|
||||
// OPTIMIZATION: Fast path when both values are Int32.
|
||||
if (lhs.is_int32() && rhs.is_int32())
|
||||
return Value(lhs.as_i32() ^ rhs.as_i32());
|
||||
|
||||
// 13.15.3 ApplyStringOrNumericBinaryOperator ( lval, opText, rval ), https://tc39.es/ecma262/#sec-applystringornumericbinaryoperator
|
||||
// 1-2, 6. N/A.
|
||||
|
||||
|
@ -1598,6 +1610,12 @@ ThrowCompletionOr<Value> left_shift(VM& vm, Value lhs, Value rhs)
|
|||
// ShiftExpression : ShiftExpression >> AdditiveExpression
|
||||
ThrowCompletionOr<Value> right_shift(VM& vm, Value lhs, Value rhs)
|
||||
{
|
||||
// OPTIMIZATION: Fast path when both values are suitable Int32 values.
|
||||
if (lhs.is_int32() && rhs.is_int32() && rhs.as_i32() >= 0) {
|
||||
auto shift_count = static_cast<u32>(rhs.as_i32()) % 32;
|
||||
return Value(lhs.as_i32() >> shift_count);
|
||||
}
|
||||
|
||||
// 13.15.3 ApplyStringOrNumericBinaryOperator ( lval, opText, rval ), https://tc39.es/ecma262/#sec-applystringornumericbinaryoperator
|
||||
// 1-2, 6. N/A.
|
||||
|
||||
|
@ -1649,6 +1667,12 @@ ThrowCompletionOr<Value> right_shift(VM& vm, Value lhs, Value rhs)
|
|||
// ShiftExpression : ShiftExpression >>> AdditiveExpression
|
||||
ThrowCompletionOr<Value> unsigned_right_shift(VM& vm, Value lhs, Value rhs)
|
||||
{
|
||||
// OPTIMIZATION: Fast path when both values are suitable Int32 values.
|
||||
if (lhs.is_int32() && rhs.is_int32() && lhs.as_i32() >= 0 && rhs.as_i32() >= 0) {
|
||||
auto shift_count = static_cast<u32>(rhs.as_i32()) % 32;
|
||||
return Value(static_cast<u32>(lhs.as_i32()) >> shift_count);
|
||||
}
|
||||
|
||||
// 13.15.3 ApplyStringOrNumericBinaryOperator ( lval, opText, rval ), https://tc39.es/ecma262/#sec-applystringornumericbinaryoperator
|
||||
// 1-2, 5-6. N/A.
|
||||
|
||||
|
|
|
@ -428,6 +428,17 @@ public:
|
|||
#endif
|
||||
}
|
||||
|
||||
// A double is any Value which does not have the full exponent and top mantissa bit set or has
|
||||
// exactly only those bits set.
|
||||
bool is_double() const { return (m_value.encoded & CANON_NAN_BITS) != CANON_NAN_BITS || (m_value.encoded == CANON_NAN_BITS); }
|
||||
bool is_int32() const { return m_value.tag == INT32_TAG; }
|
||||
|
||||
i32 as_i32() const
|
||||
{
|
||||
VERIFY(is_int32());
|
||||
return static_cast<i32>(m_value.encoded & 0xFFFFFFFF);
|
||||
}
|
||||
|
||||
private:
|
||||
Value(u64 tag, u64 val)
|
||||
{
|
||||
|
@ -459,17 +470,6 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
// A double is any Value which does not have the full exponent and top mantissa bit set or has
|
||||
// exactly only those bits set.
|
||||
bool is_double() const { return (m_value.encoded & CANON_NAN_BITS) != CANON_NAN_BITS || (m_value.encoded == CANON_NAN_BITS); }
|
||||
bool is_int32() const { return m_value.tag == INT32_TAG; }
|
||||
|
||||
i32 as_i32() const
|
||||
{
|
||||
VERIFY(is_int32());
|
||||
return static_cast<i32>(m_value.encoded & 0xFFFFFFFF);
|
||||
}
|
||||
|
||||
template<typename PointerType>
|
||||
PointerType* extract_pointer() const
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue