19#include <private/qv4global_p.h>
20#include <private/qv4value_p.h>
21#include <private/qv4scopedvalue_p.h>
22#include <private/qv4object_p.h>
23#include <private/qv4mmdefs_p.h>
34template<
typename Container,
typename UnaryPred>
36 Container &container,
typename Container::size_type first, UnaryPred &&p)
38 auto last = container.size();
39 while (first < last) {
43 }
while (++first < last);
45 Q_ASSERT(first == last);
50 last = container.size();
59template<
typename Container,
class UnaryPred>
63 auto first = reiterate(container, 0, p);
69 reiterate(container, first + 1, [&p, &container, &first](
const auto i) {
74 std::swap(container.at(i), container.at(first++));
89 Q_GADGET_EXPORT(Q_QML_EXPORT)
135 MemoryManager *
mm =
nullptr;
138 #ifdef QT_BUILD_INTERNAL
154 return state != GCState::Invalid;
158 state = GCState::MarkStart;
178 memset(freeBins, 0,
sizeof(freeBins));
190 return Chunk::AvailableSlots*chunks.size();
194 return chunks.size()*Chunk::DataSize;
198 for (
auto c : chunks)
199 used += c->nUsedSlots()*Chunk::SlotSize;
230 for (
const auto &c : chunks)
255 template <
typename ToBeMarked>
261 {
return (size + Chunk::SlotSize - 1) & ~(Chunk::SlotSize - 1); }
264
265
266
267
268
269
271 template<
typename ManagedType>
276 typename ManagedType::Data *d =
static_cast<
typename ManagedType::Data *>(allocData(size));
277 d->internalClass.set(engine, ic);
278 Q_ASSERT(d->internalClass && d->internalClass->vtable);
279 Q_ASSERT(ic
->vtable == ManagedType::staticVTable());
283 template<
typename ManagedType>
286 return allocManaged<ManagedType>(
sizeof(
typename ManagedType::Data), ic);
289 template<
typename ManagedType>
292 return allocManaged<ManagedType>(size, ic->d());
295 template<
typename ManagedType>
298 return allocManaged<ManagedType>(
sizeof(
typename ManagedType::Data), ic);
301 template<
typename ManagedType>
306 return allocManaged<ManagedType>(size, ic);
309 template<
typename ManagedType>
312 auto constexpr size =
sizeof(
typename ManagedType::Data);
315 return allocManaged<ManagedType>(size, ic);
318 template <
typename ObjectType>
321 Heap::Object *o = allocObjectWithMemberData(ObjectType::staticVTable(), ic->size);
322 o->internalClass.set(engine, ic);
323 Q_ASSERT(o->internalClass.get() && o->vtable());
324 Q_ASSERT(o->vtable() == ObjectType::staticVTable());
325 return static_cast<
typename ObjectType::Data *>(o);
328 template <
typename ObjectType>
331 return allocateObject<ObjectType>(ic->d());
334 template <
typename ObjectType>
339 ic = ic->changeVTable(ObjectType::staticVTable());
340 ic = ic->changePrototype(ObjectType::defaultPrototype(engine)->d());
341 return allocateObject<ObjectType>(ic);
344 template <
typename ManagedType,
typename Arg1>
347 typename ManagedType::Data *o =
reinterpret_cast<
typename ManagedType::Data *>(allocString(unmanagedSize));
348 o->internalClass.set(engine, ManagedType::defaultInternalClass(engine));
349 Q_ASSERT(o->internalClass && o->internalClass->vtable);
350 o->init(
std::forward<Arg1>(arg1));
354 template <
typename ObjectType,
typename... Args>
357 typename ObjectType::Data *d = allocateObject<ObjectType>(ic);
358 d->init(
std::forward<Args>(args)...);
362 template <
typename ObjectType,
typename... Args>
365 typename ObjectType::Data *d = allocateObject<ObjectType>(ic);
366 d->init(
std::forward<Args>(args)...);
370 template <
typename ObjectType,
typename... Args>
374 Scoped<ObjectType> t(scope, allocateObject<ObjectType>());
375 t->d_unchecked()->init(
std::forward<Args>(args)...);
379 template <
typename ManagedType,
typename... Args>
383 Scoped<ManagedType> t(scope, allocManaged<ManagedType>());
384 t->d_unchecked()->init(
std::forward<Args>(args)...);
405 template<
typename ManagedType>
408 Heap::Base *b = *allocate(&icAllocator, align(
sizeof(
typename ManagedType::Data)));
409 return static_cast<
typename ManagedType::Data *>(b);
437 void sweep(
bool lastSweep =
false);
441 const bool incrementalGCIsAlreadyRunning = m_markStack !=
nullptr;
442 const bool aboveUnmanagedHeapLimit = incrementalGCIsAlreadyRunning
443 ? unmanagedHeapSize > 3 * unmanagedHeapSizeGCLimit / 2
444 : unmanagedHeapSize > unmanagedHeapSizeGCLimit;
445 return aboveUnmanagedHeapLimit;
452 const bool incrementalGCIsAlreadyRunning = m_markStack !=
nullptr;
454 bool didGCRun =
false;
466 if (size > Chunk::DataSize)
467 return hugeItemAllocator.allocate(size);
469 if (HeapItem *m = allocator->allocate(size))
472 if (!didGCRun && shouldRunGC())
475 return allocator->allocate(size,
true);
512#if defined(MM_STATS) || !defined(QT_NO_DEBUG)
526
527
528
529
530
531
532template <
typename ToBeMarked =
void>
566 MemoryManager::Blockness m_oldState;
567 ToBeMarked *m_toBeMarked;
ManagedType::Data * allocManaged(InternalClass *ic)
bool isAboveUnmanagedHeapLimit()
friend struct GCCriticalSection
Heap::SetObject * weakSets
QV4::ExecutionEngine * engine
bool crossValidateIncrementalGC
ObjectType::Data * allocateObject(Heap::InternalClass *ic)
size_t getRegularItemsMem() const
Heap::Object * allocObjectWithMemberData(const QV4::VTable *vtable, uint nMembers)
size_t getLargeItemsMem() const
std::vector< QObject * > findObjectsForCompilationUnits(std::vector< QQmlRefPointer< CompiledData::CompilationUnit > > &&units)
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)
QList< Value * > m_pendingFreedObjectWrapperValue
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 cleanupDeletedQObjectWrappersInSweep()
PersistentValueStorage * m_weakValues
void sweep(bool lastSweep=false)
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
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)
ObjectsForCompilationUnit * m_recordedObjects
std::size_t unmanagedHeapSizeGCLimit
static constexpr std::size_t align(std::size_t size)
ObjectType::Data * allocateObject(InternalClass *ic)
BlockAllocator icAllocator
Combined button and popup list for selecting options.
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
Container::size_type partition(Container &container, UnaryPred &&p)
Q_STATIC_ASSERT(sizeof(CppStackFrame)==sizeof(JSTypesStackFrame))
Container::size_type reiterate(Container &container, typename Container::size_type first, UnaryPred &&p)
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)
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)