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>
38 Q_GADGET_EXPORT(Q_QML_EXPORT)
84 MemoryManager *
mm =
nullptr;
87 #ifdef QT_BUILD_INTERNAL
103 return state != GCState::Invalid;
107 state = GCState::MarkStart;
127 memset(freeBins, 0,
sizeof(freeBins));
139 return Chunk::AvailableSlots*chunks.size();
143 return chunks.size()*Chunk::DataSize;
147 for (
auto c : chunks)
148 used += c->nUsedSlots()*Chunk::SlotSize;
173 void sweep(ClassDestroyStatsCallback classCountPtr);
179 for (
const auto &c : chunks)
204 template <
typename ToBeMarked>
210 {
return (size + Chunk::SlotSize - 1) & ~(Chunk::SlotSize - 1); }
213
214
215
216
217
218
220 template<
typename ManagedType>
223 Q_STATIC_ASSERT(std::is_trivial_v<
typename ManagedType::Data>);
225 typename ManagedType::Data *d =
static_cast<
typename ManagedType::Data *>(allocData(size));
226 d->internalClass.set(engine, ic);
227 Q_ASSERT(d->internalClass && d->internalClass->vtable);
228 Q_ASSERT(ic
->vtable == ManagedType::staticVTable());
232 template<
typename ManagedType>
235 return allocManaged<ManagedType>(
sizeof(
typename ManagedType::Data), ic);
238 template<
typename ManagedType>
241 return allocManaged<ManagedType>(size, ic->d());
244 template<
typename ManagedType>
247 return allocManaged<ManagedType>(
sizeof(
typename ManagedType::Data), ic);
250 template<
typename ManagedType>
255 return allocManaged<ManagedType>(size, ic);
258 template<
typename ManagedType>
261 auto constexpr size =
sizeof(
typename ManagedType::Data);
264 return allocManaged<ManagedType>(size, ic);
267 template <
typename ObjectType>
270 Heap::Object *o = allocObjectWithMemberData(ObjectType::staticVTable(), ic->size);
271 o->internalClass.set(engine, ic);
272 Q_ASSERT(o->internalClass.get() && o->vtable());
273 Q_ASSERT(o->vtable() == ObjectType::staticVTable());
274 return static_cast<
typename ObjectType::Data *>(o);
277 template <
typename ObjectType>
280 return allocateObject<ObjectType>(ic->d());
283 template <
typename ObjectType>
288 ic = ic->changeVTable(ObjectType::staticVTable());
289 ic = ic->changePrototype(ObjectType::defaultPrototype(engine)->d());
290 return allocateObject<ObjectType>(ic);
293 template <
typename ManagedType,
typename Arg1>
296 typename ManagedType::Data *o =
reinterpret_cast<
typename ManagedType::Data *>(allocString(unmanagedSize));
297 o->internalClass.set(engine, ManagedType::defaultInternalClass(engine));
298 Q_ASSERT(o->internalClass && o->internalClass->vtable);
299 o->init(
std::forward<Arg1>(arg1));
303 template <
typename ObjectType,
typename... Args>
306 typename ObjectType::Data *d = allocateObject<ObjectType>(ic);
307 d->init(
std::forward<Args>(args)...);
311 template <
typename ObjectType,
typename... Args>
314 typename ObjectType::Data *d = allocateObject<ObjectType>(ic);
315 d->init(
std::forward<Args>(args)...);
319 template <
typename ObjectType,
typename... Args>
323 Scoped<ObjectType> t(scope, allocateObject<ObjectType>());
324 t->d_unchecked()->init(
std::forward<Args>(args)...);
328 template <
typename ManagedType,
typename... Args>
332 Scoped<ManagedType> t(scope, allocManaged<ManagedType>());
333 t->d_unchecked()->init(
std::forward<Args>(args)...);
354 template<
typename ManagedType>
357 Heap::Base *b = *allocate(&icAllocator, align(
sizeof(
typename ManagedType::Data)));
358 return static_cast<
typename ManagedType::Data *>(b);
383 void sweep(
bool lastSweep =
false, ClassDestroyStatsCallback classCountPtr =
nullptr);
387 const bool incrementalGCIsAlreadyRunning = m_markStack !=
nullptr;
388 const bool aboveUnmanagedHeapLimit = incrementalGCIsAlreadyRunning
389 ? unmanagedHeapSize > 3 * unmanagedHeapSizeGCLimit / 2
390 : unmanagedHeapSize > unmanagedHeapSizeGCLimit;
391 return aboveUnmanagedHeapLimit;
398 const bool incrementalGCIsAlreadyRunning = m_markStack !=
nullptr;
400 bool didGCRun =
false;
412 if (size > Chunk::DataSize)
413 return hugeItemAllocator.allocate(size);
415 if (HeapItem *m = allocator->allocate(size))
418 if (!didGCRun && shouldRunGC())
421 return allocator->allocate(size,
true);
462
463
464
465
466
467
468template <
typename ToBeMarked =
void>
502 MemoryManager::Blockness m_oldState;
503 ToBeMarked *m_toBeMarked;
ManagedType::Data * allocManaged(InternalClass *ic)
bool isAboveUnmanagedHeapLimit()
friend struct GCCriticalSection
QVector< Value * > m_pendingFreedObjectWrapperValue
Heap::SetObject * weakSets
bool crossValidateIncrementalGC
ObjectType::Data * allocateObject(Heap::InternalClass *ic)
Heap::Object * allocObjectWithMemberData(const QV4::VTable *vtable, uint nMembers)
size_t getLargeItemsMem() const
ManagedType::Data * allocManaged()
bool tryForceGCCompletion()
ManagedType::Data * allocManaged(std::size_t size, Heap::InternalClass *ic)
ManagedType::Data * allocManaged(std::size_t size, InternalClass *ic)
size_t lastAllocRequestedSlots
void changeUnmanagedHeapSizeUsage(qptrdiff delta)
std::unique_ptr< GCStateMachine > gcStateMachine
ObjectType::Data * allocate(Args &&... args)
ChunkAllocator * chunkAllocator
PersistentValueStorage * m_persistentValues
ManagedType::Data * allocWithStringData(std::size_t unmanagedSize, Arg1 &&arg1)
void sweep(bool lastSweep=false, ClassDestroyStatsCallback classCountPtr=nullptr)
void cleanupDeletedQObjectWrappersInSweep()
PersistentValueStorage * m_weakValues
std::size_t unmanagedHeapSize
ManagedType::Data * allocManaged(std::size_t size)
void registerWeakMap(Heap::MapObject *map)
ManagedType::Data * allocManaged(Heap::InternalClass *ic)
std::size_t usedSlotsAfterLastFullSweep
BlockAllocator blockAllocator
uint allocations[BlockAllocator::NumBins]
HugeItemAllocator hugeItemAllocator
size_t getUsedMem() const
std::unique_ptr< MarkStack > m_markStack
Heap::Base * allocData(std::size_t size)
size_t getAllocatedMem() const
ManagedType::Data * allocIC()
void setGCTimeLimit(int timeMs)
ObjectType::Data * allocateObject()
void registerWeakSet(Heap::SetObject *set)
ObjectType::Data * allocObject(InternalClass *ic, Args &&... args)
Heap::MapObject * weakMaps
void updateUnmanagedHeapSizeGCLimit()
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
static void updateProtoUsage(Heap::Object *o, Heap::InternalClass *ic)
static Heap::InternalClass * cleanInternalClass(Heap::InternalClass *orig)
static PropertyAttributes attributesFromFlags(int flags)
static void addDummyEntry(InternalClass *newClass, PropertyHash::Entry e)
GCStateMachine::GCStateInfo GCStateInfo
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
PersistentValueStorage::Iterator it
GCState(* execute)(GCStateMachine *, ExtraData &)
Q_QML_EXPORT void transition()
std::chrono::microseconds timeLimit
void handleTimeout(GCState state)
std::array< StepTiming, GCState::Count > executionTiming
std::array< GCStateInfo, GCState::Count > stateInfoMap
void init(InternalClass *other)
void init(ExecutionEngine *engine)
PropertyHash propertyTable
bool isUsedAsProto() const
bool isImplicitlyFrozen() const
InternalClassTransition Transition
bool isExtensible() const
@ MaxRedundantTransitions
InternalClassTransition & lookupOrInsertTransition(const InternalClassTransition &t)
static void markObjects(Heap::Base *ic, MarkStack *stack)
static void removeMember(QV4::Object *object, PropertyKey identifier)
PropertyHash::Entry * findEntry(const PropertyKey id)
std::vector< HugeChunk > chunks
HugeItemAllocator(ChunkAllocator *chunkAllocator, ExecutionEngine *engine)
ChunkAllocator * chunkAllocator
HeapItem * allocate(size_t size)
void sweep(ClassDestroyStatsCallback classCountPtr)
Heap::InternalClass * lookup
PropertyHashData(int numBits)
PropertyHash::Entry * entries
void addEntry(const Entry &entry, int classSize)
PropertyHash(const PropertyHash &other)
void detach(bool grow, int classSize)
bool isStringOrSymbol() const
bool isArrayIndex() const
uint asArrayIndex() const
static PropertyKey invalid()
Scope(ExecutionEngine *e)
SharedInternalClassDataPrivate(const SharedInternalClassDataPrivate &other, uint pos, PropertyKey value)
void set(uint i, PropertyKey t)
PropertyKey at(uint i) const
SharedInternalClassDataPrivate(const SharedInternalClassDataPrivate &other)