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)
89 Heap::Base *o = allocData(size);
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, typename Arg2>
113 typename ManagedType::Data *alloc(Arg1 arg1, Arg2 arg2)
115 Scope scope(engine());
116 Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data)));
117 (void)new (t->d()) typename ManagedType::Data(arg1, arg2);
121 template <typename ManagedType, typename Arg1, typename Arg2, typename Arg3>
122 typename ManagedType::Data *alloc(Arg1 arg1, Arg2 arg2, Arg3 arg3)
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, arg3);
130 template <typename ManagedType, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
131 typename ManagedType::Data *alloc(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4)
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, arg4);
139 template <typename ManagedType, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5>
140 typename ManagedType::Data *alloc(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5)
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, arg5);
148 bool isGCBlocked() const;
149 void setGCBlocked(bool blockGC);
152 ExecutionEngine *engine() const;
154 void dumpStats() const;
156 void registerDeletable(GCDeletable *d);
158 size_t getUsedMem() const;
159 size_t getAllocatedMem() const;
160 size_t getLargeItemsMem() const;
163 /// expects size to be aligned
164 // TODO: try to inline
165 Heap::Base *allocData(std::size_t size);
167 #ifdef DETAILED_MM_STATS
168 void willAllocate(std::size_t size);
169 #endif // DETAILED_MM_STATS
172 void collectFromJSStack() const;
174 void sweep(bool lastSweep = false);
177 QScopedPointer<Data> m_d;
179 PersistentValueStorage *m_persistentValues;
180 PersistentValueStorage *m_weakValues;