Rename QDeclarative symbols to QQuick and QQml
[profile/ivi/qtdeclarative.git] / src / qml / qml / qqmlcompileddata.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the QtQml module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qqmlcompiler_p.h"
43 #include "qqmlengine.h"
44 #include "qqmlcomponent.h"
45 #include "qqmlcomponent_p.h"
46 #include "qqmlcontext.h"
47 #include "qqmlcontext_p.h"
48 #ifdef QML_THREADED_VME_INTERPRETER
49 #include "qqmlvme_p.h"
50 #endif
51
52 #include <QtCore/qdebug.h>
53
54 #include <private/qobject_p.h>
55
56 QT_BEGIN_NAMESPACE
57
58 int QQmlCompiledData::pack(const char *data, size_t size)
59 {
60     const char *p = packData.constData();
61     unsigned int ps = packData.size();
62
63     for (unsigned int ii = 0; (ii + size) <= ps; ii += sizeof(int)) {
64         if (0 == ::memcmp(p + ii, data, size))
65             return ii;
66     }
67
68     int rv = packData.size();
69     packData.append(data, size);
70     return rv;
71 }
72
73 int QQmlCompiledData::indexForString(const QString &data)
74 {
75     int idx = primitives.indexOf(data);
76     if (idx == -1) {
77         idx = primitives.count();
78         primitives << data;
79     }
80     return idx;
81 }
82
83 int QQmlCompiledData::indexForByteArray(const QByteArray &data)
84 {
85     int idx = datas.indexOf(data);
86     if (idx == -1) {
87         idx = datas.count();
88         datas << data;
89     }
90     return idx;
91 }
92
93 int QQmlCompiledData::indexForUrl(const QUrl &data)
94 {
95     int idx = urls.indexOf(data);
96     if (idx == -1) {
97         idx = urls.count();
98         urls << data;
99     }
100     return idx;
101 }
102
103 QQmlCompiledData::QQmlCompiledData(QQmlEngine *engine)
104 : engine(engine), importCache(0), root(0), rootPropertyCache(0)
105 {
106     Q_ASSERT(engine);
107
108     bytecode.reserve(1024);
109 }
110
111 void QQmlCompiledData::destroy()
112 {
113     if (engine && hasEngine())
114         QQmlEnginePrivate::deleteInEngineThread(engine, this);
115     else
116         delete this;
117 }
118
119 QQmlCompiledData::~QQmlCompiledData()
120 {
121     clear();
122
123     for (int ii = 0; ii < types.count(); ++ii) {
124         if (types.at(ii).component)
125             types.at(ii).component->release();
126         if (types.at(ii).typePropertyCache)
127             types.at(ii).typePropertyCache->release();
128     }
129
130     for (int ii = 0; ii < propertyCaches.count(); ++ii) 
131         propertyCaches.at(ii)->release();
132
133     for (int ii = 0; ii < contextCaches.count(); ++ii)
134         contextCaches.at(ii)->release();
135
136     for (int ii = 0; ii < scripts.count(); ++ii)
137         scripts.at(ii)->release();
138
139     if (importCache)
140         importCache->release();
141
142     if (rootPropertyCache)
143         rootPropertyCache->release();
144 }
145
146 void QQmlCompiledData::clear()
147 {
148     for (int ii = 0; ii < programs.count(); ++ii)
149         qPersistentDispose(programs[ii].bindings);
150 }
151
152 const QMetaObject *QQmlCompiledData::TypeReference::metaObject() const
153 {
154     if (type) {
155         return type->metaObject();
156     } else {
157         Q_ASSERT(component);
158         return component->root;
159     }
160 }
161
162 /*!
163 Returns the property cache, if one alread exists.  The cache is not referenced.
164 */
165 QQmlPropertyCache *QQmlCompiledData::TypeReference::propertyCache() const
166 {
167     if (type)
168         return typePropertyCache;
169     else
170         return component->rootPropertyCache;
171 }
172
173 /*!
174 Returns the property cache, creating one if it doesn't already exist.  The cache is not referenced.
175 */
176 QQmlPropertyCache *QQmlCompiledData::TypeReference::createPropertyCache(QQmlEngine *engine) 
177 {
178     if (typePropertyCache) {
179         return typePropertyCache;
180     } else if (type) {
181         typePropertyCache = QQmlEnginePrivate::get(engine)->cache(type->metaObject());
182         typePropertyCache->addref();
183         return typePropertyCache;
184     } else {
185         return component->rootPropertyCache;
186     }
187 }
188
189
190 void QQmlCompiledData::dumpInstructions()
191 {
192     if (!name.isEmpty())
193         qWarning() << name;
194     qWarning().nospace() << "Index\tOperation\t\tData1\tData2\tData3\tComments";
195     qWarning().nospace() << "-------------------------------------------------------------------------------";
196
197     const char *instructionStream = bytecode.constData();
198     const char *endInstructionStream = bytecode.constData() + bytecode.size();
199
200     int instructionCount = 0;
201     while (instructionStream < endInstructionStream) {
202         QQmlInstruction *instr = (QQmlInstruction *)instructionStream;
203         dump(instr, instructionCount);
204         instructionStream += QQmlInstruction::size(instructionType(instr));
205         instructionCount++;
206     }
207
208     qWarning().nospace() << "-------------------------------------------------------------------------------";
209 }
210
211 int QQmlCompiledData::addInstructionHelper(QQmlInstruction::Type type, QQmlInstruction &instr)
212 {
213 #ifdef QML_THREADED_VME_INTERPRETER
214     instr.common.code = QQmlVME::instructionJumpTable()[static_cast<int>(type)];
215 #else
216     instr.common.instructionType = type;
217 #endif
218     int ptrOffset = bytecode.size();
219     int size = QQmlInstruction::size(type);
220     if (bytecode.capacity() <= bytecode.size() + size)
221         bytecode.reserve(bytecode.size() + size + 512);
222     bytecode.append(reinterpret_cast<const char *>(&instr), size);
223     return ptrOffset;
224 }
225
226 int QQmlCompiledData::nextInstructionIndex() 
227
228     return bytecode.size();
229 }
230
231 QQmlInstruction *QQmlCompiledData::instruction(int index) 
232
233     return (QQmlInstruction *)(bytecode.constData() + index);
234 }
235
236 QQmlInstruction::Type QQmlCompiledData::instructionType(const QQmlInstruction *instr)
237 {
238 #ifdef QML_THREADED_VME_INTERPRETER
239     void **jumpTable = QQmlVME::instructionJumpTable();
240     void *code = instr->common.code;
241
242 #  define QML_CHECK_INSTR_CODE(I, FMT) \
243     if (jumpTable[static_cast<int>(QQmlInstruction::I)] == code) \
244         return QQmlInstruction::I;
245
246     FOR_EACH_QML_INSTR(QML_CHECK_INSTR_CODE)
247     Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid instruction address");
248     return static_cast<QQmlInstruction::Type>(0);
249 #  undef QML_CHECK_INSTR_CODE
250 #else
251     return static_cast<QQmlInstruction::Type>(instr->common.instructionType);
252 #endif
253 }
254
255 void QQmlCompiledData::initialize(QQmlEngine *engine)
256 {
257     Q_ASSERT(!hasEngine());
258     QQmlCleanup::addToEngine(engine);
259 }
260
261 QT_END_NAMESPACE