Encapsulate and protect all accesses to the vtable of Heap objects
[platform/upstream/qtdeclarative.git] / src / qml / memory / qv4mm_p.h
1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the QtQml module of the Qt Toolkit.
7 **
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.
16 **
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.
25 **
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.
29 **
30 ** $QT_END_LICENSE$
31 **
32 ****************************************************************************/
33
34 #ifndef QV4GC_H
35 #define QV4GC_H
36
37 #include <private/qv4global_p.h>
38 #include <private/qv4value_p.h>
39 #include <private/qv4scopedvalue_p.h>
40
41 //#define DETAILED_MM_STATS
42
43 QT_BEGIN_NAMESPACE
44
45 namespace QV4 {
46
47 struct GCDeletable;
48
49 class Q_QML_EXPORT MemoryManager
50 {
51     Q_DISABLE_COPY(MemoryManager);
52
53 public:
54     struct Data;
55
56     class GCBlocker
57     {
58     public:
59         GCBlocker(MemoryManager *mm)
60             : mm(mm)
61             , wasBlocked(mm->isGCBlocked())
62         {
63             mm->setGCBlocked(true);
64         }
65
66         ~GCBlocker()
67         {
68             mm->setGCBlocked(wasBlocked);
69         }
70
71     private:
72         MemoryManager *mm;
73         bool wasBlocked;
74     };
75
76 public:
77     MemoryManager(ExecutionEngine *engine);
78     ~MemoryManager();
79
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; }
84
85     template<typename ManagedType>
86     inline typename ManagedType::Data *allocManaged(std::size_t size)
87     {
88         size = align(size);
89         Heap::Base *o = allocData(size);
90         o->setVtable(ManagedType::staticVTable());
91         return static_cast<typename ManagedType::Data *>(o);
92     }
93
94     template <typename ManagedType>
95     typename ManagedType::Data *alloc()
96     {
97         Scope scope(engine());
98         Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data)));
99         (void)new (t->d()) typename ManagedType::Data();
100         return t->d();
101     }
102
103     template <typename ManagedType, typename Arg1>
104     typename ManagedType::Data *alloc(Arg1 arg1)
105     {
106         Scope scope(engine());
107         Scoped<ManagedType> t(scope, allocManaged<ManagedType>(sizeof(typename ManagedType::Data)));
108         (void)new (t->d()) typename ManagedType::Data(arg1);
109         return t->d();
110     }
111
112     template <typename ManagedType, typename Arg1, typename Arg2>
113     typename ManagedType::Data *alloc(Arg1 arg1, Arg2 arg2)
114     {
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);
118         return t->d();
119     }
120
121     template <typename ManagedType, typename Arg1, typename Arg2, typename Arg3>
122     typename ManagedType::Data *alloc(Arg1 arg1, Arg2 arg2, Arg3 arg3)
123     {
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);
127         return t->d();
128     }
129
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)
132     {
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);
136         return t->d();
137     }
138
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)
141     {
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);
145         return t->d();
146     }
147
148     bool isGCBlocked() const;
149     void setGCBlocked(bool blockGC);
150     void runGC();
151
152     ExecutionEngine *engine() const;
153
154     void dumpStats() const;
155
156     void registerDeletable(GCDeletable *d);
157
158     size_t getUsedMem() const;
159     size_t getAllocatedMem() const;
160     size_t getLargeItemsMem() const;
161
162 protected:
163     /// expects size to be aligned
164     // TODO: try to inline
165     Heap::Base *allocData(std::size_t size);
166
167 #ifdef DETAILED_MM_STATS
168     void willAllocate(std::size_t size);
169 #endif // DETAILED_MM_STATS
170
171 private:
172     void collectFromJSStack() const;
173     void mark();
174     void sweep(bool lastSweep = false);
175
176 protected:
177     QScopedPointer<Data> m_d;
178 public:
179     PersistentValueStorage *m_persistentValues;
180     PersistentValueStorage *m_weakValues;
181 };
182
183 }
184
185 QT_END_NAMESPACE
186
187 #endif // QV4GC_H