summaryrefslogtreecommitdiffstats
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)
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