blob: ee8eeb5b7abedcc10a0d0461c3bb67d8763d8023 [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 Stilese5d729c2020-10-29 10:26:28 -040092 if (get_thread_local_memory_pool() == pool->fMemPool.get()) {
93 SkDEBUGFAIL("SkSL pool is being recycled while it is still attached to the thread");
94 }
95
John Stiles23e68662020-10-29 10:17:15 -040096 pool->fMemPool->reportLeaks();
97 SkASSERT(pool->fMemPool->isEmpty());
John Stiles2d68ea32020-10-22 15:42:27 -040098 }
99
100 SkAutoMutexExclusive lock(recycled_pool_mutex());
101 if (sRecycledPool) {
102 delete sRecycledPool;
103 }
104
John Stiles23e68662020-10-29 10:17:15 -0400105 VLOG("STASH Pool:0x%016llX\n", pool ? (uint64_t)pool->fMemPool.get() : 0ull);
John Stiles2d68ea32020-10-22 15:42:27 -0400106 sRecycledPool = pool.release();
John Stiles5c7bb322020-10-22 11:09:15 -0400107}
108
109void Pool::attachToThread() {
John Stiles23e68662020-10-29 10:17:15 -0400110 VLOG("ATTACH Pool:0x%016llX\n", (uint64_t)fMemPool.get());
111 SkASSERT(get_thread_local_memory_pool() == nullptr);
112 set_thread_local_memory_pool(fMemPool.get());
John Stiles5c7bb322020-10-22 11:09:15 -0400113}
114
John Stiles2d68ea32020-10-22 15:42:27 -0400115void Pool::detachFromThread() {
John Stilese5d729c2020-10-29 10:26:28 -0400116 MemoryPool* memPool = get_thread_local_memory_pool();
117 VLOG("DETACH Pool:0x%016llX\n", (uint64_t)memPool);
118 SkASSERT(memPool == fMemPool.get());
119 memPool->resetScratchSpace();
John Stiles23e68662020-10-29 10:17:15 -0400120 set_thread_local_memory_pool(nullptr);
John Stiles2d68ea32020-10-22 15:42:27 -0400121}
122
John Stiles270b5c02020-10-27 17:49:37 -0400123void* Pool::AllocIRNode(size_t size) {
John Stiles3898bb52020-10-27 17:03:14 +0000124 // Is a pool attached?
John Stiles23e68662020-10-29 10:17:15 -0400125 MemoryPool* memPool = get_thread_local_memory_pool();
126 if (memPool) {
127 void* node = memPool->allocate(size);
128 VLOG("ALLOC Pool:0x%016llX 0x%016llX\n", (uint64_t)memPool, (uint64_t)node);
129 return node;
John Stiles5c7bb322020-10-22 11:09:15 -0400130 }
131
John Stiles23e68662020-10-29 10:17:15 -0400132 // There's no pool attached. Allocate nodes using the system allocator.
133 void* node = ::operator new(size);
134 VLOG("ALLOC Pool:__________________ 0x%016llX\n", (uint64_t)node);
135 return node;
John Stiles5c7bb322020-10-22 11:09:15 -0400136}
137
John Stiles15bfe382020-10-27 19:07:05 -0400138void Pool::FreeIRNode(void* node) {
John Stiles5c7bb322020-10-22 11:09:15 -0400139 // Is a pool attached?
John Stiles23e68662020-10-29 10:17:15 -0400140 MemoryPool* memPool = get_thread_local_memory_pool();
141 if (memPool) {
142 VLOG("FREE Pool:0x%016llX 0x%016llX\n", (uint64_t)memPool, (uint64_t)node);
143 memPool->release(node);
144 return;
John Stiles5c7bb322020-10-22 11:09:15 -0400145 }
146
John Stiles23e68662020-10-29 10:17:15 -0400147 // There's no pool attached. Free it using the system allocator.
148 VLOG("FREE Pool:__________________ 0x%016llX\n", (uint64_t)node);
John Stiles15bfe382020-10-27 19:07:05 -0400149 ::operator delete(node);
John Stiles5c7bb322020-10-22 11:09:15 -0400150}
151
John Stiles5c7bb322020-10-22 11:09:15 -0400152} // namespace SkSL