diff options
author | Lars Knoll <lars.knoll@qt.io> | 2018-08-03 12:54:29 +0200 |
---|---|---|
committer | Lars Knoll <lars.knoll@qt.io> | 2018-08-21 14:55:18 +0000 |
commit | 7c4335d0307abde6dd17738481d006d70771714c (patch) | |
tree | 80d902e14801d72a3cf47b174f6af5fc32335363 /src | |
parent | b50165508996e10a232ee70196a820da06f1af1c (diff) |
Fix quadratic behavior when allocating very large objects
MemberData would get reallocated to exactly the required new
size. In case there's one large object dominating things, this
would then trigger a GC run on every reallocation, causing a
quadratic runtime behaviour due to marking and sweeping that
memory.
Task-number: QTBUG-69475
Change-Id: I1834cbe21412ce3409cfd47810af1f73c5a29b46
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src')
-rw-r--r-- | src/qml/jsruntime/qv4memberdata.cpp | 17 |
1 files changed, 17 insertions, 0 deletions
diff --git a/src/qml/jsruntime/qv4memberdata.cpp b/src/qml/jsruntime/qv4memberdata.cpp index 8f862d63e9..da086bd47a 100644 --- a/src/qml/jsruntime/qv4memberdata.cpp +++ b/src/qml/jsruntime/qv4memberdata.cpp @@ -45,12 +45,29 @@ using namespace QV4; DEFINE_MANAGED_VTABLE(MemberData); +static size_t nextPowerOfTwo(size_t s) +{ + --s; + s |= s >> 1; + s |= s >> 2; + s |= s >> 4; + s |= s >> 8; + s |= s >> 16; +#if (QT_POINTER_SIZE == 8) + s |= s >> 32; +#endif + ++s; + return s; +} + Heap::MemberData *MemberData::allocate(ExecutionEngine *e, uint n, Heap::MemberData *old) { Q_ASSERT(!old || old->values.size < n); Q_ASSERT(n); size_t alloc = MemoryManager::align(sizeof(Heap::MemberData) + (n - 1)*sizeof(Value)); + // round up to next power of two to avoid quadratic behaviour for very large objects + alloc = nextPowerOfTwo(alloc); Heap::MemberData *m = e->memoryManager->allocManaged<MemberData>(alloc); if (old) // no write barrier required here |