From a5ff656da170eddcdc87f84e9d4e324ce89d00d8 Mon Sep 17 00:00:00 2001 From: Ivan Inozemtsev Date: Mon, 26 Apr 2021 07:52:47 +0000 Subject: [PATCH] Revert "[vm] Switch datastream Write/WriteUnsigned to (S)LEB128." This reverts commit 80102c981b78594ceb6263a044e99e7233f7b365. Reason for revert: b/186359854 Original change's description: > [vm] Switch datastream Write/WriteUnsigned to (S)LEB128. > > This reduces the number of variable-length integer encodings in our > database from 2 to 1, and chooses the more standard one. > > TEST=Existing tests, in particular any that involve snapshots. > > Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-asan-linux-release-x64-try,vm-kernel-precomp-dwarf-linux-product-x64-try,vm-kernel-precomp-msan-linux-release-x64-try,vm-kernel-precomp-ubsan-linux-release-x64-try,vm-kernel-precomp-tsan-linux-release-x64-try,vm-kernel-precomp-nnbd-linux-debug-x64-try,vm-kernel-precomp-nnbd-linux-debug-simarm_x64-try,vm-kernel-precomp-linux-debug-simarm64c-try,vm-kernel-precomp-linux-debug-simarm_x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-debug-x64c-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-release-x64-try > Change-Id: Ia700158ac873ad32ac28c1027a669895961bc715 > Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/196321 > Commit-Queue: Tess Strickland > Reviewed-by: Ryan Macnak > Reviewed-by: Martin Kustermann # Not skipping CQ checks because original CL landed > 1 day ago. Change-Id: Idf32bdd879cf8bb7407f6dae764312140ad6eeb2 Cq-Include-Trybots: luci.dart.try:vm-kernel-precomp-asan-linux-release-x64-try,vm-kernel-precomp-dwarf-linux-product-x64-try,vm-kernel-precomp-msan-linux-release-x64-try,vm-kernel-precomp-ubsan-linux-release-x64-try,vm-kernel-precomp-tsan-linux-release-x64-try,vm-kernel-precomp-nnbd-linux-debug-x64-try,vm-kernel-precomp-nnbd-linux-debug-simarm_x64-try,vm-kernel-precomp-linux-debug-simarm64c-try,vm-kernel-precomp-linux-debug-simarm_x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-debug-x64c-try,vm-kernel-precomp-linux-product-x64-try,vm-kernel-precomp-linux-release-x64-try Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/196920 Reviewed-by: Ivan Inozemtsev Commit-Queue: Ivan Inozemtsev --- runtime/platform/utils.h | 32 +++-- runtime/vm/code_descriptors.cc | 14 +- runtime/vm/code_descriptors.h | 2 +- runtime/vm/compiler/backend/il_arm.cc | 4 +- runtime/vm/compiler/backend/il_arm64.cc | 2 +- runtime/vm/datastream.cc | 115 ---------------- runtime/vm/datastream.h | 173 ++++++++++++++++++++---- runtime/vm/datastream_test.cc | 56 ++++++++ runtime/vm/elf.cc | 4 +- runtime/vm/kernel_binary.h | 4 +- runtime/vm/object.cc | 12 +- runtime/vm/object.h | 10 +- runtime/vm/program_visitor.cc | 8 +- runtime/vm/v8_snapshot_writer.h | 2 +- 14 files changed, 251 insertions(+), 187 deletions(-) diff --git a/runtime/platform/utils.h b/runtime/platform/utils.h index 24f7e6871e8..a73d6d92e5c 100644 --- a/runtime/platform/utils.h +++ b/runtime/platform/utils.h @@ -395,23 +395,29 @@ class Utils { return ((-0x20000000000000LL <= value) && (value <= 0x20000000000000LL)); } + static constexpr uword NBitMaskUnsafe(uint32_t n) { + static_assert((sizeof(uword) * kBitsPerByte) == kBitsPerWord, + "Unexpected uword size"); + return n == kBitsPerWord ? std::numeric_limits::max() + : (static_cast(1) << n) - 1; + } + // The lowest n bits are 1, the others are 0. - template - static constexpr T NBitMask(size_t n) { - static_assert(std::is_integral::value, "Must be integral type"); - using Unsigned = typename std::make_unsigned::type; - assert(n <= sizeof(T) * kBitsPerByte); - return n == sizeof(T) * kBitsPerByte - ? static_cast(-1) - : static_cast((static_cast(1) << n) - 1); + static uword NBitMask(uint32_t n) { + ASSERT(n <= kBitsPerWord); + return NBitMaskUnsafe(n); + } + + static word SignedNBitMask(uint32_t n) { + uword mask = NBitMask(n); + return bit_cast(mask); } template - static constexpr T Bit(size_t n) { - static_assert(std::is_integral::value, "Must be integral type"); - using Unsigned = typename std::make_unsigned::type; - assert(n < sizeof(T) * kBitsPerByte); - return static_cast(static_cast(1) << n); + static T Bit(uint32_t n) { + ASSERT(n < sizeof(T) * kBitsPerByte); + T bit = 1; + return bit << n; } template diff --git a/runtime/vm/code_descriptors.cc b/runtime/vm/code_descriptors.cc index 50f2ec52406..dd8bc1d8b6d 100644 --- a/runtime/vm/code_descriptors.cc +++ b/runtime/vm/code_descriptors.cc @@ -54,8 +54,8 @@ void DescriptorList::AddDescriptor(UntaggedPcDescriptors::Kind kind, UntaggedPcDescriptors::KindAndMetadata::Encode(kind, try_index, yield_index); - encoded_data_.Write(kind_and_metadata); - encoded_data_.Write(pc_offset - prev_pc_offset); + encoded_data_.WriteSLEB128(kind_and_metadata); + encoded_data_.WriteSLEB128(pc_offset - prev_pc_offset); prev_pc_offset = pc_offset; if (!FLAG_precompiled_mode) { @@ -80,8 +80,8 @@ void DescriptorList::AddDescriptor(UntaggedPcDescriptors::Kind kind, } } const int32_t encoded_pos = token_pos.Serialize(); - encoded_data_.Write(deopt_id - prev_deopt_id); - encoded_data_.Write( + encoded_data_.WriteSLEB128(deopt_id - prev_deopt_id); + encoded_data_.WriteSLEB128( Utils::SubWithWrapAround(encoded_pos, prev_token_pos)); prev_deopt_id = deopt_id; prev_token_pos = encoded_pos; @@ -106,9 +106,9 @@ void CompressedStackMapsBuilder::AddEntry(intptr_t pc_offset, const uword pc_delta = pc_offset - last_pc_offset_; const uword non_spill_slot_bit_count = bitmap->Length() - spill_slot_bit_count; - encoded_bytes_.WriteUnsigned(pc_delta); - encoded_bytes_.WriteUnsigned(spill_slot_bit_count); - encoded_bytes_.WriteUnsigned(non_spill_slot_bit_count); + encoded_bytes_.WriteLEB128(pc_delta); + encoded_bytes_.WriteLEB128(spill_slot_bit_count); + encoded_bytes_.WriteLEB128(non_spill_slot_bit_count); bitmap->AppendAsBytesTo(&encoded_bytes_); last_pc_offset_ = pc_offset; } diff --git a/runtime/vm/code_descriptors.h b/runtime/vm/code_descriptors.h index adf53b0c4cc..0d15c386d5c 100644 --- a/runtime/vm/code_descriptors.h +++ b/runtime/vm/code_descriptors.h @@ -209,7 +209,7 @@ struct CodeSourceMapOps : AllStatic { using ArgField = BitField; static constexpr int32_t kMaxArgValue = - Utils::NBitMask(ArgField::bitsize() - 1); + Utils::NBitMaskUnsafe(ArgField::bitsize() - 1); static constexpr int32_t kMinArgValue = ~kMaxArgValue; static constexpr int32_t kSignBits = static_cast(kMinArgValue) << 1; }; diff --git a/runtime/vm/compiler/backend/il_arm.cc b/runtime/vm/compiler/backend/il_arm.cc index 8782aecfe26..70f7fb03331 100644 --- a/runtime/vm/compiler/backend/il_arm.cc +++ b/runtime/vm/compiler/backend/il_arm.cc @@ -778,8 +778,8 @@ LocationSummary* AssertAssignableInstr::MakeLocationSummary(Zone* zone, const intptr_t kCpuRegistersToPreserve = kDartAvailableCpuRegs & ~kNonChangeableInputRegs; const intptr_t kFpuRegistersToPreserve = - Utils::NBitMask(kNumberOfFpuRegisters) & - ~(Utils::NBitMask(kAbiPreservedFpuRegCount) + Utils::SignedNBitMask(kNumberOfFpuRegisters) & + ~(Utils::SignedNBitMask(kAbiPreservedFpuRegCount) << kAbiFirstPreservedFpuReg) & ~(1 << FpuTMP); diff --git a/runtime/vm/compiler/backend/il_arm64.cc b/runtime/vm/compiler/backend/il_arm64.cc index e79bfbccea4..d375c59439e 100644 --- a/runtime/vm/compiler/backend/il_arm64.cc +++ b/runtime/vm/compiler/backend/il_arm64.cc @@ -689,7 +689,7 @@ LocationSummary* AssertAssignableInstr::MakeLocationSummary(Zone* zone, const intptr_t kCpuRegistersToPreserve = kDartAvailableCpuRegs & ~kNonChangeableInputRegs; const intptr_t kFpuRegistersToPreserve = - Utils::NBitMask(kNumberOfFpuRegisters) & ~Utils::Bit(FpuTMP); + Utils::SignedNBitMask(kNumberOfFpuRegisters) & ~(1l << FpuTMP); const intptr_t kNumTemps = (Utils::CountOneBits64(kCpuRegistersToPreserve) + Utils::CountOneBits64(kFpuRegistersToPreserve)); diff --git a/runtime/vm/datastream.cc b/runtime/vm/datastream.cc index 397f9c73481..6d398fe7597 100644 --- a/runtime/vm/datastream.cc +++ b/runtime/vm/datastream.cc @@ -4,126 +4,11 @@ #include "vm/datastream.h" -#include "platform/text_buffer.h" #include "vm/compiler/runtime_api.h" -#include "vm/os.h" #include "vm/zone.h" namespace dart { -// Setting up needed variables for the unrolled loop sections below. -#define UNROLLED_INIT() \ - using Unsigned = typename std::make_unsigned::type; \ - Unsigned b = ReadByte(); \ - if ((b & C::kMoreDataMask) == 0) { \ - if ((b & C::kSignMask) != 0) { \ - b |= ~Utils::NBitMask(C::kDataBitsPerByte); \ - } \ - return static_cast(b); \ - } \ - T r = static_cast(b & C::kDataByteMask); - -// Part of the unrolled loop where the loop may stop, having read the last part, -// or continue reading. -#define UNROLLED_BODY(bit_start) \ - static_assert(bit_start % C::kDataBitsPerByte == 0, \ - "Bit start must be a multiple of the data bits per byte"); \ - static_assert(bit_start >= 0 && bit_start < kBitsPerByte * sizeof(T), \ - "Starting unrolled body at invalid bit position"); \ - static_assert(bit_start + C::kDataBitsPerByte < kBitsPerByte * sizeof(T), \ - "Unrolled body should not contain final bits in value"); \ - b = ReadByte(); \ - r |= static_cast(b & C::kDataByteMask) << bit_start; \ - if ((b & C::kMoreDataMask) == 0) { \ - if ((b & C::kSignMask) != 0) { \ - r |= ~Utils::NBitMask(bit_start + C::kDataBitsPerByte); \ - } \ - return r; \ - } - -// The end of the unrolled loop. Does not need to handle sign extension, as the -// last bits fill the rest of the bitspace. -#define UNROLLED_END(bit_start) \ - static_assert(bit_start % C::kDataBitsPerByte == 0, \ - "Bit start must be a multiple of the data bits per byte"); \ - static_assert(bit_start >= 0 && bit_start < kBitsPerByte * sizeof(T), \ - "Starting unrolled end at invalid bit position"); \ - static_assert(bit_start + C::kDataBitsPerByte >= kBitsPerByte * sizeof(T), \ - "Unrolled end does not contain final bits in value"); \ - b = ReadByte(); \ - ASSERT_EQUAL((b & C::kMoreDataMask), 0); \ - r |= static_cast(b & C::kDataByteMask) << bit_start; \ - return r; - -uint16_t ReadStream::Read16() { - using T = uint16_t; - UNROLLED_INIT(); - UNROLLED_BODY(7); - UNROLLED_END(14); -} - -uint32_t ReadStream::Read32() { - using T = uint32_t; - UNROLLED_INIT(); - UNROLLED_BODY(7); - UNROLLED_BODY(14); - UNROLLED_BODY(21); - UNROLLED_END(28); -} - -uint64_t ReadStream::Read64() { - using T = uint64_t; - UNROLLED_INIT(); - UNROLLED_BODY(7); - UNROLLED_BODY(14); - UNROLLED_BODY(21); - UNROLLED_BODY(28); - UNROLLED_BODY(35); - UNROLLED_BODY(42); - UNROLLED_BODY(49); - UNROLLED_BODY(56); - UNROLLED_END(63); -} -#undef UNROLLED_INIT -#undef UNROLLED_BODY -#undef UNROLLED_END - -static constexpr intptr_t kRowSize = 16; - -void ReadStream::WriteWindow(BaseTextBuffer* buffer, - intptr_t start, - intptr_t window_size) { - const intptr_t buffer_size = end_ - buffer_; - ASSERT(0 <= start && start <= buffer_size); - intptr_t window_start = start - (window_size / 2); - intptr_t window_end = start + (window_size / 2); - if (window_start < 0) window_start = 0; - if (buffer_size < window_start + window_end) window_end = buffer_size; - for (intptr_t i = window_start - (window_start % kRowSize); i < window_end; - i += kRowSize) { - buffer->Printf("%016" Px " ", i); - intptr_t j = i; - if (j < window_start) { - while (j < window_start) { - buffer->AddString(" "); - ++j; - } - } - for (; j < Utils::Minimum(window_end, i + kRowSize); j++) { - buffer->AddChar(j == start ? '|' : ' '); - buffer->Printf("%02x", static_cast(buffer_[j] % kMaxUint8)); - buffer->AddChar(j == start ? '|' : ' '); - } - buffer->AddChar('\n'); - } -} - -void ReadStream::PrintWindow(intptr_t start, intptr_t window_size) { - TextBuffer buffer(1024); - WriteWindow(&buffer, start, window_size); - OS::Print("%s", buffer.buffer()); -} - void BaseWriteStream::WriteTargetWord(word value) { ASSERT(compiler::target::kBitsPerWord == kBitsPerWord || Utils::IsAbsoluteUint(compiler::target::kBitsPerWord, value)); diff --git a/runtime/vm/datastream.h b/runtime/vm/datastream.h index fd343cd5cfc..7da4532621b 100644 --- a/runtime/vm/datastream.h +++ b/runtime/vm/datastream.h @@ -15,7 +15,14 @@ namespace dart { -class BaseTextBuffer; +static const int8_t kDataBitsPerByte = 7; +static const int8_t kByteMask = (1 << kDataBitsPerByte) - 1; +static const int8_t kMaxUnsignedDataPerByte = kByteMask; +static const int8_t kMinDataPerByte = -(1 << (kDataBitsPerByte - 1)); +static const int8_t kMaxDataPerByte = (~kMinDataPerByte & kByteMask); // NOLINT +static const uint8_t kEndByteMarker = (255 - kMaxDataPerByte); +static const uint8_t kEndUnsignedByteMarker = (255 - kMaxUnsignedDataPerByte); + struct LEB128Constants : AllStatic { // Convenience template for ensuring non-signed types trigger SFINAE. template @@ -28,13 +35,12 @@ struct LEB128Constants : AllStatic { typename std::enable_if::value, S>::type; // (S)LEB128 encodes 7 bits of data per byte (hence 128). - static constexpr size_t kDataBitsPerByte = 7; - static constexpr auto kDataByteMask = - Utils::NBitMask(kDataBitsPerByte); + static constexpr uint8_t kDataBitsPerByte = 7; + static constexpr uint8_t kDataByteMask = (1 << kDataBitsPerByte) - 1; // If more data follows a given data byte, the high bit is set. - static constexpr auto kMoreDataMask = Utils::Bit(kDataBitsPerByte); + static constexpr uint8_t kMoreDataMask = (1 << kDataBitsPerByte); // For SLEB128, the high bit in the data of the last byte is the sign bit. - static constexpr auto kSignMask = Utils::Bit(kDataBitsPerByte - 1); + static constexpr uint8_t kSignMask = (1 << (kDataBitsPerByte - 1)); }; class NonStreamingWriteStream; @@ -87,6 +93,11 @@ class ReadStream : public ValueObject { current_ += len; } + template + T ReadUnsigned() { + return Read(kEndUnsignedByteMarker); + } + intptr_t Position() const { return current_ - buffer_; } void SetPosition(intptr_t value) { ASSERT((end_ - buffer_) >= value); @@ -111,6 +122,11 @@ class ReadStream : public ValueObject { return (end_ - current_); } + template + T Read() { + return Read(kEndByteMarker); + } + uword ReadWordWith32BitReads() { constexpr intptr_t kNumRead32PerWord = kBitsPerWord / kBitsPerInt32; @@ -127,7 +143,7 @@ class ReadStream : public ValueObject { public: template - C::only_if_unsigned ReadUnsigned() { + C::only_if_unsigned ReadLEB128() { constexpr intptr_t kBitsPerT = kBitsPerByte * sizeof(T); T r = 0; uint8_t s = 0; @@ -143,12 +159,12 @@ class ReadStream : public ValueObject { } template - C::only_if_signed ReadUnsigned() { - return bit_cast(ReadUnsigned::type>()); + C::only_if_signed ReadLEB128() { + return bit_cast(ReadLEB128::type>()); } template - C::only_if_unsigned Read() { + C::only_if_unsigned ReadSLEB128() { constexpr intptr_t kBitsPerT = kBitsPerByte * sizeof(T); T r = 0; uint8_t s = 0; @@ -164,33 +180,114 @@ class ReadStream : public ValueObject { // value. If the value is negative and the count of data bits is less than // the size of the value, then we need to extend the sign by setting the // remaining (unset) most significant bits (MSBs). + T sign_bits = 0; if ((b & C::kSignMask) != 0 && s < kBitsPerT) { // Create a bitmask for the current data bits and invert it. - r |= ~Utils::NBitMask(s); + sign_bits = ~((static_cast(1) << s) - 1); } - return r; + return r | sign_bits; } template - C::only_if_signed Read() { - return bit_cast(Read::type>()); + C::only_if_signed ReadSLEB128() { + return bit_cast(ReadSLEB128::type>()); } private: - uint16_t Read16(); - uint32_t Read32(); - uint64_t Read64(); + uint16_t Read16() { return Read16(kEndByteMarker); } + + uint32_t Read32() { return Read32(kEndByteMarker); } + + uint64_t Read64() { return Read64(kEndByteMarker); } + + template + T Read(uint8_t end_byte_marker) { + using Unsigned = typename std::make_unsigned::type; + Unsigned b = ReadByte(); + if (b > kMaxUnsignedDataPerByte) { + return b - end_byte_marker; + } + T r = 0; + uint8_t s = 0; + do { + r |= static_cast(b) << s; + s += kDataBitsPerByte; + b = ReadByte(); + } while (b <= kMaxUnsignedDataPerByte); + return r | (static_cast(b - end_byte_marker) << s); + } + +// Setting up needed variables for the unrolled loop sections below. +#define UNROLLED_INIT() \ + using Unsigned = typename std::make_unsigned::type; \ + Unsigned b = ReadByte(); \ + if (b > kMaxUnsignedDataPerByte) { \ + return b - end_byte_marker; \ + } \ + T r = b; + +// Part of the unrolled loop where the loop may stop, having read the last part, +// or continue reading. +#define UNROLLED_BODY(bit_start) \ + static_assert(bit_start % kDataBitsPerByte == 0, \ + "Bit start must be a multiple of the data bits per byte"); \ + static_assert(bit_start >= 0 && bit_start < kBitsPerByte * sizeof(T), \ + "Starting unrolled body at invalid bit position"); \ + static_assert(bit_start + kDataBitsPerByte < kBitsPerByte * sizeof(T), \ + "Unrolled body should not contain final bits in value"); \ + b = ReadByte(); \ + if (b > kMaxUnsignedDataPerByte) { \ + return r | (static_cast(b - end_byte_marker) << bit_start); \ + } \ + r |= b << bit_start; + +// The end of the unrolled loop. +#define UNROLLED_END(bit_start) \ + static_assert(bit_start % kDataBitsPerByte == 0, \ + "Bit start must be a multiple of the data bits per byte"); \ + static_assert(bit_start >= 0 && bit_start < kBitsPerByte * sizeof(T), \ + "Starting unrolled end at invalid bit position"); \ + static_assert(bit_start + kDataBitsPerByte >= kBitsPerByte * sizeof(T), \ + "Unrolled end does not contain final bits in value"); \ + b = ReadByte(); \ + ASSERT(b > kMaxUnsignedDataPerByte); \ + return r | (static_cast(b - end_byte_marker) << bit_start); + + uint16_t Read16(uint8_t end_byte_marker) { + using T = uint16_t; + UNROLLED_INIT(); + UNROLLED_BODY(7); + UNROLLED_END(14); + } + + uint32_t Read32(uint8_t end_byte_marker) { + using T = uint32_t; + UNROLLED_INIT(); + UNROLLED_BODY(7); + UNROLLED_BODY(14); + UNROLLED_BODY(21); + UNROLLED_END(28); + } + + uint64_t Read64(uint8_t end_byte_marker) { + using T = uint64_t; + UNROLLED_INIT(); + UNROLLED_BODY(7); + UNROLLED_BODY(14); + UNROLLED_BODY(21); + UNROLLED_BODY(28); + UNROLLED_BODY(35); + UNROLLED_BODY(42); + UNROLLED_BODY(49); + UNROLLED_BODY(56); + UNROLLED_END(63); + } DART_FORCE_INLINE uint8_t ReadByte() { ASSERT(current_ < end_); return *current_++; } - void WriteWindow(BaseTextBuffer* buffer, - intptr_t start, - intptr_t window_size = 64); - void PrintWindow(intptr_t start, intptr_t window_size = 64); - private: const uint8_t* buffer_; const uint8_t* current_; @@ -267,6 +364,16 @@ class BaseWriteStream : public ValueObject { } } + template + void WriteUnsigned(T value) { + ASSERT(value >= 0); + while (value > kMaxUnsignedDataPerByte) { + WriteByte(static_cast(value & kByteMask)); + value = value >> kDataBitsPerByte; + } + WriteByte(static_cast(value + kEndUnsignedByteMarker)); + } + void WriteBytes(const void* addr, intptr_t len) { if (len != 0) { EnsureSpace(len); @@ -305,6 +412,16 @@ class BaseWriteStream : public ValueObject { current_ += len; // Not len + 1 to swallow the terminating NUL. } + template + void Write(T value) { + T v = value; + while (v < kMinDataPerByte || v > kMaxDataPerByte) { + WriteByte(static_cast(v & kByteMask)); + v = v >> kDataBitsPerByte; + } + WriteByte(static_cast(v + kEndByteMarker)); + } + template void WriteFixed(T value) { WriteBytes(&value, sizeof(value)); @@ -322,7 +439,7 @@ class BaseWriteStream : public ValueObject { public: template - C::only_if_unsigned WriteUnsigned(T value) { + C::only_if_unsigned WriteLEB128(T value) { T remainder = value; bool is_last_part; do { @@ -339,15 +456,15 @@ class BaseWriteStream : public ValueObject { } template - C::only_if_signed WriteUnsigned(T value) { + C::only_if_signed WriteLEB128(T value) { // If we're trying to LEB128 encode a negative value, chances are we should // be using SLEB128 instead. ASSERT(value >= 0); - return WriteUnsigned(bit_cast::type>(value)); + return WriteLEB128(bit_cast::type>(value)); } template - C::only_if_signed Write(T value) { + C::only_if_signed WriteSLEB128(T value) { constexpr intptr_t kBitsPerT = kBitsPerByte * sizeof(T); using Unsigned = typename std::make_unsigned::type; // Record whether the original value was negative. @@ -392,8 +509,8 @@ class BaseWriteStream : public ValueObject { } template - C::only_if_unsigned Write(T value) { - return Write(bit_cast::type>(value)); + C::only_if_unsigned WriteSLEB128(T value) { + return WriteSLEB128(bit_cast::type>(value)); } protected: diff --git a/runtime/vm/datastream_test.cc b/runtime/vm/datastream_test.cc index ec8eb5bf33a..0b9ba6c5f36 100644 --- a/runtime/vm/datastream_test.cc +++ b/runtime/vm/datastream_test.cc @@ -126,4 +126,60 @@ TEST_CASE(ReadStream_Read64) { TestRaw(); } +TEST_CASE(BaseWriteStream_WriteLEB128) { + MallocWriteStream writer(1 * KB); + for (uintptr_t i = 0; i < kUnsignedEnd; i++) { + writer.WriteLEB128(i); + } + DEFINE_LARGE_CONSTANTS(uintptr_t); + writer.WriteLEB128(all_ones); + writer.WriteLEB128(min); + writer.WriteLEB128(max); + writer.WriteLEB128(half_min); + writer.WriteLEB128(half_max); + ReadStream reader(writer.buffer(), writer.bytes_written()); + for (uintptr_t i = 0; i < kUnsignedEnd; i++) { + const uintptr_t r = reader.ReadLEB128(); + EXPECT_EQ(i, r); + } + const uintptr_t read_all_ones = reader.ReadLEB128(); + EXPECT_EQ(all_ones, read_all_ones); + const uintptr_t read_min = reader.ReadLEB128(); + EXPECT_EQ(min, read_min); + const uintptr_t read_max = reader.ReadLEB128(); + EXPECT_EQ(max, read_max); + const uintptr_t read_half_min = reader.ReadLEB128(); + EXPECT_EQ(half_min, read_half_min); + const uintptr_t read_half_max = reader.ReadLEB128(); + EXPECT_EQ(half_max, read_half_max); +} + +TEST_CASE(BaseWriteStream_WriteSLEB128) { + MallocWriteStream writer(1 * KB); + for (intptr_t i = kSignedStart; i < kSignedEnd; i++) { + writer.WriteSLEB128(i); + } + DEFINE_LARGE_CONSTANTS(intptr_t); + writer.WriteSLEB128(all_ones); + writer.WriteSLEB128(min); + writer.WriteSLEB128(max); + writer.WriteSLEB128(half_min); + writer.WriteSLEB128(half_max); + ReadStream reader(writer.buffer(), writer.bytes_written()); + for (intptr_t i = kSignedStart; i < kSignedEnd; i++) { + const intptr_t r = reader.ReadSLEB128(); + EXPECT_EQ(i, r); + } + const intptr_t read_all_ones = reader.ReadSLEB128(); + EXPECT_EQ(all_ones, read_all_ones); + const intptr_t read_min = reader.ReadSLEB128(); + EXPECT_EQ(min, read_min); + const intptr_t read_max = reader.ReadSLEB128(); + EXPECT_EQ(max, read_max); + const intptr_t read_half_min = reader.ReadSLEB128(); + EXPECT_EQ(half_min, read_half_min); + const intptr_t read_half_max = reader.ReadSLEB128(); + EXPECT_EQ(half_max, read_half_max); +} + } // namespace dart diff --git a/runtime/vm/elf.cc b/runtime/vm/elf.cc index dd11e4d5920..7f17df502c3 100644 --- a/runtime/vm/elf.cc +++ b/runtime/vm/elf.cc @@ -1106,8 +1106,8 @@ class DwarfElfStream : public DwarfWriteStream { stream_(ASSERT_NOTNULL(stream)), table_(table) {} - void sleb128(intptr_t value) { stream_->Write(value); } - void uleb128(uintptr_t value) { stream_->WriteUnsigned(value); } + void sleb128(intptr_t value) { stream_->WriteSLEB128(value); } + void uleb128(uintptr_t value) { stream_->WriteLEB128(value); } void u1(uint8_t value) { stream_->WriteByte(value); } void u2(uint16_t value) { stream_->WriteFixed(value); } void u4(uint32_t value) { stream_->WriteFixed(value); } diff --git a/runtime/vm/kernel_binary.h b/runtime/vm/kernel_binary.h index c14919a8a67..38ca8fa201c 100644 --- a/runtime/vm/kernel_binary.h +++ b/runtime/vm/kernel_binary.h @@ -309,14 +309,14 @@ class Reader : public ValueObject { intptr_t ReadSLEB128() { ReadStream stream(this->buffer(), size_, offset_); - const intptr_t result = stream.Read(); + const intptr_t result = stream.ReadSLEB128(); offset_ = stream.Position(); return result; } int64_t ReadSLEB128AsInt64() { ReadStream stream(this->buffer(), size_, offset_); - const int64_t result = stream.Read(); + const int64_t result = stream.ReadSLEB128(); offset_ = stream.Position(); return result; } diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc index 4a9f094f890..e163b570e1d 100644 --- a/runtime/vm/object.cc +++ b/runtime/vm/object.cc @@ -14667,7 +14667,7 @@ bool CompressedStackMaps::Iterator::MoveNext() { NoSafepointScope scope; ReadStream stream(maps_.untag()->data(), maps_.payload_size(), next_offset_); - auto const pc_delta = stream.ReadUnsigned(); + auto const pc_delta = stream.ReadLEB128(); ASSERT(pc_delta <= (kMaxUint32 - current_pc_offset_)); current_pc_offset_ += pc_delta; @@ -14675,7 +14675,7 @@ bool CompressedStackMaps::Iterator::MoveNext() { // the post-delta part of inlined entries has the same information as // global table entries. if (maps_.UsesGlobalTable()) { - current_global_table_offset_ = stream.ReadUnsigned(); + current_global_table_offset_ = stream.ReadLEB128(); ASSERT(current_global_table_offset_ < bits_container_.payload_size()); // Since generally we only use entries in the GC and the GC only needs @@ -14688,10 +14688,10 @@ bool CompressedStackMaps::Iterator::MoveNext() { next_offset_ = stream.Position(); } else { - current_spill_slot_bit_count_ = stream.ReadUnsigned(); + current_spill_slot_bit_count_ = stream.ReadLEB128(); ASSERT(current_spill_slot_bit_count_ >= 0); - current_non_spill_slot_bit_count_ = stream.ReadUnsigned(); + current_non_spill_slot_bit_count_ = stream.ReadLEB128(); ASSERT(current_non_spill_slot_bit_count_ >= 0); const auto stackmap_bits = @@ -14737,10 +14737,10 @@ void CompressedStackMaps::Iterator::LazyLoadGlobalTableEntry() const { bits_container_.payload_size(), current_global_table_offset_); - current_spill_slot_bit_count_ = stream.ReadUnsigned(); + current_spill_slot_bit_count_ = stream.ReadLEB128(); ASSERT(current_spill_slot_bit_count_ >= 0); - current_non_spill_slot_bit_count_ = stream.ReadUnsigned(); + current_non_spill_slot_bit_count_ = stream.ReadLEB128(); ASSERT(current_non_spill_slot_bit_count_ >= 0); const auto stackmap_bits = Length(); diff --git a/runtime/vm/object.h b/runtime/vm/object.h index a03be0a3c06..9ddb727c4c0 100644 --- a/runtime/vm/object.h +++ b/runtime/vm/object.h @@ -5641,7 +5641,7 @@ class PcDescriptors : public Object { byte_index_); // Moves to record that matches kind_mask_. while (byte_index_ < descriptors_.Length()) { - const int32_t kind_and_metadata = stream.Read(); + const int32_t kind_and_metadata = stream.ReadSLEB128(); cur_kind_ = UntaggedPcDescriptors::KindAndMetadata::DecodeKind( kind_and_metadata); cur_try_index_ = UntaggedPcDescriptors::KindAndMetadata::DecodeTryIndex( @@ -5650,12 +5650,12 @@ class PcDescriptors : public Object { UntaggedPcDescriptors::KindAndMetadata::DecodeYieldIndex( kind_and_metadata); - cur_pc_offset_ += stream.Read(); + cur_pc_offset_ += stream.ReadSLEB128(); if (!FLAG_precompiled_mode) { - cur_deopt_id_ += stream.Read(); - cur_token_pos_ = - Utils::AddWithWrapAround(cur_token_pos_, stream.Read()); + cur_deopt_id_ += stream.ReadSLEB128(); + cur_token_pos_ = Utils::AddWithWrapAround( + cur_token_pos_, stream.ReadSLEB128()); } byte_index_ = stream.Position(); diff --git a/runtime/vm/program_visitor.cc b/runtime/vm/program_visitor.cc index e90c8addc3c..4bb663a4dbd 100644 --- a/runtime/vm/program_visitor.cc +++ b/runtime/vm/program_visitor.cc @@ -502,8 +502,8 @@ class StackMapEntry : public ZoneAllocated { // initial offset of the entry in the array. intptr_t EncodeTo(NonStreamingWriteStream* stream) { auto const current_offset = stream->Position(); - stream->WriteUnsigned(spill_slot_bit_count_); - stream->WriteUnsigned(non_spill_slot_bit_count_); + stream->WriteLEB128(spill_slot_bit_count_); + stream->WriteLEB128(non_spill_slot_bit_count_); { NoSafepointScope scope; stream->WriteBytes(PayloadData(), PayloadLength()); @@ -711,8 +711,8 @@ void ProgramVisitor::NormalizeAndDedupCompressedStackMaps( StackMapEntry entry(zone_, it); const intptr_t entry_offset = entry_offsets_.LookupValue(&entry); const intptr_t pc_delta = it.pc_offset() - last_offset; - new_payload.WriteUnsigned(pc_delta); - new_payload.WriteUnsigned(entry_offset); + new_payload.WriteLEB128(pc_delta); + new_payload.WriteLEB128(entry_offset); last_offset = it.pc_offset(); } return CompressedStackMaps::NewUsingTable(new_payload.buffer(), diff --git a/runtime/vm/v8_snapshot_writer.h b/runtime/vm/v8_snapshot_writer.h index 99ba8323779..ea0a0e74b0e 100644 --- a/runtime/vm/v8_snapshot_writer.h +++ b/runtime/vm/v8_snapshot_writer.h @@ -58,7 +58,7 @@ class V8SnapshotProfileWriter : public ZoneAllocated { private: static constexpr size_t kIdSpaceBits = Utils::BitLength(static_cast(IdSpace::kArtificial)); - static constexpr int64_t kIdSpaceMask = Utils::NBitMask(kIdSpaceBits); + static constexpr int64_t kIdSpaceMask = Utils::NBitMaskUnsafe(kIdSpaceBits); static const char* IdSpaceToCString(IdSpace space); int64_t encoded_;