| OLD | NEW |
| (Empty) | |
| 1 //=- ThreadedStreamingCache.cpp - Cache for StreamingMemoryObject -*- C++ -*-=// |
| 2 // |
| 3 // The LLVM Compiler Infrastructure |
| 4 // |
| 5 // This file is distributed under the University of Illinois Open Source |
| 6 // License. See LICENSE.TXT for details. |
| 7 // |
| 8 //===----------------------------------------------------------------------===// |
| 9 |
| 10 #include "ThreadedStreamingCache.h" |
| 11 #include "llvm/Support/Compiler.h" |
| 12 #include "llvm/Support/Mutex.h" |
| 13 #include <cstring> |
| 14 |
| 15 using namespace llvm; |
| 16 using llvm::sys::ScopedLock; |
| 17 |
| 18 ThreadedStreamingCache::ThreadedStreamingCache( |
| 19 llvm::StreamingMemoryObject *S) : Streamer(S), |
| 20 Cache(kCacheSize), |
| 21 MinObjectSize(0), |
| 22 CacheBase(-1) { |
| 23 static_assert((kCacheSize & (kCacheSize - 1)) == 0, |
| 24 "kCacheSize must be a power of 2"); |
| 25 } |
| 26 |
| 27 bool ThreadedStreamingCache::fetchCacheLine(uint64_t address) const { |
| 28 uint64_t Base = address & kCacheSizeMask; |
| 29 uint64_t Ret; |
| 30 ScopedLock L(StreamerLock); |
| 31 if (Streamer->isValidAddress(Base + kCacheSize - 1)) { |
| 32 Ret = Streamer->readBytes(&Cache[0], kCacheSize, Base); |
| 33 if (Ret != kCacheSize) |
| 34 return true; |
| 35 MinObjectSize = Base + kCacheSize; |
| 36 } else { |
| 37 uint64_t End = Streamer->getExtent(); |
| 38 assert(End > address && End <= Base + kCacheSize); |
| 39 Ret = Streamer->readBytes(&Cache[0], End - Base, Base); |
| 40 if (Ret != (End - Base)) |
| 41 return true; |
| 42 MinObjectSize = End; |
| 43 } |
| 44 CacheBase = Base; |
| 45 return false; |
| 46 } |
| 47 |
| 48 uint64_t ThreadedStreamingCache::readBytes(uint8_t* Buf, uint64_t Size, |
| 49 uint64_t Address) const { |
| 50 // To keep the cache fetch simple, we currently require that no request cross |
| 51 // the cache line. This isn't a problem for the bitcode reader because it only |
| 52 // fetches a byte or a word at a time. |
| 53 if (Address < CacheBase || (Address + Size) > CacheBase + kCacheSize) { |
| 54 if ((Address & kCacheSizeMask) != ((Address + Size - 1) & kCacheSizeMask)) |
| 55 llvm::report_fatal_error("readBytes request spans cache lines"); |
| 56 if (fetchCacheLine(Address)) |
| 57 llvm::report_fatal_error("readBytes failed to fetch a full cache line"); |
| 58 } |
| 59 memcpy(Buf, &Cache[Address - CacheBase], Size); |
| 60 return Size; |
| 61 } |
| 62 |
| 63 uint64_t ThreadedStreamingCache::getExtent() const { |
| 64 llvm::report_fatal_error( |
| 65 "getExtent should not be called for pnacl streaming bitcode"); |
| 66 return 0; |
| 67 } |
| 68 |
| 69 bool ThreadedStreamingCache::isValidAddress(uint64_t address) const { |
| 70 if (address < MinObjectSize) |
| 71 return true; |
| 72 ScopedLock L(StreamerLock); |
| 73 bool Valid = Streamer->isValidAddress(address); |
| 74 if (Valid) |
| 75 MinObjectSize = address; |
| 76 return Valid; |
| 77 } |
| 78 |
| 79 bool ThreadedStreamingCache::dropLeadingBytes(size_t s) { |
| 80 ScopedLock L(StreamerLock); |
| 81 return Streamer->dropLeadingBytes(s); |
| 82 } |
| 83 |
| 84 void ThreadedStreamingCache::setKnownObjectSize(size_t size) { |
| 85 MinObjectSize = size; |
| 86 ScopedLock L(StreamerLock); |
| 87 Streamer->setKnownObjectSize(size); |
| 88 } |
| 89 |
| 90 const uint64_t ThreadedStreamingCache::kCacheSize; |
| 91 const uint64_t ThreadedStreamingCache::kCacheSizeMask; |
| 92 llvm::sys::SmartMutex<false> ThreadedStreamingCache::StreamerLock; |
| OLD | NEW |