Index: tools/pnacl-llc/ThreadedStreamingCache.cpp |
diff --git a/tools/pnacl-llc/ThreadedStreamingCache.cpp b/tools/pnacl-llc/ThreadedStreamingCache.cpp |
index 3b724e712281356ac4419f4a8cf66e6a0db96425..b62ee789084d337d28cb88d2e393cfabb5f7e9a8 100644 |
--- a/tools/pnacl-llc/ThreadedStreamingCache.cpp |
+++ b/tools/pnacl-llc/ThreadedStreamingCache.cpp |
@@ -24,48 +24,54 @@ ThreadedStreamingCache::ThreadedStreamingCache( |
"kCacheSize must be a power of 2"); |
} |
-int ThreadedStreamingCache::fetchCacheLine(uint64_t address) const { |
- uint64_t Base = address & kCacheSizeMask; |
- int Ret; |
+void ThreadedStreamingCache::fetchCacheLine(uint64_t Address) const { |
+ uint64_t Base = Address & kCacheSizeMask; |
+ uint64_t BytesFetched; |
ScopedLock L(StreamerLock); |
if (Streamer->isValidAddress(Base + kCacheSize - 1)) { |
- Ret = Streamer->readBytes(Base, kCacheSize, &Cache[0]); |
- assert(Ret == 0); |
+ BytesFetched = Streamer->readBytes(&Cache[0], kCacheSize, Base); |
+ if (BytesFetched != kCacheSize) { |
+ llvm::report_fatal_error( |
+ "fetchCacheLine failed to fetch a full cache line"); |
+ } |
MinObjectSize = Base + kCacheSize; |
} else { |
uint64_t End = Streamer->getExtent(); |
- assert(End > address && End <= Base + kCacheSize); |
- Ret = Streamer->readBytes(Base, End - Base, &Cache[0]); |
- assert(Ret == 0); |
+ assert(End > Address && End <= Base + kCacheSize); |
+ BytesFetched = Streamer->readBytes(&Cache[0], End - Base, Base); |
+ if (BytesFetched != (End - Base)) { |
+ llvm::report_fatal_error( |
+ "fetchCacheLine failed to fetch rest of stream"); |
+ } |
MinObjectSize = End; |
} |
CacheBase = Base; |
- return Ret; |
} |
-int ThreadedStreamingCache::readByte( |
- uint64_t address, uint8_t* ptr) const { |
- if (address < CacheBase || address >= CacheBase + kCacheSize) { |
- if(fetchCacheLine(address)) |
- return -1; |
- } |
- *ptr = Cache[address - CacheBase]; |
- return 0; |
-} |
- |
-int ThreadedStreamingCache::readBytes( |
- uint64_t address, uint64_t size, uint8_t* buf) const { |
+uint64_t ThreadedStreamingCache::readBytes(uint8_t* Buf, uint64_t Size, |
+ uint64_t Address) const { |
// To keep the cache fetch simple, we currently require that no request cross |
// the cache line. This isn't a problem for the bitcode reader because it only |
- // fetches a byte or a word at a time. |
- if (address < CacheBase || (address + size) > CacheBase + kCacheSize) { |
- if ((address & kCacheSizeMask) != ((address + size - 1) & kCacheSizeMask)) |
+ // fetches a byte or a word (word may be 4 to 8 bytes) at a time. |
+ uint64_t Upper = Address + Size; |
+ if (Address < CacheBase || Upper > CacheBase + kCacheSize) { |
+ // If completely outside of a cacheline, fetch the cacheline. |
+ if ((Address & kCacheSizeMask) != ((Upper - 1) & kCacheSizeMask)) |
llvm::report_fatal_error("readBytes request spans cache lines"); |
- if(fetchCacheLine(address)) |
- return -1; |
+ // Fetch a cache line first, which may be partial. |
+ fetchCacheLine(Address); |
} |
- memcpy(buf, &Cache[address - CacheBase], size); |
- return 0; |
+ // Now the start Address should at least fit in the cache line, |
+ // but Upper may still be beyond the Extent / MinObjectSize, so clamp. |
+ if (Upper > MinObjectSize) { |
+ // If in the cacheline but stretches beyone the MinObjectSize, |
+ // only read up to MinObjectSize (caller uses readBytes to check EOF, |
+ // and can guess / try to read more). MinObjectSize should be the same |
+ // as EOF in this case otherwise it would have fit in the cacheline. |
+ Size = MinObjectSize - Address; |
+ } |
+ memcpy(Buf, &Cache[Address - CacheBase], Size); |
+ return Size; |
} |
uint64_t ThreadedStreamingCache::getExtent() const { |
@@ -74,36 +80,25 @@ uint64_t ThreadedStreamingCache::getExtent() const { |
return 0; |
} |
-bool ThreadedStreamingCache::isValidAddress(uint64_t address) const { |
- if (address < MinObjectSize) |
+bool ThreadedStreamingCache::isValidAddress(uint64_t Address) const { |
+ if (Address < MinObjectSize) |
return true; |
ScopedLock L(StreamerLock); |
- bool Valid = Streamer->isValidAddress(address); |
+ bool Valid = Streamer->isValidAddress(Address); |
if (Valid) |
- MinObjectSize = address; |
+ MinObjectSize = Address; |
return Valid; |
} |
-bool ThreadedStreamingCache::isObjectEnd(uint64_t address) const { |
- if (address < MinObjectSize) |
- return false; |
- ScopedLock L(StreamerLock); |
- if (Streamer->isValidAddress(address)) { |
- MinObjectSize = address; |
- return false; |
- } |
- return Streamer->isObjectEnd(address); |
-} |
- |
-bool ThreadedStreamingCache::dropLeadingBytes(size_t s) { |
+bool ThreadedStreamingCache::dropLeadingBytes(size_t S) { |
ScopedLock L(StreamerLock); |
- return Streamer->dropLeadingBytes(s); |
+ return Streamer->dropLeadingBytes(S); |
} |
-void ThreadedStreamingCache::setKnownObjectSize(size_t size) { |
- MinObjectSize = size; |
+void ThreadedStreamingCache::setKnownObjectSize(size_t Size) { |
+ MinObjectSize = Size; |
ScopedLock L(StreamerLock); |
- Streamer->setKnownObjectSize(size); |
+ Streamer->setKnownObjectSize(Size); |
} |
const uint64_t ThreadedStreamingCache::kCacheSize; |