aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAaron Kennedy <aaron.kennedy@nokia.com>2011-06-17 11:37:17 +1000
committerAaron Kennedy <aaron.kennedy@nokia.com>2011-06-17 11:37:17 +1000
commit69a17a912a41458a2b4a20bdbda1717920275250 (patch)
treef0eb0cdb210765ddb954539a0fbe520640eae2a1
parent9c5e112e12f09ad5c8356d6815f9b23102e99bfd (diff)
Evaluate all shared bindings together using a shared context
The vast majority of bindings are capable of being shared (that is, don't introduce closures themselves) and consequently this improves the performance of almost every app.
-rw-r--r--src/declarative/qml/qdeclarativebinding.cpp33
-rw-r--r--src/declarative/qml/qdeclarativebinding_p.h4
-rw-r--r--src/declarative/qml/qdeclarativebinding_p_p.h1
-rw-r--r--src/declarative/qml/qdeclarativecompileddata.cpp2
-rw-r--r--src/declarative/qml/qdeclarativecompiler.cpp162
-rw-r--r--src/declarative/qml/qdeclarativecompiler_p.h11
-rw-r--r--src/declarative/qml/qdeclarativecontext.cpp16
-rw-r--r--src/declarative/qml/qdeclarativecontext_p.h8
-rw-r--r--src/declarative/qml/qdeclarativeexpression.cpp50
-rw-r--r--src/declarative/qml/qdeclarativeexpression.h4
-rw-r--r--src/declarative/qml/qdeclarativeexpression_p.h2
-rw-r--r--src/declarative/qml/qdeclarativeinstruction.cpp8
-rw-r--r--src/declarative/qml/qdeclarativeinstruction_p.h10
-rw-r--r--src/declarative/qml/qdeclarativerefcount_p.h67
-rw-r--r--src/declarative/qml/qdeclarativevme.cpp44
-rw-r--r--src/declarative/qml/v4/qdeclarativev4bindings.cpp1
-rw-r--r--src/declarative/qml/v8/qv8bindings.cpp235
-rw-r--r--src/declarative/qml/v8/qv8bindings_p.h94
-rw-r--r--src/declarative/qml/v8/v8.pri2
19 files changed, 623 insertions, 131 deletions
diff --git a/src/declarative/qml/qdeclarativebinding.cpp b/src/declarative/qml/qdeclarativebinding.cpp
index d1fdec5a63..fee55545cf 100644
--- a/src/declarative/qml/qdeclarativebinding.cpp
+++ b/src/declarative/qml/qdeclarativebinding.cpp
@@ -226,15 +226,6 @@ QDeclarativeBindingPrivate::~QDeclarativeBindingPrivate()
{
}
-QDeclarativeBinding::QDeclarativeBinding(void *data, QDeclarativeRefCount *rc, QObject *obj,
- QDeclarativeContextData *ctxt, const QString &url, int lineNumber,
- QObject *parent)
-: QDeclarativeExpression(ctxt, data, rc, obj, url, lineNumber, *new QDeclarativeBindingPrivate)
-{
- setParent(parent);
- setNotifyOnValueChanged(true);
-}
-
QDeclarativeBinding *
QDeclarativeBinding::createBinding(Identifier id, QObject *obj, QDeclarativeContext *ctxt,
const QString &url, int lineNumber, QObject *parent)
@@ -251,7 +242,7 @@ QDeclarativeBinding::createBinding(Identifier id, QObject *obj, QDeclarativeCont
typeData = engine->typeLoader.get(ctxtdata->url);
cdata = typeData->compiledData();
}
- QDeclarativeBinding *rv = cdata ? new QDeclarativeBinding((void*)cdata->datas.at(id).constData(), cdata, obj, ctxtdata, url, lineNumber, parent) : 0;
+ QDeclarativeBinding *rv = cdata ? new QDeclarativeBinding(cdata->primitives.at(id), true, obj, ctxtdata, url, lineNumber, parent) : 0;
if (typeData)
typeData->release();
return rv;
@@ -273,6 +264,15 @@ QDeclarativeBinding::QDeclarativeBinding(const QString &str, QObject *obj, QDecl
setNotifyOnValueChanged(true);
}
+QDeclarativeBinding::QDeclarativeBinding(const QString &str, bool isRewritten, QObject *obj,
+ QDeclarativeContextData *ctxt,
+ const QString &url, int lineNumber, QObject *parent)
+: QDeclarativeExpression(ctxt, obj, str, isRewritten, url, lineNumber, *new QDeclarativeBindingPrivate)
+{
+ setParent(parent);
+ setNotifyOnValueChanged(true);
+}
+
/*!
\internal
@@ -413,19 +413,17 @@ void QDeclarativeBinding::update(QDeclarativePropertyPrivate::WriteFlags flags)
} else {
QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(d->context()->engine);
- ep->referenceScarceResources(); // "hold" scarce resources in memory during evaluation.
+ ep->referenceScarceResources();
bool isUndefined = false;
- QVariant value;
v8::HandleScope handle_scope;
v8::Context::Scope scope(ep->v8engine.context());
v8::Local<v8::Value> result = d->v8value(0, &isUndefined);
bool needsErrorData = false;
- if (!watcher.wasDeleted() && !d->error.isValid()) {
+ if (!watcher.wasDeleted() && !d->error.isValid())
needsErrorData = !d->writeBindingResult(d, d->property, result, isUndefined, flags);
- }
if (!watcher.wasDeleted()) {
@@ -453,10 +451,15 @@ void QDeclarativeBinding::update(QDeclarativePropertyPrivate::WriteFlags flags)
if (!watcher.wasDeleted())
d->updating = false;
} else {
- qmlInfo(d->property.object()) << tr("Binding loop detected for property \"%1\"").arg(d->property.name());
+ QDeclarativeBindingPrivate::printBindingLoopError(d->property);
}
}
+void QDeclarativeBindingPrivate::printBindingLoopError(QDeclarativeProperty &prop)
+{
+ qmlInfo(prop.object()) << QDeclarativeBinding::tr("Binding loop detected for property \"%1\"").arg(prop.name());
+}
+
void QDeclarativeBindingPrivate::emitValueChanged()
{
Q_Q(QDeclarativeBinding);
diff --git a/src/declarative/qml/qdeclarativebinding_p.h b/src/declarative/qml/qdeclarativebinding_p.h
index e646c86df3..fedd63634b 100644
--- a/src/declarative/qml/qdeclarativebinding_p.h
+++ b/src/declarative/qml/qdeclarativebinding_p.h
@@ -152,8 +152,8 @@ public:
QDeclarativeBinding(const QString &, QObject *, QDeclarativeContext *, QObject *parent=0);
QDeclarativeBinding(const QString &, QObject *, QDeclarativeContextData *, QObject *parent=0);
- QDeclarativeBinding(void *, QDeclarativeRefCount *, QObject *, QDeclarativeContextData *,
- const QString &, int, QObject *parent);
+ QDeclarativeBinding(const QString &, bool isRewritten, QObject *, QDeclarativeContextData *,
+ const QString &url, int lineNumber, QObject *parent=0);
QDeclarativeBinding(void *, QObject *, QDeclarativeContextData *, QObject *parent=0);
void setTarget(const QDeclarativeProperty &);
diff --git a/src/declarative/qml/qdeclarativebinding_p_p.h b/src/declarative/qml/qdeclarativebinding_p_p.h
index 1b1b03b228..6caf13635f 100644
--- a/src/declarative/qml/qdeclarativebinding_p_p.h
+++ b/src/declarative/qml/qdeclarativebinding_p_p.h
@@ -72,6 +72,7 @@ public:
static bool writeBindingResult(QDeclarativeJavaScriptExpression *expression,
QDeclarativeProperty &prop, v8::Handle<v8::Value> value, bool isUndefined,
QDeclarativePropertyPrivate::WriteFlags flags);
+ static void printBindingLoopError(QDeclarativeProperty &prop);
protected:
virtual void refresh();
diff --git a/src/declarative/qml/qdeclarativecompileddata.cpp b/src/declarative/qml/qdeclarativecompileddata.cpp
index 2ea41d857f..fc4b28b666 100644
--- a/src/declarative/qml/qdeclarativecompileddata.cpp
+++ b/src/declarative/qml/qdeclarativecompileddata.cpp
@@ -128,6 +128,8 @@ QDeclarativeCompiledData::~QDeclarativeCompiledData()
qDeleteAll(cachedPrograms);
qDeleteAll(cachedClosures);
+
+ qPersistentDispose(v8bindings);
}
void QDeclarativeCompiledData::clear()
diff --git a/src/declarative/qml/qdeclarativecompiler.cpp b/src/declarative/qml/qdeclarativecompiler.cpp
index e4ad463dad..a0a6680d2e 100644
--- a/src/declarative/qml/qdeclarativecompiler.cpp
+++ b/src/declarative/qml/qdeclarativecompiler.cpp
@@ -708,6 +708,14 @@ void QDeclarativeCompiler::compileTree(QDeclarativeParser::Object *tree)
init.init.compiledBinding = output->indexForByteArray(compileState.compiledBindingData);
output->addInstruction(init);
+ if (!compileState.v8BindingProgram.isEmpty()) {
+ QDeclarativeInstruction bindings;
+ bindings.setType(QDeclarativeInstruction::InitV8Bindings);
+ bindings.initV8Bindings.program = output->indexForString(compileState.v8BindingProgram);
+ bindings.initV8Bindings.line = compileState.v8BindingProgramLine;
+ output->addInstruction(bindings);
+ }
+
genObject(tree);
QDeclarativeInstruction def;
@@ -1208,6 +1216,14 @@ void QDeclarativeCompiler::genComponent(QDeclarativeParser::Object *obj)
init.init.compiledBinding = output->indexForByteArray(compileState.compiledBindingData);
output->addInstruction(init);
+ if (!compileState.v8BindingProgram.isEmpty()) {
+ QDeclarativeInstruction bindings;
+ bindings.setType(QDeclarativeInstruction::InitV8Bindings);
+ bindings.initV8Bindings.program = output->indexForString(compileState.v8BindingProgram);
+ bindings.initV8Bindings.line = compileState.v8BindingProgramLine;
+ output->addInstruction(bindings);
+ }
+
genObject(root);
QDeclarativeInstruction def;
@@ -2311,33 +2327,15 @@ const QMetaObject *QDeclarativeCompiler::resolveType(const QByteArray& name) con
}
// similar to logic of completeComponentBuild, but also sticks data
-// into datas at the end
+// into primitives at the end
int QDeclarativeCompiler::rewriteBinding(const QString& expression, const QByteArray& name)
{
QDeclarativeRewrite::RewriteBinding rewriteBinding;
rewriteBinding.setName('$' + name.mid(name.lastIndexOf('.') + 1));
- bool isSharable = false;
- QString rewrite = rewriteBinding(expression, 0, &isSharable);
-
- quint32 length = rewrite.length();
- quint32 pc;
-
- if (isSharable) {
- pc = output->cachedClosures.count();
- pc |= 0x80000000;
- output->cachedClosures.append(0);
- } else {
- pc = output->cachedPrograms.length();
- output->cachedPrograms.append(0);
- }
- QByteArray compiledData =
- QByteArray((const char *)&pc, sizeof(quint32)) +
- QByteArray((const char *)&length, sizeof(quint32)) +
- QByteArray((const char *)rewrite.constData(),
- rewrite.length() * sizeof(QChar));
+ QString rewrite = rewriteBinding(expression, 0, 0);
- return output->indexForByteArray(compiledData);
+ return output->indexForString(rewrite);
}
// Ensures that the dynamic meta specification on obj is valid
@@ -2841,9 +2839,9 @@ void QDeclarativeCompiler::genBindingAssignment(QDeclarativeParser::Value *bindi
Q_ASSERT(compileState.bindings.contains(binding));
const BindingReference &ref = compileState.bindings.value(binding);
- if (ref.dataType == BindingReference::Experimental) {
+ if (ref.dataType == BindingReference::V4) {
QDeclarativeInstruction store;
- store.setType(QDeclarativeInstruction::StoreCompiledBinding);
+ store.setType(QDeclarativeInstruction::StoreV4Binding);
store.assignBinding.value = ref.compiledIndex;
store.assignBinding.context = ref.bindingContext.stack;
store.assignBinding.owner = ref.bindingContext.owner;
@@ -2855,28 +2853,43 @@ void QDeclarativeCompiler::genBindingAssignment(QDeclarativeParser::Value *bindi
store.assignBinding.property = prop->index;
store.assignBinding.line = binding->location.start.line;
output->addInstruction(store);
- return;
- }
+ } else if (ref.dataType == BindingReference::V8) {
+ QDeclarativeInstruction store;
+ store.setType(QDeclarativeInstruction::StoreV8Binding);
+ store.assignBinding.value = ref.compiledIndex;
+ store.assignBinding.context = ref.bindingContext.stack;
+ store.assignBinding.owner = ref.bindingContext.owner;
+ store.assignBinding.line = binding->location.start.line;
- QDeclarativeInstruction store;
- if (!prop->isAlias)
- store.setType(QDeclarativeInstruction::StoreBinding);
- else
- store.setType(QDeclarativeInstruction::StoreBindingOnAlias);
- store.assignBinding.value = output->indexForByteArray(ref.compiledData);
- store.assignBinding.context = ref.bindingContext.stack;
- store.assignBinding.owner = ref.bindingContext.owner;
- store.assignBinding.line = binding->location.start.line;
-
- Q_ASSERT(ref.bindingContext.owner == 0 ||
- (ref.bindingContext.owner != 0 && valueTypeProperty));
- if (ref.bindingContext.owner) {
- store.assignBinding.property = genValueTypeData(prop, valueTypeProperty);
+ Q_ASSERT(ref.bindingContext.owner == 0 ||
+ (ref.bindingContext.owner != 0 && valueTypeProperty));
+ if (ref.bindingContext.owner) {
+ store.assignBinding.property = genValueTypeData(prop, valueTypeProperty);
+ } else {
+ store.assignBinding.property = genPropertyData(prop);
+ }
+
+ output->addInstruction(store);
} else {
- store.assignBinding.property = genPropertyData(prop);
- }
+ QDeclarativeInstruction store;
+ if (!prop->isAlias)
+ store.setType(QDeclarativeInstruction::StoreBinding);
+ else
+ store.setType(QDeclarativeInstruction::StoreBindingOnAlias);
+ store.assignBinding.value = output->indexForString(ref.rewrittenExpression);
+ store.assignBinding.context = ref.bindingContext.stack;
+ store.assignBinding.owner = ref.bindingContext.owner;
+ store.assignBinding.line = binding->location.start.line;
- output->addInstruction(store);
+ Q_ASSERT(ref.bindingContext.owner == 0 ||
+ (ref.bindingContext.owner != 0 && valueTypeProperty));
+ if (ref.bindingContext.owner) {
+ store.assignBinding.property = genValueTypeData(prop, valueTypeProperty);
+ } else {
+ store.assignBinding.property = genPropertyData(prop);
+ }
+ output->addInstruction(store);
+ }
}
int QDeclarativeCompiler::genContextCache()
@@ -2929,6 +2942,8 @@ bool QDeclarativeCompiler::completeComponentBuild()
QDeclarativeV4Compiler bindingCompiler;
+ QList<BindingReference*> sharedBindings;
+
for (QHash<QDeclarativeParser::Value*,BindingReference>::Iterator iter = compileState.bindings.begin();
iter != compileState.bindings.end(); ++iter) {
@@ -2943,44 +2958,67 @@ bool QDeclarativeCompiler::completeComponentBuild()
int index = bindingCompiler.compile(expr, enginePrivate);
if (index != -1) {
- binding.dataType = BindingReference::Experimental;
+ binding.dataType = BindingReference::V4;
binding.compiledIndex = index;
componentStat.optimizedBindings.append(iter.key()->location);
continue;
}
}
- binding.dataType = BindingReference::QtScript;
-
// Pre-rewrite the expression
QString expression = binding.expression.asScript();
QDeclarativeRewrite::RewriteBinding rewriteBinding;
rewriteBinding.setName('$'+binding.property->name);
bool isSharable = false;
- expression = rewriteBinding(binding.expression.asAST(), expression, &isSharable);
-
- quint32 length = expression.length();
- quint32 pc;
-
- if (isSharable) {
- pc = output->cachedClosures.count();
- pc |= 0x80000000;
- output->cachedClosures.append(0);
+ binding.rewrittenExpression = rewriteBinding(binding.expression.asAST(), expression, &isSharable);
+
+ if (isSharable && !binding.property->isAlias /* See above re alias */ &&
+ binding.property->type != qMetaTypeId<QDeclarativeBinding*>()) {
+ binding.dataType = BindingReference::V8;
+ sharedBindings.append(&iter.value());
} else {
- pc = output->cachedPrograms.length();
- output->cachedPrograms.append(0);
+ binding.dataType = BindingReference::QtScript;
}
- binding.compiledData =
- QByteArray((const char *)&pc, sizeof(quint32)) +
- QByteArray((const char *)&length, sizeof(quint32)) +
- QByteArray((const char *)expression.constData(),
- expression.length() * sizeof(QChar));
-
componentStat.scriptBindings.append(iter.key()->location);
}
+ if (!sharedBindings.isEmpty()) {
+ struct Sort {
+ static bool lt(const BindingReference *lhs, const BindingReference *rhs)
+ {
+ return lhs->value->location.start.line < rhs->value->location.start.line;
+ }
+ };
+
+ qSort(sharedBindings.begin(), sharedBindings.end(), Sort::lt);
+
+ int startLineNumber = sharedBindings.at(0)->value->location.start.line;
+ int lineNumber = startLineNumber;
+
+ QString functionArray(QLatin1String("["));
+ for (int ii = 0; ii < sharedBindings.count(); ++ii) {
+ BindingReference *reference = sharedBindings.at(ii);
+ QDeclarativeParser::Value *value = reference->value;
+ const QString &expression = reference->rewrittenExpression;
+
+ if (ii != 0) functionArray += QLatin1String(",");
+
+ while (lineNumber < value->location.start.line) {
+ lineNumber++;
+ functionArray += QLatin1String("\n");
+ }
+
+ functionArray += expression;
+ reference->compiledIndex = ii;
+ }
+ functionArray += QLatin1String("]");
+
+ compileState.v8BindingProgram = functionArray;
+ compileState.v8BindingProgramLine = startLineNumber;
+ }
+
if (bindingCompiler.isValid())
compileState.compiledBindingData = bindingCompiler.program();
diff --git a/src/declarative/qml/qdeclarativecompiler_p.h b/src/declarative/qml/qdeclarativecompiler_p.h
index e4b9240a93..2756c3fefb 100644
--- a/src/declarative/qml/qdeclarativecompiler_p.h
+++ b/src/declarative/qml/qdeclarativecompiler_p.h
@@ -55,6 +55,7 @@
#include "qdeclarative.h"
#include "qdeclarativeerror.h"
+#include "private/qv8_p.h"
#include "private/qdeclarativeinstruction_p.h"
#include "private/qdeclarativeparser_p.h"
#include "private/qdeclarativeengine_p.h"
@@ -103,6 +104,8 @@ public:
};
QList<TypeReference> types;
+ v8::Persistent<v8::Array> v8bindings;
+
const QMetaObject *root;
QAbstractDynamicMetaObject rootData;
QDeclarativePropertyCache *rootPropertyCache;
@@ -283,12 +286,12 @@ private:
QDeclarativeParser::Property *property;
QDeclarativeParser::Value *value;
- enum DataType { QtScript, Experimental };
+ enum DataType { QtScript, V4, V8 };
DataType dataType;
int compiledIndex;
- QByteArray compiledData;
+ QString rewrittenExpression;
BindingContext bindingContext;
};
void addBindingReference(const BindingReference &);
@@ -296,7 +299,7 @@ private:
struct ComponentCompileState
{
ComponentCompileState()
- : parserStatusCount(0), pushedProperties(0), nested(false), root(0) {}
+ : parserStatusCount(0), pushedProperties(0), nested(false), v8BindingProgramLine(-1), root(0) {}
QHash<QString, QDeclarativeParser::Object *> ids;
QHash<int, QDeclarativeParser::Object *> idIndexes;
int parserStatusCount;
@@ -304,6 +307,8 @@ private:
bool nested;
QByteArray compiledBindingData;
+ QString v8BindingProgram;
+ int v8BindingProgramLine;
QHash<QDeclarativeParser::Value *, BindingReference> bindings;
QHash<QDeclarativeParser::Value *, BindingContext> signalExpressions;
diff --git a/src/declarative/qml/qdeclarativecontext.cpp b/src/declarative/qml/qdeclarativecontext.cpp
index c2c21d30fb..caa3b0c7d8 100644
--- a/src/declarative/qml/qdeclarativecontext.cpp
+++ b/src/declarative/qml/qdeclarativecontext.cpp
@@ -48,6 +48,7 @@
#include "qdeclarativeengine.h"
#include "qdeclarativeinfo.h"
#include "private/qdeclarativev4bindings_p.h"
+#include "private/qv8bindings_p.h"
#include <qscriptengine.h>
#include <QtCore/qvarlengtharray.h>
@@ -499,16 +500,16 @@ QObject *QDeclarativeContextPrivate::context_at(QDeclarativeListProperty<QObject
QDeclarativeContextData::QDeclarativeContextData()
: parent(0), engine(0), isInternal(false), ownedByParent(false), isJSContext(false), isPragmaLibraryContext(false),
publicContext(0), propertyNames(0), contextObject(0), imports(0), childContexts(0), nextChild(0), prevChild(0),
- expressions(0), contextObjects(0), contextGuards(0), idValues(0), idValueCount(0), optimizedBindings(0),
- linkedContext(0), componentAttached(0)
+ expressions(0), contextObjects(0), contextGuards(0), idValues(0), idValueCount(0), linkedContext(0),
+ componentAttached(0), v4bindings(0), v8bindings(0)
{
}
QDeclarativeContextData::QDeclarativeContextData(QDeclarativeContext *ctxt)
: parent(0), engine(0), isInternal(false), ownedByParent(false), isJSContext(false), isPragmaLibraryContext(false),
publicContext(ctxt), propertyNames(0), contextObject(0), imports(0), childContexts(0), nextChild(0), prevChild(0),
- expressions(0), contextObjects(0), contextGuards(0), idValues(0), idValueCount(0), optimizedBindings(0),
- linkedContext(0), componentAttached(0)
+ expressions(0), contextObjects(0), contextGuards(0), idValues(0), idValueCount(0), linkedContext(0),
+ componentAttached(0), v4bindings(0), v8bindings(0)
{
}
@@ -607,8 +608,11 @@ void QDeclarativeContextData::destroy()
if (imports)
imports->release();
- if (optimizedBindings)
- optimizedBindings->release();
+ if (v4bindings)
+ v4bindings->release();
+
+ if (v8bindings)
+ v8bindings->release();
for (int ii = 0; ii < importedScripts.count(); ++ii) {
qPersistentDispose(importedScripts[ii]);
diff --git a/src/declarative/qml/qdeclarativecontext_p.h b/src/declarative/qml/qdeclarativecontext_p.h
index ac933a3ae3..59d886c366 100644
--- a/src/declarative/qml/qdeclarativecontext_p.h
+++ b/src/declarative/qml/qdeclarativecontext_p.h
@@ -73,6 +73,7 @@
QT_BEGIN_NAMESPACE
+class QV8Bindings;
class QDeclarativeContext;
class QDeclarativeExpression;
class QDeclarativeEngine;
@@ -192,9 +193,6 @@ public:
void setIdProperty(int, QObject *);
void setIdPropertyData(QDeclarativeIntegerCache *);
- // Optimized binding pointer
- QDeclarativeV4Bindings *optimizedBindings;
-
// Linked contexts. this owns linkedContext.
QDeclarativeContextData *linkedContext;
@@ -202,6 +200,10 @@ public:
// context
QDeclarativeComponentAttached *componentAttached;
+ // Optimized binding objects. Needed for deferred properties.
+ QDeclarativeV4Bindings *v4bindings;
+ QV8Bindings *v8bindings;
+
// Return the outermost id for obj, if any.
QString findObjectId(const QObject *obj) const;
diff --git a/src/declarative/qml/qdeclarativeexpression.cpp b/src/declarative/qml/qdeclarativeexpression.cpp
index d709d5ce26..27bd8f8147 100644
--- a/src/declarative/qml/qdeclarativeexpression.cpp
+++ b/src/declarative/qml/qdeclarativeexpression.cpp
@@ -113,32 +113,20 @@ void QDeclarativeExpressionPrivate::init(QDeclarativeContextData *ctxt, v8::Hand
extractExpressionFromFunction = true;
}
-void QDeclarativeExpressionPrivate::init(QDeclarativeContextData *ctxt, void *expr,
- QDeclarativeRefCount *rc,
+void QDeclarativeExpressionPrivate::init(QDeclarativeContextData *ctxt, const QString &expr, bool isRewritten,
QObject *me, const QString &srcUrl, int lineNumber)
{
url = srcUrl;
line = lineNumber;
- Q_ASSERT(!dataRef);
-
- dataRef = rc;
- if (dataRef) dataRef->addref();
-
- quint32 *exprData = (quint32 *)expr;
- QDeclarativeCompiledData *dd = (QDeclarativeCompiledData *)rc;
-
- expression = QString::fromRawData((QChar *)(exprData + 2), exprData[1]);
-
- int progIdx = *(exprData);
- bool isSharedProgram = progIdx & 0x80000000;
- progIdx &= 0x7FFFFFFF;
-
- v8function = evalFunction(ctxt, me, expression, url, line, &v8qmlscope);
-
- setUseSharedContext(false);
+ expression = expr;
- expressionFunctionValid = true;
+ if (!isRewritten) {
+ expressionFunctionValid = false;
+ } else {
+ v8function = evalFunction(ctxt, me, expression, url, line, &v8qmlscope);
+ expressionFunctionValid = true;
+ }
QDeclarativeAbstractExpression::setContext(ctxt);
setScopeObject(me);
@@ -214,14 +202,14 @@ QDeclarativeExpression::QDeclarativeExpression()
}
/*! \internal */
-QDeclarativeExpression::QDeclarativeExpression(QDeclarativeContextData *ctxt, void *expr,
- QDeclarativeRefCount *rc, QObject *me,
- const QString &url, int lineNumber,
+QDeclarativeExpression::QDeclarativeExpression(QDeclarativeContextData *ctxt,
+ QObject *object, const QString &expr, bool isRewritten,
+ const QString &url, int lineNumber,
QDeclarativeExpressionPrivate &dd)
: QObject(dd, 0)
{
Q_D(QDeclarativeExpression);
- d->init(ctxt, expr, rc, me, url, lineNumber);
+ d->init(ctxt, expr, isRewritten, object, url, lineNumber);
if (QDeclarativeExpression_notifyIdx == -1)
QDeclarativeExpression_notifyIdx = QDeclarativeExpression::staticMetaObject.indexOfMethod("_q_notify()");
@@ -263,7 +251,7 @@ QDeclarativeExpression::QDeclarativeExpression(const QDeclarativeScriptString &s
}
if (cdata)
- d->init(ctxtdata, (void*)cdata->datas.at(id).constData(), cdata, script.scopeObject(),
+ d->init(ctxtdata, cdata->primitives.at(id), cdata, script.scopeObject(),
cdata->name, script.d.data()->lineNumber);
else
defaultConstruction = true;
@@ -338,7 +326,7 @@ QDeclarativeExpression::QDeclarativeExpression(QDeclarativeContextData *ctxt, QO
new QDeclarativeExpression(ctxt, scope, &function, ...);
*/
QDeclarativeExpression::QDeclarativeExpression(QDeclarativeContextData *ctxt, QObject *scope, void *functionPtr,
- QDeclarativeExpressionPrivate &dd)
+ QDeclarativeExpressionPrivate &dd)
: QObject(dd, 0)
{
v8::Handle<v8::Function> function = *(v8::Handle<v8::Function> *)functionPtr;
@@ -476,7 +464,9 @@ v8::Local<v8::Value> QDeclarativeJavaScriptExpression::evaluate(v8::Handle<v8::F
bool lastCaptureProperties = ep->captureProperties;
QPODVector<QDeclarativeEnginePrivate::CapturedProperty> lastCapturedProperties;
ep->captureProperties = notifyOnValueChanged();
- ep->capturedProperties.copyAndClear(lastCapturedProperties);
+
+ if (ep->capturedProperties.count())
+ ep->capturedProperties.copyAndClear(lastCapturedProperties);
QDeclarativeContextData *lastSharedContext = 0;
QObject *lastSharedScope = 0;
@@ -532,7 +522,11 @@ v8::Local<v8::Value> QDeclarativeJavaScriptExpression::evaluate(v8::Handle<v8::F
ep->capturedProperties);
}
- lastCapturedProperties.copyAndClear(ep->capturedProperties);
+ if (lastCapturedProperties.count())
+ lastCapturedProperties.copyAndClear(ep->capturedProperties);
+ else
+ ep->capturedProperties.clear();
+
ep->captureProperties = lastCaptureProperties;
return result;
diff --git a/src/declarative/qml/qdeclarativeexpression.h b/src/declarative/qml/qdeclarativeexpression.h
index 217545e08e..edd93a1240 100644
--- a/src/declarative/qml/qdeclarativeexpression.h
+++ b/src/declarative/qml/qdeclarativeexpression.h
@@ -98,8 +98,8 @@ protected:
QDeclarativeExpressionPrivate &dd);
QDeclarativeExpression(QDeclarativeContextData *, QObject *, void *,
QDeclarativeExpressionPrivate &dd);
- QDeclarativeExpression(QDeclarativeContextData *, void *, QDeclarativeRefCount *rc,
- QObject *me, const QString &, int, QDeclarativeExpressionPrivate &dd);
+ QDeclarativeExpression(QDeclarativeContextData *, QObject *, const QString &, bool,
+ const QString &, int, QDeclarativeExpressionPrivate &dd);
private:
QDeclarativeExpression(QDeclarativeContextData *, QObject *, const QString &);
diff --git a/src/declarative/qml/qdeclarativeexpression_p.h b/src/declarative/qml/qdeclarativeexpression_p.h
index dcf47c3134..2a26c26700 100644
--- a/src/declarative/qml/qdeclarativeexpression_p.h
+++ b/src/declarative/qml/qdeclarativeexpression_p.h
@@ -193,7 +193,7 @@ public:
void init(QDeclarativeContextData *, const QString &, QObject *);
void init(QDeclarativeContextData *, v8::Handle<v8::Function>, QObject *);
- void init(QDeclarativeContextData *, void *, QDeclarativeRefCount *, QObject *, const QString &, int);
+ void init(QDeclarativeContextData *, const QString &, bool, QObject *, const QString &, int);
QVariant value(QObject *secondaryScope = 0, bool *isUndefined = 0);
diff --git a/src/declarative/qml/qdeclarativeinstruction.cpp b/src/declarative/qml/qdeclarativeinstruction.cpp
index 79a2a1cc34..4f64e4e2ba 100644
--- a/src/declarative/qml/qdeclarativeinstruction.cpp
+++ b/src/declarative/qml/qdeclarativeinstruction.cpp
@@ -168,15 +168,21 @@ void QDeclarativeCompiledData::dump(QDeclarativeInstruction *instr, int idx)
case QDeclarativeInstruction::AssignCustomType:
qWarning().nospace() << idx << "\t\t" << "ASSIGN_CUSTOMTYPE\t" << instr->assignCustomType.propertyIndex << "\t" << instr->assignCustomType.primitive << "\t" << instr->assignCustomType.type;
break;
+ case QDeclarativeInstruction::InitV8Bindings:
+ qWarning().nospace() << idx << "\t\t" << "INIT_V8_BINDING\t" << instr->initV8Bindings.program << "\t" << instr->initV8Bindings.line;
+ break;
case QDeclarativeInstruction::StoreBinding:
qWarning().nospace() << idx << "\t\t" << "STORE_BINDING\t" << instr->assignBinding.property << "\t" << instr->assignBinding.value << "\t" << instr->assignBinding.context;
break;
case QDeclarativeInstruction::StoreBindingOnAlias:
qWarning().nospace() << idx << "\t\t" << "STORE_BINDING_ALIAS\t" << instr->assignBinding.property << "\t" << instr->assignBinding.value << "\t" << instr->assignBinding.context;
break;
- case QDeclarativeInstruction::StoreCompiledBinding:
+ case QDeclarativeInstruction::StoreV4Binding:
qWarning().nospace() << idx << "\t\t" << "STORE_COMPILED_BINDING\t" << instr->assignBinding.property << "\t" << instr->assignBinding.value << "\t" << instr->assignBinding.context;
break;
+ case QDeclarativeInstruction::StoreV8Binding:
+ qWarning().nospace() << idx << "\t\t" << "STORE_V8_BINDING\t" << instr->assignBinding.property << "\t" << instr->assignBinding.value << "\t" << instr->assignBinding.context;
+ break;
case QDeclarativeInstruction::StoreValueSource:
qWarning().nospace() << idx << "\t\t" << "STORE_VALUE_SOURCE\t" << instr->assignValueSource.property << "\t" << instr->assignValueSource.castValue;
break;
diff --git a/src/declarative/qml/qdeclarativeinstruction_p.h b/src/declarative/qml/qdeclarativeinstruction_p.h
index 3db55a66d3..5c51ea8d5f 100644
--- a/src/declarative/qml/qdeclarativeinstruction_p.h
+++ b/src/declarative/qml/qdeclarativeinstruction_p.h
@@ -95,9 +95,11 @@ QT_BEGIN_NAMESPACE
F(StoreImportedScript, storeScript) \
F(StoreScriptString, storeScriptString) \
F(BeginObject, begin) \
+ F(InitV8Bindings, initV8Bindings) \
F(StoreBinding, assignBinding) \
F(StoreBindingOnAlias, assignBinding) \
- F(StoreCompiledBinding, assignBinding) \
+ F(StoreV4Binding, assignBinding) \
+ F(StoreV8Binding, assignBinding) \
F(StoreValueSource, assignValueSource) \
F(StoreValueInterceptor, assignValueInterceptor) \
F(StoreObjectQList, common) \
@@ -182,6 +184,11 @@ union QDeclarativeInstruction
int owner;
int castValue;
};
+ struct instr_initV8Bindings {
+ QML_INSTR_HEADER
+ int program;
+ int line;
+ };
struct instr_assignBinding {
QML_INSTR_HEADER
unsigned int property;
@@ -411,6 +418,7 @@ union QDeclarativeInstruction
instr_setId setId;
instr_assignValueSource assignValueSource;
instr_assignValueInterceptor assignValueInterceptor;
+ instr_initV8Bindings initV8Bindings;
instr_assignBinding assignBinding;
instr_fetch fetch;
instr_fetchValue fetchValue;
diff --git a/src/declarative/qml/qdeclarativerefcount_p.h b/src/declarative/qml/qdeclarativerefcount_p.h
index 3bbb7b0ff3..381327098c 100644
--- a/src/declarative/qml/qdeclarativerefcount_p.h
+++ b/src/declarative/qml/qdeclarativerefcount_p.h
@@ -73,6 +73,73 @@ private:
int refCount;
};
+template<class T>
+class QDeclarativeRefPointer
+{
+public:
+ inline QDeclarativeRefPointer();
+ inline QDeclarativeRefPointer(T *);
+ inline QDeclarativeRefPointer(const QDeclarativeRefPointer<T> &);
+ inline ~QDeclarativeRefPointer();
+
+ inline QDeclarativeRefPointer<T> &operator=(const QDeclarativeRefPointer<T> &o);
+ inline QDeclarativeRefPointer<T> &operator=(T *);
+
+ inline bool isNull() const { return !o; }
+
+ inline T* operator->() const { return o; }
+ inline T& operator*() const { return *o; }
+ inline operator T*() const { return o; }
+ inline T* data() const { return o; }
+
+private:
+ T *o;
+};
+
+template<class T>
+QDeclarativeRefPointer<T>::QDeclarativeRefPointer()
+: o(0)
+{
+}
+
+template<class T>
+QDeclarativeRefPointer<T>::QDeclarativeRefPointer(T *o)
+: o(o)
+{
+ if (o) o->addref();
+}
+
+template<class T>
+QDeclarativeRefPointer<T>::QDeclarativeRefPointer(const QDeclarativeRefPointer<T> &other)
+: o(other.o)
+{
+ if (o) o->addref();
+}
+
+template<class T>
+QDeclarativeRefPointer<T>::~QDeclarativeRefPointer()
+{
+ if (o) o->release();
+}
+
+template<class T>
+QDeclarativeRefPointer<T> &QDeclarativeRefPointer<T>::operator=(const QDeclarativeRefPointer<T> &other)
+{
+ if (other.o) other.o->addref();
+ if (o) o->release();
+ o = other.o;
+ return *this;
+}
+
+template<class T>
+QDeclarativeRefPointer<T> &QDeclarativeRefPointer<T>::operator=(T *other)
+{
+ if (other) other->addref();
+ if (o) o->release();
+ o = other;
+ return *this;
+}
+
QT_END_NAMESPACE
QT_END_HEADER
diff --git a/src/declarative/qml/qdeclarativevme.cpp b/src/declarative/qml/qdeclarativevme.cpp
index 4d5fa3607c..377ef9db16 100644
--- a/src/declarative/qml/qdeclarativevme.cpp
+++ b/src/declarative/qml/qdeclarativevme.cpp
@@ -58,6 +58,7 @@
#include "private/qdeclarativebinding_p_p.h"
#include "private/qdeclarativecontext_p.h"
#include "private/qdeclarativev4bindings_p.h"
+#include "private/qv8bindings_p.h"
#include "private/qdeclarativeglobal_p.h"
#include "qdeclarativescriptstring.h"
#include "qdeclarativescriptstring_p.h"
@@ -191,8 +192,10 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEStack<QObject *> &stack,
parserStatus = QDeclarativeEnginePrivate::SimpleList<QDeclarativeParserStatus>(instr.parserStatusSize);
if (instr.contextCache != -1)
ctxt->setIdPropertyData(comp->contextCaches.at(instr.contextCache));
- if (instr.compiledBinding != -1)
- ctxt->optimizedBindings = new QDeclarativeV4Bindings(datas.at(instr.compiledBinding).constData(), ctxt);
+ if (instr.compiledBinding != -1) {
+ const char *v4data = datas.at(instr.compiledBinding).constData();
+ ctxt->v4bindings = new QDeclarativeV4Bindings(v4data, ctxt);
+ }
QML_END_INSTR(Init)
QML_BEGIN_INSTR(Done)
@@ -657,6 +660,10 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEStack<QObject *> &stack,
status->classBegin();
QML_END_INSTR(BeginObject)
+ QML_BEGIN_INSTR(InitV8Bindings)
+ ctxt->v8bindings = new QV8Bindings(primitives.at(instr.program), instr.line, comp, ctxt);
+ QML_END_INSTR(InitV8Bindings)
+
QML_BEGIN_INSTR(StoreBinding)
QObject *target =
stack.at(stack.count() - 1 - instr.owner);
@@ -671,7 +678,8 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEStack<QObject *> &stack,
if ((stack.count() - instr.owner) == 1 && bindingSkipList.testBit(coreIndex))
break;
- QDeclarativeBinding *bind = new QDeclarativeBinding((void *)datas.at(instr.value).constData(), comp, context, ctxt, comp->name, instr.line, 0);
+ QDeclarativeBinding *bind = new QDeclarativeBinding(primitives.at(instr.value), true,
+ context, ctxt, comp->name, instr.line);
bindValues.append(bind);
bind->m_mePtr = &bindValues.values[bindValues.count - 1];
bind->setTarget(mp);
@@ -693,7 +701,8 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEStack<QObject *> &stack,
if ((stack.count() - instr.owner) == 1 && bindingSkipList.testBit(coreIndex))
break;
- QDeclarativeBinding *bind = new QDeclarativeBinding((void *)datas.at(instr.value).constData(), comp, context, ctxt, comp->name, instr.line, 0);
+ QDeclarativeBinding *bind = new QDeclarativeBinding(primitives.at(instr.value), true,
+ context, ctxt, comp->name, instr.line);
bindValues.append(bind);
bind->m_mePtr = &bindValues.values[bindValues.count - 1];
bind->setTarget(mp);
@@ -702,7 +711,7 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEStack<QObject *> &stack,
if (old) { old->destroy(); }
QML_END_INSTR(StoreBindingOnAlias)
- QML_BEGIN_INSTR(StoreCompiledBinding)
+ QML_BEGIN_INSTR(StoreV4Binding)
QObject *target =
stack.at(stack.count() - 1 - instr.owner);
QObject *scope =
@@ -713,11 +722,32 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEStack<QObject *> &stack,
break;
QDeclarativeAbstractBinding *binding =
- ctxt->optimizedBindings->configBinding(instr.value, target, scope, property);
+ ctxt->v4bindings->configBinding(instr.value, target, scope, property);
bindValues.append(binding);
binding->m_mePtr = &bindValues.values[bindValues.count - 1];
binding->addToObject(target, property);
- QML_END_INSTR(StoreCompiledBinding)
+ QML_END_INSTR(StoreV4Binding)
+
+ QML_BEGIN_INSTR(StoreV8Binding)
+ QObject *target =
+ stack.at(stack.count() - 1 - instr.owner);
+ QObject *scope =
+ stack.at(stack.count() - 1 - instr.context);
+
+ QDeclarativeProperty mp =
+ QDeclarativePropertyPrivate::restore(datas.at(instr.property), target, ctxt);
+
+ int coreIndex = mp.index();
+
+ if ((stack.count() - instr.owner) == 1 && bindingSkipList.testBit(coreIndex))
+ break;
+
+ QDeclarativeAbstractBinding *binding =
+ ctxt->v8bindings->configBinding(instr.value, target, scope, mp, instr.line);
+ bindValues.append(binding);
+ binding->m_mePtr = &bindValues.values[bindValues.count - 1];
+ binding->addToObject(target, QDeclarativePropertyPrivate::bindingIndex(mp));
+ QML_END_INSTR(StoreV8Binding)
QML_BEGIN_INSTR(StoreValueSource)
QObject *obj = stack.pop();
diff --git a/src/declarative/qml/v4/qdeclarativev4bindings.cpp b/src/declarative/qml/v4/qdeclarativev4bindings.cpp
index 0ee7d4dc7d..a7946d46db 100644
--- a/src/declarative/qml/v4/qdeclarativev4bindings.cpp
+++ b/src/declarative/qml/v4/qdeclarativev4bindings.cpp
@@ -315,6 +315,7 @@ void QDeclarativeV4BindingsPrivate::Binding::destroy()
enabled = false;
removeFromObject();
clear();
+ removeError();
parent->q_func()->release();
}
diff --git a/src/declarative/qml/v8/qv8bindings.cpp b/src/declarative/qml/v8/qv8bindings.cpp
new file mode 100644
index 0000000000..424d06f083
--- /dev/null
+++ b/src/declarative/qml/v8/qv8bindings.cpp
@@ -0,0 +1,235 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** 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.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qv8bindings_p.h"
+
+#include <private/qv8_p.h>
+#include <private/qdeclarativebinding_p.h>
+#include <private/qdeclarativecompiler_p.h>
+#include <private/qdeclarativebinding_p_p.h>
+#include <private/qdeclarativeexpression_p.h>
+#include <private/qobject_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QV8BindingsPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QV8Bindings)
+public:
+ QV8BindingsPrivate();
+
+ struct Binding : public QDeclarativeJavaScriptExpression,
+ public QDeclarativeAbstractBinding {
+ Binding();
+
+ // Inherited from QDeclarativeAbstractBinding
+ virtual void setEnabled(bool, QDeclarativePropertyPrivate::WriteFlags flags);
+ virtual void update(QDeclarativePropertyPrivate::WriteFlags flags);
+ virtual void destroy();
+
+ int index:30;
+ bool enabled:1;
+ bool updating:1;
+ int line;
+ QDeclarativeProperty property;
+ QV8BindingsPrivate *parent;
+ };
+
+ QUrl url;
+ int bindingsCount;
+ Binding *bindings;
+ v8::Persistent<v8::Array> functions;
+};
+
+QV8BindingsPrivate::QV8BindingsPrivate()
+: bindingsCount(0), bindings(0)
+{
+}
+
+QV8BindingsPrivate::Binding::Binding()
+: index(-1), enabled(false), updating(false), line(-1), parent(0)
+{
+}
+
+void QV8BindingsPrivate::Binding::setEnabled(bool e, QDeclarativePropertyPrivate::WriteFlags flags)
+{
+ if (enabled != e) {
+ enabled = e;
+
+ if (e) update(flags);
+ }
+}
+
+void QV8BindingsPrivate::Binding::update(QDeclarativePropertyPrivate::WriteFlags flags)
+{
+ if (!enabled)
+ return;
+
+ QDeclarativeContextData *context = QDeclarativeAbstractExpression::context();
+ if (!context || !context->isValid())
+ return;
+
+ if (!updating) {
+ updating = true;
+ QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(context->engine);
+
+ bool isUndefined = false;
+
+ QDeclarativeDeleteWatcher watcher(this);
+ ep->referenceScarceResources();
+
+ v8::HandleScope handle_scope;
+ v8::Context::Scope scope(ep->v8engine.context());
+ v8::Local<v8::Value> result = evaluate(v8::Handle<v8::Function>::Cast(parent->functions->Get(index)),
+ &isUndefined);
+
+ bool needsErrorData = false;
+ if (!watcher.wasDeleted() && !error.isValid())
+ needsErrorData = !QDeclarativeBindingPrivate::writeBindingResult(this, property, result,
+ isUndefined, flags);
+
+ if (!watcher.wasDeleted()) {
+
+ if (needsErrorData) {
+ QUrl url = QUrl(parent->url);
+ if (url.isEmpty()) url = QUrl(QLatin1String("<Unknown File>"));
+
+ error.setUrl(url);
+ error.setLine(line);
+ error.setColumn(-1);
+ }
+
+ if (error.isValid()) {
+ if (!addError(ep)) ep->warning(error);
+ } else {
+ removeError();
+ }
+
+ updating = false;
+ }
+
+ ep->dereferenceScarceResources();
+
+ } else {
+ QDeclarativeBindingPrivate::printBindingLoopError(property);
+ }
+}
+
+void QV8BindingsPrivate::Binding::destroy()
+{
+ enabled = false;
+ removeFromObject();
+ clear();
+ removeError();
+ parent->q_func()->release();
+}
+
+QV8Bindings::QV8Bindings(const QString &program, int line,
+ QDeclarativeCompiledData *compiled,
+ QDeclarativeContextData *context)
+: QObject(*(new QV8BindingsPrivate))
+{
+ Q_D(QV8Bindings);
+
+ QV8Engine *engine = QDeclarativeEnginePrivate::getV8Engine(context->engine);
+
+ if (compiled->v8bindings.IsEmpty()) {
+ v8::HandleScope handle_scope;
+ v8::Context::Scope scope(engine->context());
+
+ v8::Local<v8::Script> script = engine->qmlModeCompile(program, compiled->name, line);
+ v8::Local<v8::Value> result = script->Run(engine->contextWrapper()->sharedContext());
+
+ if (result->IsArray())
+ compiled->v8bindings = qPersistentNew(v8::Local<v8::Array>::Cast(result));
+ }
+
+ d->url = compiled->url;
+ d->functions = qPersistentNew(compiled->v8bindings);
+ d->bindingsCount = d->functions->Length();
+ d->bindings = new QV8BindingsPrivate::Binding[d->bindingsCount];
+
+ setContext(context);
+}
+
+QV8Bindings::~QV8Bindings()
+{
+ Q_D(QV8Bindings);
+ qPersistentDispose(d->functions);
+
+ delete [] d->bindings;
+ d->bindings = 0;
+ d->bindingsCount = 0;
+}
+
+QDeclarativeAbstractBinding *QV8Bindings::configBinding(int index, QObject *target, QObject *scope,
+ const QDeclarativeProperty &property, int line)
+{
+ Q_D(QV8Bindings);
+ QV8BindingsPrivate::Binding *rv = d->bindings + index;
+
+ rv->line = line;
+ rv->index = index;
+ rv->property = property;
+ rv->setContext(context());
+ rv->setScopeObject(scope);
+ rv->setUseSharedContext(true);
+ rv->setNotifyOnValueChanged(true);
+ rv->setNotifyObject(this, index);
+ rv->parent = d;
+
+ addref(); // This is decremented in Binding::destroy()
+
+ return rv;
+}
+
+int QV8Bindings::qt_metacall(QMetaObject::Call c, int id, void **)
+{
+ Q_D(QV8Bindings);
+
+ if (c == QMetaObject::InvokeMetaMethod) {
+ QV8BindingsPrivate::Binding *binding = d->bindings + id;
+ binding->update(QDeclarativePropertyPrivate::DontRemoveBinding);
+ }
+ return -1;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/v8/qv8bindings_p.h b/src/declarative/qml/v8/qv8bindings_p.h
new file mode 100644
index 0000000000..e99e3c834d
--- /dev/null
+++ b/src/declarative/qml/v8/qv8bindings_p.h
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** 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.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** 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.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QV8BINDINGS_P_H
+#define QV8BINDINGS_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "private/qdeclarativeexpression_p.h"
+#include "private/qdeclarativebinding_p.h"
+#include "private/qdeclarativev4instruction_p.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarativeCompiledData;
+
+class QV8BindingsPrivate;
+class QV8Bindings : public QObject,
+ public QDeclarativeAbstractExpression,
+ public QDeclarativeRefCount
+{
+public:
+ QV8Bindings(const QString &program, int line,
+ QDeclarativeCompiledData *compiled,
+ QDeclarativeContextData *context);
+ virtual ~QV8Bindings();
+
+ QDeclarativeAbstractBinding *configBinding(int index, QObject *target, QObject *scope,
+ const QDeclarativeProperty &prop, int line);
+
+protected:
+ int qt_metacall(QMetaObject::Call, int, void **);
+
+private:
+ Q_DISABLE_COPY(QV8Bindings)
+ Q_DECLARE_PRIVATE(QV8Bindings)
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QV8BINDINGS_P_H
+
+
diff --git a/src/declarative/qml/v8/v8.pri b/src/declarative/qml/v8/v8.pri
index d91acd7759..61e0184884 100644
--- a/src/declarative/qml/v8/v8.pri
+++ b/src/declarative/qml/v8/v8.pri
@@ -14,6 +14,7 @@ HEADERS += \
$$PWD/qv8valuetypewrapper_p.h \
$$PWD/qv8include_p.h \
$$PWD/qv8worker_p.h \
+ $$PWD/qv8bindings_p.h \
$$PWD/../../../3rdparty/javascriptcore/DateMath.h \
SOURCES += \
@@ -28,5 +29,6 @@ SOURCES += \
$$PWD/qv8valuetypewrapper.cpp \
$$PWD/qv8include.cpp \
$$PWD/qv8worker.cpp \
+ $$PWD/qv8bindings.cpp \
$$PWD/../../../3rdparty/javascriptcore/DateMath.cpp \