Remove "All rights reserved" line from license headers.
[profile/ivi/qtdeclarative.git] / src / declarative / qml / qdeclarativevme.cpp
index 6bbc47b..ee1f8bc 100644 (file)
@@ -1,34 +1,34 @@
 /****************************************************************************
 **
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
 **
 ** This file is part of the QtDeclarative module of the Qt Toolkit.
 **
 ** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the Technology Preview License Agreement accompanying
-** this package.
-**
 ** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file.  Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 **
 ** In addition, as a special exception, Nokia gives you certain additional
-** rights.  These rights are described in the Nokia Qt LGPL Exception
+** rights. These rights are described in the Nokia Qt LGPL Exception
 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 **
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
 **
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
 **
 **
 **
 **
 ****************************************************************************/
 
-#include "private/qdeclarativevme_p.h"
+#include "qdeclarativevme_p.h"
 
-#include "private/qdeclarativecompiler_p.h"
-#include "private/qdeclarativeboundsignal_p.h"
-#include "private/qdeclarativestringconverters_p.h"
-#include "private/qmetaobjectbuilder_p.h"
-#include "private/qdeclarativedata_p.h"
+#include "qdeclarativecompiler_p.h"
+#include "qdeclarativeboundsignal_p.h"
+#include "qdeclarativestringconverters_p.h"
+#include <private/qmetaobjectbuilder_p.h>
+#include <private/qfastmetabuilder_p.h>
+#include "qdeclarativedata_p.h"
 #include "qdeclarative.h"
-#include "private/qdeclarativecustomparser_p.h"
+#include "qdeclarativecustomparser_p.h"
 #include "qdeclarativeengine.h"
 #include "qdeclarativecontext.h"
 #include "qdeclarativecomponent.h"
-#include "private/qdeclarativebinding_p.h"
-#include "private/qdeclarativeengine_p.h"
-#include "private/qdeclarativecomponent_p.h"
-#include "private/qdeclarativevmemetaobject_p.h"
-#include "private/qdeclarativebinding_p_p.h"
-#include "private/qdeclarativecontext_p.h"
-#include "private/qdeclarativev4bindings_p.h"
-#include "private/qdeclarativeglobal_p.h"
-#include "private/qdeclarativeglobalscriptclass_p.h"
+#include "qdeclarativecomponentattached_p.h"
+#include "qdeclarativebinding_p.h"
+#include "qdeclarativeengine_p.h"
+#include "qdeclarativecomponent_p.h"
+#include "qdeclarativevmemetaobject_p.h"
+#include "qdeclarativebinding_p_p.h"
+#include "qdeclarativecontext_p.h"
+#include <private/qv4bindings_p.h>
+#include <private/qv8bindings_p.h>
+#include "qdeclarativeglobal_p.h"
+#include <private/qfinitestack_p.h>
 #include "qdeclarativescriptstring.h"
+#include "qdeclarativescriptstring_p.h"
+#include "qdeclarativepropertyvalueinterceptor_p.h"
 
 #include <QStack>
-#include <QWidget>
 #include <QColor>
 #include <QPointF>
 #include <QSizeF>
 #include <QtCore/qvarlengtharray.h>
 #include <QtCore/qcoreapplication.h>
 #include <QtCore/qdatetime.h>
-#include <QtScript/qscriptvalue.h>
+#include <QtCore/qvarlengtharray.h>
+#include <QtDeclarative/qjsvalue.h>
 
 QT_BEGIN_NAMESPACE
 
-QDeclarativeVME::QDeclarativeVME()
-{
-}
+using namespace QDeclarativeVMETypes;
 
-#define VME_EXCEPTION(desc) \
+#define VME_EXCEPTION(desc, line) \
     { \
         QDeclarativeError error; \
         error.setDescription(desc.trimmed()); \
-        error.setLine(instr.line); \
-        error.setUrl(comp->url); \
-        vmeErrors << error; \
-        break; \
+        error.setLine(line); \
+        error.setUrl(COMP->url); \
+        *errors << error; \
+        goto exceptionExit; \
     }
 
-struct ListInstance
+void QDeclarativeVME::init(QDeclarativeContextData *ctxt, QDeclarativeCompiledData *comp, int start,
+                           QDeclarativeContextData *creation)
 {
-    ListInstance() 
-        : type(0) {}
-    ListInstance(int t) 
-        : type(t) {}
+    Q_ASSERT(ctxt);
+    Q_ASSERT(comp);
 
-    int type;
-    QDeclarativeListProperty<void> qListProperty;
-};
+    if (start == -1) {
+        start = 0;
+    } else {
+        creationContext = creation;
+    }
 
-QObject *QDeclarativeVME::run(QDeclarativeContextData *ctxt, QDeclarativeCompiledData *comp, 
-                              int start, int count, const QBitField &bindingSkipList)
-{
-    QDeclarativeVMEStack<QObject *> stack;
+    State initState;
+    initState.context = ctxt;
+    initState.compiledData = comp;
+    initState.instructionStream = comp->bytecode.constData() + start;
+    states.push(initState);
+
+    typedef QDeclarativeInstruction I;
+    I *i = (I *)initState.instructionStream;
+
+    Q_ASSERT(comp->instructionType(i) == I::Init);
 
-    if (start == -1) start = 0;
-    if (count == -1) count = comp->bytecode.count();
+    objects.allocate(i->init.objectStackSize);
+    lists.allocate(i->init.listStackSize);
+    bindValues.allocate(i->init.bindingsSize);
+    parserStatus.allocate(i->init.parserStatusSize);
 
-    return run(stack, ctxt, comp, start, count, bindingSkipList);
+#ifdef QML_ENABLE_TRACE
+    parserStatusData.allocate(i->init.parserStatusSize);
+    rootComponent = comp;
+#endif
+
+    rootContext = 0;
+    engine = ctxt->engine;
 }
 
-void QDeclarativeVME::runDeferred(QObject *object)
+bool QDeclarativeVME::initDeferred(QObject *object)
 {
     QDeclarativeData *data = QDeclarativeData::get(object);
 
     if (!data || !data->context || !data->deferredComponent)
-        return;
+        return false;
 
     QDeclarativeContextData *ctxt = data->context;
     QDeclarativeCompiledData *comp = data->deferredComponent;
-    int start = data->deferredIdx + 1;
-    int count = data->deferredComponent->bytecode.at(data->deferredIdx).defer.deferCount;
-    QDeclarativeVMEStack<QObject *> stack;
-    stack.push(object);
-
-    run(stack, ctxt, comp, start, count, QBitField());
-}
+    int start = data->deferredIdx;
 
-inline bool fastHasBinding(QObject *o, int index) 
-{
-    QDeclarativeData *ddata = static_cast<QDeclarativeData *>(QObjectPrivate::get(o)->declarativeData);
+    State initState;
+    initState.flags = State::Deferred;
+    initState.context = ctxt;
+    initState.compiledData = comp;
+    initState.instructionStream = comp->bytecode.constData() + start;
+    states.push(initState);
 
-    return ddata && (ddata->bindingBitsSize > index) && 
-           (ddata->bindingBits[index / 32] & (1 << (index % 32)));
-}
+    typedef QDeclarativeInstruction I;
+    I *i = (I *)initState.instructionStream;
 
-static void removeBindingOnProperty(QObject *o, int index)
-{
-    QDeclarativeAbstractBinding *binding = QDeclarativePropertyPrivate::setBinding(o, index, -1, 0);
-    if (binding) binding->destroy();
-}
+    Q_ASSERT(comp->instructionType(i) == I::DeferInit);
 
