tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

BlobCache.h (6233B)


      1 //
      2 // Copyright 2018 The ANGLE Project Authors. All rights reserved.
      3 // Use of this source code is governed by a BSD-style license that can be
      4 // found in the LICENSE file.
      5 //
      6 // BlobCache: Stores compiled and linked programs in memory so they don't
      7 //   always have to be re-compiled. Can be used in conjunction with the platform
      8 //   layer to warm up the cache from disk.
      9 
     10 #ifndef LIBANGLE_BLOB_CACHE_H_
     11 #define LIBANGLE_BLOB_CACHE_H_
     12 
     13 #include <array>
     14 #include <cstring>
     15 
     16 #include <anglebase/sha1.h>
     17 #include "common/MemoryBuffer.h"
     18 #include "common/hash_utils.h"
     19 #include "libANGLE/Error.h"
     20 #include "libANGLE/SizedMRUCache.h"
     21 
     22 namespace gl
     23 {
     24 class Context;
     25 }  // namespace gl
     26 
     27 namespace egl
     28 {
     29 // 160-bit SHA-1 hash key used for hasing a program.  BlobCache opts in using fixed keys for
     30 // simplicity and efficiency.
     31 static constexpr size_t kBlobCacheKeyLength = angle::base::kSHA1Length;
     32 using BlobCacheKey                          = std::array<uint8_t, kBlobCacheKeyLength>;
     33 }  // namespace egl
     34 
     35 namespace std
     36 {
     37 template <>
     38 struct hash<egl::BlobCacheKey>
     39 {
     40    // Simple routine to hash four ints.
     41    size_t operator()(const egl::BlobCacheKey &key) const
     42    {
     43        return angle::ComputeGenericHash(key.data(), key.size());
     44    }
     45 };
     46 }  // namespace std
     47 
     48 namespace egl
     49 {
     50 
     51 bool CompressBlobCacheData(const size_t cacheSize,
     52                           const uint8_t *cacheData,
     53                           angle::MemoryBuffer *compressedData);
     54 bool DecompressBlobCacheData(const uint8_t *compressedData,
     55                             const size_t compressedSize,
     56                             angle::MemoryBuffer *uncompressedData);
     57 
     58 class BlobCache final : angle::NonCopyable
     59 {
     60  public:
     61    // 160-bit SHA-1 hash key used for hasing a program.  BlobCache opts in using fixed keys for
     62    // simplicity and efficiency.
     63    static constexpr size_t kKeyLength = kBlobCacheKeyLength;
     64    using Key                          = BlobCacheKey;
     65    class Value
     66    {
     67      public:
     68        Value() : mPtr(nullptr), mSize(0) {}
     69        Value(const uint8_t *ptr, size_t sz) : mPtr(ptr), mSize(sz) {}
     70 
     71        // A very basic struct to hold the pointer and size together.  The objects of this class
     72        // don't own the memory.
     73        const uint8_t *data() { return mPtr; }
     74        size_t size() { return mSize; }
     75 
     76        const uint8_t &operator[](size_t pos) const
     77        {
     78            ASSERT(pos < mSize);
     79            return mPtr[pos];
     80        }
     81 
     82      private:
     83        const uint8_t *mPtr;
     84        size_t mSize;
     85    };
     86    enum class CacheSource
     87    {
     88        Memory,
     89        Disk,
     90    };
     91 
     92    explicit BlobCache(size_t maxCacheSizeBytes);
     93    ~BlobCache();
     94 
     95    // Store a key-blob pair in the cache.  If application callbacks are set, the application cache
     96    // will be used.  Otherwise the value is cached in this object.
     97    void put(const BlobCache::Key &key, angle::MemoryBuffer &&value);
     98 
     99    // Store a key-blob pair in the cache, but compress the blob before insertion. Returns false if
    100    // compression fails, returns true otherwise.
    101    bool compressAndPut(const BlobCache::Key &key,
    102                        angle::MemoryBuffer &&uncompressedValue,
    103                        size_t *compressedSize);
    104 
    105    // Store a key-blob pair in the application cache, only if application callbacks are set.
    106    void putApplication(const BlobCache::Key &key, const angle::MemoryBuffer &value);
    107 
    108    // Store a key-blob pair in the cache without making callbacks to the application.  This is used
    109    // to repopulate this object's cache on startup without generating callback calls.
    110    void populate(const BlobCache::Key &key,
    111                  angle::MemoryBuffer &&value,
    112                  CacheSource source = CacheSource::Disk);
    113 
    114    // Check if the cache contains the blob corresponding to this key.  If application callbacks are
    115    // set, those will be used.  Otherwise they key is looked up in this object's cache.
    116    [[nodiscard]] bool get(angle::ScratchBuffer *scratchBuffer,
    117                           const BlobCache::Key &key,
    118                           BlobCache::Value *valueOut,
    119                           size_t *bufferSizeOut);
    120 
    121    // For querying the contents of the cache.
    122    [[nodiscard]] bool getAt(size_t index,
    123                             const BlobCache::Key **keyOut,
    124                             BlobCache::Value *valueOut);
    125 
    126    enum class GetAndDecompressResult
    127    {
    128        GetSuccess,
    129        NotFound,
    130        DecompressFailure,
    131    };
    132    [[nodiscard]] GetAndDecompressResult getAndDecompress(
    133        angle::ScratchBuffer *scratchBuffer,
    134        const BlobCache::Key &key,
    135        angle::MemoryBuffer *uncompressedValueOut);
    136 
    137    // Evict a blob from the binary cache.
    138    void remove(const BlobCache::Key &key);
    139 
    140    // Empty the cache.
    141    void clear() { mBlobCache.clear(); }
    142 
    143    // Resize the cache. Discards current contents.
    144    void resize(size_t maxCacheSizeBytes) { mBlobCache.resize(maxCacheSizeBytes); }
    145 
    146    // Returns the number of entries in the cache.
    147    size_t entryCount() const { return mBlobCache.entryCount(); }
    148 
    149    // Reduces the current cache size and returns the number of bytes freed.
    150    size_t trim(size_t limit) { return mBlobCache.shrinkToSize(limit); }
    151 
    152    // Returns the current cache size in bytes.
    153    size_t size() const { return mBlobCache.size(); }
    154 
    155    // Returns whether the cache is empty
    156    bool empty() const { return mBlobCache.empty(); }
    157 
    158    // Returns the maximum cache size in bytes.
    159    size_t maxSize() const { return mBlobCache.maxSize(); }
    160 
    161    void setBlobCacheFuncs(EGLSetBlobFuncANDROID set, EGLGetBlobFuncANDROID get);
    162 
    163    bool areBlobCacheFuncsSet() const;
    164 
    165    bool isCachingEnabled() const { return areBlobCacheFuncsSet() || maxSize() > 0; }
    166 
    167    std::mutex &getMutex() { return mBlobCacheMutex; }
    168 
    169  private:
    170    // This internal cache is used only if the application is not providing caching callbacks
    171    using CacheEntry = std::pair<angle::MemoryBuffer, CacheSource>;
    172 
    173    mutable std::mutex mBlobCacheMutex;
    174    angle::SizedMRUCache<BlobCache::Key, CacheEntry> mBlobCache;
    175 
    176    EGLSetBlobFuncANDROID mSetBlobFunc;
    177    EGLGetBlobFuncANDROID mGetBlobFunc;
    178 };
    179 
    180 }  // namespace egl
    181 
    182 #endif  // LIBANGLE_MEMORY_PROGRAM_CACHE_H_