Encapsulate and protect all accesses to the vtable of Heap objects
[platform/upstream/qtdeclarative.git] / src / qml / jsruntime / qv4managed_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 #ifndef QMLJS_MANAGED_H
34 #define QMLJS_MANAGED_H
35
36 #include "qv4global_p.h"
37 #include "qv4value_p.h"
38 #include <private/qv4heap_p.h>
39
40 QT_BEGIN_NAMESPACE
41
42 namespace QV4 {
43
44 #define Q_MANAGED_CHECK \
45     template <typename _T> inline void qt_check_for_QMANAGED_macro(const _T *_q_argument) const \
46     { int i = qYouForgotTheQ_MANAGED_Macro(this, _q_argument); i = i + 1; }
47
48 template <typename T>
49 inline int qYouForgotTheQ_MANAGED_Macro(T, T) { return 0; }
50
51 template <typename T1, typename T2>
52 inline void qYouForgotTheQ_MANAGED_Macro(T1, T2) {}
53
54 #ifdef Q_COMPILER_STATIC_ASSERT
55 #define V4_MANAGED_SIZE_TEST void __dataTest() { Q_STATIC_ASSERT(sizeof(*this) == sizeof(Managed)); }
56 #else
57 #define V4_MANAGED_SIZE_TEST
58 #endif
59
60 #define V4_NEEDS_DESTROY static void destroy(QV4::Heap::Base *b) { static_cast<Data *>(b)->~Data(); }
61
62
63 #define V4_MANAGED(DataClass, superClass) \
64     public: \
65         Q_MANAGED_CHECK \
66         typedef QV4::Heap::DataClass Data; \
67         typedef superClass SuperClass; \
68         static const QV4::VTable static_vtbl; \
69         static inline const QV4::VTable *staticVTable() { return &static_vtbl; } \
70         V4_MANAGED_SIZE_TEST \
71         QV4::Heap::DataClass *d() const { return static_cast<QV4::Heap::DataClass *>(m()); }
72
73 #define Q_MANAGED_TYPE(type) \
74     public: \
75         enum { MyType = Type_##type };
76
77 #define Q_VTABLE_FUNCTION(classname, func) \
78     (classname::func == QV4::Managed::func ? 0 : classname::func)
79
80
81 struct GCDeletable
82 {
83     GCDeletable() : next(0), lastCall(false) {}
84     virtual ~GCDeletable() {}
85     GCDeletable *next;
86     bool lastCall;
87 };
88
89 #define DEFINE_MANAGED_VTABLE_INT(classname, parentVTable) \
90 {     \
91     parentVTable, \
92     classname::IsExecutionContext,   \
93     classname::IsString,   \
94     classname::IsObject,   \
95     classname::IsFunctionObject,   \
96     classname::IsErrorObject,   \
97     classname::IsArrayData,   \
98     0,                                          \
99     classname::MyType,                          \
100     #classname, \
101     Q_VTABLE_FUNCTION(classname, destroy),                                    \
102     markObjects,                                \
103     isEqualTo                                  \
104 }
105
106 #define DEFINE_MANAGED_VTABLE(classname) \
107 const QV4::VTable classname::static_vtbl = DEFINE_MANAGED_VTABLE_INT(classname, 0)
108
109 struct Q_QML_PRIVATE_EXPORT Managed : Value
110 {
111     V4_MANAGED(Base, Managed)
112     enum {
113         IsExecutionContext = false,
114         IsString = false,
115         IsObject = false,
116         IsFunctionObject = false,
117         IsErrorObject = false,
118         IsArrayData = false
119     };
120 private:
121     void *operator new(size_t);
122     Managed() Q_DECL_EQ_DELETE;
123     Q_DISABLE_COPY(Managed)
124
125 public:
126
127     enum Type {
128         Type_Invalid,
129         Type_String,
130         Type_Object,
131         Type_ArrayObject,
132         Type_FunctionObject,
133         Type_BooleanObject,
134         Type_NumberObject,
135         Type_StringObject,
136         Type_DateObject,
137         Type_RegExpObject,
138         Type_ErrorObject,
139         Type_ArgumentsObject,
140         Type_JsonObject,
141         Type_MathObject,
142
143         Type_ExecutionContext,
144         Type_ForeachIteratorObject,
145         Type_RegExp,
146
147         Type_QmlSequence
148     };
149     Q_MANAGED_TYPE(Invalid)
150
151     bool isListType() const { return d()->vtable()->type == Type_QmlSequence; }
152
153     bool isArrayObject() const { return d()->vtable()->type == Type_ArrayObject; }
154     bool isStringObject() const { return d()->vtable()->type == Type_StringObject; }
155
156     QString className() const;
157
158     bool isEqualTo(const Managed *other) const
159     { return d()->vtable()->isEqualTo(const_cast<Managed *>(this), const_cast<Managed *>(other)); }
160
161     static bool isEqualTo(Managed *m, Managed *other);
162
163     bool inUse() const { return d()->inUse(); }
164     bool markBit() const { return d()->isMarked(); }
165
166     static void destroy(Heap::Base *) {}
167 private:
168     friend class MemoryManager;
169     friend struct Identifiers;
170     friend struct ObjectIterator;
171 };
172
173
174 template<>
175 inline const Managed *Value::as() const {
176     if (isManaged())
177         return managed();
178     return 0;
179 }
180
181 template<>
182 inline const Object *Value::as() const {
183     return isManaged() && m() && m()->vtable()->isObject ? objectValue() : 0;
184 }
185
186 }
187
188
189 QT_END_NAMESPACE
190
191 #endif