Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qv4executableallocator.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
5#include <QtQml/private/qv4functiontable_p.h>
6
7#include <wtf/StdLibExtras.h>
8#include <wtf/PageAllocation.h>
9
10using namespace QV4;
11
13{
14 return reinterpret_cast<void*>(addr);
15}
16
21
23{
24 return reinterpret_cast<void*>(addr);
25}
26
28{
29 return reinterpret_cast<void*>(addr + exceptionHandlerSize());
30}
31
33{
34 if (isValid())
35 allocator->free(this);
36 else
37 delete this;
38}
39
40ExecutableAllocator::Allocation *ExecutableAllocator::Allocation::split(size_t dividingSize)
41{
42 Allocation *remainder = new Allocation;
43 if (next)
44 next->prev = remainder;
45
46 remainder->next = next;
47 next = remainder;
48
49 remainder->prev = this;
50
51 remainder->size = size - dividingSize;
52 remainder->free = free;
53 remainder->addr = addr + dividingSize;
54 size = dividingSize;
55
56 return remainder;
57}
58
59bool ExecutableAllocator::Allocation::mergeNext(ExecutableAllocator *allocator)
60{
62 if (!next || !next->free)
63 return false;
64
65 allocator->freeAllocations.remove(size, this);
66 allocator->freeAllocations.remove(next->size, next);
67
68 size += next->size;
69 Allocation *newNext = next->next;
70 delete next;
71 next = newNext;
72 if (next)
73 next->prev = this;
74
75 allocator->freeAllocations.insert(size, this);
76 return true;
77}
78
79bool ExecutableAllocator::Allocation::mergePrevious(ExecutableAllocator *allocator)
80{
82 if (!prev || !prev->free)
83 return false;
84
85 allocator->freeAllocations.remove(size, this);
86 allocator->freeAllocations.remove(prev->size, prev);
87
88 prev->size += size;
89 if (next)
90 next->prev = prev;
91 prev->next = next;
92
93 allocator->freeAllocations.insert(prev->size, prev);
94
95 delete this;
96 return true;
97}
98
100{
101 Allocation *alloc = firstAllocation;
102 while (alloc) {
103 Allocation *next = alloc->next;
104 if (alloc->isValid())
105 delete alloc;
106 alloc = next;
107 }
108 pages->deallocate();
109 delete pages;
110}
111
113{
114 Allocation *it = firstAllocation;
115 while (it) {
116 if (it == alloc)
117 return true;
118 it = it->next;
119 }
120 return false;
121}
122
124 = default;
125
127{
128 for (ChunkOfPages *chunk : std::as_const(chunks)) {
129 for (Allocation *allocation = chunk->firstAllocation; allocation; allocation = allocation->next)
130 if (!allocation->free)
131 allocation->invalidate();
132 }
133
134 qDeleteAll(chunks);
135}
136
138{
139 QMutexLocker locker(&mutex);
140 Allocation *allocation = nullptr;
141
142 // Code is best aligned to 16-byte boundaries.
143 size = WTF::roundUpToMultipleOf(16, size + exceptionHandlerSize());
144
145 QMultiMap<size_t, Allocation*>::Iterator it = freeAllocations.lowerBound(size);
146 if (it != freeAllocations.end()) {
147 allocation = *it;
148 freeAllocations.erase(it);
149 }
150
151 if (!allocation) {
152 ChunkOfPages *chunk = new ChunkOfPages;
153 size_t allocSize = WTF::roundUpToMultipleOf(WTF::pageSize(), size);
154 chunk->pages = new WTF::PageAllocation(WTF::PageAllocation::allocate(allocSize, OSAllocator::JSJITCodePages));
155 chunks.insert(reinterpret_cast<quintptr>(chunk->pages->base()) - 1, chunk);
157 allocation->addr = reinterpret_cast<quintptr>(chunk->pages->base());
158 allocation->size = allocSize;
159 allocation->free = true;
161 }
162
164 Q_ASSERT(allocation->free);
165
166 allocation->free = false;
167
168 if (allocation->size > size) {
169 Allocation *remainder = allocation->split(size);
170 remainder->free = true;
171 if (!remainder->mergeNext(this))
172 freeAllocations.insert(remainder->size, remainder);
173 }
174
175 return allocation;
176}
177
179{
180 QMutexLocker locker(&mutex);
181
183
184 allocation->free = true;
185
186 QMap<quintptr, ChunkOfPages*>::Iterator it = chunks.lowerBound(allocation->addr);
187 if (it != chunks.begin())
188 --it;
189 Q_ASSERT(it != chunks.end());
190 ChunkOfPages *chunk = *it;
192
193 bool merged = allocation->mergeNext(this);
194 merged |= allocation->mergePrevious(this);
195 if (!merged)
196 freeAllocations.insert(allocation->size, allocation);
197
198 allocation = nullptr;
199
200 if (!chunk->firstAllocation->next) {
201 freeAllocations.remove(chunk->firstAllocation->size, chunk->firstAllocation);
202 chunks.erase(it);
203 delete chunk;
204 return;
205 }
206}
207
209{
210 QMutexLocker locker(&mutex);
211
213 if (it != chunks.begin())
214 --it;
215 if (it == chunks.end())
216 return nullptr;
217 return *it;
218}
219
\inmodule QtCore
Definition qmutex.h:313
void free(Allocation *allocation)
Allocation * allocate(size_t size)
ChunkOfPages * chunkForAllocation(Allocation *allocation) const
qDeleteAll(list.begin(), list.end())
QSet< QString >::iterator it
short next
Definition keywords.cpp:445
size_t exceptionHandlerSize()
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLenum const void * addr
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
std::unique_ptr< ThunkPool::ThunkAllocation > allocation
Definition qstdweb.cpp:276
size_t quintptr
Definition qtypes.h:167
void deallocate(ExecutableAllocator *allocator)