-#define CLEAN_PROPERTY(o, index) if (fastHasBinding(o, index)) removeBindingOnProperty(o, index)
-
-QObject *QDeclarativeVME::run(QDeclarativeVMEStack<QObject *> &stack, 
-                              QDeclarativeContextData *ctxt, 
-                              QDeclarativeCompiledData *comp, 
-                              int start, int count, 
-                              const QBitField &bindingSkipList)
-{
-    Q_ASSERT(comp);
-    Q_ASSERT(ctxt);
-    const QList<QDeclarativeCompiledData::TypeReference> &types = comp->types;
-    const QList<QString> &primitives = comp->primitives;
-    const QList<QByteArray> &datas = comp->datas;
-    const QList<QDeclarativeCompiledData::CustomTypeData> &customTypeData = comp->customTypeData;
-    const QList<int> &intData = comp->intData;
-    const QList<float> &floatData = comp->floatData;
-    const QList<QDeclarativePropertyCache *> &propertyCaches = comp->propertyCaches;
-    const QList<QDeclarativeScriptData *> &scripts = comp->scripts;
-    const QList<QUrl> &urls = comp->urls;
+    objects.allocate(i->deferInit.objectStackSize);
+    lists.allocate(i->deferInit.listStackSize);
+    bindValues.allocate(i->deferInit.bindingsSize);
+    parserStatus.allocate(i->deferInit.parserStatusSize);
 
-    QDeclarativeEnginePrivate::SimpleList<QDeclarativeAbstractBinding> bindValues;
-    QDeclarativeEnginePrivate::SimpleList<QDeclarativeParserStatus> parserStatus;
+    objects.push(object);
 
-    QDeclarativeVMEStack<ListInstance> qliststack;
+#ifdef QML_ENABLE_TRACE
+    parserStatusData.allocate(i->deferInit.parserStatusSize);
+    rootComponent = comp;
+#endif
 
-    vmeErrors.clear();
-    QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(ctxt->engine);
+    rootContext = 0;
+    engine = ctxt->engine;
 
-    int status = -1;    //for dbus
-    QDeclarativePropertyPrivate::WriteFlags flags = QDeclarativePropertyPrivate::BypassInterceptor |
-                                                    QDeclarativePropertyPrivate::RemoveBindingOnAliasWrite;
-
-    for (int ii = start; !isError() && ii < (start + count); ++ii) {
-        const QDeclarativeInstruction &instr = comp->bytecode.at(ii);
-
-        switch(instr.type) {
-        case QDeclarativeInstruction::Init:
-            {
-                if (instr.init.bindingsSize) 
-                    bindValues = QDeclarativeEnginePrivate::SimpleList<QDeclarativeAbstractBinding>(instr.init.bindingsSize);
-                if (instr.init.parserStatusSize)
-                    parserStatus = QDeclarativeEnginePrivate::SimpleList<QDeclarativeParserStatus>(instr.init.parserStatusSize);
-                if (instr.init.contextCache != -1) 
-                    ctxt->setIdPropertyData(comp->contextCaches.at(instr.init.contextCache));
-                if (instr.init.compiledBinding != -1) 
-                    ctxt->optimizedBindings = new QDeclarativeV4Bindings(datas.at(instr.init.compiledBinding).constData(), ctxt);
-            }
-            break;
+    return true;
+}
 
-        case QDeclarativeInstruction::CreateObject:
-            {
-                QBitField bindings;
-                if (instr.create.bindingBits != -1) {
-                    const QByteArray &bits = datas.at(instr.create.bindingBits);
-                    bindings = QBitField((const quint32*)bits.constData(),
-                                         bits.size() * 8);
-                }
-                if (stack.isEmpty())
-                    bindings = bindings.united(bindingSkipList);
+namespace {
+struct ActiveVMERestorer 
+{
+    ActiveVMERestorer(QDeclarativeVME *me, QDeclarativeEnginePrivate *ep) 
+    : ep(ep), oldVME(ep->activeVME) { ep->activeVME = me; }
+    ~ActiveVMERestorer() { ep->activeVME = oldVME; }
 
-                QObject *o = 
-                    types.at(instr.create.type).createInstance(ctxt, bindings, &vmeErrors);
+    QDeclarativeEnginePrivate *ep;
+    QDeclarativeVME *oldVME;
+};
+}
 
-                if (!o) {
-                    VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Unable to create object of type %1").arg(QString::fromLatin1(types.at(instr.create.type).className)));
-                }
+QObject *QDeclarativeVME::execute(QList<QDeclarativeError> *errors, const Interrupt &interrupt)
+{
+    Q_ASSERT(states.count() >= 1);
 
-                QDeclarativeData *ddata = QDeclarativeData::get(o);
-                Q_ASSERT(ddata);
-
-                if (stack.isEmpty()) {
-                    if (ddata->context) {
-                        Q_ASSERT(ddata->context != ctxt);
-                        Q_ASSERT(ddata->outerContext);
-                        Q_ASSERT(ddata->outerContext != ctxt);
-                        QDeclarativeContextData *c = ddata->context;
-                        while (c->linkedContext) c = c->linkedContext;
-                        c->linkedContext = ctxt;
-                    } else {
-                        ctxt->addObject(o);
-                    }
+#ifdef QML_ENABLE_TRACE
+    QDeclarativeTrace trace("VME Execute");
+    trace.addDetail("URL", rootComponent->url);
+#endif
 
-                    ddata->ownContext = true;
-                } else if (!ddata->context) {
-                    ctxt->addObject(o);
-                }
+    QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(states.at(0).context->engine);
 
-                ddata->setImplicitDestructible();
-                ddata->outerContext = ctxt;
-                ddata->lineNumber = instr.line;
-                ddata->columnNumber = instr.create.column;
+    ActiveVMERestorer restore(this, ep);
 
-                if (instr.create.data != -1) {
-                    QDeclarativeCustomParser *customParser =
-                        types.at(instr.create.type).type->customParser();
-                    customParser->setCustomData(o, datas.at(instr.create.data));
-                }
-                if (!stack.isEmpty()) {
-                    QObject *parent = stack.top();
-                    if (o->isWidgetType()) { 
-                        QWidget *widget = static_cast<QWidget*>(o); 
-                        if (parent->isWidgetType()) { 
-                            QWidget *parentWidget = static_cast<QWidget*>(parent); 
-                            widget->setParent(parentWidget); 
-                        } else { 
-                            // TODO: parent might be a layout 
-                        } 
-                    } else { 
-                           QDeclarative_setParent_noEvent(o, parent);
-                    } 
-                }
-                stack.push(o);
-            }
-            break;
+    QObject *rv = run(errors, interrupt);
 
-        case QDeclarativeInstruction::CreateSimpleObject:
-            {
-                QObject *o = (QObject *)operator new(instr.createSimple.typeSize + 
-                                                     sizeof(QDeclarativeData));   
-                ::memset(o, 0, instr.createSimple.typeSize + sizeof(QDeclarativeData));
-                instr.createSimple.create(o);
-
-                QDeclarativeData *ddata = (QDeclarativeData *)(((const char *)o) + instr.createSimple.typeSize);
-                const QDeclarativeCompiledData::TypeReference &ref = types.at(instr.createSimple.type);
-                if (!ddata->propertyCache && ref.typePropertyCache) {
-                    ddata->propertyCache = ref.typePropertyCache;
-                    ddata->propertyCache->addref();
-                }
-                ddata->lineNumber = instr.line;
-                ddata->columnNumber = instr.createSimple.column;
+    return rv;
+}
 
-                QObjectPrivate::get(o)->declarativeData = ddata;                                                      
-                ddata->context = ddata->outerContext = ctxt;
-                ddata->nextContextObject = ctxt->contextObjects; 
-                if (ddata->nextContextObject) 
-                    ddata->nextContextObject->prevContextObject = &ddata->nextContextObject; 
-                ddata->prevContextObject = &ctxt->contextObjects; 
-                ctxt->contextObjects = ddata; 
+inline bool fastHasBinding(QObject *o, int index) 
+{
+    QDeclarativeData *ddata = static_cast<QDeclarativeData *>(QObjectPrivate::get(o)->declarativeData);
 
-                QObject *parent = stack.top();                                                                    
-                QDeclarative_setParent_noEvent(o, parent);                                                        
+    return ddata && (ddata->bindingBitsSize > index) && 
+           (ddata->bindingBits[index / 32] & (1 << (index % 32)));
+}
 
-                stack.push(o);
-            }
-            break;
+static void removeBindingOnProperty(QObject *o, int index)
+{
+    QDeclarativeAbstractBinding *binding = QDeclarativePropertyPrivate::setBinding(o, index, -1, 0);
+    if (binding) binding->destroy();
+}
 
-        case QDeclarativeInstruction::SetId:
-            {
-                QObject *target = stack.top();
-                ctxt->setIdProperty(instr.setId.index, target);
-            }
-            break;
+static QVariant variantFromString(const QString &string)
+{
+    return QDeclarativeStringConverters::variantFromString(string);
+}
 
+// XXX we probably need some form of "work count" here to prevent us checking this 
+// for every instruction.
+#define QML_BEGIN_INSTR_COMMON(I) { \
+    const QDeclarativeInstructionMeta<(int)QDeclarativeInstruction::I>::DataType &instr = QDeclarativeInstructionMeta<(int)QDeclarativeInstruction::I>::data(*genericInstr); \
+    INSTRUCTIONSTREAM += QDeclarativeInstructionMeta<(int)QDeclarativeInstruction::I>::Size; \
+    Q_UNUSED(instr);
+
+#ifdef QML_THREADED_VME_INTERPRETER
+#  define QML_BEGIN_INSTR(I) op_##I: \
+    QML_BEGIN_INSTR_COMMON(I)
+
+#  define QML_NEXT_INSTR(I) { \
+    if (watcher.hasRecursed()) return 0; \
+    genericInstr = reinterpret_cast<const QDeclarativeInstruction *>(INSTRUCTIONSTREAM); \
+    goto *genericInstr->common.code; \
+    }
 
-        case QDeclarativeInstruction::SetDefault:
-            {
-                ctxt->contextObject = stack.top();
-            }
-            break;
+#  define QML_END_INSTR(I) } \
+    if (watcher.hasRecursed()) return 0; \
+    genericInstr = reinterpret_cast<const QDeclarativeInstruction *>(INSTRUCTIONSTREAM); \
+    if (interrupt.shouldInterrupt()) return 0; \
+    goto *genericInstr->common.code;
 
-        case QDeclarativeInstruction::CreateComponent:
-            {
-                QDeclarativeComponent *qcomp = 
-                    new QDeclarativeComponent(ctxt->engine, comp, ii + 1, instr.createComponent.count,
-                                              stack.isEmpty() ? 0 : stack.top());
+#else
+#  define QML_BEGIN_INSTR(I) \
+    case QDeclarativeInstruction::I: \
+    QML_BEGIN_INSTR_COMMON(I)
 
-                QDeclarativeData *ddata = QDeclarativeData::get(qcomp, true);
-                Q_ASSERT(ddata);
+#  define QML_NEXT_INSTR(I) { \
+    if (watcher.hasRecursed()) return 0; \
+    break; \
+    }
 
-                ctxt->addObject(qcomp);
+#  define QML_END_INSTR(I) \
+    if (watcher.hasRecursed() || interrupt.shouldInterrupt()) return 0; \
+    } break;
+#endif
+
+#define QML_STORE_VALUE(name, cpptype, value) \
+    QML_BEGIN_INSTR(name) \
+        cpptype v = value; \
+        void *a[] = { (void *)&v, 0, &status, &flags }; \
+        QObject *target = objects.top(); \
+        CLEAN_PROPERTY(target, instr.propertyIndex); \
+        QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.propertyIndex, a); \
+    QML_END_INSTR(name)
+
+#define QML_STORE_LIST(name, cpptype, value) \
+    QML_BEGIN_INSTR(name) \
+        cpptype v; \
+        v.append(value); \
+        void *a[] = { (void *)&v, 0, &status, &flags }; \
+        QObject *target = objects.top(); \
+        CLEAN_PROPERTY(target, instr.propertyIndex); \
+        QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.propertyIndex, a); \
+    QML_END_INSTR(name)
+
+#define QML_STORE_VAR(name, value) \
+    QML_BEGIN_INSTR(name) \
+        v8::Handle<v8::Value> v8value = value; \
+        QObject *target = objects.top(); \
+        CLEAN_PROPERTY(target, instr.propertyIndex); \
+        QMetaObject *mo = const_cast<QMetaObject *>(target->metaObject()); \
+        QDeclarativeVMEMetaObject *vmemo = static_cast<QDeclarativeVMEMetaObject *>(mo); \
+        vmemo->setVMEProperty(instr.propertyIndex, v8value); \
+    QML_END_INSTR(name)
+
+#define QML_STORE_POINTER(name, value) \
+    QML_BEGIN_INSTR(name) \
+        void *a[] = { (void *)value, 0, &status, &flags }; \
+        QObject *target = objects.top(); \
+        CLEAN_PROPERTY(target, instr.propertyIndex); \
+        QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.propertyIndex, a); \
+    QML_END_INSTR(name)
+
+#define CLEAN_PROPERTY(o, index) \
+    if (fastHasBinding(o, index)) \
+        removeBindingOnProperty(o, index)
+
+QObject *QDeclarativeVME::run(QList<QDeclarativeError> *errors,
+                              const Interrupt &interrupt
+#ifdef QML_THREADED_VME_INTERPRETER
+                              , void ***storeJumpTable
+#endif
+                              )
+{
+#ifdef QML_THREADED_VME_INTERPRETER
+    if (storeJumpTable) {
+#define QML_INSTR_ADDR(I, FMT) &&op_##I,
+        static void *jumpTable[] = {
+            FOR_EACH_QML_INSTR(QML_INSTR_ADDR)
+        };
+#undef QML_INSTR_ADDR
+        *storeJumpTable = jumpTable;
+        return 0;
+    }
+#endif
+    Q_ASSERT(errors->isEmpty());
+    Q_ASSERT(states.count() >= 1);
 
-                if (stack.isEmpty()) 
-                    ddata->ownContext = true;
+    QDeclarativeEngine *engine = states.at(0).context->engine;
+    QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
 
-                ddata->setImplicitDestructible();
-                ddata->outerContext = ctxt;
-                ddata->lineNumber = instr.line;
-                ddata->columnNumber = instr.create.column;
+    // Need a v8 handle scope and execution context for StoreVar instructions.
+    v8::HandleScope handleScope;
+    v8::Context::Scope contextScope(ep->v8engine()->context());
 
-                QDeclarativeComponentPrivate::get(qcomp)->creationContext = ctxt;
+    int status = -1; // needed for dbus
+    QDeclarativePropertyPrivate::WriteFlags flags = QDeclarativePropertyPrivate::BypassInterceptor |
+                                                    QDeclarativePropertyPrivate::RemoveBindingOnAliasWrite;
 
-                stack.push(qcomp);
-                ii += instr.createComponent.count;
+    QRecursionWatcher<QDeclarativeVME, &QDeclarativeVME::recursion> watcher(this);
+
+#define COMP states.top().compiledData
+#define CTXT states.top().context
+#define INSTRUCTIONSTREAM states.top().instructionStream
+#define BINDINGSKIPLIST states.top().bindingSkipList
+
+#define TYPES COMP->types
+#define PRIMITIVES COMP->primitives
+#define DATAS COMP->datas
+#define PROPERTYCACHES COMP->propertyCaches
+#define SCRIPTS COMP->scripts
+#define URLS COMP->urls
+
+#ifdef QML_THREADED_VME_INTERPRETER
+    const QDeclarativeInstruction *genericInstr = reinterpret_cast<const QDeclarativeInstruction *>(INSTRUCTIONSTREAM);
+    goto *genericInstr->common.code;
+#else
+    for (;;) {
+        const QDeclarativeInstruction *genericInstr = reinterpret_cast<const QDeclarativeInstruction *>(INSTRUCTIONSTREAM);
+
+        switch (genericInstr->common.instructionType) {
+#endif
+
+        // Store a created object in a property.  These all pop from the objects stack.
+        QML_STORE_VALUE(StoreObject, QObject *, objects.pop());
+        QML_STORE_VALUE(StoreVariantObject, QVariant, QVariant::fromValue(objects.pop()));
+        QML_STORE_VAR(StoreVarObject, ep->v8engine()->newQObject(objects.pop()));
+
+        // Store a literal value in a corresponding property
+        QML_STORE_VALUE(StoreFloat, float, instr.value);
+        QML_STORE_VALUE(StoreDouble, double, instr.value);
+        QML_STORE_VALUE(StoreBool, bool, instr.value);
+        QML_STORE_VALUE(StoreInteger, int, instr.value);
+        QML_STORE_VALUE(StoreColor, QColor, QColor::fromRgba(instr.value));
+        QML_STORE_VALUE(StoreDate, QDate, QDate::fromJulianDay(instr.value));
+        QML_STORE_VALUE(StoreDateTime, QDateTime,
+                        QDateTime(QDate::fromJulianDay(instr.date), *(QTime *)&instr.time));
+        QML_STORE_POINTER(StoreTime, (QTime *)&instr.time);
+        QML_STORE_POINTER(StorePoint, (QPoint *)&instr.point);
+        QML_STORE_POINTER(StorePointF, (QPointF *)&instr.point);
+        QML_STORE_POINTER(StoreSize, (QSize *)&instr.size);
+        QML_STORE_POINTER(StoreSizeF, (QSizeF *)&instr.size);
+        QML_STORE_POINTER(StoreRect, (QRect *)&instr.rect);
+        QML_STORE_POINTER(StoreRectF, (QRectF *)&instr.rect);
+        QML_STORE_POINTER(StoreVector3D, (QVector3D *)&instr.vector);
+        QML_STORE_POINTER(StoreVector4D, (QVector4D *)&instr.vector);
+        QML_STORE_POINTER(StoreString, &PRIMITIVES.at(instr.value));
+        QML_STORE_POINTER(StoreByteArray, &DATAS.at(instr.value));
+        QML_STORE_POINTER(StoreUrl, &URLS.at(instr.value));
+        QML_STORE_VALUE(StoreTrString, QString,
+                        QCoreApplication::translate(DATAS.at(instr.context).constData(),
+                                                    DATAS.at(instr.text).constData(),
+                                                    DATAS.at(instr.comment).constData(),
+                                                    QCoreApplication::UnicodeUTF8,
+                                                    instr.n));
+        QML_STORE_VALUE(StoreTrIdString, QString, qtTrId(DATAS.at(instr.text).constData(), instr.n));
+
+        // Store a literal value in a QList
+        QML_STORE_LIST(StoreStringList, QStringList, PRIMITIVES.at(instr.value));
+        QML_STORE_LIST(StoreStringQList, QList<QString>, PRIMITIVES.at(instr.value));
+        QML_STORE_LIST(StoreUrlQList, QList<QUrl>, URLS.at(instr.value));
+        QML_STORE_LIST(StoreDoubleQList, QList<double>, instr.value);
+        QML_STORE_LIST(StoreBoolQList, QList<bool>, instr.value);
+        QML_STORE_LIST(StoreIntegerQList, QList<int>, instr.value);
+
+        // Store a literal value in a QVariant property
+        QML_STORE_VALUE(StoreVariant, QVariant, variantFromString(PRIMITIVES.at(instr.value)));
+        QML_STORE_VALUE(StoreVariantInteger, QVariant, QVariant(instr.value));
+        QML_STORE_VALUE(StoreVariantDouble, QVariant, QVariant(instr.value));
+        QML_STORE_VALUE(StoreVariantBool, QVariant, QVariant(instr.value));
+
+        // Store a literal value in a var property.
+        // We deliberately do not use string converters here
+        QML_STORE_VAR(StoreVar, ep->v8engine()->fromVariant(PRIMITIVES.at(instr.value)));
+        QML_STORE_VAR(StoreVarInteger, v8::Integer::New(instr.value));
+        QML_STORE_VAR(StoreVarDouble, v8::Number::New(instr.value));
+        QML_STORE_VAR(StoreVarBool, v8::Boolean::New(instr.value));
+
+
+        QML_BEGIN_INSTR(Init)
+            // Ensure that the compiled data has been initialized
+            if (!COMP->isInitialized()) COMP->initialize(engine);
+
+            QDeclarativeContextData *parentCtxt = CTXT;
+            CTXT = new QDeclarativeContextData;
+            CTXT->isInternal = true;
+            CTXT->url = COMP->url;
+            CTXT->imports = COMP->importCache;
+            CTXT->imports->addref();
+            CTXT->setParent(parentCtxt);
+            if (instr.contextCache != -1) 
+                CTXT->setIdPropertyData(COMP->contextCaches.at(instr.contextCache));
+            if (instr.compiledBinding != -1) {
+                const char *v4data = DATAS.at(instr.compiledBinding).constData();
+                CTXT->v4bindings = new QV4Bindings(v4data, CTXT, COMP);
             }
-            break;
-
-        case QDeclarativeInstruction::StoreMetaObject:
-            {
-                QObject *target = stack.top();
-
-                QMetaObject mo;
-                const QByteArray &metadata = datas.at(instr.storeMeta.data);
-                QMetaObjectBuilder::fromRelocatableData(&mo, 0, metadata);
-
-                const QDeclarativeVMEMetaData *data = 
-                    (const QDeclarativeVMEMetaData *)datas.at(instr.storeMeta.aliasData).constData();
-
-                (void)new QDeclarativeVMEMetaObject(target, &mo, data, comp);
-
-                if (instr.storeMeta.propertyCache != -1) {
-                    QDeclarativeData *ddata = QDeclarativeData::get(target, true);
-                    if (ddata->propertyCache) ddata->propertyCache->release();
-                    ddata->propertyCache = propertyCaches.at(instr.storeMeta.propertyCache);
-                    ddata->propertyCache->addref();
-                }
+            if (states.count() == 1) {
+                rootContext = CTXT;
+                rootContext->activeVMEData = data;
             }
-            break;
-
-        case QDeclarativeInstruction::StoreVariant:
-            {
-                QObject *target = stack.top();
-                CLEAN_PROPERTY(target, instr.storeString.propertyIndex);
-
-                // XXX - can be more efficient
-                QVariant v = QDeclarativeStringConverters::variantFromString(primitives.at(instr.storeString.value));
-                void *a[] = { &v, 0, &status, &flags };
-                QMetaObject::metacall(target, QMetaObject::WriteProperty, 
-                                      instr.storeString.propertyIndex, a);
+            if (states.count() == 1 && !creationContext.isNull()) {
+                // A component that is logically created within another component instance shares the 
+                // same instances of script imports.  For example:
+                //
+                //     import QtQuick 1.0
+                //     import "test.js" as Test
+                //     ListView {
+                //         model: Test.getModel()
+                //         delegate: Component {
+                //             Text { text: Test.getValue(index); }
+                //         }
+                //     }
+                //
+                // Has the same "Test" instance.  To implement this, we simply copy the v8 handles into
+                // the inner context.  We have to create a fresh persistent handle for each to prevent 
+                // double dispose.  It is possible we could do this more efficiently using some form of
+                // referencing instead.
+                CTXT->importedScripts = creationContext->importedScripts;
+                for (int ii = 0; ii < CTXT->importedScripts.count(); ++ii)
+                    CTXT->importedScripts[ii] = qPersistentNew<v8::Object>(CTXT->importedScripts[ii]);
             }
-            break;
-
-        case QDeclarativeInstruction::StoreVariantInteger:
-            {
-                QObject *target = stack.top();
-                CLEAN_PROPERTY(target, instr.storeString.propertyIndex);
+        QML_END_INSTR(Init)
 
-                QVariant v(instr.storeInteger.value);
-                void *a[] = { &v, 0, &status, &flags };
-                QMetaObject::metacall(target, QMetaObject::WriteProperty, 
-                                      instr.storeString.propertyIndex, a);
-            }
-            break;
+        QML_BEGIN_INSTR(DeferInit)
+        QML_END_INSTR(DeferInit)
 
-        case QDeclarativeInstruction::StoreVariantDouble:
-            {
-                QObject *target = stack.top();
-                CLEAN_PROPERTY(target, instr.storeString.propertyIndex);
+        QML_BEGIN_INSTR(Done)
+            states.pop();
 
-                QVariant v(instr.storeDouble.value);
-                void *a[] = { &v, 0, &status, &flags };
-                QMetaObject::metacall(target, QMetaObject::WriteProperty, 
-                                      instr.storeString.propertyIndex, a);
-            }
-            break;
+            if (states.isEmpty())
+                goto normalExit;
+        QML_END_INSTR(Done)
 
-        case QDeclarativeInstruction::StoreVariantBool:
-            {
-                QObject *target = stack.top();
-                CLEAN_PROPERTY(target, instr.storeString.propertyIndex);
+        QML_BEGIN_INSTR(CreateQMLObject)
+            const QDeclarativeCompiledData::TypeReference &type = TYPES.at(instr.type);
+            Q_ASSERT(type.component);
 
-                QVariant v(instr.storeBool.value);
-                void *a[] = { &v, 0, &status, &flags };
-                QMetaObject::metacall(target, QMetaObject::WriteProperty, 
-                                      instr.storeString.propertyIndex, a);
-            }
-            break;
+            states.push(State());
 
-        case QDeclarativeInstruction::StoreString:
-            {
-                QObject *target = stack.top();
-                CLEAN_PROPERTY(target, instr.storeString.propertyIndex);
+            State *cState = &states[states.count() - 2];
+            State *nState = &states[states.count() - 1];
 
-                void *a[] = { (void *)&primitives.at(instr.storeString.value), 0, &status, &flags };
-                QMetaObject::metacall(target, QMetaObject::WriteProperty, 
-                                      instr.storeString.propertyIndex, a);
-            }
-            break;
+            nState->context = cState->context;
+            nState->compiledData = type.component;
+            nState->instructionStream = type.component->bytecode.constData();
 
-        case QDeclarativeInstruction::StoreByteArray:
-            {
-                QObject *target = stack.top();
-                void *a[] = { (void *)&datas.at(instr.storeByteArray.value), 0, &status, &flags };
-                QMetaObject::metacall(target, QMetaObject::WriteProperty,
-                                      instr.storeByteArray.propertyIndex, a);
+            if (instr.bindingBits != -1) {
+                const QByteArray &bits = cState->compiledData->datas.at(instr.bindingBits);
+                nState->bindingSkipList = QBitField((const quint32*)bits.constData(),
+                                                    bits.size() * 8);
             }
-            break;
-
-        case QDeclarativeInstruction::StoreUrl:
-            {
-                QObject *target = stack.top();
-                CLEAN_PROPERTY(target, instr.storeUrl.propertyIndex);
+            if (instr.isRoot)
+                nState->bindingSkipList = nState->bindingSkipList.united(cState->bindingSkipList);
+
+            // As the state in the state stack changed, execution will continue in the new program.
+        QML_END_INSTR(CreateQMLObject)
+
+        QML_BEGIN_INSTR(CompleteQMLObject)
+            QObject *o = objects.top();
+
+            QDeclarativeData *ddata = QDeclarativeData::get(o);
+            Q_ASSERT(ddata);
+
+            if (instr.isRoot) {
+                if (ddata->context) {
+                    Q_ASSERT(ddata->context != CTXT);
+                    Q_ASSERT(ddata->outerContext);
+                    Q_ASSERT(ddata->outerContext != CTXT);
+                    QDeclarativeContextData *c = ddata->context;
+                    while (c->linkedContext) c = c->linkedContext;
+                    c->linkedContext = CTXT;
+                } else {
+                    CTXT->addObject(o);
+                }
 
-                void *a[] = { (void *)&urls.at(instr.storeUrl.value), 0, &status, &flags };
-                QMetaObject::metacall(target, QMetaObject::WriteProperty, 
-                                      instr.storeUrl.propertyIndex, a);
+                ddata->ownContext = true;
+            } else if (!ddata->context) {
+                CTXT->addObject(o);
             }
-            break;
 
-        case QDeclarativeInstruction::StoreFloat:
-            {
-                QObject *target = stack.top();
-                CLEAN_PROPERTY(target, instr.storeFloat.propertyIndex);
-
-                float f = instr.storeFloat.value;
-                void *a[] = { &f, 0, &status, &flags };
-                QMetaObject::metacall(target, QMetaObject::WriteProperty,
-                                      instr.storeFloat.propertyIndex, a);
+            ddata->setImplicitDestructible();
+            ddata->outerContext = CTXT;
+            ddata->lineNumber = instr.line;
+            ddata->columnNumber = instr.column;
+        QML_END_INSTR(CompleteQMLObject)
+
+        QML_BEGIN_INSTR(CreateCppObject)
+            const QDeclarativeCompiledData::TypeReference &type = TYPES.at(instr.type);
+            Q_ASSERT(type.type);
+
+            QObject *o = 0;
+            void *memory = 0;
+            type.type->create(&o, &memory, sizeof(QDeclarativeData));
+            QDeclarativeData *ddata = new (memory) QDeclarativeData;
+            ddata->ownMemory = false;
+            QObjectPrivate::get(o)->declarativeData = ddata;
+
+            if (type.typePropertyCache && !ddata->propertyCache) {
+                ddata->propertyCache = type.typePropertyCache;
+                ddata->propertyCache->addref();
             }
-            break;
 
-        case QDeclarativeInstruction::StoreDouble:
-            {
-                QObject *target = stack.top();
-                CLEAN_PROPERTY(target, instr.storeDouble.propertyIndex);
+            if (!o) 
+                VME_EXCEPTION(tr("Unable to create object of type %1").arg(type.className), instr.line);
+
+            if (instr.isRoot) {
+                if (ddata->context) {
+                    Q_ASSERT(ddata->context != CTXT);
+                    Q_ASSERT(ddata->outerContext);
+                    Q_ASSERT(ddata->outerContext != CTXT);
+                    QDeclarativeContextData *c = ddata->context;
+                    while (c->linkedContext) c = c->linkedContext;
+                    c->linkedContext = CTXT;
+                } else {
+                    CTXT->addObject(o);
+                }
 
-                double d = instr.storeDouble.value;
-                void *a[] = { &d, 0, &status, &flags };
-                QMetaObject::metacall(target, QMetaObject::WriteProperty,
-                                      instr.storeDouble.propertyIndex, a);
+                ddata->ownContext = true;
+            } else if (!ddata->context) {
+                CTXT->addObject(o);
             }
-            break;
 
-        case QDeclarativeInstruction::StoreBool:
-            {
-                QObject *target = stack.top();
-                CLEAN_PROPERTY(target, instr.storeBool.propertyIndex);
+            ddata->setImplicitDestructible();
+            ddata->outerContext = CTXT;
+            ddata->lineNumber = instr.line;
+            ddata->columnNumber = instr.column;
 
-                void *a[] = { (void *)&instr.storeBool.value, 0, &status, &flags };
-                QMetaObject::metacall(target, QMetaObject::WriteProperty, 
-                                      instr.storeBool.propertyIndex, a);
+            if (instr.data != -1) {
+                QDeclarativeCustomParser *customParser =
+                    TYPES.at(instr.type).type->customParser();
+                customParser->setCustomData(o, DATAS.at(instr.data));
             }
-            break;
-
-        case QDeclarativeInstruction::StoreInteger:
-            {
-                QObject *target = stack.top();
-                CLEAN_PROPERTY(target, instr.storeInteger.propertyIndex);
-
-                void *a[] = { (void *)&instr.storeInteger.value, 0, &status, &flags };
-                QMetaObject::metacall(target, QMetaObject::WriteProperty, 
-                                      instr.storeInteger.propertyIndex, a);
+            if (!objects.isEmpty()) {
+                QObject *parent = objects.top();
+#if 0 // ### refactor
+                if (o->isWidgetType() && parent->isWidgetType()) 
+                    static_cast<QWidget*>(o)->setParent(static_cast<QWidget*>(parent));
+                else 
+#endif
+                    QDeclarative_setParent_noEvent(o, parent);
             }
-            break;
-
-        case QDeclarativeInstruction::StoreColor:
-            {
-                QObject *target = stack.top();
-                CLEAN_PROPERTY(target, instr.storeColor.propertyIndex);
-
-                QColor c = QColor::fromRgba(instr.storeColor.value);
-                void *a[] = { &c, 0, &status, &flags };
-                QMetaObject::metacall(target, QMetaObject::WriteProperty, 
-                                      instr.storeColor.propertyIndex, a);
+            objects.push(o);
+        QML_END_INSTR(CreateCppObject)
+
+        QML_BEGIN_INSTR(CreateSimpleObject)
+            QObject *o = (QObject *)operator new(instr.typeSize + sizeof(QDeclarativeData));   
+            ::memset(o, 0, instr.typeSize + sizeof(QDeclarativeData));
+            instr.create(o);
+
+            QDeclarativeData *ddata = (QDeclarativeData *)(((const char *)o) + instr.typeSize);
+            const QDeclarativeCompiledData::TypeReference &ref = TYPES.at(instr.type);
+            if (!ddata->propertyCache && ref.typePropertyCache) {
+                ddata->propertyCache = ref.typePropertyCache;
+                ddata->propertyCache->addref();
             }
-            break;
+            ddata->lineNumber = instr.line;
+            ddata->columnNumber = instr.column;
 
-        case QDeclarativeInstruction::StoreDate:
-            {
-                QObject *target = stack.top();
-                CLEAN_PROPERTY(target, instr.storeDate.propertyIndex);
+            QObjectPrivate::get(o)->declarativeData = ddata;                                                      
+            ddata->context = ddata->outerContext = CTXT;
+            ddata->nextContextObject = CTXT->contextObjects; 
+            if (ddata->nextContextObject) 
+                ddata->nextContextObject->prevContextObject = &ddata->nextContextObject; 
+            ddata->prevContextObject = &CTXT->contextObjects; 
+            CTXT->contextObjects = ddata; 
 
-                QDate d = QDate::fromJulianDay(instr.storeDate.value);
-                void *a[] = { &d, 0, &status, &flags };
-                QMetaObject::metacall(target, QMetaObject::WriteProperty, 
-                                      instr.storeDate.propertyIndex, a);
-            }
-            break;
+            QObject *parent = objects.top();                                                                    
+            QDeclarative_setParent_noEvent(o, parent);                                                        
 
-        case QDeclarativeInstruction::StoreTime:
-            {
-                QObject *target = stack.top();
-                CLEAN_PROPERTY(target, instr.storeTime.propertyIndex);
-
-                QTime t;
-                t.setHMS(intData.at(instr.storeTime.valueIndex),
-                         intData.at(instr.storeTime.valueIndex+1),
-                         intData.at(instr.storeTime.valueIndex+2),
-                         intData.at(instr.storeTime.valueIndex+3));
-                void *a[] = { &t, 0, &status, &flags };
-                QMetaObject::metacall(target, QMetaObject::WriteProperty, 
-                                      instr.storeTime.propertyIndex, a);
-            }
-            break;
+            objects.push(o);
+        QML_END_INSTR(CreateSimpleObject)
 
-        case QDeclarativeInstruction::StoreDateTime:
-            {
-                QObject *target = stack.top();
-                CLEAN_PROPERTY(target, instr.storeDateTime.propertyIndex);
-
-                QTime t;
-                t.setHMS(intData.at(instr.storeDateTime.valueIndex+1),
-                         intData.at(instr.storeDateTime.valueIndex+2),
-                         intData.at(instr.storeDateTime.valueIndex+3),
-                         intData.at(instr.storeDateTime.valueIndex+4));
-                QDateTime dt(QDate::fromJulianDay(intData.at(instr.storeDateTime.valueIndex)), t);
-                void *a[] = { &dt, 0, &status, &flags };
-                QMetaObject::metacall(target, QMetaObject::WriteProperty,
-                                      instr.storeDateTime.propertyIndex, a);
-            }
-            break;
+        QML_BEGIN_INSTR(SetId)
+            QObject *target = objects.top();
+            CTXT->setIdProperty(instr.index, target);
+        QML_END_INSTR(SetId)
 
-        case QDeclarativeInstruction::StorePoint:
-            {
-                QObject *target = stack.top();
-                CLEAN_PROPERTY(target, instr.storeRealPair.propertyIndex);
+        QML_BEGIN_INSTR(SetDefault)
+            CTXT->contextObject = objects.top();
+        QML_END_INSTR(SetDefault)
 
-                QPoint p = QPointF(floatData.at(instr.storeRealPair.valueIndex),
-                                   floatData.at(instr.storeRealPair.valueIndex+1)).toPoint();
-                void *a[] = { &p, 0, &status, &flags };
-                QMetaObject::metacall(target, QMetaObject::WriteProperty, 
-                                      instr.storeRealPair.propertyIndex, a);
-            }
-            break;
+        QML_BEGIN_INSTR(CreateComponent)
+            QDeclarativeComponent *qcomp = 
+                new QDeclarativeComponent(CTXT->engine, COMP, INSTRUCTIONSTREAM - COMP->bytecode.constData(),
+                                          objects.isEmpty() ? 0 : objects.top());
 
-        case QDeclarativeInstruction::StorePointF:
-            {
-                QObject *target = stack.top();
-                CLEAN_PROPERTY(target, instr.storeRealPair.propertyIndex);
+            QDeclarativeData *ddata = QDeclarativeData::get(qcomp, true);
+            Q_ASSERT(ddata);
 
-                QPointF p(floatData.at(instr.storeRealPair.valueIndex),
-                          floatData.at(instr.storeRealPair.valueIndex+1));
-                void *a[] = { &p, 0, &status, &flags };
-                QMetaObject::metacall(target, QMetaObject::WriteProperty, 
-                                      instr.storeRealPair.propertyIndex, a);
-            }
-            break;
+            CTXT->addObject(qcomp);
 
-        case QDeclarativeInstruction::StoreSize:
-            {
-                QObject *target = stack.top();
-                CLEAN_PROPERTY(target, instr.storeRealPair.propertyIndex);
+            if (instr.isRoot)
+                ddata->ownContext = true;
 
-                QSize p = QSizeF(floatData.at(instr.storeRealPair.valueIndex),
-                                 floatData.at(instr.storeRealPair.valueIndex+1)).toSize();
-                void *a[] = { &p, 0, &status, &flags };
-                QMetaObject::metacall(target, QMetaObject::WriteProperty, 
-                                      instr.storeRealPair.propertyIndex, a);
-            }
-            break;
+            ddata->setImplicitDestructible();
+            ddata->outerContext = CTXT;
+            ddata->lineNumber = instr.line;
+            ddata->columnNumber = instr.column;
 
-        case QDeclarativeInstruction::StoreSizeF:
-            {
-                QObject *target = stack.top();
-                CLEAN_PROPERTY(target, instr.storeRealPair.propertyIndex);
+            QDeclarativeComponentPrivate::get(qcomp)->creationContext = CTXT;
 
-                QSizeF s(floatData.at(instr.storeRealPair.valueIndex),
-                         floatData.at(instr.storeRealPair.valueIndex+1));
-                void *a[] = { &s, 0, &status, &flags };
-                QMetaObject::metacall(target, QMetaObject::WriteProperty, 
-                                      instr.storeRealPair.propertyIndex, a);
-            }
-            break;
+            objects.push(qcomp);
+            INSTRUCTIONSTREAM += instr.count;
+        QML_END_INSTR(CreateComponent)
 
-        case QDeclarativeInstruction::StoreRect:
-            {
-                QObject *target = stack.top();
-                CLEAN_PROPERTY(target, instr.storeRect.propertyIndex);
-
-                QRect r = QRectF(floatData.at(instr.storeRect.valueIndex),
-                                 floatData.at(instr.storeRect.valueIndex+1),
-                                 floatData.at(instr.storeRect.valueIndex+2),
-                                 floatData.at(instr.storeRect.valueIndex+3)).toRect();
-                void *a[] = { &r, 0, &status, &flags };
-                QMetaObject::metacall(target, QMetaObject::WriteProperty, 
-                                      instr.storeRect.propertyIndex, a);
-            }
-            break;
+        QML_BEGIN_INSTR(StoreMetaObject)
+            QObject *target = objects.top();
 
-        case QDeclarativeInstruction::StoreRectF:
-            {
-                QObject *target = stack.top();
-                CLEAN_PROPERTY(target, instr.storeRect.propertyIndex);
-
-                QRectF r(floatData.at(instr.storeRect.valueIndex),
-                         floatData.at(instr.storeRect.valueIndex+1),
-                         floatData.at(instr.storeRect.valueIndex+2),
-                         floatData.at(instr.storeRect.valueIndex+3));
-                void *a[] = { &r, 0, &status, &flags };
-                QMetaObject::metacall(target, QMetaObject::WriteProperty, 
-                                      instr.storeRect.propertyIndex, a);
-            }
-            break;
+            QMetaObject mo;
+            const QByteArray &metadata = DATAS.at(instr.data);
+            QFastMetaBuilder::fromData(&mo, 0, metadata);
 
-        case QDeclarativeInstruction::StoreVector3D:
-            {
-                QObject *target = stack.top();
-                CLEAN_PROPERTY(target, instr.storeVector3D.propertyIndex);
-
-                QVector3D p(floatData.at(instr.storeVector3D.valueIndex),
-                            floatData.at(instr.storeVector3D.valueIndex+1),
-                            floatData.at(instr.storeVector3D.valueIndex+2));
-                void *a[] = { &p, 0, &status, &flags };
-                QMetaObject::metacall(target, QMetaObject::WriteProperty, 
-                                      instr.storeVector3D.propertyIndex, a);
-            }
-            break;
+            const QDeclarativeVMEMetaData *data = 
+                (const QDeclarativeVMEMetaData *)DATAS.at(instr.aliasData).constData();
 
-        case QDeclarativeInstruction::StoreObject:
-            {
-                QObject *assignObj = stack.pop();
-                QObject *target = stack.top();
-                CLEAN_PROPERTY(target, instr.storeObject.propertyIndex);
+            (void)new QDeclarativeVMEMetaObject(target, &mo, data, COMP);
 
-                void *a[] = { (void *)&assignObj, 0, &status, &flags };
-                QMetaObject::metacall(target, QMetaObject::WriteProperty, 
-                                      instr.storeObject.propertyIndex, a);
+            if (instr.propertyCache != -1) {
+                QDeclarativeData *ddata = QDeclarativeData::get(target, true);
+                if (ddata->propertyCache) ddata->propertyCache->release();
+                ddata->propertyCache = PROPERTYCACHES.at(instr.propertyCache);
+                ddata->propertyCache->addref();
             }
-            break;
+        QML_END_INSTR(StoreMetaObject)
 
+        QML_BEGIN_INSTR(AssignCustomType)
+            QObject *target = objects.top();
+            CLEAN_PROPERTY(target, instr.propertyIndex);
 
-        case QDeclarativeInstruction::AssignCustomType:
-            {
-                QObject *target = stack.top();
-                CLEAN_PROPERTY(target, instr.assignCustomType.propertyIndex);
+            const QString &primitive = PRIMITIVES.at(instr.primitive);
+            int type = instr.type;
+            QDeclarativeMetaType::StringConverter converter = QDeclarativeMetaType::customStringConverter(type);
+            QVariant v = (*converter)(primitive);
 
-                QDeclarativeCompiledData::CustomTypeData data = customTypeData.at(instr.assignCustomType.valueIndex);
-                const QString &primitive = primitives.at(data.index);
-                QDeclarativeMetaType::StringConverter converter = 
-                    QDeclarativeMetaType::customStringConverter(data.type);
-                QVariant v = (*converter)(primitive);
+            QMetaProperty prop = 
+                    target->metaObject()->property(instr.propertyIndex);
+            if (v.isNull() || ((int)prop.type() != type && prop.userType() != type)) 
+                VME_EXCEPTION(tr("Cannot assign value %1 to property %2").arg(primitive).arg(QString::fromUtf8(prop.name())), instr.line);
 
-                QMetaProperty prop = 
-                        target->metaObject()->property(instr.assignCustomType.propertyIndex);
-                if (v.isNull() || ((int)prop.type() != data.type && prop.userType() != data.type)) 
-                    VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign value %1 to property %2").arg(primitive).arg(QString::fromUtf8(prop.name())));
+            void *a[] = { (void *)v.data(), 0, &status, &flags };
+            QMetaObject::metacall(target, QMetaObject::WriteProperty, 
+                                  instr.propertyIndex, a);
+        QML_END_INSTR(AssignCustomType)
 
-                void *a[] = { (void *)v.data(), 0, &status, &flags };
-                QMetaObject::metacall(target, QMetaObject::WriteProperty, 
-                                      instr.assignCustomType.propertyIndex, a);
-            }
-            break;
+        QML_BEGIN_INSTR(AssignSignalObject)
+            // XXX optimize
 
-        case QDeclarativeInstruction::AssignSignalObject:
-            {
-                // XXX optimize
+            QObject *assign = objects.pop();
+            QObject *target = objects.top();
+            int sigIdx = instr.signal;
+            const QString &pr = PRIMITIVES.at(sigIdx);
 
-                QObject *assign = stack.pop();
-                QObject *target = stack.top();
-                int sigIdx = instr.assignSignalObject.signal;
-                const QByteArray &pr = datas.at(sigIdx);
+            QDeclarativeProperty prop(target, pr);
+            if (prop.type() & QDeclarativeProperty::SignalProperty) {
 
-                QDeclarativeProperty prop(target, QString::fromUtf8(pr));
-                if (prop.type() & QDeclarativeProperty::SignalProperty) {
+                QMetaMethod method = QDeclarativeMetaType::defaultMethod(assign);
+                if (method.signature() == 0)
+                    VME_EXCEPTION(tr("Cannot assign object type %1 with no default method").arg(QString::fromLatin1(assign->metaObject()->className())), instr.line);
 
-                    QMetaMethod method = QDeclarativeMetaType::defaultMethod(assign);
-                    if (method.signature() == 0)
-                        VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign object type %1 with no default method").arg(QString::fromLatin1(assign->metaObject()->className())));
-
-                    if (!QMetaObject::checkConnectArgs(prop.method().signature(), method.signature()))
-                        VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot connect mismatched signal/slot %1 %vs. %2").arg(QString::fromLatin1(method.signature())).arg(QString::fromLatin1(prop.method().signature())));
-
-                    QDeclarativePropertyPrivate::connect(target, prop.index(), assign, method.methodIndex());
-
-                } else {
-                    VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign an object to signal property %1").arg(QString::fromUtf8(pr)));
-                }
+                if (!QMetaObject::checkConnectArgs(prop.method().signature(), method.signature()))
+                    VME_EXCEPTION(tr("Cannot connect mismatched signal/slot %1 %vs. %2").arg(QString::fromLatin1(method.signature())).arg(QString::fromLatin1(prop.method().signature())), instr.line);
 
+                QDeclarativePropertyPrivate::connect(target, prop.index(), assign, method.methodIndex());
 
+            } else {
+                VME_EXCEPTION(tr("Cannot assign an object to signal property %1").arg(pr), instr.line);
             }
-            break;
 
-        case QDeclarativeInstruction::StoreSignal:
-            {
-                QObject *target = stack.top();
-                QObject *context = stack.at(stack.count() - 1 - instr.storeSignal.context);
 
-                QMetaMethod signal = target->metaObject()->method(instr.storeSignal.signalIndex);
+        QML_END_INSTR(AssignSignalObject)
+
+        QML_BEGIN_INSTR(StoreSignal)
+            QObject *target = objects.top();
+            QObject *context = objects.at(objects.count() - 1 - instr.context);
+
+            QMetaMethod signal = target->metaObject()->method(instr.signalIndex);
+
+            QDeclarativeBoundSignal *bs = new QDeclarativeBoundSignal(target, signal, target);
+            QDeclarativeExpression *expr = 
+                new QDeclarativeExpression(CTXT, context, PRIMITIVES.at(instr.value), true, COMP->name, instr.line, instr.column, *new QDeclarativeExpressionPrivate);
+            bs->setExpression(expr);
+        QML_END_INSTR(StoreSignal)
+
+        QML_BEGIN_INSTR(StoreImportedScript)
+            CTXT->importedScripts << run(CTXT, SCRIPTS.at(instr.value));
+        QML_END_INSTR(StoreImportedScript)
+
+        QML_BEGIN_INSTR(StoreScriptString)
+            QObject *target = objects.top();
+            QObject *scope = objects.at(objects.count() - 1 - instr.scope);
+            QDeclarativeScriptString ss;
+            ss.setContext(CTXT->asQDeclarativeContext());
+            ss.setScopeObject(scope);
+            ss.setScript(PRIMITIVES.at(instr.value));
+            ss.d.data()->bindingId = instr.bindingId;
+            ss.d.data()->lineNumber = instr.line;
+            ss.d.data()->columnNumber = instr.column;
+
+            void *a[] = { &ss, 0, &status, &flags };
+            QMetaObject::metacall(target, QMetaObject::WriteProperty, 
+                                  instr.propertyIndex, a);
+        QML_END_INSTR(StoreScriptString)
+
+        QML_BEGIN_INSTR(BeginObject)
+            QObject *target = objects.top();
+            QDeclarativeParserStatus *status = reinterpret_cast<QDeclarativeParserStatus *>(reinterpret_cast<char *>(target) + instr.castValue);
+            parserStatus.push(status);
+#ifdef QML_ENABLE_TRACE
+            Q_ASSERT(QObjectPrivate::get(target)->declarativeData);
+            parserStatusData.push(static_cast<QDeclarativeData *>(QObjectPrivate::get(target)->declarativeData));
+#endif
+            status->d = &parserStatus.top();
+
+            status->classBegin();
+        QML_END_INSTR(BeginObject)
+
+        QML_BEGIN_INSTR(InitV8Bindings)
+            CTXT->v8bindings = new QV8Bindings(PRIMITIVES.at(instr.program), instr.programIndex, 
+                                                       instr.line, COMP, CTXT);
+        QML_END_INSTR(InitV8Bindings)
+
+        QML_BEGIN_INSTR(StoreBinding)
+            QObject *target = 
+                objects.at(objects.count() - 1 - instr.owner);
+            QObject *context = 
+                objects.at(objects.count() - 1 - instr.context);
+
+            if (instr.isRoot && BINDINGSKIPLIST.testBit(instr.property.coreIndex))
+                QML_NEXT_INSTR(StoreBinding);
+
+            QDeclarativeBinding *bind = new QDeclarativeBinding(PRIMITIVES.at(instr.value), true, 
+                                                                context, CTXT, COMP->name, instr.line,
+                                                                instr.column);
+            bindValues.push(bind);
+            bind->m_mePtr = &bindValues.top();
+            bind->setTarget(target, instr.property, CTXT);
+
+            bind->addToObject(target, QDeclarativePropertyPrivate::bindingIndex(instr.property));
+        QML_END_INSTR(StoreBinding)
+
+        QML_BEGIN_INSTR(StoreBindingOnAlias)
+            QObject *target = 
+                objects.at(objects.count() - 1 - instr.owner);
+            QObject *context = 
+                objects.at(objects.count() - 1 - instr.context);
+
+            if (instr.isRoot && BINDINGSKIPLIST.testBit(instr.property.coreIndex))
+                QML_NEXT_INSTR(StoreBindingOnAlias);
+
+            QDeclarativeBinding *bind = new QDeclarativeBinding(PRIMITIVES.at(instr.value), true,
+                                                                context, CTXT, COMP->name, instr.line,
+                                                                instr.column);
+            bindValues.push(bind);
+            bind->m_mePtr = &bindValues.top();
+            bind->setTarget(target, instr.property, CTXT);
+
+            QDeclarativeAbstractBinding *old =
+                QDeclarativePropertyPrivate::setBindingNoEnable(target, instr.property.coreIndex,
+                                                                instr.property.getValueTypeCoreIndex(),
+                                                                bind);
+            if (old) { old->destroy(); }
+        QML_END_INSTR(StoreBindingOnAlias)
+
+        QML_BEGIN_INSTR(StoreV4Binding)
+            QObject *target = 
+                objects.at(objects.count() - 1 - instr.owner);
+            QObject *scope = 
+                objects.at(objects.count() - 1 - instr.context);
+
+            int property = instr.property;
+            if (instr.isRoot && BINDINGSKIPLIST.testBit(property & 0xFFFF))
+                QML_NEXT_INSTR(StoreV4Binding);
+
+            QDeclarativeAbstractBinding *binding = 
+                CTXT->v4bindings->configBinding(instr.value, target, scope, property,
+                                                instr.line, instr.column);
+            bindValues.push(binding);
+            binding->m_mePtr = &bindValues.top();
+            binding->addToObject(target, property);
+        QML_END_INSTR(StoreV4Binding)
+
+        QML_BEGIN_INSTR(StoreV8Binding)
+            QObject *target = 
+                objects.at(objects.count() - 1 - instr.owner);
+            QObject *scope = 
+                objects.at(objects.count() - 1 - instr.context);
+
+            if (instr.isRoot && BINDINGSKIPLIST.testBit(instr.property.coreIndex))
+                QML_NEXT_INSTR(StoreV8Binding);
+
+            QDeclarativeAbstractBinding *binding = 
+                CTXT->v8bindings->configBinding(instr.value, target, scope, 
+                                                instr.property, instr.line,
+                                                instr.column);
+            bindValues.push(binding);
+            binding->m_mePtr = &bindValues.top();
+            binding->addToObject(target, QDeclarativePropertyPrivate::bindingIndex(instr.property));
+        QML_END_INSTR(StoreV8Binding)
+
+        QML_BEGIN_INSTR(StoreValueSource)
+            QObject *obj = objects.pop();
+            QDeclarativePropertyValueSource *vs = reinterpret_cast<QDeclarativePropertyValueSource *>(reinterpret_cast<char *>(obj) + instr.castValue);
+            QObject *target = objects.at(objects.count() - 1 - instr.owner);
+
+            obj->setParent(target);
+            vs->setTarget(QDeclarativePropertyPrivate::restore(target, instr.property, CTXT));
+        QML_END_INSTR(StoreValueSource)
+
+        QML_BEGIN_INSTR(StoreValueInterceptor)
+            QObject *obj = objects.pop();
+            QDeclarativePropertyValueInterceptor *vi = reinterpret_cast<QDeclarativePropertyValueInterceptor *>(reinterpret_cast<char *>(obj) + instr.castValue);
+            QObject *target = objects.at(objects.count() - 1 - instr.owner);
+            QDeclarativeProperty prop = 
+                QDeclarativePropertyPrivate::restore(target, instr.property, CTXT);
+            obj->setParent(target);
+            vi->setTarget(prop);
+            QDeclarativeVMEMetaObject *mo = static_cast<QDeclarativeVMEMetaObject *>((QMetaObject*)target->metaObject());
+            mo->registerInterceptor(prop.index(), QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), vi);
+        QML_END_INSTR(StoreValueInterceptor)
+
+        QML_BEGIN_INSTR(StoreObjectQList)
+            QObject *assign = objects.pop();
+
+            const List &list = lists.top();
+            list.qListProperty.append((QDeclarativeListProperty<void>*)&list.qListProperty, assign);
+        QML_END_INSTR(StoreObjectQList)
+
+        QML_BEGIN_INSTR(AssignObjectList)
+            // This is only used for assigning interfaces
+            QObject *assign = objects.pop();
+            const List &list = lists.top();
+
+            int type = list.type;
+
+            void *ptr = 0;
+
+            const char *iid = QDeclarativeMetaType::interfaceIId(type);
+            if (iid) 
+                ptr = assign->qt_metacast(iid);
+            if (!ptr) 
+                VME_EXCEPTION(tr("Cannot assign object to list"), instr.line);
+
+
+            list.qListProperty.append((QDeclarativeListProperty<void>*)&list.qListProperty, ptr);
+        QML_END_INSTR(AssignObjectList)
+
+        QML_BEGIN_INSTR(StoreInterface)
+            QObject *assign = objects.pop();
+            QObject *target = objects.top();
+            CLEAN_PROPERTY(target, instr.propertyIndex);
+
+            int coreIdx = instr.propertyIndex;
+            QMetaProperty prop = target->metaObject()->property(coreIdx);
+            int t = prop.userType();
+            const char *iid = QDeclarativeMetaType::interfaceIId(t);
+            bool ok = false;
+            if (iid) {
+                void *ptr = assign->qt_metacast(iid);
+                if (ptr) {
+                    void *a[] = { &ptr, 0, &status, &flags };
+                    QMetaObject::metacall(target, 
+                                          QMetaObject::WriteProperty,
+                                          coreIdx, a);
+                    ok = true;
+                }
+            } 
 
-                QDeclarativeBoundSignal *bs = new QDeclarativeBoundSignal(target, signal, target);
-                QDeclarativeExpression *expr = 
-                    new QDeclarativeExpression(ctxt, context, primitives.at(instr.storeSignal.value));
-                expr->setSourceLocation(comp->name, instr.line);
-                static_cast<QDeclarativeExpressionPrivate *>(QObjectPrivate::get(expr))->name = datas.at(instr.storeSignal.name);
-                bs->setExpression(expr);
+            if (!ok) 
+                VME_EXCEPTION(tr("Cannot assign object to interface property"), instr.line);
+        QML_END_INSTR(StoreInterface)
+            
+        QML_BEGIN_INSTR(FetchAttached)
+            QObject *target = objects.top();
+
+            QObject *qmlObject = qmlAttachedPropertiesObjectById(instr.id, target);
+
+            if (!qmlObject)
+                VME_EXCEPTION(tr("Unable to create attached object"), instr.line);
+
+            objects.push(qmlObject);
+        QML_END_INSTR(FetchAttached)
+
+        QML_BEGIN_INSTR(FetchQList)
+            QObject *target = objects.top();
+
+            lists.push(List(instr.type));
+
+            void *a[1];
+            a[0] = (void *)&(lists.top().qListProperty);
+            QMetaObject::metacall(target, QMetaObject::ReadProperty, 
+                                  instr.property, a);
+        QML_END_INSTR(FetchQList)
+
+        QML_BEGIN_INSTR(FetchObject)
+            QObject *target = objects.top();
+
+            QObject *obj = 0;
+            // NOTE: This assumes a cast to QObject does not alter the 
+            // object pointer
+            void *a[1];
+            a[0] = &obj;
+            QMetaObject::metacall(target, QMetaObject::ReadProperty, 
+                                  instr.property, a);
+
+            if (!obj)
+                VME_EXCEPTION(tr("Cannot set properties on %1 as it is null").arg(QString::fromUtf8(target->metaObject()->property(instr.property).name())), instr.line);
+
+            objects.push(obj);
+        QML_END_INSTR(FetchObject)
+
+        QML_BEGIN_INSTR(PopQList)
+            lists.pop();
+        QML_END_INSTR(PopQList)
+
+        QML_BEGIN_INSTR(Defer)
+            if (instr.deferCount) {
+                QObject *target = objects.top();
+                QDeclarativeData *data = 
+                    QDeclarativeData::get(target, true);
+                COMP->addref();
+                data->deferredComponent = COMP;
+                data->deferredIdx = INSTRUCTIONSTREAM - COMP->bytecode.constData();
+                INSTRUCTIONSTREAM += instr.deferCount;
             }
-            break;
-
-        case QDeclarativeInstruction::StoreImportedScript:
-            {
-                ctxt->importedScripts << run(ctxt, scripts.at(instr.storeScript.value));
+        QML_END_INSTR(Defer)
+
+        QML_BEGIN_INSTR(PopFetchedObject)
+            objects.pop();
+        QML_END_INSTR(PopFetchedObject)
+
+        QML_BEGIN_INSTR(FetchValueType)
+            QObject *target = objects.top();
+
+            if (instr.bindingSkipList != 0) {
+                // Possibly need to clear bindings
+                QDeclarativeData *targetData = QDeclarativeData::get(target);
+                if (targetData) {
+                    QDeclarativeAbstractBinding *binding = 
+                        QDeclarativePropertyPrivate::binding(target, instr.property, -1);
+
+                    if (binding && binding->bindingType() != QDeclarativeAbstractBinding::ValueTypeProxy) {
+                        QDeclarativePropertyPrivate::setBinding(target, instr.property, -1, 0);
+                        binding->destroy();
+                    } else if (binding) {
+                        QDeclarativeValueTypeProxyBinding *proxy = 
+                            static_cast<QDeclarativeValueTypeProxyBinding *>(binding);
+                        proxy->removeBindings(instr.bindingSkipList);
+                    }
+                }
             }
-            break;
 
-        case QDeclarativeInstruction::StoreScriptString:
-            {
-                QObject *target = stack.top();
-                QObject *scope = stack.at(stack.count() - 1 - instr.storeScriptString.scope);
-                QDeclarativeScriptString ss;
-                ss.setContext(ctxt->asQDeclarativeContext());
-                ss.setScopeObject(scope);
-                ss.setScript(primitives.at(instr.storeScriptString.value));
-
-                void *a[] = { &ss, 0, &status, &flags };
-                QMetaObject::metacall(target, QMetaObject::WriteProperty, 
-                                      instr.storeScriptString.propertyIndex, a);
-            }
+            QDeclarativeValueType *valueHandler = ep->valueTypes[instr.type];
+            valueHandler->read(target, instr.property);
+            objects.push(valueHandler);
+        QML_END_INSTR(FetchValueType)
+
+        QML_BEGIN_INSTR(PopValueType)
+            QDeclarativeValueType *valueHandler = 
+                static_cast<QDeclarativeValueType *>(objects.pop());
+            QObject *target = objects.top();
+            valueHandler->write(target, instr.property, QDeclarativePropertyPrivate::BypassInterceptor);
+        QML_END_INSTR(PopValueType)
+
+#ifdef QML_THREADED_VME_INTERPRETER
+    // nothing to do
+#else
+        default:
+            qFatal("QDeclarativeCompiledData: Internal error - unknown instruction %d", genericInstr->common.instructionType);
             break;
+        }
+    }
+#endif
 
-        case QDeclarativeInstruction::BeginObject:
-            {
-                QObject *target = stack.top();
-                QDeclarativeParserStatus *status = reinterpret_cast<QDeclarativeParserStatus *>(reinterpret_cast<char *>(target) + instr.begin.castValue);
-                parserStatus.append(status);
-                status->d = &parserStatus.values[parserStatus.count - 1];
+exceptionExit:
+    Q_ASSERT(!states.isEmpty());
+    Q_ASSERT(!errors->isEmpty());
 
-                status->classBegin();
-            }
-            break;
+    reset();
 
-        case QDeclarativeInstruction::StoreBinding:
-        case QDeclarativeInstruction::StoreBindingOnAlias:
-            {
-                QObject *target = 
-                    stack.at(stack.count() - 1 - instr.assignBinding.owner);
-                QObject *context = 
-                    stack.at(stack.count() - 1 - instr.assignBinding.context);
+    return 0;
 
-                QDeclarativeProperty mp = 
-                    QDeclarativePropertyPrivate::restore(datas.at(instr.assignBinding.property), target, ctxt);
+normalExit:
+    Q_ASSERT(objects.count() == 1);
 
-                int coreIndex = mp.index();
+    QObject *rv = objects.top();
 
-                if ((stack.count() - instr.assignBinding.owner) == 1 && bindingSkipList.testBit(coreIndex)) 
-                    break;
+    objects.deallocate();
+    lists.deallocate();
+    states.clear();
 
-                QDeclarativeBinding *bind = new QDeclarativeBinding((void *)datas.at(instr.assignBinding.value).constData(), comp, context, ctxt, comp->name, instr.line, 0);
-                bindValues.append(bind);
-                bind->m_mePtr = &bindValues.values[bindValues.count - 1];
-                bind->setTarget(mp);
+    return rv;
+}
 
-                if (instr.type == QDeclarativeInstruction::StoreBindingOnAlias) {
-                    QDeclarativeAbstractBinding *old = QDeclarativePropertyPrivate::setBindingNoEnable(target, coreIndex, QDeclarativePropertyPrivate::valueTypeCoreIndex(mp), bind);
-                    if (old) { old->destroy(); }
-                } else {
-                    bind->addToObject(target, QDeclarativePropertyPrivate::bindingIndex(mp));
-                }
-            }
-            break;
+void QDeclarativeVME::reset()
+{
+    Q_ASSERT(!states.isEmpty() || objects.isEmpty());
 
-        case QDeclarativeInstruction::StoreCompiledBinding:
-            {
-                QObject *target = 
-                    stack.at(stack.count() - 1 - instr.assignBinding.owner);
-                QObject *scope = 
-                    stack.at(stack.count() - 1 - instr.assignBinding.context);
-
-                int property = instr.assignBinding.property;
-                if (stack.count() == 1 && bindingSkipList.testBit(property & 0xFFFF))  
-                    break;
-
-                QDeclarativeAbstractBinding *binding = 
-                    ctxt->optimizedBindings->configBinding(instr.assignBinding.value, target, scope, property);
-                bindValues.append(binding);
-                binding->m_mePtr = &bindValues.values[bindValues.count - 1];
-                binding->addToObject(target, property);
-            }
-            break;
+    QRecursionWatcher<QDeclarativeVME, &QDeclarativeVME::recursion> watcher(this);
 
-        case QDeclarativeInstruction::StoreValueSource:
-            {
-                QObject *obj = stack.pop();
-                QDeclarativePropertyValueSource *vs = reinterpret_cast<QDeclarativePropertyValueSource *>(reinterpret_cast<char *>(obj) + instr.assignValueSource.castValue);
-                QObject *target = stack.at(stack.count() - 1 - instr.assignValueSource.owner);
+    if (!objects.isEmpty() && !(states.at(0).flags & State::Deferred))
+        delete objects.at(0); 
+    
+    if (!rootContext.isNull()) 
+        rootContext->activeVMEData = 0;
 
-                QDeclarativeProperty prop = 
-                    QDeclarativePropertyPrivate::restore(datas.at(instr.assignValueSource.property), target, ctxt);
-                obj->setParent(target);
-                vs->setTarget(prop);
-            }
-            break;
+    // Remove the QDeclarativeParserStatus and QDeclarativeAbstractBinding back pointers
+    blank(parserStatus);
+    blank(bindValues);
 
-        case QDeclarativeInstruction::StoreValueInterceptor:
-            {
-                QObject *obj = stack.pop();
-                QDeclarativePropertyValueInterceptor *vi = reinterpret_cast<QDeclarativePropertyValueInterceptor *>(reinterpret_cast<char *>(obj) + instr.assignValueInterceptor.castValue);
-                QObject *target = stack.at(stack.count() - 1 - instr.assignValueInterceptor.owner);
-                QDeclarativeProperty prop = 
-                    QDeclarativePropertyPrivate::restore(datas.at(instr.assignValueInterceptor.property), target, ctxt);
-                obj->setParent(target);
-                vi->setTarget(prop);
-                QDeclarativeVMEMetaObject *mo = static_cast<QDeclarativeVMEMetaObject *>((QMetaObject*)target->metaObject());
-                mo->registerInterceptor(prop.index(), QDeclarativePropertyPrivate::valueTypeCoreIndex(prop), vi);
-            }
-            break;
+    while (componentAttached) {
+        QDeclarativeComponentAttached *a = componentAttached;
+        a->rem();
+    }
+    
+    engine = 0;
+    objects.deallocate();
+    lists.deallocate();
+    bindValues.deallocate();
+    parserStatus.deallocate();
+#ifdef QML_ENABLE_TRACE
+    parserStatusData.deallocate();
+#endif
+    finalizeCallbacks.clear();
+    states.clear();
+    rootContext = 0;
+    creationContext = 0;
+}
 
-        case QDeclarativeInstruction::StoreObjectQList:
-            {
-                QObject *assign = stack.pop();
+// Must be called with a handle scope and context
+void QDeclarativeScriptData::initialize(QDeclarativeEngine *engine)
+{
+    Q_ASSERT(m_program.IsEmpty());
+    Q_ASSERT(engine);
+    Q_ASSERT(!hasEngine());
 
-                const ListInstance &list = qliststack.top();
-                list.qListProperty.append((QDeclarativeListProperty<void>*)&list.qListProperty, assign);
-            }
-            break;
+    QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
+    QV8Engine *v8engine = ep->v8engine();
 
-        case QDeclarativeInstruction::AssignObjectList:
-            {
-                // This is only used for assigning interfaces
-                QObject *assign = stack.pop();
-                const ListInstance &list = qliststack.top();
+    // If compilation throws an error, a surrounding v8::TryCatch will record it.
+    v8::Local<v8::Script> program = v8engine->qmlModeCompile(m_programSource, url.toString(), 1);
+    if (program.IsEmpty())
+        return;
 
-                int type = list.type;
+    m_program = qPersistentNew<v8::Script>(program);
 
-                void *ptr = 0;
+    addToEngine(engine);
 
-                const char *iid = QDeclarativeMetaType::interfaceIId(type);
-                if (iid) 
-                    ptr = assign->qt_metacast(iid);
-                if (!ptr) 
-                    VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign object to list"));
+    addref();
+}
 
+v8::Persistent<v8::Object> QDeclarativeVME::run(QDeclarativeContextData *parentCtxt, QDeclarativeScriptData *script)
+{
+    if (script->m_loaded)
+        return qPersistentNew<v8::Object>(script->m_value);
 
-                list.qListProperty.append((QDeclarativeListProperty<void>*)&list.qListProperty, ptr);
-            }
-            break;
+    Q_ASSERT(parentCtxt && parentCtxt->engine);
+    QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(parentCtxt->engine);
+    QV8Engine *v8engine = ep->v8engine();
 
-        case QDeclarativeInstruction::StoreVariantObject:
-            {
-                QObject *assign = stack.pop();
-                QObject *target = stack.top();
-                CLEAN_PROPERTY(target, instr.storeObject.propertyIndex);
+    bool shared = script->pragmas & QDeclarativeScript::Object::ScriptBlock::Shared;
 
-                QVariant v = QVariant::fromValue(assign);
-                void *a[] = { &v, 0, &status, &flags };
-                QMetaObject::metacall(target, QMetaObject::WriteProperty, 
-                                      instr.storeObject.propertyIndex, a);
-            }
-            break;
+    QDeclarativeContextData *effectiveCtxt = parentCtxt;
+    if (shared)
+        effectiveCtxt = 0;
 
-        case QDeclarativeInstruction::StoreInterface:
-            {
-                QObject *assign = stack.pop();
-                QObject *target = stack.top();
-                CLEAN_PROPERTY(target, instr.storeObject.propertyIndex);
-
-                int coreIdx = instr.storeObject.propertyIndex;
-                QMetaProperty prop = target->metaObject()->property(coreIdx);
-                int t = prop.userType();
-                const char *iid = QDeclarativeMetaType::interfaceIId(t);
-                bool ok = false;
-                if (iid) {
-                    void *ptr = assign->qt_metacast(iid);
-                    if (ptr) {
-                        void *a[] = { &ptr, 0, &status, &flags };
-                        QMetaObject::metacall(target, 
-                                              QMetaObject::WriteProperty,
-                                              coreIdx, a);
-                        ok = true;
-                    }
-                } 
+    // Create the script context if required
+    QDeclarativeContextData *ctxt = new QDeclarativeContextData;
+    ctxt->isInternal = true;
+    ctxt->isJSContext = true;
+    if (shared)
+        ctxt->isPragmaLibraryContext = true;
+    else
+        ctxt->isPragmaLibraryContext = parentCtxt->isPragmaLibraryContext;
+    ctxt->url = script->url;
+
+    // For backward compatibility, if there are no imports, we need to use the
+    // imports from the parent context.  See QTBUG-17518.
+    if (!script->importCache->isEmpty()) {
+        ctxt->imports = script->importCache;
+    } else if (effectiveCtxt) {
+        ctxt->imports = effectiveCtxt->imports;
+        ctxt->importedScripts = effectiveCtxt->importedScripts;
+        for (int ii = 0; ii < ctxt->importedScripts.count(); ++ii)
+            ctxt->importedScripts[ii] = qPersistentNew<v8::Object>(ctxt->importedScripts[ii]);
+    }
 
-                if (!ok) 
-                    VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot assign object to interface property"));
-            }
-            break;
-            
-        case QDeclarativeInstruction::FetchAttached:
-            {
-                QObject *target = stack.top();
+    if (ctxt->imports) {
+        ctxt->imports->addref();
+    }
 
-                QObject *qmlObject = qmlAttachedPropertiesObjectById(instr.fetchAttached.id, target);
+    if (effectiveCtxt) {
+        ctxt->setParent(effectiveCtxt, true);
+    } else {
+        ctxt->engine = parentCtxt->engine; // Fix for QTBUG-21620
+    }
 
-                if (!qmlObject)
-                    VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Unable to create attached object"));
+    for (int ii = 0; ii < script->scripts.count(); ++ii) {
+        ctxt->importedScripts << run(ctxt, script->scripts.at(ii)->scriptData());
+    }
 
-                stack.push(qmlObject);
-            }
-            break;
+    v8::HandleScope handle_scope;
+    v8::Context::Scope scope(v8engine->context());
 
-        case QDeclarativeInstruction::FetchQList:
-            {
-                QObject *target = stack.top();
+    v8::TryCatch try_catch;
+    if (!script->isInitialized())
+        script->initialize(parentCtxt->engine);
 
-                qliststack.push(ListInstance(instr.fetchQmlList.type));
+    v8::Local<v8::Object> qmlglobal = v8engine->qmlScope(ctxt, 0);
 
-                void *a[1];
-                a[0] = (void *)&(qliststack.top().qListProperty);
-                QMetaObject::metacall(target, QMetaObject::ReadProperty, 
-                                      instr.fetchQmlList.property, a);
-            }
-            break;
+    if (!script->m_program.IsEmpty()) {
+        script->m_program->Run(qmlglobal);
+    } else {
+        // Compilation failed.
+        Q_ASSERT(try_catch.HasCaught());
+    }
 
-        case QDeclarativeInstruction::FetchObject:
-            {
-                QObject *target = stack.top();
+    v8::Persistent<v8::Object> rv;
+    
+    if (try_catch.HasCaught()) {
+        v8::Local<v8::Message> message = try_catch.Message();
+        if (!message.IsEmpty()) {
+            QDeclarativeError error;
+            QDeclarativeExpressionPrivate::exceptionToError(message, error);
+            ep->warning(error);
+        }
+    } 
 
-                QObject *obj = 0;
-                // NOTE: This assumes a cast to QObject does not alter the 
-                // object pointer
-                void *a[1];
-                a[0] = &obj;
-                QMetaObject::metacall(target, QMetaObject::ReadProperty, 
-                                      instr.fetch.property, a);
+    rv = qPersistentNew<v8::Object>(qmlglobal);
+    if (shared) {
+        script->m_value = qPersistentNew<v8::Object>(qmlglobal);
+        script->m_loaded = true;
+    }
 
-                if (!obj)
-                    VME_EXCEPTION(QCoreApplication::translate("QDeclarativeVME","Cannot set properties on %1 as it is null").arg(QString::fromUtf8(target->metaObject()->property(instr.fetch.property).name())));
+    return rv;
+}
 
-                stack.push(obj);
-            }
-            break;
+#ifdef QML_THREADED_VME_INTERPRETER
+void **QDeclarativeVME::instructionJumpTable()
+{
+    static void **jumpTable = 0;
+    if (!jumpTable) {
+        QDeclarativeVME dummy;
+        QDeclarativeVME::Interrupt i;
+        dummy.run(0, i, &jumpTable);
+    }
+    return jumpTable;
+}
+#endif
 
-        case QDeclarativeInstruction::PopQList:
-            {
-                qliststack.pop();
-            }
-            break;
+QDeclarativeContextData *QDeclarativeVME::complete(const Interrupt &interrupt)
+{
+    Q_ASSERT(engine ||
+             (bindValues.isEmpty() &&
+              parserStatus.isEmpty() &&
+              componentAttached == 0 &&
+              rootContext.isNull() &&
+              finalizeCallbacks.isEmpty()));
+
+    if (!engine)
+        return 0;
 
-        case QDeclarativeInstruction::Defer:
-            {
-                if (instr.defer.deferCount) {
-                    QObject *target = stack.top();
-                    QDeclarativeData *data = 
-                        QDeclarativeData::get(target, true);
-                    comp->addref();
-                    data->deferredComponent = comp;
-                    data->deferredIdx = ii;
-                    ii += instr.defer.deferCount;
-                }
-            }
-            break;
+    QDeclarativeTrace trace("VME Complete");
+#ifdef QML_ENABLE_TRACE
+    trace.addDetail("URL", rootComponent->url);
+#endif
 
-        case QDeclarativeInstruction::PopFetchedObject:
-            {
-                stack.pop();
-            }
-            break;
+    ActiveVMERestorer restore(this, QDeclarativeEnginePrivate::get(engine));
+    QRecursionWatcher<QDeclarativeVME, &QDeclarativeVME::recursion> watcher(this);
 
-        case QDeclarativeInstruction::FetchValueType:
-            {
-                QObject *target = stack.top();
-
-                if (instr.fetchValue.bindingSkipList != 0) {
-                    // Possibly need to clear bindings
-                    QDeclarativeData *targetData = QDeclarativeData::get(target);
-                    if (targetData) {
-                        QDeclarativeAbstractBinding *binding = 
-                            QDeclarativePropertyPrivate::binding(target, instr.fetchValue.property, -1);
-
-                        if (binding && binding->bindingType() != QDeclarativeAbstractBinding::ValueTypeProxy) {
-                            QDeclarativePropertyPrivate::setBinding(target, instr.fetchValue.property, -1, 0);
-                            binding->destroy();
-                        } else if (binding) {
-                            QDeclarativeValueTypeProxyBinding *proxy = 
-                                static_cast<QDeclarativeValueTypeProxyBinding *>(binding);
-                            proxy->removeBindings(instr.fetchValue.bindingSkipList);
-                        }
-                    }
-                }
+    {
+    QDeclarativeTrace trace("VME Binding Enable");
+    trace.event("begin binding eval");
+    while (!bindValues.isEmpty()) {
+        QDeclarativeAbstractBinding *b = bindValues.pop();
 
-                QDeclarativeValueType *valueHandler = ep->valueTypes[instr.fetchValue.type];
-                valueHandler->read(target, instr.fetchValue.property);
-                stack.push(valueHandler);
-            }
-            break;
+        if(b) {
+            b->m_mePtr = 0;
+            b->setEnabled(true, QDeclarativePropertyPrivate::BypassInterceptor | 
+                                QDeclarativePropertyPrivate::DontRemoveBinding);
+        }
 
-        case QDeclarativeInstruction::PopValueType:
-            {
-                QDeclarativeValueType *valueHandler = 
-                    static_cast<QDeclarativeValueType *>(stack.pop());
-                QObject *target = stack.top();
-                valueHandler->write(target, instr.fetchValue.property, 
-                                    QDeclarativePropertyPrivate::BypassInterceptor);
-            }
-            break;
+        if (watcher.hasRecursed() || interrupt.shouldInterrupt())
+            return 0;
+    }
+    bindValues.deallocate();
+    }
 
-        default:
-            qFatal("QDeclarativeCompiledData: Internal error - unknown instruction %d", instr.type);
-            break;
+    {
+    QDeclarativeTrace trace("VME Component Complete");
+    while (!parserStatus.isEmpty()) {
+        QDeclarativeParserStatus *status = parserStatus.pop();
+#ifdef QML_ENABLE_TRACE
+        QDeclarativeData *data = parserStatusData.pop();
+#endif
+
+        if (status && status->d) {
+            status->d = 0;
+#ifdef QML_ENABLE_TRACE
+            QDeclarativeTrace trace("Component complete");
+            trace.addDetail("URL", data->outerContext->url);
+            trace.addDetail("Line", data->lineNumber);
+#endif
+            status->componentComplete();
         }
+        
+        if (watcher.hasRecursed() || interrupt.shouldInterrupt())
+            return 0;
+    }
+    parserStatus.deallocate();
     }
 
-    if (isError()) {
-        if (!stack.isEmpty()) {
-            delete stack.at(0); // ### What about failures in deferred creation?
-        } else {
-            ctxt->destroy();
+    {
+    QDeclarativeTrace trace("VME Finalize Callbacks");
+    for (int ii = 0; ii < finalizeCallbacks.count(); ++ii) {
+        QDeclarativeEnginePrivate::FinalizeCallback callback = finalizeCallbacks.at(ii);
+        QObject *obj = callback.first;
+        if (obj) {
+            void *args[] = { 0 };
+            QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, callback.second, args);
         }
+        if (watcher.hasRecursed())
+            return 0;
+    }
+    finalizeCallbacks.clear();
+    }
 
-        QDeclarativeEnginePrivate::clear(bindValues);
-        QDeclarativeEnginePrivate::clear(parserStatus);
-        return 0;
+    {
+    QDeclarativeTrace trace("VME Component.onCompleted Callbacks");
+    while (componentAttached) {
+        QDeclarativeComponentAttached *a = componentAttached;
+        a->rem();
+        QDeclarativeData *d = QDeclarativeData::get(a->parent());
+        Q_ASSERT(d);
+        Q_ASSERT(d->context);
+        a->add(&d->context->componentAttached);
+        emit a->completed();
+
+        if (watcher.hasRecursed() || interrupt.shouldInterrupt())
+            return 0;
     }
+    }
+
+    QDeclarativeContextData *rv = rootContext;
 
-    if (bindValues.count)
-        ep->bindValues << bindValues;
-    else if (bindValues.values)
-        bindValues.clear();
+    reset();
 
-    if (parserStatus.count)
-        ep->parserStatus << parserStatus;
-    else if (parserStatus.values)
-        parserStatus.clear();
+    if (rv) rv->activeVMEData = data;
 
-    Q_ASSERT(stack.count() == 1);
-    return stack.top();
+    return rv;
 }
 
-bool QDeclarativeVME::isError() const
+void QDeclarativeVME::blank(QFiniteStack<QDeclarativeAbstractBinding *> &bs)
 {
-    return !vmeErrors.isEmpty();
+    for (int ii = 0; ii < bs.count(); ++ii) {
+        QDeclarativeAbstractBinding *b = bs.at(ii);
+        if (b) b->m_mePtr = 0;
+    }
 }
 
-QList<QDeclarativeError> QDeclarativeVME::errors() const
+void QDeclarativeVME::blank(QFiniteStack<QDeclarativeParserStatus *> &pss)
 {
-    return vmeErrors;
+    for (int ii = 0; ii < pss.count(); ++ii) {
+        QDeclarativeParserStatus *ps = pss.at(ii);
+        if(ps) ps->d = 0;
+    }
 }
 
-QObject *
-QDeclarativeCompiledData::TypeReference::createInstance(QDeclarativeContextData *ctxt,
-                                                        const QBitField &bindings,
-                                                        QList<QDeclarativeError> *errors) const
+QDeclarativeVMEGuard::QDeclarativeVMEGuard()
+: m_objectCount(0), m_objects(0), m_contextCount(0), m_contexts(0)
 {
-    if (type) {
-        QObject *rv = 0;
-        void *memory = 0;
-
-        type->create(&rv, &memory, sizeof(QDeclarativeData));
-        QDeclarativeData *ddata = new (memory) QDeclarativeData;
-        ddata->ownMemory = false;
-        QObjectPrivate::get(rv)->declarativeData = ddata;
-
-        if (typePropertyCache && !ddata->propertyCache) {
-            ddata->propertyCache = typePropertyCache;
-            ddata->propertyCache->addref();
-        }
-
-        return rv;
-    } else {
-        Q_ASSERT(component);
-        return QDeclarativeComponentPrivate::begin(ctxt, 0, component, -1, -1, 0, errors, bindings);
-    } 
 }
 
-QScriptValue QDeclarativeVME::run(QDeclarativeContextData *parentCtxt, QDeclarativeScriptData *script)
+QDeclarativeVMEGuard::~QDeclarativeVMEGuard()
 {
-    if (script->m_loaded)
-        return script->m_value;
-
-    QDeclarativeEnginePrivate *enginePriv = QDeclarativeEnginePrivate::get(parentCtxt->engine);
-    QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(parentCtxt->engine);
-
-    bool shared = script->pragmas & QDeclarativeParser::Object::ScriptBlock::Shared;
-
-    // Create the script context if required
-    QDeclarativeContextData *ctxt = 0;
-    if (!shared) {
-        ctxt = new QDeclarativeContextData;
-        ctxt->isInternal = true;
-        ctxt->url = script->url;
-
-        // For backward compatibility, if there are no imports, we need to use the
-        // imports from the parent context.  See QTBUG-17518.
-        if (!script->importCache->isEmpty()) {
-            ctxt->imports = script->importCache;
-        } else {
-            ctxt->imports = parentCtxt->imports;
-        }
-
-        if (ctxt->imports) {
-            ctxt->imports->addref();
-        }
-
-        ctxt->setParent(parentCtxt, true);
-
-        for (int ii = 0; ii < script->scripts.count(); ++ii)
-            ctxt->importedScripts << run(ctxt, script->scripts.at(ii)->scriptData());
-    }
-
-    QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(scriptEngine);
-    if (shared) {
-        scriptContext->pushScope(enginePriv->contextClass->newUrlContext(script->url.toString())); // XXX toString()?
-    } else {
-        scriptContext->pushScope(enginePriv->contextClass->newUrlContext(ctxt, 0, script->url.toString()));
-    }
+    clear();
+}
 
-    scriptContext->pushScope(enginePriv->globalClass->staticGlobalObject());
-    QScriptValue scope = QScriptDeclarativeClass::newStaticScopeObject(scriptEngine);
-    scriptContext->pushScope(scope);
+void QDeclarativeVMEGuard::guard(QDeclarativeVME *vme)
+{
+    clear();
+    
+    m_objectCount = vme->objects.count();
+    m_objects = new QDeclarativeGuard<QObject>[m_objectCount];
+    for (int ii = 0; ii < m_objectCount; ++ii)
+        m_objects[ii] = vme->objects[ii];
+
+    m_contextCount = (vme->rootContext.isNull()?0:1) + vme->states.count();
+    m_contexts = new QDeclarativeGuardedContextData[m_contextCount];
+    for (int ii = 0; ii < vme->states.count(); ++ii) 
+        m_contexts[ii] = vme->states.at(ii).context;
+    if (!vme->rootContext.isNull())
+        m_contexts[m_contextCount - 1] = vme->rootContext.contextData();
+}
 
-    scriptEngine->evaluate(script->m_program);
+void QDeclarativeVMEGuard::clear()
+{
+    delete [] m_objects;
+    delete [] m_contexts;
 
-    if (scriptEngine->hasUncaughtException()) {
-        QDeclarativeError error;
-        QDeclarativeExpressionPrivate::exceptionToError(scriptEngine, error);
-        enginePriv->warning(error);
-    }
+    m_objectCount = 0;
+    m_objects = 0;
+    m_contextCount = 0;
+    m_contexts = 0;
+}
 
-    scriptEngine->popContext();
+bool QDeclarativeVMEGuard::isOK() const
+{
+    for (int ii = 0; ii < m_objectCount; ++ii)
+        if (m_objects[ii].isNull())
+            return false;
 
-    if (shared) {
-        script->m_loaded = true;
-        script->m_value = scope;
-    }
+    for (int ii = 0; ii < m_contextCount; ++ii)
+        if (m_contexts[ii].isNull())
+            return false;
 
-    return scope;
+    return true;
 }
 
 QT_END_NAMESPACE