Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(332)

Side by Side Diff: src/core/SkSmallAllocator.h

Issue 1755293002: update SkSmallAllocator to force internal allocations to be 16-byte aligned (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « include/core/SkTypes.h ('k') | tests/SmallAllocatorTest.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2014 Google, Inc 2 * Copyright 2014 Google, Inc
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #ifndef SkSmallAllocator_DEFINED 8 #ifndef SkSmallAllocator_DEFINED
9 #define SkSmallAllocator_DEFINED 9 #define SkSmallAllocator_DEFINED
10 10
11 #include "SkTDArray.h" 11 #include "SkTDArray.h"
12 #include "SkTypes.h" 12 #include "SkTypes.h"
13 13
14 #include <new> 14 #include <new>
15 15
16 /* 16 /*
17 * Template class for allocating small objects without additional heap memory 17 * Template class for allocating small objects without additional heap memory
18 * allocations. kMaxObjects is a hard limit on the number of objects that can 18 * allocations. kMaxObjects is a hard limit on the number of objects that can
19 * be allocated using this class. After that, attempts to create more objects 19 * be allocated using this class. After that, attempts to create more objects
20 * with this class will assert and return nullptr. 20 * with this class will assert and return nullptr.
21 *
21 * kTotalBytes is the total number of bytes provided for storage for all 22 * kTotalBytes is the total number of bytes provided for storage for all
22 * objects created by this allocator. If an object to be created is larger 23 * objects created by this allocator. If an object to be created is larger
23 * than the storage (minus storage already used), it will be allocated on the 24 * than the storage (minus storage already used), it will be allocated on the
24 * heap. This class's destructor will handle calling the destructor for each 25 * heap. This class's destructor will handle calling the destructor for each
25 * object it allocated and freeing its memory. 26 * object it allocated and freeing its memory.
27 *
28 * Current the class always aligns each allocation to 16-bytes to be safe, but future
29 * may reduce this to only the alignment that is required per alloc.
26 */ 30 */
27 template<uint32_t kMaxObjects, size_t kTotalBytes> 31 template<uint32_t kMaxObjects, size_t kTotalBytes>
28 class SkSmallAllocator : SkNoncopyable { 32 class SkSmallAllocator : SkNoncopyable {
29 public: 33 public:
30 SkSmallAllocator() 34 SkSmallAllocator()
31 : fStorageUsed(0) 35 : fStorageUsed(0)
32 , fNumObjects(0) 36 , fNumObjects(0)
33 {} 37 {}
34 38
35 ~SkSmallAllocator() { 39 ~SkSmallAllocator() {
(...skipping 24 matching lines...) Expand all
60 return new (buf) T(args...); 64 return new (buf) T(args...);
61 } 65 }
62 66
63 /* 67 /*
64 * Reserve a specified amount of space (must be enough space for one T). 68 * Reserve a specified amount of space (must be enough space for one T).
65 * The space will be in fStorage if there is room, or on the heap otherwise . 69 * The space will be in fStorage if there is room, or on the heap otherwise .
66 * Either way, this class will call ~T() in its destructor and free the hea p 70 * Either way, this class will call ~T() in its destructor and free the hea p
67 * allocation if necessary. 71 * allocation if necessary.
68 * Unlike createT(), this method will not call the constructor of T. 72 * Unlike createT(), this method will not call the constructor of T.
69 */ 73 */
70 template<typename T> void* reserveT(size_t storageRequired = sizeof(T)) { 74 template<typename T> void* reserveT(size_t storageRequested = sizeof(T)) {
71 SkASSERT(fNumObjects < kMaxObjects); 75 SkASSERT(fNumObjects < kMaxObjects);
72 SkASSERT(storageRequired >= sizeof(T)); 76 SkASSERT(storageRequested >= sizeof(T));
73 if (kMaxObjects == fNumObjects) { 77 if (kMaxObjects == fNumObjects) {
74 return nullptr; 78 return nullptr;
75 } 79 }
76 const size_t storageRemaining = SkAlign4(kTotalBytes) - fStorageUsed; 80 const size_t storageRemaining = sizeof(fStorage) - fStorageUsed;
77 storageRequired = SkAlign4(storageRequired); 81 const size_t storageRequired = SkAlign16(storageRequested);
78 Rec* rec = &fRecs[fNumObjects]; 82 Rec* rec = &fRecs[fNumObjects];
79 if (storageRequired > storageRemaining) { 83 if (storageRequired > storageRemaining) {
80 // Allocate on the heap. Ideally we want to avoid this situation, 84 // Allocate on the heap. Ideally we want to avoid this situation,
81 // but we're not sure we can catch all callers, so handle it but 85 // but we're not sure we can catch all callers, so handle it but
82 // assert false in debug mode. 86 // assert false in debug mode.
83 SkASSERT(false); 87 SkASSERT(false);
84 rec->fStorageSize = 0; 88 rec->fStorageSize = 0;
85 rec->fHeapStorage = sk_malloc_throw(storageRequired); 89 rec->fHeapStorage = sk_malloc_throw(storageRequired);
86 rec->fObj = static_cast<void*>(rec->fHeapStorage); 90 rec->fObj = static_cast<void*>(rec->fHeapStorage);
87 } else { 91 } else {
88 // There is space in fStorage. 92 // There is space in fStorage.
89 rec->fStorageSize = storageRequired; 93 rec->fStorageSize = storageRequired;
90 rec->fHeapStorage = nullptr; 94 rec->fHeapStorage = nullptr;
91 SkASSERT(SkIsAlign4(fStorageUsed)); 95 SkASSERT(SkIsAlign16(fStorageUsed));
92 rec->fObj = static_cast<void*>(fStorage + (fStorageUsed / 4)); 96 rec->fObj = static_cast<void*>(fStorage.fBytes + fStorageUsed);
93 fStorageUsed += storageRequired; 97 fStorageUsed += storageRequired;
94 } 98 }
95 rec->fKillProc = DestroyT<T>; 99 rec->fKillProc = DestroyT<T>;
96 fNumObjects++; 100 fNumObjects++;
97 return rec->fObj; 101 return rec->fObj;
98 } 102 }
99 103
100 /* 104 /*
101 * Free the memory reserved last without calling the destructor. 105 * Free the memory reserved last without calling the destructor.
102 * Can be used in a nested way, i.e. after reserving A and B, calling 106 * Can be used in a nested way, i.e. after reserving A and B, calling
(...skipping 15 matching lines...) Expand all
118 void* fHeapStorage; 122 void* fHeapStorage;
119 void (*fKillProc)(void*); 123 void (*fKillProc)(void*);
120 }; 124 };
121 125
122 // Used to call the destructor for allocated objects. 126 // Used to call the destructor for allocated objects.
123 template<typename T> 127 template<typename T>
124 static void DestroyT(void* ptr) { 128 static void DestroyT(void* ptr) {
125 static_cast<T*>(ptr)->~T(); 129 static_cast<T*>(ptr)->~T();
126 } 130 }
127 131
132 struct SK_STRUCT_ALIGN(16) Storage {
133 // we add kMaxObjects * 15 to account for the worst-case slop, where eac h allocation wasted
134 // 15 bytes (due to forcing each to be 16-byte aligned)
135 char fBytes[kTotalBytes + kMaxObjects * 15];
136 };
137
138 Storage fStorage;
128 // Number of bytes used so far. 139 // Number of bytes used so far.
129 size_t fStorageUsed; 140 size_t fStorageUsed;
130 // Pad the storage size to be 4-byte aligned. 141 uint32_t fNumObjects;
131 uint32_t fStorage[SkAlign4(kTotalBytes) >> 2]; 142 Rec fRecs[kMaxObjects];
132 uint32_t fNumObjects;
133 Rec fRecs[kMaxObjects];
134 }; 143 };
135 144
136 #endif // SkSmallAllocator_DEFINED 145 #endif // SkSmallAllocator_DEFINED
OLDNEW
« no previous file with comments | « include/core/SkTypes.h ('k') | tests/SmallAllocatorTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698