Remove "All rights reserved" line from license headers.
[profile/ivi/qtdeclarative.git] / src / declarative / qml / qdeclarativecompileddata.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 QtDeclarative 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 "qdeclarativecompiler_p.h"
43 #include "qdeclarativeengine.h"
44 #include "qdeclarativecomponent.h"
45 #include "qdeclarativecomponent_p.h"
46 #include "qdeclarativecontext.h"
47 #include "qdeclarativecontext_p.h"
48 #ifdef QML_THREADED_VME_INTERPRETER
49 #include "qdeclarativevme_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 QDeclarativeCompiledData::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 QDeclarativeCompiledData::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 QDeclarativeCompiledData::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 QDeclarativeCompiledData::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 QDeclarativeCompiledData::QDeclarativeCompiledData(QDeclarativeEngine *engine)
104 : engine(engine), importCache(0), root(0), rootPropertyCache(0)
105 {
106     Q_ASSERT(engine);
107
108     bytecode.reserve(1024);
109 }
110
111 void QDeclarativeCompiledData::destroy()
112 {
113     if (engine && hasEngine())
114         QDeclarativeEnginePrivate::deleteInEngineThread(engine, this);
115     else
116         delete this;
117 }
118
119 QDeclarativeCompiledData::~QDeclarativeCompiledData()
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 QDeclarativeCompiledData::clear()
147 {
148     for (int ii = 0; ii < v8bindings.count(); ++ii)
149         qPersistentDispose(v8bindings[ii]);
150     v8bindings.clear();
151 }
152
153 const QMetaObject *QDeclarativeCompiledData::TypeReference::metaObject() const
154 {
155     if (type) {
156         return type->metaObject();
157     } else {
158         Q_ASSERT(component);
159         return component->root;
160     }
161 }
162
163 /*!
164 Returns the property cache, if one alread exists.  The cache is not referenced.
165 */
166 QDeclarativePropertyCache *QDeclarativeCompiledData::TypeReference::propertyCache() const
167 {
168     if (type)
169         return typePropertyCache;
170     else
171         return component->rootPropertyCache;
172 }
173
174 /*!
175 Returns the property cache, creating one if it doesn't already exist.  The cache is not referenced.
176 */
177 QDeclarativePropertyCache *QDeclarativeCompiledData::TypeReference::createPropertyCache(QDeclarativeEngine *engine) 
178 {
179     if (typePropertyCache) {
180         return typePropertyCache;
181     } else if (type) {
182         typePropertyCache = QDeclarativeEnginePrivate::get(engine)->cache(type->metaObject());
183         typePropertyCache->addref();
184         return typePropertyCache;
185     } else {
186         return component->rootPropertyCache;
187     }
188 }
189
190
191 void QDeclarativeCompiledData::dumpInstructions()
192 {
193     if (!name.isEmpty())
194         qWarning() << name;
195     qWarning().nospace() << "Index\tOperation\t\tData1\tData2\tData3\tComments";
196     qWarning().nospace() << "-------------------------------------------------------------------------------";
197
198     const char *instructionStream = bytecode.constData();
199     const char *endInstructionStream = bytecode.constData() + bytecode.size();
200
201     int instructionCount = 0;
202     while (instructionStream < endInstructionStream) {
203         QDeclarativeInstruction *instr = (QDeclarativeInstruction *)instructionStream;
204         dump(instr, instructionCount);
205         instructionStream += QDeclarativeInstruction::size(instructionType(instr));
206         instructionCount++;
207     }
208
209     qWarning().nospace() << "-------------------------------------------------------------------------------";
210 }
211
212 int QDeclarativeCompiledData::addInstructionHelper(QDeclarativeInstruction::Type type, QDeclarativeInstruction &instr)
213 {
214 #ifdef QML_THREADED_VME_INTERPRETER
215     instr.common.code = QDeclarativeVME::instructionJumpTable()[static_cast<int>(type)];
216 #else
217     instr.common.instructionType = type;
218 #endif
219     int ptrOffset = bytecode.size();
220     int size = QDeclarativeInstruction::size(type);
221     if (bytecode.capacity() <= bytecode.size() + size)
222         bytecode.reserve(bytecode.size() + size + 512);
223     bytecode.append(reinterpret_cast<const char *>(&instr), size);
224     return ptrOffset;
225 }
226
227 int QDeclarativeCompiledData::nextInstructionIndex() 
228
229     return bytecode.size();
230 }
231
232 QDeclarativeInstruction *QDeclarativeCompiledData::instruction(int index) 
233
234     return (QDeclarativeInstruction *)(bytecode.constData() + index);
235 }
236
237 QDeclarativeInstruction::Type QDeclarativeCompiledData::instructionType(const QDeclarativeInstruction *instr)
238 {
239 #ifdef QML_THREADED_VME_INTERPRETER
240     void **jumpTable = QDeclarativeVME::instructionJumpTable();
241     void *code = instr->common.code;
242
243 #  define QML_CHECK_INSTR_CODE(I, FMT) \
244     if (jumpTable[static_cast<int>(QDeclarativeInstruction::I)] == code) \
245         return QDeclarativeInstruction::I;
246
247     FOR_EACH_QML_INSTR(QML_CHECK_INSTR_CODE)
248     Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid instruction address");
249     return static_cast<QDeclarativeInstruction::Type>(0);
250 #  undef QML_CHECK_INSTR_CODE
251 #else
252     return static_cast<QDeclarativeInstruction::Type>(instr->common.instructionType);
253 #endif
254 }
255
256 void QDeclarativeCompiledData::initialize(QDeclarativeEngine *engine)
257 {
258     Q_ASSERT(!hasEngine());
259     QDeclarativeCleanup::addToEngine(engine);
260 }
261
262 QT_END_NAMESPACE