Encapsulate and protect all accesses to the vtable of Heap objects
[platform/upstream/qtdeclarative.git] / src / qml / jsruntime / qv4arraydata_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 QV4ARRAYDATA_H
34 #define QV4ARRAYDATA_H
35
36 #include "qv4global_p.h"
37 #include "qv4managed_p.h"
38 #include "qv4property_p.h"
39 #include "qv4sparsearray_p.h"
40
41 QT_BEGIN_NAMESPACE
42
43 namespace QV4 {
44
45 #define V4_ARRAYDATA(DataClass) \
46     public: \
47         Q_MANAGED_CHECK \
48         typedef QV4::Heap::DataClass Data; \
49         static const QV4::ArrayVTable static_vtbl; \
50         static inline const QV4::VTable *staticVTable() { return &static_vtbl.vTable; } \
51         V4_MANAGED_SIZE_TEST \
52         const Data *d() const { return static_cast<const Data *>(m()); } \
53         Data *d() { return static_cast<Data *>(m()); }
54
55
56 struct ArrayData;
57
58 struct ArrayVTable
59 {
60     VTable vTable;
61     uint type;
62     Heap::ArrayData *(*reallocate)(Object *o, uint n, bool enforceAttributes);
63     ReturnedValue (*get)(const Heap::ArrayData *d, uint index);
64     bool (*put)(Object *o, uint index, const Value &value);
65     bool (*putArray)(Object *o, uint index, const Value *values, uint n);
66     bool (*del)(Object *o, uint index);
67     void (*setAttribute)(Object *o, uint index, PropertyAttributes attrs);
68     void (*push_front)(Object *o, const Value *values, uint n);
69     ReturnedValue (*pop_front)(Object *o);
70     uint (*truncate)(Object *o, uint newLen);
71     uint (*length)(const Heap::ArrayData *d);
72 };
73
74 namespace Heap {
75
76 struct ArrayData : public Base {
77     enum Type {
78         Simple = 0,
79         Complex = 1,
80         Sparse = 2,
81         Custom = 3
82     };
83
84     uint alloc;
85     Type type;
86     PropertyAttributes *attrs;
87     union {
88         uint len;
89         ReturnedValue freeList;
90     };
91     union {
92         uint offset;
93         SparseArray *sparse;
94     };
95     Value arrayData[1];
96
97     bool isSparse() const { return type == Sparse; }
98
99     const ArrayVTable *vtable() const { return reinterpret_cast<const ArrayVTable *>(Base::vtable()); }
100
101     inline ReturnedValue get(uint i) const {
102         return vtable()->get(this, i);
103     }
104     inline Property *getProperty(uint index);
105     inline PropertyAttributes attributes(uint i) const;
106
107     bool isEmpty(uint i) const {
108         return get(i) == Primitive::emptyValue().asReturnedValue();
109     }
110
111     inline ReturnedValue length() const {
112         return vtable()->length(this);
113     }
114
115 };
116
117 struct SimpleArrayData : public ArrayData {
118     uint mappedIndex(uint index) const { return (index + offset) % alloc; }
119     Value data(uint index) const { return arrayData[mappedIndex(index)]; }
120     Value &data(uint index) { return arrayData[mappedIndex(index)]; }
121
122     Property *getProperty(uint index) {
123         if (index >= len)
124             return 0;
125         index = mappedIndex(index);
126         if (arrayData[index].isEmpty())
127             return 0;
128         return reinterpret_cast<Property *>(arrayData + index);
129     }
130
131     PropertyAttributes attributes(uint i) const {
132         return attrs ? attrs[i] : Attr_Data;
133     }
134 };
135
136 struct SparseArrayData : public ArrayData {
137     inline ~SparseArrayData();
138
139     uint mappedIndex(uint index) const {
140         SparseArrayNode *n = sparse->findNode(index);
141         if (!n)
142             return UINT_MAX;
143         return n->value;
144     }
145
146     Property *getProperty(uint index) {
147         SparseArrayNode *n = sparse->findNode(index);
148         if (!n)
149             return 0;
150         return reinterpret_cast<Property *>(arrayData + n->value);
151     }
152
153     PropertyAttributes attributes(uint i) const {
154         if (!attrs)
155             return Attr_Data;
156         uint index = mappedIndex(i);
157         return index < UINT_MAX ? attrs[index] : Attr_Data;
158     }
159 };
160
161 }
162
163 struct Q_QML_EXPORT ArrayData : public Managed
164 {
165     typedef Heap::ArrayData::Type Type;
166     V4_MANAGED(ArrayData, Managed)
167
168     uint alloc() const { return d()->alloc; }
169     uint &alloc() { return d()->alloc; }
170     void setAlloc(uint a) { d()->alloc = a; }
171     Type type() const { return d()->type; }
172     void setType(Type t) { d()->type = t; }
173     PropertyAttributes *attrs() const { return d()->attrs; }
174     void setAttrs(PropertyAttributes *a) { d()->attrs = a; }
175     const Value *arrayData() const { return &d()->arrayData[0]; }
176     Value *arrayData() { return &d()->arrayData[0]; }
177
178     const ArrayVTable *vtable() const { return d()->vtable(); }
179     bool isSparse() const { return type() == Heap::ArrayData::Sparse; }
180
181     uint length() const {
182         return d()->length();
183     }
184
185     bool hasAttributes() const {
186         return attrs();
187     }
188     PropertyAttributes attributes(uint i) const {
189         return d()->attributes(i);
190     }
191
192     bool isEmpty(uint i) const {
193         return d()->isEmpty(i);
194     }
195
196     ReturnedValue get(uint i) const {
197         return d()->get(i);
198     }
199     inline Property *getProperty(uint index) {
200         return d()->getProperty(index);
201     }
202
203     static void ensureAttributes(Object *o);
204     static void realloc(Object *o, Type newType, uint alloc, bool enforceAttributes);
205
206     static void sort(ExecutionEngine *engine, Object *thisObject, const Value &comparefn, uint dataLen);
207     static uint append(Object *obj, ArrayObject *otherObj, uint n);
208     static Property *insert(Object *o, uint index, bool isAccessor = false);
209 };
210
211 struct Q_QML_EXPORT SimpleArrayData : public ArrayData
212 {
213     V4_ARRAYDATA(SimpleArrayData)
214
215     uint mappedIndex(uint index) const { return d()->mappedIndex(index); }
216     Value data(uint index) const { return d()->data(index); }
217     Value &data(uint index) { return d()->data(index); }
218
219     uint &len() { return d()->len; }
220     uint len() const { return d()->len; }
221
222     static Heap::ArrayData *reallocate(Object *o, uint n, bool enforceAttributes);
223
224     static void markObjects(Heap::Base *d, ExecutionEngine *e);
225
226     static ReturnedValue get(const Heap::ArrayData *d, uint index);
227     static bool put(Object *o, uint index, const Value &value);
228     static bool putArray(Object *o, uint index, const Value *values, uint n);
229     static bool del(Object *o, uint index);
230     static void setAttribute(Object *o, uint index, PropertyAttributes attrs);
231     static void push_front(Object *o, const Value *values, uint n);
232     static ReturnedValue pop_front(Object *o);
233     static uint truncate(Object *o, uint newLen);
234     static uint length(const Heap::ArrayData *d);
235 };
236
237 struct Q_QML_EXPORT SparseArrayData : public ArrayData
238 {
239     V4_ARRAYDATA(SparseArrayData)
240     V4_NEEDS_DESTROY
241
242     ReturnedValue &freeList() { return d()->freeList; }
243     ReturnedValue freeList() const { return d()->freeList; }
244     SparseArray *sparse() const { return d()->sparse; }
245     void setSparse(SparseArray *s) { d()->sparse = s; }
246
247     static uint allocate(Object *o, bool doubleSlot = false);
248     static void free(Heap::ArrayData *d, uint idx);
249
250     uint mappedIndex(uint index) const { return d()->mappedIndex(index); }
251
252     static void markObjects(Heap::Base *d, ExecutionEngine *e);
253
254     static Heap::ArrayData *reallocate(Object *o, uint n, bool enforceAttributes);
255     static ReturnedValue get(const Heap::ArrayData *d, uint index);
256     static bool put(Object *o, uint index, const Value &value);
257     static bool putArray(Object *o, uint index, const Value *values, uint n);
258     static bool del(Object *o, uint index);
259     static void setAttribute(Object *o, uint index, PropertyAttributes attrs);
260     static void push_front(Object *o, const Value *values, uint n);
261     static ReturnedValue pop_front(Object *o);
262     static uint truncate(Object *o, uint newLen);
263     static uint length(const Heap::ArrayData *d);
264 };
265
266 namespace Heap {
267
268 inline SparseArrayData::~SparseArrayData()
269 {
270     delete sparse;
271 }
272
273 inline Property *ArrayData::getProperty(uint index)
274 {
275     if (isSparse())
276         return static_cast<SparseArrayData *>(this)->getProperty(index);
277     return static_cast<SimpleArrayData *>(this)->getProperty(index);
278 }
279
280 inline PropertyAttributes ArrayData::attributes(uint i) const
281 {
282     if (isSparse())
283         return static_cast<const SparseArrayData *>(this)->attributes(i);
284     return static_cast<const SimpleArrayData *>(this)->attributes(i);
285 }
286
287
288 }
289
290 }
291
292 QT_END_NAMESPACE
293
294 #endif