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 ****************************************************************************/
34 #include "qv4persistent_p.h"
35 #include <private/qv4mm_p.h>
36 #include "qv4object_p.h"
37 #include "PageAllocation.h"
45 WTF::PageAllocation alloc;
46 ExecutionEngine *engine;
53 static const int kEntriesPerPage = int((WTF::pageSize() - sizeof(Header)) / sizeof(Value));
57 Value values[1]; // Really kEntriesPerPage, but keep the compiler happy
60 Page *getPage(Value *val) {
61 return reinterpret_cast<Page *>(reinterpret_cast<quintptr>(val) & ~((quintptr)(WTF::pageSize() - 1)));
65 Page *allocatePage(PersistentValueStorage *storage)
67 PageAllocation page = WTF::PageAllocation::allocate(WTF::pageSize());
68 Page *p = reinterpret_cast<Page *>(page.base());
70 Q_ASSERT(!((quintptr)p & (WTF::pageSize() - 1)));
72 p->header.engine = storage->engine;
73 p->header.alloc = page;
74 p->header.next = reinterpret_cast<Page *>(storage->firstPage);
75 p->header.prev = reinterpret_cast<Page **>(&storage->firstPage);
76 p->header.refCount = 0;
77 p->header.freeList = 0;
79 p->header.next->header.prev = &p->header.next;
80 for (int i = 0; i < kEntriesPerPage - 1; ++i) {
81 p->values[i].setTag(QV4::Value::Empty_Type);
82 p->values[i].setInt_32(i + 1);
84 p->values[kEntriesPerPage - 1].setTag(QV4::Value::Empty_Type);
85 p->values[kEntriesPerPage - 1].setInt_32(-1);
87 storage->firstPage = p;
96 PersistentValueStorage::Iterator &PersistentValueStorage::Iterator::operator++() {
98 while (index < kEntriesPerPage - 1) {
100 if (static_cast<Page *>(p)->values[index].tag() != QV4::Value::Empty_Type)
104 p = static_cast<Page *>(p)->header.next;
110 Value &PersistentValueStorage::Iterator::operator *()
112 return static_cast<Page *>(p)->values[index];
115 PersistentValueStorage::PersistentValueStorage(ExecutionEngine *engine)
121 PersistentValueStorage::~PersistentValueStorage()
123 Page *p = static_cast<Page *>(firstPage);
125 for (int i = 0; i < kEntriesPerPage; ++i) {
126 if (!p->values[i].isEmpty())
127 p->values[i] = Encode::undefined();
129 Page *n = p->header.next;
130 p->header.engine = 0;
133 Q_ASSERT(p->header.refCount);
138 Value *PersistentValueStorage::allocate()
140 Page *p = static_cast<Page *>(firstPage);
142 if (p->header.freeList != -1)
147 p = allocatePage(this);
149 Value *v = p->values + p->header.freeList;
150 p->header.freeList = v->int_32();
151 ++p->header.refCount;
153 v->setRawValue(Encode::undefined());
158 void PersistentValueStorage::free(Value *v)
163 Page *p = getPage(v);
165 v->setTag(QV4::Value::Empty_Type);
166 v->setInt_32(p->header.freeList);
167 p->header.freeList = v - p->values;
168 if (!--p->header.refCount) {
170 *p->header.prev = p->header.next;
172 p->header.next->header.prev = p->header.prev;
173 p->header.alloc.deallocate();
177 static void drainMarkStack(QV4::ExecutionEngine *engine, Value *markBase)
179 while (engine->jsStackTop > markBase) {
180 Heap::Base *h = engine->popForGC();
181 Q_ASSERT (h->vtable()->markObjects);
182 h->vtable()->markObjects(h, engine);
186 void PersistentValueStorage::mark(ExecutionEngine *e)
188 Value *markBase = e->jsStackTop;
190 Page *p = static_cast<Page *>(firstPage);
192 for (int i = 0; i < kEntriesPerPage; ++i) {
193 if (Managed *m = p->values[i].as<Managed>())
196 drainMarkStack(e, markBase);
202 ExecutionEngine *PersistentValueStorage::getEngine(Value *v)
204 return getPage(v)->header.engine;
208 PersistentValue::PersistentValue(const PersistentValue &other)
212 val = other.engine()->memoryManager->m_persistentValues->allocate();
217 PersistentValue::PersistentValue(ExecutionEngine *engine, const Value &value)
219 val = engine->memoryManager->m_persistentValues->allocate();
223 PersistentValue::PersistentValue(ExecutionEngine *engine, ReturnedValue value)
225 val = engine->memoryManager->m_persistentValues->allocate();
229 PersistentValue::PersistentValue(ExecutionEngine *engine, Object *object)
235 val = engine->memoryManager->m_persistentValues->allocate();
239 PersistentValue::~PersistentValue()
241 PersistentValueStorage::free(val);
244 PersistentValue &PersistentValue::operator=(const PersistentValue &other)
249 val = other.engine()->memoryManager->m_persistentValues->allocate();
252 Q_ASSERT(engine() == other.engine());
258 PersistentValue &PersistentValue::operator=(const WeakValue &other)
261 if (!other.valueRef())
263 val = other.engine()->memoryManager->m_persistentValues->allocate();
266 Q_ASSERT(engine() == other.engine());
268 *val = *other.valueRef();
272 PersistentValue &PersistentValue::operator=(Object *object)
275 PersistentValueStorage::free(val);
279 val = object->engine()->memoryManager->m_persistentValues->allocate();
285 void PersistentValue::set(ExecutionEngine *engine, const Value &value)
288 val = engine->memoryManager->m_persistentValues->allocate();
292 void PersistentValue::set(ExecutionEngine *engine, ReturnedValue value)
295 val = engine->memoryManager->m_persistentValues->allocate();
299 void PersistentValue::set(ExecutionEngine *engine, Heap::Base *obj)
302 val = engine->memoryManager->m_persistentValues->allocate();
306 WeakValue::WeakValue(const WeakValue &other)
310 val = other.engine()->memoryManager->m_weakValues->allocate();
315 WeakValue::WeakValue(ExecutionEngine *engine, const Value &value)
317 val = engine->memoryManager->m_weakValues->allocate();
321 WeakValue &WeakValue::operator=(const WeakValue &other)
326 val = other.engine()->memoryManager->m_weakValues->allocate();
329 Q_ASSERT(engine() == other.engine());
335 WeakValue::~WeakValue()
337 PersistentValueStorage::free(val);
340 void WeakValue::set(ExecutionEngine *engine, const Value &value)
343 val = engine->memoryManager->m_weakValues->allocate();
347 void WeakValue::set(ExecutionEngine *engine, ReturnedValue value)
350 val = engine->memoryManager->m_weakValues->allocate();
354 void WeakValue::set(ExecutionEngine *engine, Heap::Base *obj)
357 val = engine->memoryManager->m_weakValues->allocate();
361 void WeakValue::markOnce(ExecutionEngine *e)