summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2018-08-03 12:54:29 +0200
committerLars Knoll <lars.knoll@qt.io>2018-08-21 14:55:18 +0000
commit7c4335d0307abde6dd17738481d006d70771714c (patch)
tree80d902e14801d72a3cf47b174f6af5fc32335363
parentb50165508996e10a232ee70196a820da06f1af1c (diff)
downloadqtdeclarative-7c4335d0307abde6dd17738481d006d70771714c.tar.gz
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>
-rw-r--r--src/qml/jsruntime/qv4memberdata.cpp17
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