18 using namespace llvm::msf;
21 template <
typename Base>
class MappedBlockStreamImpl :
public Base {
23 template <
typename...
Args>
24 MappedBlockStreamImpl(
Args &&... Params)
25 : Base(std::forward<
Args>(Params)...) {}
33 assert(FpmBlock == 1 || FpmBlock == 2);
34 while (NumFpmIntervals > 0) {
35 FpmLayout.
Blocks.push_back(FpmBlock);
42 typedef std::pair<uint32_t, uint32_t>
Interval;
44 return std::make_pair(std::max(I1.first, I2.first),
51 : BlockSize(BlockSize), NumBlocks(NumBlocks), StreamLayout(Layout),
54 std::unique_ptr<MappedBlockStream>
58 return llvm::make_unique<MappedBlockStreamImpl<MappedBlockStream>>(
59 BlockSize, NumBlocks, Layout, MsfData);
62 std::unique_ptr<MappedBlockStream>
66 assert(StreamIndex < Layout.
StreamMap.size() &&
"Invalid stream index");
70 return llvm::make_unique<MappedBlockStreamImpl<MappedBlockStream>>(
74 std::unique_ptr<MappedBlockStream>
83 std::unique_ptr<MappedBlockStream>
94 if (Size > StreamLayout.
Length)
96 if (Offset > StreamLayout.
Length - Size)
99 if (tryReadContiguously(Offset, Size, Buffer))
102 auto CacheIter = CacheMap.find(Offset);
103 if (CacheIter != CacheMap.end()) {
105 for (
auto &Entry : CacheIter->second) {
106 if (Entry.size() >= Size) {
107 Buffer = Entry.
slice(0, Size);
116 for (
auto &CacheItem : CacheMap) {
117 Interval RequestExtent = std::make_pair(Offset, Offset + Size);
120 if (CacheItem.first == Offset)
124 if (CacheItem.first >= Offset + Size)
129 if (CacheItem.second.empty())
132 auto CachedAlloc = CacheItem.second.back();
136 std::make_pair(CacheItem.first, CacheItem.first + CachedAlloc.size());
137 if (RequestExtent.first >= CachedExtent.first + CachedExtent.second)
143 if (Intersection != RequestExtent)
148 Buffer = CachedAlloc.
slice(CacheRangeOffset, Size);
156 uint8_t *WriteBuffer =
static_cast<uint8_t *
>(Pool.
Allocate(Size, 8));
160 if (CacheIter != CacheMap.end()) {
161 CacheIter->second.emplace_back(WriteBuffer, Size);
163 std::vector<CacheEntry>
List;
164 List.emplace_back(WriteBuffer, Size);
165 CacheMap.insert(std::make_pair(Offset, List));
174 if (Offset >= StreamLayout.
Length)
176 uint32_t First = Offset / BlockSize;
179 while (Last < NumBlocks - 1) {
180 if (StreamLayout.
Blocks[Last] != StreamLayout.
Blocks[Last + 1] - 1)
185 uint32_t OffsetInFirstBlock = Offset % BlockSize;
186 uint32_t BytesFromFirstBlock = BlockSize - OffsetInFirstBlock;
187 uint32_t BlockSpan = Last - First + 1;
188 uint32_t ByteSpan = BytesFromFirstBlock + (BlockSpan - 1) * BlockSize;
192 if (
auto EC = MsfData.
readBytes(MsfOffset, BlockSize, BlockData))
195 BlockData = BlockData.drop_front(OffsetInFirstBlock);
213 uint32_t BlockNum = Offset / BlockSize;
214 uint32_t OffsetInBlock = Offset % BlockSize;
217 llvm::alignTo(Size - BytesFromFirstBlock, BlockSize) / BlockSize;
219 uint32_t RequiredContiguousBlocks = NumAdditionalBlocks + 1;
221 for (
uint32_t I = 0;
I < RequiredContiguousBlocks; ++
I, ++
E) {
222 if (StreamLayout.
Blocks[
I + BlockNum] != E)
234 if (
auto EC = MsfData.
readBytes(MsfOffset, BlockSize, BlockData)) {
238 BlockData = BlockData.
drop_front(OffsetInBlock);
245 uint32_t BlockNum = Offset / BlockSize;
246 uint32_t OffsetInBlock = Offset % BlockSize;
251 if (Offset > StreamLayout.
Length - Buffer.
size())
256 uint8_t *WriteBuffer = Buffer.
data();
257 while (BytesLeft > 0) {
262 if (
auto EC = MsfData.
readBytes(Offset, BlockSize, BlockData))
265 const uint8_t *ChunkStart = BlockData.
data() + OffsetInBlock;
267 ::memcpy(WriteBuffer + BytesWritten, ChunkStart, BytesInChunk);
269 BytesWritten += BytesInChunk;
270 BytesLeft -= BytesInChunk;
284 void MappedBlockStream::fixCacheAfterWrite(
uint32_t Offset,
290 for (
const auto &MapEntry : CacheMap) {
293 if (Offset + Data.
size() < MapEntry.first)
295 for (
const auto &Alloc : MapEntry.second) {
298 if (MapEntry.first + Alloc.size() <
Offset)
302 Interval WriteInterval = std::make_pair(Offset, Offset + Data.
size());
304 std::make_pair(MapEntry.first, MapEntry.first + Alloc.size());
307 auto Intersection =
intersect(WriteInterval, CachedInterval);
308 assert(Intersection.first <= Intersection.second);
310 uint32_t Length = Intersection.second - Intersection.first;
315 ::memcpy(Alloc.data() + DestOffset, Data.
data() + SrcOffset, Length);
323 : ReadInterface(BlockSize, NumBlocks, Layout, MsfData),
324 WriteInterface(MsfData) {}
326 std::unique_ptr<WritableMappedBlockStream>
330 return llvm::make_unique<MappedBlockStreamImpl<WritableMappedBlockStream>>(
334 std::unique_ptr<WritableMappedBlockStream>
338 assert(StreamIndex < Layout.
StreamMap.size() &&
"Invalid stream index");
345 std::unique_ptr<WritableMappedBlockStream>
354 std::unique_ptr<WritableMappedBlockStream>
364 return ReadInterface.
readBytes(Offset, Size, Buffer);
390 while (BytesLeft > 0) {
395 const uint8_t *Chunk = Buffer.
data() + BytesWritten;
398 MsfOffset += OffsetInBlock;
399 if (
auto EC = WriteInterface.
writeBytes(MsfOffset, ChunkData))
402 BytesLeft -= BytesToWriteInChunk;
403 BytesWritten += BytesToWriteInChunk;
408 ReadInterface.fixCacheAfterWrite(Offset, Buffer);
414 return WriteInterface.
commit();
static std::unique_ptr< MappedBlockStream > createStream(uint32_t BlockSize, uint32_t NumBlocks, const MSFStreamLayout &Layout, const ReadableStream &MsfData)
Error writeBytes(uint32_t Offset, ArrayRef< uint8_t > Buffer) const override
static void initializeFpmStreamLayout(const MSFLayout &Layout, MSFStreamLayout &FpmLayout)
size_t getBytesAllocated() const
Interval Class - An Interval is a set of nodes defined such that every node in the interval has all o...
uint64_t blockToOffset(uint64_t BlockNumber, uint64_t BlockSize)
static std::unique_ptr< WritableMappedBlockStream > createDirectoryStream(const MSFLayout &Layout, const WritableStream &MsfData)
static Interval intersect(const Interval &I1, const Interval &I2)
uint64_t alignTo(uint64_t Value, uint64_t Align, uint64_t Skew=0)
Returns the next integer (mod 2**64) that is greater than or equal to Value and is a multiple of Alig...
uint32_t getLength() const override
ArrayRef< T > slice(size_t N, size_t M) const
slice(n, m) - Chop off the first N elements of the array, and keep M elements in the array...
Describes the layout of a stream in an MSF layout.
Error readLongestContiguousChunk(uint32_t Offset, ArrayRef< uint8_t > &Buffer) const override
Error readBytes(uint32_t Offset, uint32_t Size, ArrayRef< uint8_t > &Buffer) const override
uint32_t getFpmIntervalLength(const MSFLayout &L)
static std::unique_ptr< WritableMappedBlockStream > createFpmStream(const MSFLayout &Layout, const WritableStream &MsfData)
static std::unique_ptr< MappedBlockStream > createDirectoryStream(const MSFLayout &Layout, const ReadableStream &MsfData)
static std::unique_ptr< WritableMappedBlockStream > createStream(uint32_t BlockSize, uint32_t NumBlocks, const MSFStreamLayout &Layout, const WritableStream &MsfData)
std::vector< support::ulittle32_t > Blocks
static std::unique_ptr< MappedBlockStream > createFpmStream(const MSFLayout &Layout, const ReadableStream &MsfData)
support::ulittle32_t BlockSize
Error readBytes(uint32_t Offset, uint32_t Size, ArrayRef< uint8_t > &Buffer) const override
size_t size() const
size - Get the array size.
Maximum length of the test input libFuzzer tries to guess a good value based on the corpus and reports it always prefer smaller inputs during the corpus shuffle When libFuzzer itself reports a bug this exit code will be used If indicates the maximal total time in seconds to run the fuzzer minimizes the provided crash input Use with etc Experimental Use value profile to guide fuzzing Number of simultaneous worker processes to run the jobs If min(jobs, NumberOfCpuCores()/2)\" is used.") FUZZER_FLAG_INT(reload
static GCRegistry::Add< CoreCLRGC > E("coreclr","CoreCLR-compatible GC")
MappedBlockStream(uint32_t BlockSize, uint32_t NumBlocks, const MSFStreamLayout &StreamLayout, const ReadableStream &MsfData)
LLVM_ATTRIBUTE_RETURNS_NONNULL LLVM_ATTRIBUTE_RETURNS_NOALIAS void * Allocate(size_t Size, size_t Alignment)
Allocate space at the specified alignment.
virtual Error commit() const =0
void consumeError(Error Err)
Consume a Error without doing anything.
uint32_t getStreamLength() const
uint32_t getNumFpmIntervals(const MSFLayout &L)
static const int BlockSize
std::pair< uint32_t, uint32_t > Interval
static ErrorSuccess success()
Create a success value.
WritableMappedBlockStream(uint32_t BlockSize, uint32_t NumBlocks, const MSFStreamLayout &StreamLayout, const WritableStream &MsfData)
ArrayRef< support::ulittle32_t > DirectoryBlocks
static std::unique_ptr< MappedBlockStream > createIndexedStream(const MSFLayout &Layout, const ReadableStream &MsfData, uint32_t StreamIndex)
Error readLongestContiguousChunk(uint32_t Offset, ArrayRef< uint8_t > &Buffer) const override
virtual Error readBytes(uint32_t Offset, uint32_t Size, ArrayRef< uint8_t > &Buffer) const =0
uint32_t getNumBytesCopied() const
uint32_t getLength() const override
std::enable_if< std::is_unsigned< T >::value, T >::type AbsoluteDifference(T X, T Y)
Subtract two unsigned integers, X and Y, of type T and return the absolute value of the result...
std::vector< ArrayRef< support::ulittle32_t > > StreamMap
static std::unique_ptr< WritableMappedBlockStream > createIndexedStream(const MSFLayout &Layout, const WritableStream &MsfData, uint32_t StreamIndex)
uint32_t getFullFpmByteSize(const MSFLayout &L)
ArrayRef< support::ulittle32_t > StreamSizes
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
ArrayRef< T > drop_front(size_t N=1) const
Drop the first N elements of the array.
support::ulittle32_t FreeBlockMapBlock
Error commit() const override
Lightweight error class with error context and mandatory checking.
uint32_t getBlockSize() const
support::ulittle32_t NumDirectoryBytes
support::ulittle32_t NumBlocks
const MSFStreamLayout & getStreamLayout() const
virtual Error writeBytes(uint32_t Offset, ArrayRef< uint8_t > Data) const =0