1 /****************************************************************************
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
6 ** This file is part of the QtQml module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL21$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
32 ****************************************************************************/
37 #include <private/qv4global_p.h>
38 #include <private/qv4value_p.h>
39 #include <private/qv4scopedvalue_p.h>
41 //#define DETAILED_MM_STATS
49 class Q_QML_EXPORT MemoryManager
51 Q_DISABLE_COPY(MemoryManager);
59 GCBlocker(MemoryManager *mm)
61 , wasBlocked(mm->isGCBlocked())
63 mm->setGCBlocked(true);
68 mm->setGCBlocked(wasBlocked);
77 MemoryManager(ExecutionEngine *engine);
80 // TODO: this is only for 64bit (and x86 with SSE/AVX), so exend it for other architectures to be slightly more efficient (meaning, align on 8-byte boundaries).
81 // Note: all occurrences of "16" in alloc/dealloc are also due to the alignment.
82 static inline std::size_t align(std::size_t size)
83 { return (size + 15) & ~0xf; }
85 template<typename ManagedType>
86 inline typename ManagedType::Data *allocManaged(std::size_t size, std::size_t unmanagedSize = 0)
89 Heap::Base *o = allocData(size, unmanagedSize);
90 o->setVtable(ManagedType::staticVTable());
91 return static_cast<typename ManagedType::Data *>(o);
94 template <typename ManagedType>
95 typename ManagedType::Data *alloc()
97 Scope scope(engine());
98 Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data)));
99 (void)new (t->d()) typename ManagedType::Data();
103 template <typename ManagedType, typename Arg1>
104 typename ManagedType::Data *alloc(Arg1 arg1)
106 Scope scope(engine());
107 Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data)));
108 (void)new (t->d()) typename ManagedType::Data(arg1);
112 template <typename ManagedType, typename Arg1>
113 typename ManagedType::Data *allocWithStringData(std::size_t unmanagedSize, Arg1 arg1)
115 Scope scope(engine());
116 Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data), unmanagedSize));
117 (void)new (t->d()) typename ManagedType::Data(this, arg1);
121 template <typename ManagedType, typename Arg1, typename Arg2>
122 typename ManagedType::Data *alloc(Arg1 arg1, Arg2 arg2)
124 Scope scope(engine());
125 Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data)));
126 (void)new (t->d()) typename ManagedType::Data(arg1, arg2);
130 template <typename ManagedType, typename Arg1, typename Arg2, typename Arg3>
131 typename ManagedType::Data *alloc(Arg1 arg1, Arg2 arg2, Arg3 arg3)
133 Scope scope(engine());
134 Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data)));
135 (void)new (t->d()) typename ManagedType::Data(arg1, arg2, arg3);
139 template <typename ManagedType, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
140 typename ManagedType::Data *alloc(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4)
142 Scope scope(engine());
143 Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data)));
144 (void)new (t->d()) typename ManagedType::Data(arg1, arg2, arg3, arg4);
148 template <typename ManagedType, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5>
149 typename ManagedType::Data *alloc(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5)
151 Scope scope(engine());
152 Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data)));
153 (void)new (t->d()) typename ManagedType::Data(arg1, arg2, arg3, arg4, arg5);
157 bool isGCBlocked() const;
158 void setGCBlocked(bool blockGC);
161 ExecutionEngine *engine() const;
163 void dumpStats() const;
165 size_t getUsedMem() const;
166 size_t getAllocatedMem() const;
167 size_t getLargeItemsMem() const;
169 void growUnmanagedHeapSizeUsage(size_t delta); // called when a JS object grows itself. Specifically: Heap::String::append
172 /// expects size to be aligned
173 // TODO: try to inline
174 Heap::Base *allocData(std::size_t size, std::size_t unmanagedSize);
176 #ifdef DETAILED_MM_STATS
177 void willAllocate(std::size_t size);
178 #endif // DETAILED_MM_STATS
181 void collectFromJSStack() const;
183 void sweep(bool lastSweep = false);
186 QScopedPointer<Data> m_d;
188 PersistentValueStorage *m_persistentValues;
189 PersistentValueStorage *m_weakValues;