!3100 Use union instead of memcpy in bit_cast

Merge pull request !3100 from 武万琦/master
This commit is contained in:
openharmony_ci 2022-12-05 08:23:17 +00:00 committed by Gitee
commit 30d057f576
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
15 changed files with 100 additions and 29 deletions

View File

@ -22,6 +22,12 @@
#include <type_traits>
namespace panda::ecmascript::base {
template <class S, class R>
union Data {
S src;
R dst;
};
template <typename T>
inline constexpr uint32_t CountLeadingZeros(T value)
{
@ -123,11 +129,10 @@ template <class To, class From>
inline To bit_cast(const From &src) noexcept // NOLINT(readability-identifier-naming)
{
static_assert(sizeof(To) == sizeof(From), "size of the types must be equal");
To dst;
// The use of security functions 'memccpy_s' here will have a greater impact on performance
// todo use union instance of memcpy
memcpy(&dst, &src, sizeof(To));
return dst;
// The use of security functions 'memcpy_s' here will have a greater impact on performance
Data<From, To> data_;
data_.src = src;
return data_.dst;
}
template <typename T>

View File

@ -45,6 +45,18 @@ public:
EcmaVM *instance {nullptr};
EcmaHandleScope *scope {nullptr};
JSThread *thread {nullptr};
protected:
template <class To, class From>
inline To MemoryCast(const From &src) noexcept
{
static_assert(sizeof(To) == sizeof(From), "size of the types must be equal");
To dst;
if (memcpy_s(&dst, sizeof(To), &src, sizeof(From)) != EOK) {
LOG_FULL(FATAL) << "memcpy_s failed";
UNREACHABLE();
}
return dst;
}
};
HWTEST_F_L0(BitHelperTest, CountLeadingZeros_CountTrailingZeros)
@ -109,4 +121,54 @@ HWTEST_F_L0(BitHelperTest, CountLeadingZeros64_CountLeadingOnes64)
EXPECT_EQ(CountLeadingOnes64(uint64CommonValue2), 0U);
EXPECT_EQ(CountLeadingOnes64(uint64MinValue), 0U);
}
HWTEST_F_L0(BitHelperTest, bit_cast)
{
int8_t int8Value = -128;
uint8_t uint8Value = 255;
char char8Value = 127;
EXPECT_EQ(bit_cast<uint8_t>(int8Value), MemoryCast<uint8_t>(int8Value));
EXPECT_EQ(bit_cast<char>(int8Value), MemoryCast<char>(int8Value));
EXPECT_EQ(bit_cast<int8_t>(uint8Value), MemoryCast<int8_t>(uint8Value));
EXPECT_EQ(bit_cast<char>(uint8Value), MemoryCast<char>(uint8Value));
EXPECT_EQ(bit_cast<int8_t>(char8Value), MemoryCast<int8_t>(char8Value));
EXPECT_EQ(bit_cast<uint8_t>(char8Value), MemoryCast<uint8_t>(char8Value));
int16_t int16Value = -32768;
uint16_t uint16Value = 65535;
char16_t char16Value = 32767;
EXPECT_EQ(bit_cast<uint16_t>(int16Value), MemoryCast<uint16_t>(int16Value));
EXPECT_EQ(bit_cast<char16_t>(int16Value), MemoryCast<char16_t>(int16Value));
EXPECT_EQ(bit_cast<int16_t>(uint16Value), MemoryCast<int16_t>(uint16Value));
EXPECT_EQ(bit_cast<char16_t>(uint16Value), MemoryCast<char16_t>(uint16Value));
EXPECT_EQ(bit_cast<int16_t>(char16Value), MemoryCast<int16_t>(char16Value));
EXPECT_EQ(bit_cast<uint16_t>(char16Value), MemoryCast<uint16_t>(char16Value));
int32_t int32Value = -2147483648;
uint32_t uint32Value = 2147483648;
float floatValue = -13.569243f;
char32_t char32Value = 2147483648;
EXPECT_EQ(bit_cast<uint32_t>(int32Value), MemoryCast<uint32_t>(int32Value));
EXPECT_EQ(bit_cast<float>(int32Value), MemoryCast<float>(int32Value));
EXPECT_EQ(bit_cast<char32_t>(int32Value), MemoryCast<char32_t>(int32Value));
EXPECT_EQ(bit_cast<int32_t>(uint32Value), MemoryCast<int32_t>(uint32Value));
EXPECT_EQ(bit_cast<float>(uint32Value), MemoryCast<float>(uint32Value));
EXPECT_EQ(bit_cast<char32_t>(uint32Value), MemoryCast<char32_t>(uint32Value));
EXPECT_EQ(bit_cast<int32_t>(floatValue), MemoryCast<int32_t>(floatValue));
EXPECT_EQ(bit_cast<uint32_t>(floatValue), MemoryCast<uint32_t>(floatValue));
EXPECT_EQ(bit_cast<char32_t>(floatValue), MemoryCast<char32_t>(floatValue));
EXPECT_EQ(bit_cast<int32_t>(char32Value), MemoryCast<int32_t>(char32Value));
EXPECT_EQ(bit_cast<uint32_t>(char32Value), MemoryCast<uint32_t>(char32Value));
EXPECT_EQ(bit_cast<float>(char32Value), MemoryCast<float>(char32Value));
int64_t int64Value = -9223372036854775807LL;
uint64_t uint64Value = 9223372036854775808ULL;
double doubleValue = -257.93458301390463;
EXPECT_EQ(bit_cast<uint64_t>(int64Value), MemoryCast<uint64_t>(int64Value));
EXPECT_EQ(bit_cast<double>(int64Value), MemoryCast<double>(int64Value));
EXPECT_EQ(bit_cast<int64_t>(uint64Value), MemoryCast<int64_t>(uint64Value));
EXPECT_EQ(bit_cast<double>(uint64Value), MemoryCast<double>(uint64Value));
EXPECT_EQ(bit_cast<int64_t>(doubleValue), MemoryCast<int64_t>(doubleValue));
EXPECT_EQ(bit_cast<uint64_t>(doubleValue), MemoryCast<uint64_t>(doubleValue));
}
} // namespace panda::test

