1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtQml module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
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 https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://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 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39#ifndef QMLJS_MANAGED_H
40#define QMLJS_MANAGED_H
41
42//
43// W A R N I N G
44// -------------
45//
46// This file is not part of the Qt API. It exists purely as an
47// implementation detail. This header file may change from version to
48// version without notice, or even be removed.
49//
50// We mean it.
51//
52
53#include "qv4global_p.h"
54#include "qv4value_p.h"
55#include "qv4enginebase_p.h"
56#include <private/qv4heap_p.h>
57#include <private/qv4vtable_p.h>
58
59QT_BEGIN_NAMESPACE
60
61namespace QV4 {
62
63#define Q_MANAGED_CHECK \
64 template <typename Type> inline void qt_check_for_QMANAGED_macro(const Type *_q_argument) const \
65 { int i = qYouForgotTheQ_MANAGED_Macro(this, _q_argument); i = i + 1; }
66
67template <typename T>
68inline int qYouForgotTheQ_MANAGED_Macro(T, T) { return 0; }
69
70template <typename T1, typename T2>
71inline void qYouForgotTheQ_MANAGED_Macro(T1, T2) {}
72
73#define V4_MANAGED_SIZE_TEST void __dataTest() { static_assert (sizeof(*this) == sizeof(Managed), "Classes derived from Managed can't have own data members."); }
74
75#define V4_NEEDS_DESTROY static void virtualDestroy(QV4::Heap::Base *b) { static_cast<Data *>(b)->destroy(); }
76
77
78#define V4_MANAGED_ITSELF(DataClass, superClass) \
79 public: \
80 Q_MANAGED_CHECK \
81 typedef QV4::Heap::DataClass Data; \
82 typedef superClass SuperClass; \
83 static const QV4::VTable static_vtbl; \
84 static inline const QV4::VTable *staticVTable() { return &static_vtbl; } \
85 V4_MANAGED_SIZE_TEST \
86 QV4::Heap::DataClass *d_unchecked() const { return static_cast<QV4::Heap::DataClass *>(m()); } \
87 QV4::Heap::DataClass *d() const { \
88 QV4::Heap::DataClass *dptr = d_unchecked(); \
89 dptr->_checkIsInitialized(); \
90 return dptr; \
91 }
92
93#define V4_MANAGED(DataClass, superClass) \
94 private: \
95 DataClass() Q_DECL_EQ_DELETE; \
96 Q_DISABLE_COPY(DataClass) \
97 V4_MANAGED_ITSELF(DataClass, superClass) \
98 Q_STATIC_ASSERT(std::is_trivial< QV4::Heap::DataClass >::value);
99
100#define Q_MANAGED_TYPE(type) \
101 public: \
102 enum { MyType = Type_##type };
103
104#define V4_INTERNALCLASS(c) \
105 static Heap::InternalClass *defaultInternalClass(QV4::EngineBase *e) \
106 { return e->internalClasses(QV4::EngineBase::Class_##c); }
107
108struct Q_QML_PRIVATE_EXPORT Managed : Value, VTableBase
109{
110 V4_MANAGED_ITSELF(Base, Managed)
111 enum {
112 IsExecutionContext = false,
113 IsString = false,
114 IsStringOrSymbol = false,
115 IsObject = false,
116 IsFunctionObject = false,
117 IsErrorObject = false,
118 IsArrayData = false
119 };
120private:
121 void *operator new(size_t);
122 Managed() Q_DECL_EQ_DELETE;
123 Q_DISABLE_COPY(Managed)
124
125public:
126 enum { NInlineProperties = 0 };
127
128 enum Type {
129 Type_Invalid,
130 Type_String,
131 Type_Object,
132 Type_Symbol,
133 Type_ArrayObject,
134 Type_FunctionObject,
135 Type_GeneratorObject,
136 Type_BooleanObject,
137 Type_NumberObject,
138 Type_StringObject,
139 Type_SymbolObject,
140 Type_DateObject,
141 Type_RegExpObject,
142 Type_ErrorObject,
143 Type_ArgumentsObject,
144 Type_JsonObject,
145 Type_MathObject,
146 Type_ProxyObject,
147
148 Type_ExecutionContext,
149 Type_InternalClass,
150 Type_SetIteratorObject,
151 Type_MapIteratorObject,
152 Type_ArrayIteratorObject,
153 Type_StringIteratorObject,
154 Type_ForInIterator,
155 Type_RegExp,
156
157 Type_QmlSequence
158 };
159 Q_MANAGED_TYPE(Invalid)
160
161 Heap::InternalClass *internalClass() const { return d()->internalClass; }
162 const VTable *vtable() const { return d()->internalClass->vtable; }
163 inline ExecutionEngine *engine() const { return internalClass()->engine; }
164
165 bool isListType() const { return d()->internalClass->vtable->type == Type_QmlSequence; }
166 bool isArrayLike() const { return isArrayObject() || isListType(); }
167
168 bool isArrayObject() const { return d()->internalClass->vtable->type == Type_ArrayObject; }
169 bool isStringObject() const { return d()->internalClass->vtable->type == Type_StringObject; }
170 bool isSymbolObject() const { return d()->internalClass->vtable->type == Type_SymbolObject; }
171
172 QString className() const;
173
174 bool isEqualTo(const Managed *other) const
175 { return d()->internalClass->vtable->isEqualTo(const_cast<Managed *>(this), const_cast<Managed *>(other)); }
176
177 bool inUse() const { return d()->inUse(); }
178 bool markBit() const { return d()->isMarked(); }
179 inline void mark(MarkStack *markStack);
180
181 Q_ALWAYS_INLINE Heap::Base *heapObject() const {
182 return m();
183 }
184
185 template<typename T> inline T *cast() {
186 return static_cast<T *>(this);
187 }
188 template<typename T> inline const T *cast() const {
189 return static_cast<const T *>(this);
190 }
191
192protected:
193 static bool virtualIsEqualTo(Managed *m, Managed *other);
194
195private:
196 friend class MemoryManager;
197 friend struct Identifiers;
198 friend struct ObjectIterator;
199};
200
201inline void Managed::mark(MarkStack *markStack)
202{
203 Q_ASSERT(m());
204 m()->mark(markStack);
205}
206
207template<>
208inline const Managed *Value::as() const {
209 return managed();
210}
211
212template<>
213inline const Object *Value::as() const {
214 return objectValue();
215}
216
217
218struct InternalClass : Managed
219{
220 V4_MANAGED_ITSELF(InternalClass, Managed)
221 Q_MANAGED_TYPE(InternalClass)
222 V4_INTERNALCLASS(Empty)
223 V4_NEEDS_DESTROY
224
225 Q_REQUIRED_RESULT Heap::InternalClass *changeVTable(const VTable *vt) {
226 return d()->changeVTable(vt);
227 }
228 Q_REQUIRED_RESULT Heap::InternalClass *changePrototype(Heap::Object *proto) {
229 return d()->changePrototype(proto);
230 }
231 Q_REQUIRED_RESULT Heap::InternalClass *addMember(PropertyKey identifier, PropertyAttributes data, InternalClassEntry *entry = nullptr) {
232 return d()->addMember(identifier, data, entry);
233 }
234
235 Q_REQUIRED_RESULT Heap::InternalClass *changeMember(PropertyKey identifier, PropertyAttributes data, InternalClassEntry *entry = nullptr) {
236 return d()->changeMember(identifier, data, entry);
237 }
238
239 void operator =(Heap::InternalClass *ic) {
240 Value::operator=(ic);
241 }
242};
243
244}
245
246
247QT_END_NAMESPACE
248
249#endif
250