1 //
2 // Copyright (c) 2015 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 
7 // Cache.cpp: Implements a cache for various commonly created objects.
8 
9 #include <limits>
10 
11 #include "common/angleutils.h"
12 #include "common/debug.h"
13 #include "compiler/translator/Cache.h"
14 
15 namespace sh
16 {
17 
18 namespace
19 {
20 
21 class TScopedAllocator : angle::NonCopyable
22 {
23   public:
TScopedAllocator(TPoolAllocator * allocator)24     TScopedAllocator(TPoolAllocator *allocator) : mPreviousAllocator(GetGlobalPoolAllocator())
25     {
26         SetGlobalPoolAllocator(allocator);
27     }
~TScopedAllocator()28     ~TScopedAllocator() { SetGlobalPoolAllocator(mPreviousAllocator); }
29 
30   private:
31     TPoolAllocator *mPreviousAllocator;
32 };
33 
34 }  // namespace
35 
TypeKey(TBasicType basicType,TPrecision precision,TQualifier qualifier,unsigned char primarySize,unsigned char secondarySize)36 TCache::TypeKey::TypeKey(TBasicType basicType,
37                          TPrecision precision,
38                          TQualifier qualifier,
39                          unsigned char primarySize,
40                          unsigned char secondarySize)
41 {
42     static_assert(sizeof(components) <= sizeof(value), "TypeKey::value is too small");
43 
44     const size_t MaxEnumValue = std::numeric_limits<EnumComponentType>::max();
45 
46     // TODO: change to static_assert() once we deprecate MSVC 2013 support
47     ASSERT(MaxEnumValue >= EbtLast && MaxEnumValue >= EbpLast && MaxEnumValue >= EvqLast &&
48            "TypeKey::EnumComponentType is too small");
49 
50     value                    = 0;
51     components.basicType     = static_cast<EnumComponentType>(basicType);
52     components.precision     = static_cast<EnumComponentType>(precision);
53     components.qualifier     = static_cast<EnumComponentType>(qualifier);
54     components.primarySize   = primarySize;
55     components.secondarySize = secondarySize;
56 }
57 
58 TCache *TCache::sCache = nullptr;
59 
TCache()60 TCache::TCache()
61 {
62 }
63 
initialize()64 void TCache::initialize()
65 {
66     if (sCache == nullptr)
67     {
68         sCache = new TCache();
69     }
70 }
71 
destroy()72 void TCache::destroy()
73 {
74     SafeDelete(sCache);
75 }
76 
getType(TBasicType basicType,TPrecision precision,TQualifier qualifier,unsigned char primarySize,unsigned char secondarySize)77 const TType *TCache::getType(TBasicType basicType,
78                              TPrecision precision,
79                              TQualifier qualifier,
80                              unsigned char primarySize,
81                              unsigned char secondarySize)
82 {
83     TypeKey key(basicType, precision, qualifier, primarySize, secondarySize);
84     auto it = sCache->mTypes.find(key);
85     if (it != sCache->mTypes.end())
86     {
87         return it->second;
88     }
89 
90     TScopedAllocator scopedAllocator(&sCache->mAllocator);
91 
92     TType *type = new TType(basicType, precision, qualifier, primarySize, secondarySize);
93     type->realize();
94     sCache->mTypes.insert(std::make_pair(key, type));
95 
96     return type;
97 }
98 
99 }  // namespace sh
100