View File

@ -492,7 +492,7 @@ JSTaggedValue BuiltinsArrayBuffer::GetValueFromBufferForFloat(uint8_t *block, ui
}
if (!littleEndian) {
uint32_t res = LittleEndianToBigEndian(unionValue.uValue);
return GetTaggedDouble(bit_cast<T>(res));
return GetTaggedDouble(base::bit_cast<T>(res));
}
} else if constexpr (std::is_same_v<T, double>) { // NOLINTNEXTLINE(readability-braces-around-statements)
unionValue.uValue = *reinterpret_cast<uint64_t *>(block + byteIndex);
@ -501,7 +501,7 @@ JSTaggedValue BuiltinsArrayBuffer::GetValueFromBufferForFloat(uint8_t *block, ui
}
if (!littleEndian) {
uint64_t res = LittleEndianToBigEndian64Bit(unionValue.uValue);
return GetTaggedDouble(bit_cast<T>(res));
return GetTaggedDouble(base::bit_cast<T>(res));
}
}
@ -593,11 +593,11 @@ void BuiltinsArrayBuffer::SetValueInBufferForFloat(double val, uint8_t *block, u
}
if (!littleEndian) {
if constexpr (std::is_same_v<T, float>) {
uint32_t res = bit_cast<uint32_t>(data);
data = bit_cast<T>(LittleEndianToBigEndian(res));
uint32_t res = base::bit_cast<uint32_t>(data);
data = base::bit_cast<T>(LittleEndianToBigEndian(res));
} else if constexpr (std::is_same_v<T, double>) {
uint64_t res = bit_cast<uint64_t>(data);
data = bit_cast<T>(LittleEndianToBigEndian64Bit(res));
uint64_t res = base::bit_cast<uint64_t>(data);
data = base::bit_cast<T>(LittleEndianToBigEndian64Bit(res));
}
}
SetTypeData(block, data, byteIndex);

View File

@ -474,7 +474,7 @@ JSTaggedValue BuiltinsMath::Log2(EcmaRuntimeCallInfo *argv)
inline bool IsNegZero(double value)
{
return (value == 0.0 && (bit_cast<uint64_t>(value) & base::DOUBLE_SIGN_MASK) == base::DOUBLE_SIGN_MASK);
return (value == 0.0 && (base::bit_cast<uint64_t>(value) & base::DOUBLE_SIGN_MASK) == base::DOUBLE_SIGN_MASK);
}
// 20.2.2.24

View File

@ -298,7 +298,7 @@ public:
ImmValueType ToJSTaggedValueDouble() const
{
return JSTaggedValue(bit_cast<double>(value_)).GetRawData();
return JSTaggedValue(base::bit_cast<double>(value_)).GetRawData();
}
ImmValueType GetValue() const

View File

