OLD | NEW |
---|---|
1 //=- ThreadedStreamingCache.cpp - Cache for StreamingMemoryObject -*- C++ -*-=// | 1 //=- ThreadedStreamingCache.cpp - Cache for StreamingMemoryObject -*- C++ -*-=// |
2 // | 2 // |
3 // The LLVM Compiler Infrastructure | 3 // The LLVM Compiler Infrastructure |
4 // | 4 // |
5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
7 // | 7 // |
8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
9 | 9 |
10 #include "ThreadedStreamingCache.h" | 10 #include "ThreadedStreamingCache.h" |
11 #include "llvm/Support/Compiler.h" | 11 #include "llvm/Support/Compiler.h" |
12 #include "llvm/Support/Mutex.h" | 12 #include "llvm/Support/Mutex.h" |
13 #include <cstring> | 13 #include <cstring> |
14 | 14 |
15 using namespace llvm; | 15 using namespace llvm; |
16 using llvm::sys::ScopedLock; | 16 using llvm::sys::ScopedLock; |
17 | 17 |
18 ThreadedStreamingCache::ThreadedStreamingCache( | 18 ThreadedStreamingCache::ThreadedStreamingCache( |
19 llvm::StreamingMemoryObject *S) : Streamer(S), | 19 llvm::StreamingMemoryObject *S) : Streamer(S), |
20 Cache(kCacheSize), | 20 Cache(kCacheSize), |
21 MinObjectSize(0), | 21 MinObjectSize(0), |
22 CacheBase(-1) { | 22 CacheBase(-1) { |
23 static_assert((kCacheSize & (kCacheSize - 1)) == 0, | 23 static_assert((kCacheSize & (kCacheSize - 1)) == 0, |
24 "kCacheSize must be a power of 2"); | 24 "kCacheSize must be a power of 2"); |
25 } | 25 } |
26 | 26 |
27 int ThreadedStreamingCache::fetchCacheLine(uint64_t address) const { | 27 void ThreadedStreamingCache::fetchCacheLine(uint64_t Address) const { |
28 uint64_t Base = address & kCacheSizeMask; | 28 uint64_t Base = Address & kCacheSizeMask; |
29 int Ret; | 29 uint64_t BytesFetched; |
30 ScopedLock L(StreamerLock); | 30 ScopedLock L(StreamerLock); |
31 if (Streamer->isValidAddress(Base + kCacheSize - 1)) { | 31 if (Streamer->isValidAddress(Base + kCacheSize - 1)) { |
32 Ret = Streamer->readBytes(Base, kCacheSize, &Cache[0]); | 32 BytesFetched = Streamer->readBytes(&Cache[0], kCacheSize, Base); |
33 assert(Ret == 0); | 33 if (BytesFetched != kCacheSize) { |
34 llvm::report_fatal_error( | |
35 "fetchCacheLine failed to fetch a full cache line"); | |
36 } | |
34 MinObjectSize = Base + kCacheSize; | 37 MinObjectSize = Base + kCacheSize; |
35 } else { | 38 } else { |
36 uint64_t End = Streamer->getExtent(); | 39 uint64_t End = Streamer->getExtent(); |
37 assert(End > address && End <= Base + kCacheSize); | 40 assert(End > Address && End <= Base + kCacheSize); |
38 Ret = Streamer->readBytes(Base, End - Base, &Cache[0]); | 41 BytesFetched = Streamer->readBytes(&Cache[0], End - Base, Base); |
39 assert(Ret == 0); | 42 if (BytesFetched != (End - Base)) { |
43 llvm::report_fatal_error( | |
44 "fetchCacheLine failed to fetch rest of stream"); | |
45 } | |
40 MinObjectSize = End; | 46 MinObjectSize = End; |
Karl
2015/02/23 17:46:55
Is this correct? Shouldn't it be relative to Base?
jvoung (off chromium)
2015/02/23 21:27:19
The: "Base = Address & kCacheSizeMask"?
As far as
Karl
2015/02/23 21:40:27
Ok. I see. I didn't realize that MinObjectSize was
| |
41 } | 47 } |
42 CacheBase = Base; | 48 CacheBase = Base; |
43 return Ret; | |
44 } | 49 } |
45 | 50 |
46 int ThreadedStreamingCache::readByte( | 51 uint64_t ThreadedStreamingCache::readBytes(uint8_t* Buf, uint64_t Size, |
47 uint64_t address, uint8_t* ptr) const { | 52 uint64_t Address) const { |
48 if (address < CacheBase || address >= CacheBase + kCacheSize) { | |
49 if(fetchCacheLine(address)) | |
50 return -1; | |
51 } | |
52 *ptr = Cache[address - CacheBase]; | |
53 return 0; | |
54 } | |
55 | |
56 int ThreadedStreamingCache::readBytes( | |
57 uint64_t address, uint64_t size, uint8_t* buf) const { | |
58 // To keep the cache fetch simple, we currently require that no request cross | 53 // To keep the cache fetch simple, we currently require that no request cross |
59 // the cache line. This isn't a problem for the bitcode reader because it only | 54 // the cache line. This isn't a problem for the bitcode reader because it only |
60 // fetches a byte or a word at a time. | 55 // fetches a byte or a word (word may be 4 to 8 bytes) at a time. |
61 if (address < CacheBase || (address + size) > CacheBase + kCacheSize) { | 56 uint64_t Upper = Address + Size; |
62 if ((address & kCacheSizeMask) != ((address + size - 1) & kCacheSizeMask)) | 57 if (Address < CacheBase || Upper > CacheBase + kCacheSize) { |
58 // If completely outside of a cacheline, fetch the cacheline. | |
59 if ((Address & kCacheSizeMask) != ((Upper - 1) & kCacheSizeMask)) | |
63 llvm::report_fatal_error("readBytes request spans cache lines"); | 60 llvm::report_fatal_error("readBytes request spans cache lines"); |
64 if(fetchCacheLine(address)) | 61 // Fetch a cache line first, which may be partial. |
65 return -1; | 62 fetchCacheLine(Address); |
66 } | 63 } |
67 memcpy(buf, &Cache[address - CacheBase], size); | 64 // Now the start Address should at least fit in the cache line, |
68 return 0; | 65 // but Upper may still be beyond the Extent / MinObjectSize, so clamp. |
66 if (Upper > MinObjectSize) { | |
67 // If in the cacheline but stretches beyone the MinObjectSize, | |
68 // only read up to MinObjectSize (caller uses readBytes to check EOF, | |
69 // and can guess / try to read more). MinObjectSize should be the same | |
70 // as EOF in this case otherwise it would have fit in the cacheline. | |
71 Size = MinObjectSize - Address; | |
72 } | |
73 memcpy(Buf, &Cache[Address - CacheBase], Size); | |
74 return Size; | |
69 } | 75 } |
70 | 76 |
71 uint64_t ThreadedStreamingCache::getExtent() const { | 77 uint64_t ThreadedStreamingCache::getExtent() const { |
72 llvm::report_fatal_error( | 78 llvm::report_fatal_error( |
73 "getExtent should not be called for pnacl streaming bitcode"); | 79 "getExtent should not be called for pnacl streaming bitcode"); |
74 return 0; | 80 return 0; |
75 } | 81 } |
76 | 82 |
77 bool ThreadedStreamingCache::isValidAddress(uint64_t address) const { | 83 bool ThreadedStreamingCache::isValidAddress(uint64_t Address) const { |
78 if (address < MinObjectSize) | 84 if (Address < MinObjectSize) |
79 return true; | 85 return true; |
80 ScopedLock L(StreamerLock); | 86 ScopedLock L(StreamerLock); |
81 bool Valid = Streamer->isValidAddress(address); | 87 bool Valid = Streamer->isValidAddress(Address); |
82 if (Valid) | 88 if (Valid) |
83 MinObjectSize = address; | 89 MinObjectSize = Address; |
84 return Valid; | 90 return Valid; |
85 } | 91 } |
86 | 92 |
87 bool ThreadedStreamingCache::isObjectEnd(uint64_t address) const { | 93 bool ThreadedStreamingCache::dropLeadingBytes(size_t S) { |
88 if (address < MinObjectSize) | |
89 return false; | |
90 ScopedLock L(StreamerLock); | 94 ScopedLock L(StreamerLock); |
91 if (Streamer->isValidAddress(address)) { | 95 return Streamer->dropLeadingBytes(S); |
92 MinObjectSize = address; | |
93 return false; | |
94 } | |
95 return Streamer->isObjectEnd(address); | |
96 } | 96 } |
97 | 97 |
98 bool ThreadedStreamingCache::dropLeadingBytes(size_t s) { | 98 void ThreadedStreamingCache::setKnownObjectSize(size_t Size) { |
99 MinObjectSize = Size; | |
99 ScopedLock L(StreamerLock); | 100 ScopedLock L(StreamerLock); |
100 return Streamer->dropLeadingBytes(s); | 101 Streamer->setKnownObjectSize(Size); |
101 } | |
102 | |
103 void ThreadedStreamingCache::setKnownObjectSize(size_t size) { | |
104 MinObjectSize = size; | |
105 ScopedLock L(StreamerLock); | |
106 Streamer->setKnownObjectSize(size); | |
107 } | 102 } |
108 | 103 |
109 const uint64_t ThreadedStreamingCache::kCacheSize; | 104 const uint64_t ThreadedStreamingCache::kCacheSize; |
110 const uint64_t ThreadedStreamingCache::kCacheSizeMask; | 105 const uint64_t ThreadedStreamingCache::kCacheSizeMask; |
111 llvm::sys::SmartMutex<false> ThreadedStreamingCache::StreamerLock; | 106 llvm::sys::SmartMutex<false> ThreadedStreamingCache::StreamerLock; |
OLD | NEW |