41 : Allocator(Allocator), IsGrowable(CanGrow),
42 FreePageMap(kDefaultFreePageMap), BlockSize(BlockSize),
43 BlockMapAddr(kDefaultBlockMapAddr), FreeBlocks(MinBlockCount,
true) {
47 FreeBlocks[BlockMapAddr] =
false;
52 uint32_t MinBlockCount,
bool CanGrow) {
55 "The requested block size is unsupported");
63 if (Addr == BlockMapAddr)
66 if (Addr >= FreeBlocks.
size()) {
69 "Cannot grow the number of blocks");
70 FreeBlocks.
resize(Addr + 1,
true);
74 return make_error<MSFError>(
76 "Requested block map address is already in use");
77 FreeBlocks[BlockMapAddr] =
true;
78 FreeBlocks[Addr] =
false;
88 for (
auto B : DirectoryBlocks)
90 for (
auto B : DirBlocks) {
93 "Attempt to reuse an allocated block");
95 FreeBlocks[
B] =
false;
98 DirectoryBlocks = DirBlocks;
108 if (NumFreeBlocks < NumBlocks) {
111 "There are no free Blocks in the file");
112 uint32_t AllocBlocks = NumBlocks - NumFreeBlocks;
114 uint32_t NewBlockCount = AllocBlocks + OldBlockCount;
116 FreeBlocks.
resize(NewBlockCount,
true);
124 while (NextFpmBlock < NewBlockCount) {
126 FreeBlocks.
resize(NewBlockCount,
true);
127 FreeBlocks.
reset(NextFpmBlock, NextFpmBlock + 2);
128 NextFpmBlock += BlockSize;
135 assert(Block != -1 &&
"We ran out of Blocks!");
138 Blocks[I++] = NextBlock;
139 FreeBlocks.
reset(NextBlock);
141 }
while (--NumBlocks > 0);
161 if (ReqBlocks != Blocks.
size())
162 return make_error<MSFError>(
164 "Incorrect number of blocks for requested stream size");
165 for (
auto Block : Blocks) {
166 if (Block >= FreeBlocks.
size())
167 FreeBlocks.
resize(Block + 1,
true);
169 if (!FreeBlocks.
test(Block))
170 return make_error<MSFError>(
172 "Attempt to re-use an already allocated block");
175 for (
auto Block : Blocks) {
176 FreeBlocks.
reset(Block);
178 StreamData.push_back(std::make_pair(Size, Blocks));
179 return StreamData.size() - 1;
184 std::vector<uint32_t> NewBlocks;
185 NewBlocks.resize(ReqBlocks);
186 if (
auto EC = allocateBlocks(ReqBlocks, NewBlocks))
187 return std::move(EC);
188 StreamData.push_back(std::make_pair(Size, NewBlocks));
189 return StreamData.size() - 1;
200 if (NewBlocks > OldBlocks) {
201 uint32_t AddedBlocks = NewBlocks - OldBlocks;
203 std::vector<uint32_t> AddedBlockList;
204 AddedBlockList.resize(AddedBlocks);
205 if (
auto EC = allocateBlocks(AddedBlocks, AddedBlockList))
207 auto &CurrentBlocks = StreamData[Idx].second;
208 CurrentBlocks.insert(CurrentBlocks.end(), AddedBlockList.begin(),
209 AddedBlockList.end());
210 }
else if (OldBlocks > NewBlocks) {
213 uint32_t RemovedBlocks = OldBlocks - NewBlocks;
215 auto RemovedBlockList = CurrentBlocks.
drop_front(NewBlocks);
216 for (
auto P : RemovedBlockList)
217 FreeBlocks[
P] =
true;
218 StreamData[Idx].second = CurrentBlocks.drop_back(RemovedBlocks);
221 StreamData[Idx].first =
Size;
228 return StreamData[StreamIdx].first;
232 return StreamData[StreamIdx].second;
235 uint32_t MSFBuilder::computeDirectoryByteSize()
const {
242 for (
const auto &
D : StreamData) {
244 assert(ExpectedNumBlocks ==
D.second.size() &&
245 "Unexpected number of blocks");
264 if (NumDirectoryBlocks > DirectoryBlocks.size()) {
267 std::vector<uint32_t> ExtraBlocks;
268 uint32_t NumExtraBlocks = NumDirectoryBlocks - DirectoryBlocks.size();
269 ExtraBlocks.resize(NumExtraBlocks);
270 if (
auto EC = allocateBlocks(NumExtraBlocks, ExtraBlocks))
271 return std::move(EC);
272 DirectoryBlocks.insert(DirectoryBlocks.end(), ExtraBlocks.begin(),
274 }
else if (NumDirectoryBlocks < DirectoryBlocks.size()) {
275 uint32_t NumUnnecessaryBlocks = DirectoryBlocks.size() - NumDirectoryBlocks;
278 FreeBlocks[
B] =
true;
279 DirectoryBlocks.resize(NumDirectoryBlocks);
288 std::uninitialized_copy_n(DirectoryBlocks.begin(), NumDirectoryBlocks,
294 if (!StreamData.empty()) {
297 L.StreamMap.resize(StreamData.size());
299 Sizes[
I] = StreamData[
I].first;
302 std::uninitialized_copy_n(StreamData[
I].
second.begin(),
303 StreamData[
I].second.size(), BlockList);
309 L.FreePageMap = FreeBlocks;
325 while (BI < Layout.SB->NumBlocks) {
326 uint8_t ThisByte = 0;
330 uint8_t
Mask = uint8_t(IsFree) <<
I;
345 Layout = std::move(*L);
349 if (
auto EC = OutFileOrError.takeError())
350 return std::move(EC);
357 return std::move(EC);
365 return std::move(EC);
368 Layout, Buffer, Allocator);
371 return std::move(EC);
374 return std::move(EC);
376 for (
const auto &Blocks : Layout.
StreamMap) {
378 return std::move(EC);
381 return std::move(Buffer);
Error writeObject(const T &Obj)
Writes the object Obj to the underlying stream, as if by using memcpy.
void resize(unsigned N, bool t=false)
resize - Grow or shrink the bitvector.
char MagicBytes[sizeof(Magic)]
void setFreePageMap(uint32_t Fpm)
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
static std::unique_ptr< WritableMappedBlockStream > createDirectoryStream(const MSFLayout &Layout, WritableBinaryStreamRef MsfData, BumpPtrAllocator &Allocator)
GCNRegPressure max(const GCNRegPressure &P1, const GCNRegPressure &P2)
static Expected< std::unique_ptr< FileOutputBuffer > > create(StringRef FilePath, size_t Size, unsigned Flags=0)
Factory method to create an OutputBuffer object which manages a read/write buffer of the specified si...
This class represents lattice values for constants.
static const uint32_t kFreePageMap0Block
Error setBlockMapAddr(uint32_t Addr)
Request the block map to be at a specific block address.
uint64_t blockToOffset(uint64_t BlockNumber, uint64_t BlockSize)
bool test(unsigned Idx) const
uint32_t getMinimumBlockCount()
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...
block Block Frequency true
Error takeError()
Take ownership of the stored error.
Expected< MSFLayout > generateLayout()
Finalize the layout and build the headers and structures that describe the MSF layout and can be writ...
static const uint32_t kNumReservedPages
static const uint32_t kDefaultFreePageMap
int find_first() const
find_first - Returns the index of the first set bit, -1 if none of the bits are set.
int find_next(unsigned Prev) const
find_next - Returns the index of the next set bit following the "Prev" bit.
uint32_t getNumFreeBlocks() const
Get the total number of blocks that exist in the MSF file but are not allocated to any valid data...
Tagged union holding either a T or a Error.
static const uint32_t kSuperBlockBlock
Error setDirectoryBlocksHint(ArrayRef< uint32_t > DirBlocks)
support::ulittle32_t BlockSize
Error writeArray(ArrayRef< T > Array)
Writes an array of objects of type T to the underlying stream, as if by using memcpy.
static void commitFpm(WritableBinaryStream &MsfBuffer, const MSFLayout &Layout, BumpPtrAllocator &Allocator)
uint32_t getNumUsedBlocks() const
Get the total number of blocks that will be allocated to actual data in this MSF file.
support::ulittle32_t BlockMapAddr
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...
uint32_t getTotalBlockCount() const
Get the total number of blocks in the MSF file.
detail::packed_endian_specific_integral< uint32_t, little, unaligned > ulittle32_t
Allocate memory in an ever growing pool, as if by bump-pointer.
size_t size() const
size - Get the array size.
LLVM_ATTRIBUTE_RETURNS_NONNULL LLVM_ATTRIBUTE_RETURNS_NOALIAS void * Allocate(size_t Size, size_t Alignment)
Allocate space at the specified alignment.
bool isBlockFree(uint32_t Idx) const
Check whether a particular block is allocated or free.
Provides write only access to a subclass of WritableBinaryStream.
static const char Magic[]
Error writeInteger(T Value)
Write the integer Value to the underlying stream in the specified endianness.
support::ulittle32_t Unknown1
uint32_t getStreamSize(uint32_t StreamIdx) const
Get the size of a stream by index.
uint32_t bytesRemaining() const
Error setStreamSize(uint32_t Idx, uint32_t Size)
Update the size of an existing stream.
static const int BlockSize
static const uint32_t kDefaultBlockMapAddr
static ErrorSuccess success()
Create a success value.
size_type count() const
count - Returns the number of bits which are set.
ArrayRef< support::ulittle32_t > DirectoryBlocks
static std::unique_ptr< WritableMappedBlockStream > createFpmStream(const MSFLayout &Layout, WritableBinaryStreamRef MsfData, BumpPtrAllocator &Allocator, bool AltFpm=false)
Expected< uint32_t > addStream(uint32_t Size, ArrayRef< uint32_t > Blocks)
Add a stream to the MSF file with the given size, occupying the given list of blocks.
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
Expected< FileBufferByteStream > commit(StringRef Path, MSFLayout &Layout)
Write the MSF layout to the underlying file.
void setOffset(uint32_t Off)
uint32_t getNumStreams() const
Get the total number of streams in the MSF layout.
uint64_t bytesToBlocks(uint64_t NumBytes, uint64_t BlockSize)
static const uint32_t kFreePageMap1Block
ArrayRef< T > drop_front(size_t N=1) const
Drop the first N elements of the array.
void setUnknown1(uint32_t Unk1)
size_type size() const
size - Returns the number of bits in this bitvector.
std::vector< ArrayRef< support::ulittle32_t > > StreamMap
ArrayRef< uint32_t > getStreamBlocks(uint32_t StreamIdx) const
Get the list of blocks allocated to a particular stream.
ArrayRef< support::ulittle32_t > StreamSizes
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
support::ulittle32_t FreeBlockMapBlock
Lightweight error class with error context and mandatory checking.
std::underlying_type< E >::type Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
bool isValidBlockSize(uint32_t Size)
An implementation of WritableBinaryStream backed by an llvm FileOutputBuffer.
StringRef - Represent a constant reference to a string, i.e.
support::ulittle32_t NumDirectoryBytes
support::ulittle32_t NumBlocks
A BinaryStream which can be read from as well as written to.