Update Value constructors

Improve Value::Value(double) performance.
Add missing double and int32 type testing on interpreter

Signed-off-by: Seonghyun Kim <sh8281.kim@samsung.com>
This commit is contained in:
Seonghyun Kim 2022-05-03 16:14:14 +09:00
commit 3631ae6097
4 changed files with 62 additions and 37 deletions

View file

@ -65,7 +65,7 @@ Value builtinArrayConstructor(ExecutionState& state, Value thisValue, size_t arg
if (interpretArgumentsAsElements) {
Value val = argv[0];
if (argc > 1 || !val.isInt32()) {
if (argc > 1 || !val.isNumber()) {
if (array->isFastModeArray()) {
for (size_t idx = 0; idx < argc; idx++) {
array->m_fastModeData[idx] = argv[idx];

View file

@ -246,7 +246,7 @@ Value ByteCodeInterpreter::interpret(ExecutionState* state, ByteCodeBlock* byteC
BinaryPlus* code = (BinaryPlus*)programCounter;
const Value& v0 = registerFile[code->m_srcIndex0];
const Value& v1 = registerFile[code->m_srcIndex1];
Value ret(Value::ForceUninitialized);
Value& ret = registerFile[code->m_dstIndex];
if (v0.isInt32() && v1.isInt32()) {
int32_t a = v0.asInt32();
int32_t b = v1.asInt32();
@ -262,7 +262,6 @@ Value ByteCodeInterpreter::interpret(ExecutionState* state, ByteCodeBlock* byteC
} else {
ret = plusSlowCase(*state, v0, v1);
}
registerFile[code->m_dstIndex] = ret;
ADD_PROGRAM_COUNTER(BinaryPlus);
NEXT_INSTRUCTION();
}
@ -273,7 +272,7 @@ Value ByteCodeInterpreter::interpret(ExecutionState* state, ByteCodeBlock* byteC
BinaryMinus* code = (BinaryMinus*)programCounter;
const Value& left = registerFile[code->m_srcIndex0];
const Value& right = registerFile[code->m_srcIndex1];
Value ret(Value::ForceUninitialized);
Value& ret = registerFile[code->m_dstIndex];
if (left.isInt32() && right.isInt32()) {
int32_t a = left.asInt32();
int32_t b = right.asInt32();
@ -289,7 +288,6 @@ Value ByteCodeInterpreter::interpret(ExecutionState* state, ByteCodeBlock* byteC
} else {
ret = minusSlowCase(*state, left, right);
}
registerFile[code->m_dstIndex] = ret;
ADD_PROGRAM_COUNTER(BinaryMinus);
NEXT_INSTRUCTION();
}
@ -300,7 +298,7 @@ Value ByteCodeInterpreter::interpret(ExecutionState* state, ByteCodeBlock* byteC
BinaryMultiply* code = (BinaryMultiply*)programCounter;
const Value& left = registerFile[code->m_srcIndex0];
const Value& right = registerFile[code->m_srcIndex1];
Value ret(Value::ForceUninitialized);
Value& ret = registerFile[code->m_dstIndex];
if (left.isInt32() && right.isInt32()) {
int32_t a = left.asInt32();
int32_t b = right.asInt32();
@ -316,11 +314,10 @@ Value ByteCodeInterpreter::interpret(ExecutionState* state, ByteCodeBlock* byteC
}
}
} else if (LIKELY(left.isNumber() && right.isNumber())) {
ret = Value(Value::EncodeAsDouble, left.asNumber() * right.asNumber());
ret = Value(left.asNumber() * right.asNumber());
} else {
ret = multiplySlowCase(*state, left, right);
}
registerFile[code->m_dstIndex] = ret;
ADD_PROGRAM_COUNTER(BinaryMultiply);
NEXT_INSTRUCTION();
}
@ -331,10 +328,11 @@ Value ByteCodeInterpreter::interpret(ExecutionState* state, ByteCodeBlock* byteC
BinaryDivision* code = (BinaryDivision*)programCounter;
const Value& left = registerFile[code->m_srcIndex0];
const Value& right = registerFile[code->m_srcIndex1];
Value& ret = registerFile[code->m_dstIndex];
if (LIKELY(left.isNumber() && right.isNumber())) {
registerFile[code->m_dstIndex] = Value(left.asNumber() / right.asNumber());
ret = Value(left.asNumber() / right.asNumber());
} else {
registerFile[code->m_dstIndex] = divisionSlowCase(*state, left, right);
ret = divisionSlowCase(*state, left, right);
}
ADD_PROGRAM_COUNTER(BinaryDivision);
NEXT_INSTRUCTION();
@ -1633,7 +1631,7 @@ NEVER_INLINE Value ByteCodeInterpreter::multiplySlowCase(ExecutionState& state,
if (UNLIKELY(lnum.second)) {
return Value(lnum.first.asBigInt()->multiply(state, rnum.first.asBigInt()));
} else {
return Value(Value::EncodeAsDouble, lnum.first.asNumber() * rnum.first.asNumber());
return Value(lnum.first.asNumber() * rnum.first.asNumber());
}
}
@ -1650,7 +1648,7 @@ NEVER_INLINE Value ByteCodeInterpreter::divisionSlowCase(ExecutionState& state,
}
return Value(lnum.first.asBigInt()->division(state, rnum.first.asBigInt()));
} else {
return Value(Value::EncodeAsDouble, lnum.first.asNumber() / rnum.first.asNumber());
return Value(lnum.first.asNumber() / rnum.first.asNumber());
}
}

View file

@ -143,8 +143,8 @@ public:
#endif
// Numbers
Value(EncodeAsDoubleTag, double);
explicit Value(double);
Value(EncodeAsDoubleTag, const double&);
explicit Value(const double&);
explicit Value(bool);
explicit Value(char);
explicit Value(unsigned char);
@ -274,6 +274,9 @@ public:
intptr_t payload() const;
static constexpr double maximumLength();
static bool isInt32ConvertibleDouble(const double& d);
static bool isInt32ConvertibleDouble(const double& d, int32_t& asInt32);
private:
ValueDescriptor u;
double toNumberSlowCase(ExecutionState& ec) const; // $7.1.3 ToNumber

View file

@ -175,7 +175,7 @@ inline Value::Value(FromTagTag, uint32_t tag)
u.asBits.payload = 0;
}
inline Value::Value(EncodeAsDoubleTag, double d)
inline Value::Value(EncodeAsDoubleTag, const double& d)
{
u.asDouble = d;
}
@ -412,7 +412,7 @@ inline double reinterpretInt64ToDouble(int64_t value)
return bitwise_cast<double>(value);
}
inline Value::Value(EncodeAsDoubleTag, double d)
inline Value::Value(EncodeAsDoubleTag, const double& d)
{
u.asInt64 = reinterpretDoubleToInt64(d) + DoubleEncodeOffset;
}
@ -589,19 +589,38 @@ inline intptr_t Value::payload() const
// ===common architecture========================================================
// ==============================================================================
inline Value::Value(double d)
ALWAYS_INLINE bool Value::isInt32ConvertibleDouble(const double& d)
{
const int32_t asInt32 = static_cast<int32_t>(d);
if (asInt32 != d || (!asInt32 && std::signbit(d))) { // true for -0.0
#ifdef ESCARGOT_64
if (UNLIKELY((bitwise_cast<int64_t>(d) & DoubleInvalidBeginning) == DoubleInvalidBeginning)) {
d = std::numeric_limits<double>::quiet_NaN();
}
#endif
*this = Value(EncodeAsDouble, d);
int32_t asInt32 = static_cast<int32_t>(d);
if (LIKELY(LIKELY(asInt32 != d) || UNLIKELY(!asInt32 && std::signbit(d)))) { // true for -0.0
return false;
}
return true;
}
ALWAYS_INLINE bool Value::isInt32ConvertibleDouble(const double& d, int32_t& asInt32)
{
asInt32 = static_cast<int32_t>(d);
if (LIKELY(LIKELY(asInt32 != d) || UNLIKELY(!asInt32 && std::signbit(d)))) { // true for -0.0
return false;
}
return true;
}
inline Value::Value(const double& d)
{
int32_t asInt32;
if (UNLIKELY(isInt32ConvertibleDouble(d, asInt32))) {
*this = Value(asInt32);
return;
}
*this = Value(static_cast<int32_t>(d));
#ifdef ESCARGOT_64
if (UNLIKELY((bitwise_cast<int64_t>(d) & DoubleInvalidBeginning) == DoubleInvalidBeginning)) {
*this = Value(EncodeAsDouble, std::numeric_limits<double>::quiet_NaN());
return;
}
#endif
*this = Value(EncodeAsDouble, d);
}
inline Value::Value(char i)
@ -626,25 +645,28 @@ inline Value::Value(unsigned short i)
inline Value::Value(unsigned i)
{
if (static_cast<int32_t>(i) < 0) {
const int32_t asInt32 = static_cast<int32_t>(i);
if (UNLIKELY(asInt32 < 0)) {
*this = Value(EncodeAsDouble, static_cast<double>(i));
return;
}
*this = Value(static_cast<int32_t>(i));
*this = Value(asInt32);
}
inline Value::Value(long i)
{
if (static_cast<int32_t>(i) != i) {
const int32_t asInt32 = static_cast<int32_t>(i);
if (UNLIKELY(asInt32 != i)) {
*this = Value(EncodeAsDouble, static_cast<double>(i));
return;
}
*this = Value(static_cast<int32_t>(i));
*this = Value(asInt32);
}
inline Value::Value(unsigned long i)
{
if (static_cast<uint32_t>(i) != i) {
const uint32_t asInt32 = static_cast<uint32_t>(i);
if (UNLIKELY(asInt32 != i)) {
*this = Value(EncodeAsDouble, static_cast<double>(i));
return;
}
@ -653,20 +675,22 @@ inline Value::Value(unsigned long i)
inline Value::Value(long long i)
{
if (static_cast<int32_t>(i) != i) {
const int32_t asInt32 = static_cast<int32_t>(i);
if (UNLIKELY(asInt32 != i)) {
*this = Value(EncodeAsDouble, static_cast<double>(i));
return;
}
*this = Value(static_cast<int32_t>(i));
*this = Value(asInt32);
}
inline Value::Value(unsigned long long i)
{
if (static_cast<uint32_t>(i) != i) {
const uint32_t asInt32 = static_cast<uint32_t>(i);
if (UNLIKELY(asInt32 != i)) {
*this = Value(EncodeAsDouble, static_cast<double>(i));
return;
}
*this = Value(static_cast<uint32_t>(i));
*this = Value(asInt32);
}
inline bool Value::isUInt32() const
@ -887,7 +911,7 @@ uint32_t Value::tryToUseAsIndexProperty(ExecutionState& ec) const
inline double Value::toInteger(ExecutionState& state) const
{
if (isInt32()) {
if (LIKELY(isInt32())) {
return asInt32();
}
@ -903,7 +927,7 @@ inline double Value::toInteger(ExecutionState& state) const
inline bool Value::isInteger(ExecutionState& state) const
{
if (isInt32()) {
if (LIKELY(isInt32())) {
return true;
}
@ -917,7 +941,7 @@ inline bool Value::isInteger(ExecutionState& state) const
inline uint64_t Value::toLength(ExecutionState& state) const
{
double len = toInteger(state);
if (len <= 0.0) {
if (UNLIKELY(len <= 0.0)) {
return 0;
}
return std::min(len, maximumLength());