@ -255,7 +255,7 @@ GateRef CircuitBuilder::Boolean(bool val)
GateRef CircuitBuilder::Double(double val)
{
return GetCircuit()->GetConstantGate(MachineType::F64, bit_cast<int64_t>(val), GateType::NJSValue());
return GetCircuit()->GetConstantGate(MachineType::F64, base::bit_cast<int64_t>(val), GateType::NJSValue());
}
GateRef CircuitBuilder::HoleConstant()

View File

@ -1041,7 +1041,7 @@ void LLVMIRBuilder::VisitConstant(GateRef gate, std::bitset<64> value) // 64: bi
UNREACHABLE();
}
} else if (machineType == MachineType::F64) {
auto doubleValue = bit_cast<double>(value.to_ullong()); // actual double value
auto doubleValue = base::bit_cast<double>(value.to_ullong()); // actual double value
llvmValue = LLVMConstReal(LLVMDoubleType(), doubleValue);
} else if (machineType == MachineType::I8) {
llvmValue = LLVMConstInt(LLVMInt8Type(), value.to_ulong(), 0);

View File

@ -180,9 +180,10 @@ public:
if (dLeft == 0.0 || std::isnan(dLeft)) {
return JSTaggedValue(base::NAN_VALUE);
}
uint64_t flagBit = ((bit_cast<uint64_t>(dLeft)) ^ (bit_cast<uint64_t>(dRight))) &
uint64_t flagBit = ((base::bit_cast<uint64_t>(dLeft)) ^ (base::bit_cast<uint64_t>(dRight))) &
base::DOUBLE_SIGN_MASK;
return JSTaggedValue(bit_cast<double>(flagBit ^ (bit_cast<uint64_t>(base::POSITIVE_INFINITY))));
return JSTaggedValue(base::bit_cast<double>(
flagBit ^ (base::bit_cast<uint64_t>(base::POSITIVE_INFINITY))));
}
return JSTaggedValue(dLeft / dRight);
}

View File

@ -63,8 +63,10 @@ JSTaggedValue FastRuntimeStub::FastDiv(JSTaggedValue left, JSTaggedValue right)
if (dLeft == 0.0 || std::isnan(dLeft)) {
return JSTaggedValue(base::NAN_VALUE);
}
uint64_t flagBit = ((bit_cast<uint64_t>(dLeft)) ^ (bit_cast<uint64_t>(dRight))) & base::DOUBLE_SIGN_MASK;
return JSTaggedValue(bit_cast<double>(flagBit ^ (bit_cast<uint64_t>(base::POSITIVE_INFINITY))));
uint64_t flagBit = ((base::bit_cast<uint64_t>(dLeft)) ^ (base::bit_cast<uint64_t>(dRight))) &
base::DOUBLE_SIGN_MASK;
return JSTaggedValue(base::bit_cast<double>(
flagBit ^ (base::bit_cast<uint64_t>(base::POSITIVE_INFINITY))));
}
return JSTaggedValue(dLeft / dRight);
}

View File

@ -1076,7 +1076,7 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, const uint8_t
}
HANDLE_OPCODE(FLDAI_IMM64) {
auto imm = bit_cast<double>(READ_INST_64_0());
auto imm = base::bit_cast<double>(READ_INST_64_0());
LOG_INST() << "fldai " << imm;
SET_ACC(JSTaggedValue(imm));
DISPATCH(FLDAI_IMM64);
@ -2028,7 +2028,7 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, const uint8_t
SET_ACC(JSTaggedValue(base::NAN_VALUE));
}
bool baseZero = doubleBase == 0 &&
(bit_cast<uint64_t>(doubleBase) & base::DOUBLE_SIGN_MASK) == base::DOUBLE_SIGN_MASK;
(base::bit_cast<uint64_t>(doubleBase) & base::DOUBLE_SIGN_MASK) == base::DOUBLE_SIGN_MASK;
bool isFinite = std::isfinite(doubleExponent);
bool truncEqual = base::NumberHelper::TruncateDouble(doubleExponent) == doubleExponent;
bool halfTruncEqual = (base::NumberHelper::TruncateDouble(doubleExponent / 2) + base::HALF) ==

View File

