blob: 31f32ec7c333deb5d8abdad5aa3bc3af37a57116 [file] [log] [blame]
John Stiles5c7bb322020-10-22 11:09:15 -04001/*
2 * Copyright 2020 Google LLC
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "src/sksl/SkSLPool.h"
9
John Stiles15bfe382020-10-27 19:07:05 -040010#include <bitset>
11
John Stiles2d68ea32020-10-22 15:42:27 -040012#include "include/private/SkMutex.h"
John Stiles5c7bb322020-10-22 11:09:15 -040013
14#define VLOG(...) // printf(__VA_ARGS__)
15
16namespace SkSL {
17
John Stiles0bb9ec52020-10-22 11:35:18 -040018#if defined(SK_BUILD_FOR_IOS) && \
19 (!defined(__IPHONE_9_0) || __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_9_0)
20
21#include <pthread.h>
22
23static pthread_key_t get_pthread_key() {
24 static pthread_key_t sKey = []{
25 pthread_key_t key;
26 int result = pthread_key_create(&key, /*destructor=*/nullptr);
27 if (result != 0) {
28 SK_ABORT("pthread_key_create failure: %d", result);
29 }
30 return key;
31 }();
32 return sKey;
33}
34
John Stiles23e68662020-10-29 10:17:15 -040035static MemoryPool* get_thread_local_memory_pool() {
36 return static_cast<MemoryPool*>(pthread_getspecific(get_pthread_key()));
John Stiles0bb9ec52020-10-22 11:35:18 -040037}
38
John Stiles23e68662020-10-29 10:17:15 -040039static void set_thread_local_memory_pool(MemoryPool* poolData) {
John Stiles0bb9ec52020-10-22 11:35:18 -040040 pthread_setspecific(get_pthread_key(), poolData);
41}
42
43#else
44
John Stiles23e68662020-10-29 10:17:15 -040045static thread_local MemoryPool* sMemPool = nullptr;
John Stiles5c7bb322020-10-22 11:09:15 -040046
John Stiles23e68662020-10-29 10:17:15 -040047static MemoryPool* get_thread_local_memory_pool() {
48 return sMemPool;
John Stiles0bb9ec52020-10-22 11:35:18 -040049}
50
John Stiles23e68662020-10-29 10:17:15 -040051static void set_thread_local_memory_pool(MemoryPool* memPool) {
52 sMemPool = memPool;
John Stiles0bb9ec52020-10-22 11:35:18 -040053}
54
55#endif
56
John Stiles2d68ea32020-10-22 15:42:27 -040057static Pool* sRecycledPool; // GUARDED_BY recycled_pool_mutex
58static SkMutex& recycled_pool_mutex() {
59 static SkMutex* mutex = new SkMutex;
60 return *mutex;
61}
62
John Stiles5c7bb322020-10-22 11:09:15 -040063Pool::~Pool() {
John Stiles23e68662020-10-29 10:17:15 -040064 if (get_thread_local_memory_pool() == fMemPool.get()) {
John Stiles5c7bb322020-10-22 11:09:15 -040065 SkDEBUGFAIL("SkSL pool is being destroyed while it is still attached to the thread");
John Stiles23e68662020-10-29 10:17:15 -040066 set_thread_local_memory_pool(nullptr);
John Stiles5c7bb322020-10-22 11:09:15 -040067 }
68
John Stiles23e68662020-10-29 10:17:15 -040069 fMemPool->reportLeaks();
70 SkASSERT(fMemPool->isEmpty());
John Stiles5c7bb322020-10-22 11:09:15 -040071
John Stiles23e68662020-10-29 10:17:15 -040072 VLOG("DELETE Pool:0x%016llX\n", (uint64_t)fMemPool.get());
John Stiles5c7bb322020-10-22 11:09:15 -040073}
74
John Stiles2d68ea32020-10-22 15:42:27 -040075std::unique_ptr<Pool> Pool::Create() {
John Stiles2d68ea32020-10-22 15:42:27 -040076 SkAutoMutexExclusive lock(recycled_pool_mutex());
77 std::unique_ptr<Pool> pool;
78 if (sRecycledPool) {
79 pool = std::unique_ptr<Pool>(sRecycledPool);
80 sRecycledPool = nullptr;
John Stiles23e68662020-10-29 10:17:15 -040081 VLOG("REUSE Pool:0x%016llX\n", (uint64_t)pool->fMemPool.get());
John Stiles2d68ea32020-10-22 15:42:27 -040082 } else {
83 pool = std::unique_ptr<Pool>(new Pool);
John Stiles23e68662020-10-29 10:17:15 -040084 pool->fMemPool = MemoryPool::Make(/*preallocSize=*/65536, /*minAllocSize=*/32768);
85 VLOG("CREATE Pool:0x%016llX\n", (uint64_t)pool->fMemPool.get());
John Stiles2d68ea32020-10-22 15:42:27 -040086 }
John Stiles5c7bb322020-10-22 11:09:15 -040087 return pool;
88}
89
John Stiles2d68ea32020-10-22 15:42:27 -040090void Pool::Recycle(std::unique_ptr<Pool> pool) {
91 if (pool) {
John Stiles23e68662020-10-29 10:17:15 -040092 pool->fMemPool->reportLeaks();
93 SkASSERT(pool->fMemPool->isEmpty());
John Stiles2d68ea32020-10-22 15:42:27 -040094 }
95
96 SkAutoMutexExclusive lock(recycled_pool_mutex());
97 if (sRecycledPool) {
98 delete sRecycledPool;
99 }
100
John Stiles23e68662020-10-29 10:17:15 -0400101 VLOG("STASH Pool:0x%016llX\n", pool ? (uint64_t)pool->fMemPool.get() : 0ull);
John Stiles2d68ea32020-10-22 15:42:27 -0400102 sRecycledPool = pool.release();
John Stiles5c7bb322020-10-22 11:09:15 -0400103}
104
105void Pool::attachToThread() {
John Stiles23e68662020-10-29 10:17:15 -0400106 VLOG("ATTACH Pool:0x%016llX\n", (uint64_t)fMemPool.get());
107 SkASSERT(get_thread_local_memory_pool() == nullptr);
108 set_thread_local_memory_pool(fMemPool.get());
John Stiles5c7bb322020-10-22 11:09:15 -0400109}
110
John Stiles2d68ea32020-10-22 15:42:27 -0400111void Pool::detachFromThread() {
John Stiles23e68662020-10-29 10:17:15 -0400112 VLOG("DETACH Pool:0x%016llX\n", (uint64_t)get_thread_local_memory_pool());
113 SkASSERT(get_thread_local_memory_pool() != nullptr);
114 set_thread_local_memory_pool(nullptr);
John Stiles2d68ea32020-10-22 15:42:27 -0400115}
116
John Stiles270b5c02020-10-27 17:49:37 -0400117void* Pool::AllocIRNode(size_t size) {
John Stiles3898bb52020-10-27 17:03:14 +0000118 // Is a pool attached?
John Stiles23e68662020-10-29 10:17:15 -0400119 MemoryPool* memPool = get_thread_local_memory_pool();
120 if (memPool) {
121 void* node = memPool->allocate(size);
122 VLOG("ALLOC Pool:0x%016llX 0x%016llX\n", (uint64_t)memPool, (uint64_t)node);
123 return node;
John Stiles5c7bb322020-10-22 11:09:15 -0400124 }
125
John Stiles23e68662020-10-29 10:17:15 -0400126 // There's no pool attached. Allocate nodes using the system allocator.
127 void* node = ::operator new(size);
128 VLOG("ALLOC Pool:__________________ 0x%016llX\n", (uint64_t)node);
129 return node;
John Stiles5c7bb322020-10-22 11:09:15 -0400130}
131
John Stiles15bfe382020-10-27 19:07:05 -0400132void Pool::FreeIRNode(void* node) {
John Stiles5c7bb322020-10-22 11:09:15 -0400133 // Is a pool attached?
John Stiles23e68662020-10-29 10:17:15 -0400134 MemoryPool* memPool = get_thread_local_memory_pool();
135 if (memPool) {
136 VLOG("FREE Pool:0x%016llX 0x%016llX\n", (uint64_t)memPool, (uint64_t)node);
137 memPool->release(node);
138 return;
John Stiles5c7bb322020-10-22 11:09:15 -0400139 }
140
John Stiles23e68662020-10-29 10:17:15 -0400141 // There's no pool attached. Free it using the system allocator.
142 VLOG("FREE Pool:__________________ 0x%016llX\n", (uint64_t)node);
John Stiles15bfe382020-10-27 19:07:05 -0400143 ::operator delete(node);
John Stiles5c7bb322020-10-22 11:09:15 -0400144}
145
John Stiles5c7bb322020-10-22 11:09:15 -0400146} // namespace SkSL