[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:
Predrag Rudic 2018-04-25 08:28:35 +02:00 committed by Commit Bot
parent a12413531d
commit 2393710a27
3 changed files with 83 additions and 1 deletions

View File

@ -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))

View File

@ -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);
}

View File

@ -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.