[bigint] Add big endian support for BigInts serialization
Cq-Include-Trybots: luci.chromium.try:linux_chromium_rel_ng Change-Id: I3fc1b53c43e53e12e041178912f372f33068d67c Reviewed-on: https://chromium-review.googlesource.com/1023418 Commit-Queue: Ivica Bogosavljevic <ivica.bogosavljevic@mips.com> Reviewed-by: Jakob Kummerow <jkummerow@chromium.org> Cr-Commit-Position: refs/heads/master@{#52775}
This commit is contained in:
parent
a12413531d
commit
2393710a27
@ -177,6 +177,9 @@
|
||||
// V8_HAS_ATTRIBUTE_VISIBILITY - __attribute__((visibility)) supported
|
||||
// V8_HAS_ATTRIBUTE_WARN_UNUSED_RESULT - __attribute__((warn_unused_result))
|
||||
// supported
|
||||
// V8_HAS_BUILTIN_BSWAP16 - __builtin_bswap16() supported
|
||||
// V8_HAS_BUILTIN_BSWAP32 - __builtin_bswap32() supported
|
||||
// V8_HAS_BUILTIN_BSWAP64 - __builtin_bswap64() supported
|
||||
// V8_HAS_BUILTIN_CLZ - __builtin_clz() supported
|
||||
// V8_HAS_BUILTIN_CTZ - __builtin_ctz() supported
|
||||
// V8_HAS_BUILTIN_EXPECT - __builtin_expect() supported
|
||||
@ -217,6 +220,9 @@
|
||||
# define V8_HAS_ATTRIBUTE_WARN_UNUSED_RESULT \
|
||||
(__has_attribute(warn_unused_result))
|
||||
|
||||
# define V8_HAS_BUILTIN_BSWAP16 (__has_builtin(__builtin_bswap16))
|
||||
# define V8_HAS_BUILTIN_BSWAP32 (__has_builtin(__builtin_bswap32))
|
||||
# define V8_HAS_BUILTIN_BSWAP64 (__has_builtin(__builtin_bswap64))
|
||||
# define V8_HAS_BUILTIN_CLZ (__has_builtin(__builtin_clz))
|
||||
# define V8_HAS_BUILTIN_CTZ (__has_builtin(__builtin_ctz))
|
||||
# define V8_HAS_BUILTIN_EXPECT (__has_builtin(__builtin_expect))
|
||||
|
@ -1825,10 +1825,20 @@ int BigInt::DigitsByteLengthForBitfield(uint32_t bitfield) {
|
||||
// The serialization format MUST NOT CHANGE without updating the format
|
||||
// version in value-serializer.cc!
|
||||
void BigInt::SerializeDigits(uint8_t* storage) {
|
||||
int bytelength = length() * kDigitSize;
|
||||
void* digits = reinterpret_cast<void*>(reinterpret_cast<Address>(this) +
|
||||
kDigitsOffset - kHeapObjectTag);
|
||||
#if defined(V8_TARGET_LITTLE_ENDIAN)
|
||||
int bytelength = length() * kDigitSize;
|
||||
memcpy(storage, digits, bytelength);
|
||||
#elif defined(V8_TARGET_BIG_ENDIAN)
|
||||
digit_t* digit_storage = reinterpret_cast<digit_t*>(storage);
|
||||
const digit_t* digit = reinterpret_cast<const digit_t*>(digits);
|
||||
for (int i = 0; i < length(); i++) {
|
||||
*digit_storage = ByteReverse(*digit);
|
||||
digit_storage++;
|
||||
digit++;
|
||||
}
|
||||
#endif // V8_TARGET_BIG_ENDIAN
|
||||
}
|
||||
|
||||
// The serialization format MUST NOT CHANGE without updating the format
|
||||
@ -1845,10 +1855,33 @@ MaybeHandle<BigInt> BigInt::FromSerializedDigits(
|
||||
result->initialize_bitfield(sign, length);
|
||||
void* digits = reinterpret_cast<void*>(reinterpret_cast<Address>(*result) +
|
||||
kDigitsOffset - kHeapObjectTag);
|
||||
#if defined(V8_TARGET_LITTLE_ENDIAN)
|
||||
memcpy(digits, digits_storage.start(), bytelength);
|
||||
void* padding_start =
|
||||
reinterpret_cast<void*>(reinterpret_cast<Address>(digits) + bytelength);
|
||||
memset(padding_start, 0, length * kDigitSize - bytelength);
|
||||
#elif defined(V8_TARGET_BIG_ENDIAN)
|
||||
digit_t* digit = reinterpret_cast<digit_t*>(digits);
|
||||
const digit_t* digit_storage =
|
||||
reinterpret_cast<const digit_t*>(digits_storage.start());
|
||||
for (int i = 0; i < bytelength / kDigitSize; i++) {
|
||||
*digit = ByteReverse(*digit_storage);
|
||||
digit_storage++;
|
||||
digit++;
|
||||
}
|
||||
if (bytelength % kDigitSize) {
|
||||
*digit = 0;
|
||||
byte* digit_byte = reinterpret_cast<byte*>(digit);
|
||||
digit_byte += sizeof(*digit) - 1;
|
||||
const byte* digit_storage_byte =
|
||||
reinterpret_cast<const byte*>(digit_storage);
|
||||
for (int i = 0; i < bytelength % kDigitSize; i++) {
|
||||
*digit_byte = *digit_storage_byte;
|
||||
digit_byte--;
|
||||
digit_storage_byte++;
|
||||
}
|
||||
}
|
||||
#endif // V8_TARGET_BIG_ENDIAN
|
||||
return MutableBigInt::MakeImmutable(result);
|
||||
}
|
||||
|
||||
|
43
src/utils.h
43
src/utils.h
@ -1658,6 +1658,49 @@ static inline void WriteLittleEndianValue(Address p, V value) {
|
||||
#endif // V8_TARGET_LITTLE_ENDIAN
|
||||
}
|
||||
|
||||
template <typename V>
|
||||
static inline V ByteReverse(V value) {
|
||||
size_t size_of_v = sizeof(value);
|
||||
switch (size_of_v) {
|
||||
case 2:
|
||||
#if V8_HAS_BUILTIN_BSWAP16
|
||||
return __builtin_bswap16(value);
|
||||
#else
|
||||
return value << 8 | (value >> 8 & 0x00FF);
|
||||
#endif
|
||||
case 4:
|
||||
#if V8_HAS_BUILTIN_BSWAP32
|
||||
return __builtin_bswap32(value);
|
||||
#else
|
||||
{
|
||||
size_t bits_of_v = size_of_v * kBitsPerByte;
|
||||
return value << (bits_of_v - 8) |
|
||||
((value << (bits_of_v - 24)) & 0x00FF0000) |
|
||||
((value >> (bits_of_v - 24)) & 0x0000FF00) |
|
||||
((value >> (bits_of_v - 8)) & 0x00000FF);
|
||||
}
|
||||
#endif
|
||||
case 8:
|
||||
#if V8_HAS_BUILTIN_BSWAP64
|
||||
return __builtin_bswap64(value);
|
||||
#else
|
||||
{
|
||||
size_t bits_of_v = size_of_v * kBitsPerByte;
|
||||
return value << (bits_of_v - 8) |
|
||||
((value << (bits_of_v - 24)) & 0x00FF000000000000) |
|
||||
((value << (bits_of_v - 40)) & 0x0000FF0000000000) |
|
||||
((value << (bits_of_v - 56)) & 0x000000FF00000000) |
|
||||
((value >> (bits_of_v - 56)) & 0x00000000FF000000) |
|
||||
((value >> (bits_of_v - 40)) & 0x0000000000FF0000) |
|
||||
((value >> (bits_of_v - 24)) & 0x000000000000FF00) |
|
||||
((value >> (bits_of_v - 8)) & 0x00000000000000FF);
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
// Represents a linked list that threads through the nodes in the linked list.
|
||||
// Entries in the list are pointers to nodes. The nodes need to have a T**
|
||||
// next() method that returns the location where the next value is stored.
|
||||
|
Loading…
Reference in New Issue
Block a user