Index: lib/Bitcode/NaCl/Reader/NaClBitstreamReader.cpp |
diff --git a/lib/Bitcode/NaCl/Reader/NaClBitstreamReader.cpp b/lib/Bitcode/NaCl/Reader/NaClBitstreamReader.cpp |
index bd43d0b390e8edad754de9a8a8d7b6ad184a89d3..630ecdaa3316e619734fb965c3920ff8fa311b82 100644 |
--- a/lib/Bitcode/NaCl/Reader/NaClBitstreamReader.cpp |
+++ b/lib/Bitcode/NaCl/Reader/NaClBitstreamReader.cpp |
@@ -49,8 +49,7 @@ Fatal(const std::string &ErrorMessage) const { |
// the error occurred. |
std::string Buffer; |
raw_string_ostream StrBuf(Buffer); |
- naclbitc::ErrorAt(StrBuf, naclbitc::Fatal, Cursor.GetCurrentBitNo()) |
- << ErrorMessage; |
+ naclbitc::ErrorAt(StrBuf, naclbitc::Fatal, getCurrentBitNo()) << ErrorMessage; |
report_fatal_error(StrBuf.str()); |
} |
@@ -74,8 +73,7 @@ bool NaClBitstreamCursor::EnterSubBlock(unsigned BlockID, unsigned *NumWordsP) { |
const bool IsFixed = true; |
NaClBitcodeSelectorAbbrev |
CodeAbbrev(IsFixed, ReadVBR(naclbitc::CodeLenWidth)); |
- BlockScope.push_back(Block(&BitStream->getOrCreateBlockInfo(BlockID), |
- CodeAbbrev)); |
+ BlockScope.push_back(Block(BitStream->getBlockInfo(BlockID), CodeAbbrev)); |
SkipToFourByteBoundary(); |
unsigned NumWords = Read(naclbitc::BlockSizeWidth); |
if (NumWordsP) *NumWordsP = NumWords; |
@@ -330,13 +328,60 @@ void NaClBitstreamCursor::SkipAbbrevRecord() { |
SkipToByteBoundaryIfAligned(); |
} |
+namespace { |
+ |
+unsigned ValidBlockIDs[] = { |
+ naclbitc::BLOCKINFO_BLOCK_ID, |
+ naclbitc::CONSTANTS_BLOCK_ID, |
+ naclbitc::FUNCTION_BLOCK_ID, |
+ naclbitc::GLOBALVAR_BLOCK_ID, |
+ naclbitc::MODULE_BLOCK_ID, |
+ naclbitc::TOP_LEVEL_BLOCKID, |
+ naclbitc::TYPE_BLOCK_ID_NEW, |
+ naclbitc::VALUE_SYMTAB_BLOCK_ID |
+}; |
+ |
+} // end of anonymous namespace |
+ |
+NaClBitstreamReader::BlockInfoRecordsMap:: |
+BlockInfoRecordsMap() : IsFrozen(false) { |
+ for (size_t BlockID : ValidBlockIDs) { |
+ std::unique_ptr<BlockInfo> Info(new BlockInfo(BlockID)); |
+ KnownInfos.emplace(BlockID, std::move(Info)); |
+ } |
+} |
+ |
+NaClBitstreamReader::BlockInfo * NaClBitstreamReader::BlockInfoRecordsMap:: |
+getOrCreateUnknownBlockInfo(unsigned BlockID) { |
+ std::unique_lock<std::mutex> Lock(UnknownBlockInfoLock); |
+ while (true) { |
+ auto Pos = UnknownInfos.find(BlockID); |
+ if (Pos != UnknownInfos.end()) |
+ return Pos->second.get(); |
+ // Install, then let next iteration find. |
+ std::unique_ptr<BlockInfo> Info(new BlockInfo(BlockID)); |
+ UnknownInfos.emplace(BlockID, std::move(Info)); |
+ } |
+} |
+ |
+NaClBitstreamReader::BlockInfoRecordsMap::UpdateLock:: |
+UpdateLock(BlockInfoRecordsMap &BlockInfoRecords) |
+ : BlockInfoRecords(BlockInfoRecords), |
+ Lock(BlockInfoRecords.UpdateRecordsLock) {} |
+ |
+NaClBitstreamReader::BlockInfoRecordsMap::UpdateLock:: |
+~UpdateLock() { |
+ if (BlockInfoRecords.freeze()) |
+ report_fatal_error("Global abbreviations block frozen while building."); |
+} |
+ |
bool NaClBitstreamCursor::ReadBlockInfoBlock(NaClAbbrevListener *Listener) { |
- // If this is the second stream to get to the block info block, skip it. |
- if (BitStream->HasReadBlockInfoBlock) |
+ // If this is the second read of the block info block, skip it. |
+ if (BitStream->BlockInfoRecords->isFrozen()) |
return SkipBlock(); |
- BitStream->HasReadBlockInfoBlock = true; |
- |
+ NaClBitstreamReader::BlockInfoRecordsMap::UpdateLock |
+ Lock(*BitStream->BlockInfoRecords); |
unsigned NumWords; |
if (EnterSubBlock(naclbitc::BLOCKINFO_BLOCK_ID, &NumWords)) return true; |
@@ -387,7 +432,7 @@ bool NaClBitstreamCursor::ReadBlockInfoBlock(NaClAbbrevListener *Listener) { |
if (Record.size() < 1) return true; |
FoundSetBID = true; |
UpdateAbbrevs = |
- &BitStream->getOrCreateBlockInfo((unsigned)Record[0]).getAbbrevs(); |
+ &BitStream->getBlockInfo((unsigned)Record[0])->getAbbrevs(); |
if (Listener) { |
Listener->Values = Record; |
Listener->SetBID(); |