Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Toggle main menu visibility
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
// Qt-Security score:significant
4
5
#
include
"qv4executableallocator_p.h"
6
#
include
<
QtQml
/
private
/
qv4functiontable_p
.
h
>
7
8
#
include
<
wtf
/
StdLibExtras
.
h
>
9
#
include
<
wtf
/
PageAllocation
.
h
>
10
11
using
namespace
QV4;
12
13
void
*ExecutableAllocator::Allocation::exceptionHandlerStart()
const
14
{
15
return
reinterpret_cast
<
void
*>(addr);
16
}
17
18
size_t ExecutableAllocator::Allocation::exceptionHandlerSize()
const
19
{
20
return
QV4::exceptionHandlerSize();
21
}
22
23
void
*ExecutableAllocator::Allocation::memoryStart()
const
24
{
25
return
reinterpret_cast
<
void
*>(addr);
26
}
27
28
void
*ExecutableAllocator::Allocation::codeStart()
const
29
{
30
return
reinterpret_cast
<
void
*>(addr + exceptionHandlerSize());
31
}
32
33
void
ExecutableAllocator::Allocation::deallocate(ExecutableAllocator *allocator)
34
{
35
if
(isValid())
36
allocator->free(
this
);
37
else
38
delete
this
;
39
}
40
41
ExecutableAllocator::Allocation *ExecutableAllocator::Allocation::split(size_t dividingSize)
42
{
43
Allocation *remainder =
new
Allocation;
44
if
(next)
45
next->prev = remainder;
46
47
remainder->next = next;
48
next = remainder;
49
50
remainder->prev =
this
;
51
52
remainder->size = size - dividingSize;
53
remainder->free = free;
54
remainder->addr = addr + dividingSize;
55
size = dividingSize;
56
57
return
remainder;
58
}
59
60
bool
ExecutableAllocator::Allocation::mergeNext(ExecutableAllocator *allocator)
61
{
62
Q_ASSERT(free);
63
if
(!next || !next->free)
64
return
false
;
65
66
allocator->freeAllocations.remove(size,
this
);
67
allocator->freeAllocations.remove(next->size, next);
68
69
size += next->size;
70
Allocation *newNext = next->next;
71
delete
next;
72
next = newNext;
73
if
(next)
74
next->prev =
this
;
75
76
allocator->freeAllocations.insert(size,
this
);
77
return
true
;
78
}
79
80
bool
ExecutableAllocator::Allocation::mergePrevious(ExecutableAllocator *allocator)
81
{
82
Q_ASSERT(free);
83
if
(!prev || !prev->free)
84
return
false
;
85
86
allocator->freeAllocations.remove(size,
this
);
87
allocator->freeAllocations.remove(prev->size, prev);
88
89
prev->size += size;
90
if
(next)
91
next->prev = prev;
92
prev->next = next;
93
94
allocator->freeAllocations.insert(prev->size, prev);
95
96
delete
this
;
97
return
true
;
98
}
99
100
ExecutableAllocator::ChunkOfPages::~ChunkOfPages()
101
{
102
Allocation *alloc = firstAllocation;
103
while
(alloc) {
104
Allocation *next = alloc->next;
105
if
(alloc->isValid())
106
delete
alloc;
107
alloc = next;
108
}
109
pages->deallocate();
110
delete
pages;
111
}
112
113
bool
ExecutableAllocator::ChunkOfPages::contains(Allocation *alloc)
const
114
{
115
Allocation *it = firstAllocation;
116
while
(it) {
117
if
(it == alloc)
118
return
true
;
119
it = it->next;
120
}
121
return
false
;
122
}
123
124
ExecutableAllocator::ExecutableAllocator()
125
=
default
;
126
127
ExecutableAllocator::~ExecutableAllocator()
128
{
129
for
(ChunkOfPages *chunk : std::as_const(chunks)) {
130
for
(Allocation *allocation = chunk->firstAllocation; allocation; allocation = allocation->next)
131
if
(!allocation->free)
132
allocation->invalidate();
133
}
134
135
qDeleteAll(chunks);
136
}
137
138
ExecutableAllocator::Allocation *ExecutableAllocator::allocate(size_t size)
139
{
140
QMutexLocker locker(&mutex);
141
Allocation *allocation =
nullptr
;
142
143
// Code is best aligned to 16-byte boundaries.
144
size = WTF::roundUpToMultipleOf(16, size + exceptionHandlerSize());
145
146
QMultiMap<size_t, Allocation*>::Iterator it = freeAllocations.lowerBound(size);
147
if
(it != freeAllocations.end()) {
148
allocation = *it;
149
freeAllocations.erase(it);
150
}
151
152
if
(!allocation) {
153
ChunkOfPages *chunk =
new
ChunkOfPages;
154
size_t allocSize = WTF::roundUpToMultipleOf(WTF::pageSize(), size);
155
chunk->pages =
new
WTF::PageAllocation(WTF::PageAllocation::allocate(allocSize, OSAllocator::JSJITCodePages));
156
chunks.insert(
reinterpret_cast
<quintptr>(chunk->pages->base()) - 1, chunk);
157
allocation =
new
Allocation;
158
allocation->addr =
reinterpret_cast
<quintptr>(chunk->pages->base());
159
allocation->size = allocSize;
160
allocation->free =
true
;
161
chunk->firstAllocation = allocation;
162
}
163
164
Q_ASSERT(allocation);
165
Q_ASSERT(allocation->free);
166
167
allocation->free =
false
;
168
169
if
(allocation->size > size) {
170
Allocation *remainder = allocation->split(size);
171
remainder->free =
true
;
172
if
(!remainder->mergeNext(
this
))
173
freeAllocations.insert(remainder->size, remainder);
174
}
175
176
return
allocation;
177
}
178
179
void
ExecutableAllocator::free(Allocation *allocation)
180
{
181
QMutexLocker locker(&mutex);
182
183
Q_ASSERT(allocation);
184
185
allocation->free =
true
;
186
187
QMap<quintptr, ChunkOfPages*>::Iterator it = chunks.lowerBound(allocation->addr);
188
if
(it != chunks.begin())
189
--it;
190
Q_ASSERT(it != chunks.end());
191
ChunkOfPages *chunk = *it;
192
Q_ASSERT(chunk->contains(allocation));
193
194
bool
merged = allocation->mergeNext(
this
);
195
merged |= allocation->mergePrevious(
this
);
196
if
(!merged)
197
freeAllocations.insert(allocation->size, allocation);
198
199
allocation =
nullptr
;
200
201
if
(!chunk->firstAllocation->next) {
202
freeAllocations.remove(chunk->firstAllocation->size, chunk->firstAllocation);
203
chunks.erase(it);
204
delete
chunk;
205
return
;
206
}
207
}
208
209
ExecutableAllocator::ChunkOfPages *ExecutableAllocator::chunkForAllocation(Allocation *allocation)
const
210
{
211
QMutexLocker locker(&mutex);
212
213
QMap<quintptr, ChunkOfPages*>::ConstIterator it = chunks.lowerBound(allocation->addr);
214
if
(it != chunks.begin())
215
--it;
216
if
(it == chunks.end())
217
return
nullptr
;
218
return
*it;
219
}
qtdeclarative
src
qml
jsruntime
qv4executableallocator.cpp
Generated on
for Qt by
1.18.0