aboutsummaryrefslogtreecommitdiffstats
path: root/src
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 /src
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.
Diffstat (limited to 'src')
-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 \