aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/compiler/qv4compileddata.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/compiler/qv4compileddata.cpp')
-rw-r--r--src/qml/compiler/qv4compileddata.cpp85
1 files changed, 84 insertions, 1 deletions
diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp
index 8f5ea44599..8f8d374e24 100644
--- a/src/qml/compiler/qv4compileddata.cpp
+++ b/src/qml/compiler/qv4compileddata.cpp
@@ -476,7 +476,90 @@ bool CompilationUnit::saveCodeToDisk(QIODevice *device, const Unit *unit, QStrin
Unit *CompilationUnit::createUnitData(QmlIR::Document *irDocument)
{
- return irDocument->jsGenerator.generateUnit(QV4::Compiler::JSUnitGenerator::GenerateWithoutStringTable);
+ if (!irDocument->javaScriptCompilationUnit->data)
+ return irDocument->jsGenerator.generateUnit(QV4::Compiler::JSUnitGenerator::GenerateWithoutStringTable);
+
+ QQmlRefPointer<QV4::CompiledData::CompilationUnit> compilationUnit = irDocument->javaScriptCompilationUnit;
+ QV4::CompiledData::Unit *jsUnit = const_cast<QV4::CompiledData::Unit*>(irDocument->javaScriptCompilationUnit->data);
+
+ QV4::Compiler::StringTableGenerator &stringTable = irDocument->jsGenerator.stringTable;
+
+ // Collect signals that have had a change in signature (from onClicked to onClicked(mouse) for example)
+ // and now need fixing in the QV4::CompiledData. Also register strings at the same time, to finalize
+ // the string table.
+ QVector<quint32> changedSignals;
+ QVector<QQmlJS::AST::FormalParameterList*> changedSignalParameters;
+ for (QmlIR::Object *o: qAsConst(irDocument->objects)) {
+ for (QmlIR::Binding *binding = o->firstBinding(); binding; binding = binding->next) {
+ if (!(binding->flags & QV4::CompiledData::Binding::IsSignalHandlerExpression))
+ continue;
+
+ quint32 functionIndex = binding->value.compiledScriptIndex;
+ QmlIR::CompiledFunctionOrExpression *foe = o->functionsAndExpressions->slowAt(functionIndex);
+ if (!foe)
+ continue;
+
+ // save absolute index
+ changedSignals << o->runtimeFunctionIndices.at(functionIndex);
+
+ Q_ASSERT(foe->node);
+ Q_ASSERT(QQmlJS::AST::cast<QQmlJS::AST::FunctionDeclaration*>(foe->node));
+
+ QQmlJS::AST::FormalParameterList *parameters = QQmlJS::AST::cast<QQmlJS::AST::FunctionDeclaration*>(foe->node)->formals;
+ changedSignalParameters << parameters;
+
+ for (; parameters; parameters = parameters->next)
+ stringTable.registerString(parameters->name.toString());
+ }
+ }
+
+ QVector<quint32> signalParameterNameTable;
+ quint32 signalParameterNameTableOffset = jsUnit->unitSize;
+
+ // Update signal signatures
+ if (!changedSignals.isEmpty()) {
+ if (jsUnit == compilationUnit->data) {
+ char *unitCopy = (char*)malloc(jsUnit->unitSize);
+ memcpy(unitCopy, jsUnit, jsUnit->unitSize);
+ jsUnit = reinterpret_cast<QV4::CompiledData::Unit*>(unitCopy);
+ }
+
+ for (int i = 0; i < changedSignals.count(); ++i) {
+ const uint functionIndex = changedSignals.at(i);
+ // The data is now read-write due to the copy above, so the const_cast is ok.
+ QV4::CompiledData::Function *function = const_cast<QV4::CompiledData::Function *>(jsUnit->functionAt(functionIndex));
+ Q_ASSERT(function->nFormals == quint32(0));
+
+ function->formalsOffset = signalParameterNameTableOffset - jsUnit->functionOffsetTable()[functionIndex];
+
+ for (QQmlJS::AST::FormalParameterList *parameters = changedSignalParameters.at(i);
+ parameters; parameters = parameters->next) {
+ signalParameterNameTable.append(stringTable.getStringId(parameters->name.toString()));
+ function->nFormals = function->nFormals + 1;
+ }
+
+ // Hack to ensure an activation is created.
+ function->flags |= QV4::CompiledData::Function::HasCatchOrWith | QV4::CompiledData::Function::HasDirectEval;
+
+ signalParameterNameTableOffset += function->nFormals * sizeof(quint32);
+ }
+ }
+
+ if (!signalParameterNameTable.isEmpty()) {
+ Q_ASSERT(jsUnit != compilationUnit->data);
+ const uint signalParameterTableSize = signalParameterNameTable.count() * sizeof(quint32);
+ uint newSize = jsUnit->unitSize + signalParameterTableSize;
+ const uint oldSize = jsUnit->unitSize;
+ char *unitWithSignalParameters = (char*)realloc(jsUnit, newSize);
+ memcpy(unitWithSignalParameters + oldSize, signalParameterNameTable.constData(), signalParameterTableSize);
+ jsUnit = reinterpret_cast<QV4::CompiledData::Unit*>(unitWithSignalParameters);
+ jsUnit->unitSize = newSize;
+ }
+
+ if (jsUnit != compilationUnit->data)
+ jsUnit->flags &= ~QV4::CompiledData::Unit::StaticData;
+
+ return jsUnit;
}
QString Binding::valueAsString(const Unit *unit) const