Chromium Code Reviews| Index: include/llvm/Bitcode/NaCl/NaClBitstreamReader.h |
| diff --git a/include/llvm/Bitcode/NaCl/NaClBitstreamReader.h b/include/llvm/Bitcode/NaCl/NaClBitstreamReader.h |
| index 05cd91eb2aa92af2eb788d8c7289919604754b2e..29b476e4c1722a84594e4ac7d735c36c4d45e2da 100644 |
| --- a/include/llvm/Bitcode/NaCl/NaClBitstreamReader.h |
| +++ b/include/llvm/Bitcode/NaCl/NaClBitstreamReader.h |
| @@ -27,6 +27,7 @@ |
| namespace llvm { |
| class Deserializer; |
| +class NaClBitstreamCursor; |
| namespace naclbitc { |
| @@ -55,12 +56,93 @@ raw_ostream &ErrorAt(raw_ostream &Out, ErrorLevel Level, |
| /// the NaClBitstreamCursor class. |
| class NaClBitstreamReader { |
| public: |
| - /// This contains information emitted to BLOCKINFO_BLOCK blocks. These |
| - /// describe abbreviations that all blocks of the specified ID inherit. |
| - struct BlockInfo { |
| + // Models a raw list of abbreviations. |
| + static const size_t DefaultAbbrevListSize = 12; |
| + using AbbrevListVector = SmallVector<NaClBitCodeAbbrev *, |
| + DefaultAbbrevListSize>; |
| + |
| + // Models and maintains a list of abbreviations. In particular, it maintains |
| + // updating reference counts of abbreviation operators within the abbreviation |
| + // list. |
| + class AbbrevList { |
| + public: |
| + AbbrevList() = default; |
| + explicit AbbrevList(const AbbrevList &NewAbbrevs) { |
| + appendList(NewAbbrevs); |
| + } |
| + AbbrevList &operator=(const AbbrevList &Rhs) { |
| + clear(); |
| + appendList(Rhs); |
| + return *this; |
| + } |
| + // appends Abbrev assuming that Abbv is not shared (i.e. already has the |
| + // refernce count incremented). Takes ownership of Abbv. |
| + void appendUnique(NaClBitCodeAbbrev *Abbv) { |
|
Derek Schuff
2016/03/17 16:20:17
Does appendUnique mean that nothing else will ever
Karl
2016/03/17 18:37:08
Simplified the class by adding a "appendCreate" me
|
| + Abbrevs.push_back(Abbv); |
| + } |
| + // appends Abbrev assuming that that Abbv is shared elsewhere (i.e. has not |
| + // yet had the reference count incremented for sharing). |
| + void appendShare(NaClBitCodeAbbrev *Abbrv) { |
| + Abbrv->addRef(); |
| + Abbrevs.push_back(Abbrv); |
| + } |
| + // Returns last abbreviation on list, and returns an unique reference (i.e. |
| + // the reference count has been incremented before returning). |
| + NaClBitCodeAbbrev *lastUnique() { |
| + NaClBitCodeAbbrev *Abbrv = Abbrevs.back(); |
| + Abbrv->addRef(); |
| + return Abbrv; |
| + } |
| + // Removes the last element of the list. |
| + void popLast() { |
| + Abbrevs.back()->dropRef(); |
| + Abbrevs.pop_back(); |
| + } |
| + // Copies contents of NewAbbrevs and appends to this. |
| + void appendList(const AbbrevList &NewAbbrevs) { |
| + for (NaClBitCodeAbbrev *Abbrv : NewAbbrevs.Abbrevs) |
| + appendShare(Abbrv); |
| + } |
| + // Empties abbreviation list. |
| + void clear() { |
| + while(!Abbrevs.empty()) |
| + popLast(); |
| + } |
| + // Allow read access to vector defining list. |
| + const AbbrevListVector &getVector() const { return Abbrevs; } |
| + ~AbbrevList() { clear(); } |
| + private: |
| + AbbrevListVector Abbrevs; |
| + }; |
| + |
| + /// This contains information about abbreviations in blocks defined in the |
| + /// BLOCKINFO_BLOCK block. These describe global abbreviations that apply to |
| + /// all succeeding blocks of the specified ID. |
| + class BlockInfo { |
| + BlockInfo &operator=(const BlockInfo&) = delete; |
| + public: |
| + BlockInfo() = default; |
| + explicit BlockInfo(unsigned BlockID) |
| + : BlockID(BlockID), Abbrevs() {} |
| + BlockInfo(const BlockInfo&) = default; |
| + unsigned getBlockID() const { return BlockID; } |
| + void setBlockID(unsigned ID) { BlockID = ID; } |
| + AbbrevList &getAbbrevs() { return Abbrevs; } |
| + // Allow read access to vector defining abbreviation list. |
| + const AbbrevListVector &getVector() const { |
| + return Abbrevs.getVector(); |
| + } |
| + // appends Abbrev assuming that Abbv is not shared (i.e. already has the |
| + // refernce count incremented). Takes ownership of Abbv. |
| + void appendUnique(NaClBitCodeAbbrev *Abbv) { |
| + Abbrevs.appendUnique(Abbv); |
| + } |
| + ~BlockInfo() {} |
| + private: |
| unsigned BlockID; |
| - std::vector<NaClBitCodeAbbrev*> Abbrevs; |
| + AbbrevList Abbrevs; |
| }; |
| + |
| private: |
| friend class NaClBitstreamCursor; |
| @@ -68,6 +150,9 @@ private: |
| std::vector<BlockInfo> BlockInfoRecords; |
| + // True if the BlockInfo block has been read. |
| + bool HasReadBlockInfoBlock = false; |
| + |
| /// \brief Holds the offset of the first byte after the header. |
| size_t InitialAddress; |
| @@ -106,17 +191,7 @@ public: |
| // Returns the memory object that is being read. |
| MemoryObject &getBitcodeBytes() { return *BitcodeBytes; } |
| - ~NaClBitstreamReader() { |
| - // Free the BlockInfoRecords. |
| - while (!BlockInfoRecords.empty()) { |
| - BlockInfo &Info = BlockInfoRecords.back(); |
| - // Free blockinfo abbrev info. |
| - for (unsigned i = 0, e = static_cast<unsigned>(Info.Abbrevs.size()); |
| - i != e; ++i) |
| - Info.Abbrevs[i]->dropRef(); |
| - BlockInfoRecords.pop_back(); |
| - } |
| - } |
| + ~NaClBitstreamReader() {} |
| /// \brief Returns the initial address (after the header) of the input stream. |
| size_t getInitialAddress() const { |
| @@ -127,21 +202,17 @@ public: |
| // Block Manipulation |
| //===--------------------------------------------------------------------===// |
| - /// Return true if we've already read and processed the block info block for |
| - /// this Bitstream. We only process it for the first cursor that walks over |
| - /// it. |
| - bool hasBlockInfoRecords() const { return !BlockInfoRecords.empty(); } |
| - |
| /// If there is block info for the specified ID, return it, otherwise return |
| /// null. |
| const BlockInfo *getBlockInfo(unsigned BlockID) const { |
| // Common case, the most recent entry matches BlockID. |
| - if (!BlockInfoRecords.empty() && BlockInfoRecords.back().BlockID == BlockID) |
| + if (!BlockInfoRecords.empty() && |
| + BlockInfoRecords.back().getBlockID() == BlockID) |
| return &BlockInfoRecords.back(); |
| for (unsigned i = 0, e = static_cast<unsigned>(BlockInfoRecords.size()); |
| i != e; ++i) |
| - if (BlockInfoRecords[i].BlockID == BlockID) |
| + if (BlockInfoRecords[i].getBlockID() == BlockID) |
| return &BlockInfoRecords[i]; |
| return nullptr; |
| } |
| @@ -151,8 +222,7 @@ public: |
| return *const_cast<BlockInfo*>(BI); |
| // Otherwise, add a new record. |
| - BlockInfoRecords.push_back(BlockInfo()); |
| - BlockInfoRecords.back().BlockID = BlockID; |
| + BlockInfoRecords.push_back(BlockInfo(BlockID)); |
| return BlockInfoRecords.back(); |
| } |
| }; |
| @@ -205,7 +275,7 @@ public: |
| virtual ~NaClAbbrevListener() {} |
| /// Called to process the read abbreviation. |
| - virtual void ProcessAbbreviation(NaClBitCodeAbbrev *Abbrev, |
| + virtual void ProcessAbbreviation(NaClBitCodeAbbrev *Abbrv, |
| bool IsLocal) = 0; |
| /// Called after entering block. NumWords is the number of words |
| @@ -276,22 +346,67 @@ private: |
| /// is always from [0...bits_of(word_t)-1] inclusive. |
| unsigned BitsInCurWord; |
| - /// This is the declared size of code values used for the current |
| - /// block, in bits. |
| - NaClBitcodeSelectorAbbrev CurCodeSize; |
| - |
| - /// Abbrevs installed in this block. |
| - std::vector<NaClBitCodeAbbrev*> CurAbbrevs; |
| - |
| - struct Block { |
| - NaClBitcodeSelectorAbbrev PrevCodeSize; |
| - std::vector<NaClBitCodeAbbrev*> PrevAbbrevs; |
| - Block() : PrevCodeSize() {} |
| - explicit Block(const NaClBitcodeSelectorAbbrev& PCS) |
| - : PrevCodeSize(PCS) {} |
| + // Data specific to a block being scanned. |
| + class Block { |
| + public: |
| + Block() = delete; |
| + Block &operator=(const Block &Rhs) { |
| + GlobalAbbrevs = Rhs.GlobalAbbrevs; |
| + NumGlobalAbbrevs = Rhs.NumGlobalAbbrevs; |
| + LocalAbbrevs = Rhs.LocalAbbrevs; |
| + CodeAbbrev = Rhs.CodeAbbrev; |
| + return *this; |
| + } |
| + Block(NaClBitstreamReader::BlockInfo *GlobalAbbrevs, |
| + NaClBitcodeSelectorAbbrev& CodeAbbrev) |
| + : GlobalAbbrevs(GlobalAbbrevs), |
| + NumGlobalAbbrevs(GlobalAbbrevs->getVector().size()), |
| + LocalAbbrevs(), CodeAbbrev(CodeAbbrev) {} |
| + Block(NaClBitstreamReader::BlockInfo *GlobalAbbrevs) |
| + : GlobalAbbrevs(GlobalAbbrevs), |
| + NumGlobalAbbrevs(GlobalAbbrevs->getVector().size()), |
| + LocalAbbrevs(), CodeAbbrev() {} |
| + ~Block() = default; |
| + const NaClBitstreamReader::AbbrevList &getGlobalAbbrevs() const { |
| + return GlobalAbbrevs->getAbbrevs(); |
| + } |
| + unsigned getNumGlobalAbbrevs() const { return NumGlobalAbbrevs; } |
| + const NaClBitstreamReader::AbbrevList &getLocalAbbrevs() const { |
| + return LocalAbbrevs; |
| + } |
| + const NaClBitcodeSelectorAbbrev &getCodeAbbrev() const { |
| + return CodeAbbrev; |
| + } |
| + void setCodeAbbrev(NaClBitcodeSelectorAbbrev &Abbrev) { |
| + CodeAbbrev = Abbrev; |
| + } |
| + // Appends Abbrev to local abbreviations assuming that Abbv is not shared |
| + // (i.e. already has the refernce count incremented). Takes ownship of Abbv. |
| + void appendUniqueLocalAbbrev(NaClBitCodeAbbrev *Abbv) { |
| + LocalAbbrevs.appendUnique(Abbv); |
| + } |
| + /// removes the last added local abbreviation and moves it to the given |
| + /// abbreviation list. |
| + void moveLocalAbbrevToAbbrevList(NaClBitstreamReader::AbbrevList *List) { |
| + NaClBitCodeAbbrev *Abbv = LocalAbbrevs.lastUnique(); |
| + LocalAbbrevs.popLast(); |
| + List->appendUnique(Abbv); |
| + } |
| + private: |
| + friend class NaClBitstreamCursor; |
| + // The global abbreviations associated with this scope. |
| + NaClBitstreamReader::BlockInfo *GlobalAbbrevs; |
| + // Number of abbreviations when block was entered. Used to limit scope of |
| + // CurBlockInfo, since any abbreviation added inside a BlockInfo block |
| + // (within this block) must not effect global abbreviations. |
| + unsigned NumGlobalAbbrevs; |
| + NaClBitstreamReader::AbbrevList LocalAbbrevs; |
| + // This is the declared size of code values used for the current block, in |
| + // bits. |
| + NaClBitcodeSelectorAbbrev CodeAbbrev; |
| }; |
| - /// This tracks the codesize of parent blocks. |
| + /// This tracks the Block-specific information for each nested block. |
| SmallVector<Block, 8> BlockScope; |
| NaClBitstreamCursor(const NaClBitstreamCursor &) = delete; |
| @@ -311,13 +426,20 @@ public: |
| NextChar = (BitStream == nullptr) ? 0 : BitStream->getInitialAddress(); |
| Size = 0; |
| BitsInCurWord = 0; |
| + if (BitStream) { |
| + BlockScope.push_back( |
| + Block(&BitStream->getOrCreateBlockInfo(naclbitc::TOP_LEVEL_BLOCKID))); |
| + } |
| } |
| ~NaClBitstreamCursor() { |
| freeState(); |
| } |
| - void freeState(); |
| + void freeState() { |
| + while (!BlockScope.empty()) |
| + BlockScope.pop_back(); |
| + } |
| // Replaces the current bitstream error handler with the new |
| // handler. Takes ownership of the new handler and deletes it when |
| @@ -342,7 +464,9 @@ public: |
| } |
| /// Return the number of bits used to encode an abbrev #. |
| - unsigned getAbbrevIDWidth() const { return CurCodeSize.NumBits; } |
| + unsigned getAbbrevIDWidth() const { |
| + return BlockScope.back().getCodeAbbrev().NumBits; |
| + } |
| /// Return the bit # of the bit we are reading. |
| uint64_t GetCurrentBitNo() const { |
| @@ -559,9 +683,11 @@ private: |
| public: |
| unsigned ReadCode() { |
| - return CurCodeSize.IsFixed |
| - ? Read(CurCodeSize.NumBits) |
| - : ReadVBR(CurCodeSize.NumBits); |
| + const NaClBitcodeSelectorAbbrev &CodeAbbrev = |
| + BlockScope.back().getCodeAbbrev(); |
| + return CodeAbbrev.IsFixed |
| + ? Read(CodeAbbrev.NumBits) |
| + : ReadVBR(CodeAbbrev.NumBits); |
| } |
| // Block header: |
| @@ -602,24 +728,12 @@ public: |
| // [END_BLOCK, <align4bytes>] |
| SkipToFourByteBoundary(); |
| - popBlockScope(); |
| + BlockScope.pop_back(); |
| return false; |
| } |
| private: |
| - void popBlockScope() { |
| - CurCodeSize = BlockScope.back().PrevCodeSize; |
| - |
| - // Delete abbrevs from popped scope. |
| - for (unsigned i = 0, e = static_cast<unsigned>(CurAbbrevs.size()); |
| - i != e; ++i) |
| - CurAbbrevs[i]->dropRef(); |
| - |
| - BlockScope.back().PrevAbbrevs.swap(CurAbbrevs); |
| - BlockScope.pop_back(); |
| - } |
| - |
| //===--------------------------------------------------------------------===// |
| // Record Processing |
| //===--------------------------------------------------------------------===// |
| @@ -657,9 +771,16 @@ public: |
| /// Return the abbreviation for the specified AbbrevId. |
| const NaClBitCodeAbbrev *getAbbrev(unsigned AbbrevID) const { |
| unsigned AbbrevNo = AbbrevID-naclbitc::FIRST_APPLICATION_ABBREV; |
| - if (AbbrevNo >= CurAbbrevs.size()) |
| + const Block &CurBlock = BlockScope.back(); |
| + const unsigned NumGlobalAbbrevs = CurBlock.getNumGlobalAbbrevs(); |
| + if (AbbrevNo < NumGlobalAbbrevs) |
| + return CurBlock.getGlobalAbbrevs().getVector()[AbbrevNo]; |
| + unsigned LocalAbbrevNo = AbbrevNo - NumGlobalAbbrevs; |
| + NaClBitstreamReader::AbbrevListVector |
| + LocalAbbrevs = CurBlock.getLocalAbbrevs().getVector(); |
| + if (LocalAbbrevNo >= LocalAbbrevs.size()) |
| reportInvalidAbbrevNumber(AbbrevID); |
| - return CurAbbrevs[AbbrevNo]; |
| + return LocalAbbrevs[LocalAbbrevNo]; |
| } |
| /// Read the current record and discard it. |