@ -476,7 +476,7 @@ void InterpreterAssembly::HandleFldaiImm64(
JSThread *thread, const uint8_t *pc, JSTaggedType *sp, JSTaggedValue constpool, JSTaggedValue profileTypeInfo,
JSTaggedValue acc, int16_t hotnessCounter)
{
auto imm = bit_cast<double>(READ_INST_64_0());
auto imm = base::bit_cast<double>(READ_INST_64_0());
LOG_INST() << "fldai " << imm;
SET_ACC(JSTaggedValue(imm));
DISPATCH(FLDAI_IMM64);
@ -1475,7 +1475,7 @@ void InterpreterAssembly::HandleExpImm8V8(
SET_ACC(JSTaggedValue(base::NAN_VALUE));
}
bool baseZero = doubleBase == 0 &&
(bit_cast<uint64_t>(doubleBase) & base::DOUBLE_SIGN_MASK) == base::DOUBLE_SIGN_MASK;
(base::bit_cast<uint64_t>(doubleBase) & base::DOUBLE_SIGN_MASK) == base::DOUBLE_SIGN_MASK;
bool isFinite = std::isfinite(doubleExponent);
bool truncEqual = base::NumberHelper::TruncateDouble(doubleExponent) == doubleExponent;
bool halfTruncEqual = (base::NumberHelper::TruncateDouble(doubleExponent / 2) + base::HALF) ==

View File

@ -106,7 +106,7 @@ bool JSTaggedValue::WithinInt32() const
}
double doubleValue = GetNumber();
if (bit_cast<int64_t>(doubleValue) == bit_cast<int64_t>(-0.0)) {
if (base::bit_cast<int64_t>(doubleValue) == base::bit_cast<int64_t>(-0.0)) {
return false;
}

View File

@ -540,7 +540,7 @@ JSHandle<TaggedArray> LiteralDataExtractor::GetTypeLiteral(JSThread *thread, con
JSTaggedValue jt = JSTaggedValue::Null();
switch (tag) {
case LiteralTag::INTEGER: {
jt = JSTaggedValue(bit_cast<int32_t>(std::get<uint32_t>(value)));
jt = JSTaggedValue(base::bit_cast<int32_t>(std::get<uint32_t>(value)));
break;
}
case LiteralTag::LITERALARRAY: {

View File

@ -90,7 +90,8 @@ JSTaggedValue RuntimeStubs::RuntimeExp(JSThread *thread, JSTaggedValue base, JST
if (std::abs(doubleBase) == 1 && std::isinf(doubleExponent)) {
return JSTaggedValue(base::NAN_VALUE);
}
if (((doubleBase == 0) && ((bit_cast<uint64_t>(doubleBase)) & base::DOUBLE_SIGN_MASK) == base::DOUBLE_SIGN_MASK) &&
if (((doubleBase == 0) &&
((base::bit_cast<uint64_t>(doubleBase)) & base::DOUBLE_SIGN_MASK) == base::DOUBLE_SIGN_MASK) &&
std::isfinite(doubleExponent) && base::NumberHelper::TruncateDouble(doubleExponent) == doubleExponent &&
base::NumberHelper::TruncateDouble(doubleExponent / 2) + base::HALF == (doubleExponent / 2)) { // 2: half
if (doubleExponent > 0) {
@ -1502,8 +1503,8 @@ JSTaggedValue RuntimeStubs::RuntimeDiv2(JSThread *thread, const JSHandle<JSTagge
if (dLeft == 0 || std::isnan(dLeft)) {
return JSTaggedValue(base::NAN_VALUE);
}
bool positive = (((bit_cast<uint64_t>(dRight)) & base::DOUBLE_SIGN_MASK) ==
((bit_cast<uint64_t>(dLeft)) & base::DOUBLE_SIGN_MASK));
bool positive = (((base::bit_cast<uint64_t>(dRight)) & base::DOUBLE_SIGN_MASK) ==
((base::bit_cast<uint64_t>(dLeft)) & base::DOUBLE_SIGN_MASK));
return JSTaggedValue(positive ? base::POSITIVE_INFINITY : -base::POSITIVE_INFINITY);
}
return JSTaggedValue(dLeft / dRight);

View File

@ -430,7 +430,7 @@ DEF_RUNTIME_STUBS(Exp)
return JSTaggedValue(base::NAN_VALUE).GetRawData();
}
if ((doubleBase == 0 &&
((bit_cast<uint64_t>(doubleBase)) & base::DOUBLE_SIGN_MASK) == base::DOUBLE_SIGN_MASK) &&
((base::bit_cast<uint64_t>(doubleBase)) & base::DOUBLE_SIGN_MASK) == base::DOUBLE_SIGN_MASK) &&
std::isfinite(doubleExponent) && base::NumberHelper::TruncateDouble(doubleExponent) == doubleExponent &&
base::NumberHelper::TruncateDouble(doubleExponent / 2) + base::HALF == // 2 : half
(doubleExponent / 2)) { // 2 : half