Merge branch 'master' of git://gitorious.org/qt/qtdeclarative into api_changes
[profile/ivi/qtdeclarative.git] / src / qml / qml / qqmlvme_p.h
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 #ifndef QQMLVME_P_H
43 #define QQMLVME_P_H
44
45 //
46 //  W A R N I N G
47 //  -------------
48 //
49 // This file is not part of the Qt API.  It exists purely as an
50 // implementation detail.  This header file may change from version to
51 // version without notice, or even be removed.
52 //
53 // We mean it.
54 //
55
56 #include "qqmlerror.h"
57 #include <private/qbitfield_p.h>
58 #include "qqmlinstruction_p.h"
59 #include <private/qrecursionwatcher_p.h>
60
61 #include <QtCore/QStack>
62 #include <QtCore/QString>
63 #include <QtCore/qelapsedtimer.h>
64 #include <QtCore/qcoreapplication.h>
65
66 #include <private/qv8_p.h>
67 #include <private/qqmlengine_p.h>
68 #include <private/qfinitestack_p.h>
69
70 #include <private/qqmltrace_p.h>
71
72 QT_BEGIN_NAMESPACE
73
74 class QObject;
75 class QJSValue;
76 class QQmlScriptData;
77 class QQmlCompiledData;
78 class QQmlCompiledData;
79 class QQmlContextData;
80
81 namespace QQmlVMETypes {
82     struct List
83     {
84         List() : type(0) {}
85         List(int t) : type(t) {}
86
87         int type;
88         QQmlListProperty<void> qListProperty;
89     };
90 }
91 Q_DECLARE_TYPEINFO(QQmlVMETypes::List, Q_PRIMITIVE_TYPE  | Q_MOVABLE_TYPE);
92
93 class QQmlVME
94 {
95     Q_DECLARE_TR_FUNCTIONS(QQmlVME)
96 public:
97     class Interrupt {
98     public:
99         inline Interrupt();
100         inline Interrupt(volatile bool *runWhile, int nsecs=0);
101         inline Interrupt(int nsecs);
102
103         inline void reset();
104         inline bool shouldInterrupt() const;
105     private:
106         enum Mode { None, Time, Flag };
107         Mode mode;
108         struct {
109             QElapsedTimer timer;
110             int nsecs;
111         };
112         volatile bool *runWhile;
113     };
114
115     QQmlVME() : data(0), componentAttached(0) {}
116     QQmlVME(void *data) : data(data), componentAttached(0) {}
117
118     void *data;
119     QQmlComponentAttached *componentAttached;
120     QList<QQmlEnginePrivate::FinalizeCallback> finalizeCallbacks;
121
122     void init(QQmlContextData *, QQmlCompiledData *, int start,
123               QQmlContextData * = 0);
124     bool initDeferred(QObject *);
125     void reset();
126
127     QObject *execute(QList<QQmlError> *errors, const Interrupt & = Interrupt());
128     QQmlContextData *complete(const Interrupt & = Interrupt());
129
130 private:
131     friend class QQmlVMEGuard;
132
133     QObject *run(QList<QQmlError> *errors, const Interrupt &
134 #ifdef QML_THREADED_VME_INTERPRETER
135                  , void ***storeJumpTable = 0
136 #endif
137                 );
138     v8::Persistent<v8::Object> run(QQmlContextData *, QQmlScriptData *);
139
140 #ifdef QML_THREADED_VME_INTERPRETER
141     static void **instructionJumpTable();
142     friend class QQmlCompiledData;
143 #endif
144
145     QQmlEngine *engine;
146     QRecursionNode recursion;
147
148 #ifdef QML_ENABLE_TRACE
149     QQmlCompiledData *rootComponent;
150 #endif
151
152     QFiniteStack<QObject *> objects;
153     QFiniteStack<QQmlVMETypes::List> lists;
154
155     QFiniteStack<QQmlAbstractBinding *> bindValues;
156     QFiniteStack<QQmlParserStatus *> parserStatus;
157 #ifdef QML_ENABLE_TRACE
158     QFiniteStack<QQmlData *> parserStatusData;
159 #endif
160
161     QQmlGuardedContextData rootContext;
162     QQmlGuardedContextData creationContext;
163
164     struct State {
165         enum Flag { Deferred = 0x00000001 };
166
167         State() : flags(0), context(0), compiledData(0), instructionStream(0) {}
168         quint32 flags;
169         QQmlContextData *context;
170         QQmlCompiledData *compiledData;
171         const char *instructionStream;
172         QBitField bindingSkipList;
173     };
174
175     QStack<State> states;
176
177     static void blank(QFiniteStack<QQmlParserStatus *> &);
178     static void blank(QFiniteStack<QQmlAbstractBinding *> &);
179 };
180
181 // Used to check that a QQmlVME that is interrupted mid-execution
182 // is still valid.  Checks all the objects and contexts have not been 
183 // deleted.
184 class QQmlVMEGuard
185 {
186 public:
187     QQmlVMEGuard();
188     ~QQmlVMEGuard();
189
190     void guard(QQmlVME *);
191     void clear();
192
193     bool isOK() const;
194
195 private:
196     int m_objectCount;
197     QQmlGuard<QObject> *m_objects;
198     int m_contextCount;
199     QQmlGuardedContextData *m_contexts;
200 };
201
202 QQmlVME::Interrupt::Interrupt()
203     : mode(None), nsecs(0), runWhile(0)
204 {
205 }
206
207 QQmlVME::Interrupt::Interrupt(volatile bool *runWhile, int nsecs)
208     : mode(Flag), nsecs(nsecs), runWhile(runWhile)
209 {
210 }
211
212 QQmlVME::Interrupt::Interrupt(int nsecs)
213     : mode(Time), nsecs(nsecs), runWhile(0)
214 {
215 }
216
217 void QQmlVME::Interrupt::reset()
218 {
219     if (mode == Time || nsecs)
220         timer.start();
221 }
222
223 bool QQmlVME::Interrupt::shouldInterrupt() const
224 {
225     if (mode == None) {
226         return false;
227     } else if (mode == Time) {
228         return timer.nsecsElapsed() > nsecs;
229     } else if (mode == Flag) {
230         return !*runWhile || (nsecs && timer.nsecsElapsed() > nsecs);
231     } else {
232         return false;
233     }
234 }
235
236 QT_END_NAMESPACE
237
238 #endif // QQMLVME_P_H