18#include <private/qv4global_p.h>
19#include <private/qv4value_p.h>
20#include <private/qv4scopedvalue_p.h>
21#include <private/qv4object_p.h>
22#include <private/qv4mmdefs_p.h>
59 using ExtraData = std::variant<std::monostate, GCIteratorStorage>;
182 template <
typename ToBeMarked>
187 constexpr static inline std::size_t
align(std::size_t
size)
188 {
return (
size + Chunk::SlotSize - 1) & ~(Chunk::SlotSize - 1); }
198 template<
typename ManagedType>
203 typename ManagedType::Data *
d =
static_cast<typename ManagedType::Data *
>(allocData(
size));
204 d->internalClass.set(
engine, ic);
205 Q_ASSERT(
d->internalClass &&
d->internalClass->vtable);
210 template<
typename ManagedType>
213 return allocManaged<ManagedType>(
sizeof(
typename ManagedType::Data), ic);
216 template<
typename ManagedType>
219 return allocManaged<ManagedType>(
size, ic->d());
222 template<
typename ManagedType>
225 return allocManaged<ManagedType>(
sizeof(
typename ManagedType::Data), ic);
228 template<
typename ManagedType>
232 Scoped<InternalClass> ic(scope, ManagedType::defaultInternalClass(
engine));
233 return allocManaged<ManagedType>(
size, ic);
236 template<
typename ManagedType>
239 auto constexpr size =
sizeof(
typename ManagedType::Data);
241 Scoped<InternalClass> ic(scope, ManagedType::defaultInternalClass(
engine));
242 return allocManaged<ManagedType>(
size, ic);
245 template <
typename ObjectType>
248 Heap::Object *
o = allocObjectWithMemberData(ObjectType::staticVTable(), ic->
size);
249 o->internalClass.set(
engine, ic);
250 Q_ASSERT(
o->internalClass.get() &&
o->vtable());
251 Q_ASSERT(
o->vtable() == ObjectType::staticVTable());
252 return static_cast<typename ObjectType::Data *
>(
o);
255 template <
typename ObjectType>
258 return allocateObject<ObjectType>(ic->d());
261 template <
typename ObjectType>
265 Scoped<InternalClass> ic(scope, ObjectType::defaultInternalClass(
engine));
266 ic = ic->changeVTable(ObjectType::staticVTable());
267 ic = ic->changePrototype(ObjectType::defaultPrototype(
engine)->
d());
268 return allocateObject<ObjectType>(ic);
271 template <
typename ManagedType,
typename Arg1>
274 typename ManagedType::Data *
o =
reinterpret_cast<typename ManagedType::Data *
>(allocString(unmanagedSize));
275 o->internalClass.set(
engine, ManagedType::defaultInternalClass(
engine));
276 Q_ASSERT(
o->internalClass &&
o->internalClass->vtable);
277 o->init(std::forward<Arg1>(
arg1));
281 template <
typename ObjectType,
typename... Args>
284 typename ObjectType::Data *
d = allocateObject<ObjectType>(ic);
285 d->init(std::forward<Args>(
args)...);
289 template <
typename ObjectType,
typename... Args>
292 typename ObjectType::Data *
d = allocateObject<ObjectType>(ic);
293 d->init(std::forward<Args>(
args)...);
297 template <
typename ObjectType,
typename... Args>
301 Scoped<ObjectType>
t(scope, allocateObject<ObjectType>());
302 t->d_unchecked()->init(std::forward<Args>(
args)...);
306 template <
typename ManagedType,
typename... Args>
310 Scoped<ManagedType>
t(scope, allocManaged<ManagedType>());
311 t->d_unchecked()->init(std::forward<Args>(
args)...);
316 bool tryForceGCCompletion();
319 void dumpStats()
const;
321 size_t getUsedMem()
const;
322 size_t getAllocatedMem()
const;
323 size_t getLargeItemsMem()
const;
330 void updateUnmanagedHeapSizeGCLimit();
332 template<
typename ManagedType>
335 Heap::Base *
b = *allocate(&icAllocator, align(
sizeof(
typename ManagedType::Data)));
336 return static_cast<typename ManagedType::Data *
>(
b);
345 void setGCTimeLimit(
int timeMs);
350 Heap::Base *allocString(std::size_t unmanagedSize);
352 Heap::Object *allocObjectWithMemberData(
const QV4::VTable *vtable,
uint nMembers);
356 MinUnmanagedHeapSizeGCLimit = 128 * 1024
360 void collectFromJSStack(MarkStack *markStack)
const;
361 void sweep(
bool lastSweep =
false, ClassDestroyStatsCallback classCountPtr =
nullptr);
362 void cleanupDeletedQObjectWrappersInSweep();
365 const bool incrementalGCIsAlreadyRunning = m_markStack !=
nullptr;
366 const bool aboveUnmanagedHeapLimit = incrementalGCIsAlreadyRunning
367 ? unmanagedHeapSize > 3 * unmanagedHeapSizeGCLimit / 2
368 : unmanagedHeapSize > unmanagedHeapSizeGCLimit;
369 return aboveUnmanagedHeapLimit;
372 bool shouldRunGC()
const;
376 const bool incrementalGCIsAlreadyRunning = m_markStack !=
nullptr;
378 bool didGCRun =
false;
384 if (isAboveUnmanagedHeapLimit()) {
386 incrementalGCIsAlreadyRunning ? (
void) tryForceGCCompletion() : runGC();
390 if (
size > Chunk::DataSize)
391 return hugeItemAllocator.allocate(
size);
396 if (!didGCRun && shouldRunGC())
414 std::unique_ptr<GCStateMachine> gcStateMachine{
nullptr};
415 std::unique_ptr<MarkStack> m_markStack{
nullptr};
417 std::size_t unmanagedHeapSize = 0;
419 std::size_t usedSlotsAfterLastFullSweep = 0;
423 bool aggressiveGC =
false;
424 bool gcStats =
false;
425 bool gcCollectorStats =
false;
427 int allocationCount = 0;
428 size_t lastAllocRequestedSlots = 0;
431 size_t maxReservedMem = 0;
432 size_t maxAllocatedMem = 0;
433 size_t maxUsedMem = 0;
434 uint allocations[BlockAllocator::NumBins];
445template <
typename ToBeMarked =
void>
452 , m_toBeMarked(toBeMarked)
461 if constexpr (!std::is_same_v<ToBeMarked, void>)
480 ToBeMarked *m_toBeMarked;
ManagedType::Data * allocManaged(InternalClass *ic)
bool isAboveUnmanagedHeapLimit()
QVector< Value * > m_pendingFreedObjectWrapperValue
QV4::ExecutionEngine * engine
ObjectType::Data * allocateObject(Heap::InternalClass *ic)
ManagedType::Data * allocManaged()
bool tryForceGCCompletion()
ManagedType::Data * allocManaged(std::size_t size, Heap::InternalClass *ic)
ManagedType::Data * allocManaged(std::size_t size, InternalClass *ic)
void changeUnmanagedHeapSizeUsage(qptrdiff delta)
ObjectType::Data * allocate(Args &&... args)
ChunkAllocator * chunkAllocator
PersistentValueStorage * m_persistentValues
ManagedType::Data * allocWithStringData(std::size_t unmanagedSize, Arg1 &&arg1)
PersistentValueStorage * m_weakValues
ManagedType::Data * allocManaged(std::size_t size)
ManagedType::Data * allocManaged(Heap::InternalClass *ic)
BlockAllocator blockAllocator
HugeItemAllocator hugeItemAllocator
ManagedType::Data * allocIC()
ObjectType::Data * allocateObject()
ObjectType::Data * allocObject(InternalClass *ic, Args &&... args)
ManagedType::Data * alloc(Args &&... args)
ObjectType::Data * allocObject(Heap::InternalClass *ic, Args &&... args)
std::size_t unmanagedHeapSizeGCLimit
static constexpr std::size_t align(std::size_t size)
ObjectType::Data * allocateObject(InternalClass *ic)
BlockAllocator icAllocator
QMap< QString, QString > map
[6]
Combined button and popup list for selecting options.
void(* ClassDestroyStatsCallback)(const char *)
@ InitMarkPersistentValues
#define Q_STATIC_ASSERT(Condition)
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char return DBusMessage return DBusMessage const char return DBusMessage dbus_bool_t return DBusMessage dbus_uint32_t return DBusMessage void
GLboolean GLboolean GLboolean b
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint GLuint GLuint GLuint arg1
QFuture< QSet< QChar > > set
[10]
ChunkAllocator * chunkAllocator
HeapItem * freeBins[NumBins]
size_t usedSlotsAfterLastSweep
std::vector< Chunk * > chunks
BlockAllocator(ChunkAllocator *chunkAllocator, ExecutionEngine *engine)
HeapItem * allocate(size_t size, bool forceAllocation=false)
size_t totalSlots() const
static size_t binForSlots(size_t nSlots)
size_t allocatedMem() const
MemoryManager * memoryManager
PersistentValueStorage::Iterator it
std::variant< std::monostate, GCIteratorStorage > ExtraData
GCState(* execute)(GCStateMachine *, ExtraData &)
Q_QML_EXPORT void transition()
std::chrono::microseconds timeLimit
void handleTimeout(GCState state)
std::array< GCStateInfo, GCState::Count > stateInfoMap
GCStateInfo::ExtraData ExtraData
std::vector< HugeChunk > chunks
HugeItemAllocator(ChunkAllocator *chunkAllocator, ExecutionEngine *engine)
ChunkAllocator * chunkAllocator
HeapItem * allocate(size_t size)
void sweep(ClassDestroyStatsCallback classCountPtr)