aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/compiler/qv4compiler.cpp
diff options
context:
space:
mode:
authorYulong Bai <yulong.bai@qt.io>2018-06-15 14:44:19 +0200
committerLars Knoll <lars.knoll@qt.io>2018-06-26 10:03:56 +0000
commit74f4065caa7254b0e30afa955aa59092024decdb (patch)
treeb9b5555807ebfb2e7b6a80a56aec8785b4066ae1 /src/qml/compiler/qv4compiler.cpp
parentc9fa5b8071f4a32afd05cc9fa5cd8ab28e60dc55 (diff)
Add basic support for EcmaScript classes
Most of the class creation is done inside the runtime in the CreateClass method. Added a corresponding instruction to the interpreter and jit. The compiled data now contains an array of classes containing the compile time generated layout of the class. Currently, classes without an explicit constructor and classes with inheritance are not supported. Done-with: Yulong Bai <yulong.bai@qt.io> Change-Id: I0185dcc1e3b0b8f44deff74e44a8262fc646aa9e Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src/qml/compiler/qv4compiler.cpp')
-rw-r--r--src/qml/compiler/qv4compiler.cpp70
1 files changed, 64 insertions, 6 deletions
diff --git a/src/qml/compiler/qv4compiler.cpp b/src/qml/compiler/qv4compiler.cpp
index d5a02a3ac8..eb38ba564d 100644
--- a/src/qml/compiler/qv4compiler.cpp
+++ b/src/qml/compiler/qv4compiler.cpp
@@ -227,34 +227,41 @@ QV4::CompiledData::Unit *QV4::Compiler::JSUnitGenerator::generateUnit(GeneratorO
registerString(c->locals.at(i));
}
- Q_ALLOCA_VAR(quint32_le, blockAndFunctionOffsets, (module->functions.size() + module->blocks.size()) * sizeof(quint32_le));
+ Q_ALLOCA_VAR(quint32_le, blockClassAndFunctionOffsets, (module->functions.size() + module->classes.size() + module->blocks.size()) * sizeof(quint32_le));
uint jsClassDataOffset = 0;
char *dataPtr;
CompiledData::Unit *unit;
{
- QV4::CompiledData::Unit tempHeader = generateHeader(option, blockAndFunctionOffsets, &jsClassDataOffset);
+ QV4::CompiledData::Unit tempHeader = generateHeader(option, blockClassAndFunctionOffsets, &jsClassDataOffset);
dataPtr = reinterpret_cast<char *>(malloc(tempHeader.unitSize));
memset(dataPtr, 0, tempHeader.unitSize);
memcpy(&unit, &dataPtr, sizeof(CompiledData::Unit*));
memcpy(unit, &tempHeader, sizeof(tempHeader));
}
- memcpy(dataPtr + unit->offsetToFunctionTable, blockAndFunctionOffsets, unit->functionTableSize * sizeof(quint32_le));
- memcpy(dataPtr + unit->offsetToBlockTable, blockAndFunctionOffsets + unit->functionTableSize, unit->blockTableSize * sizeof(quint32_le));
+ memcpy(dataPtr + unit->offsetToFunctionTable, blockClassAndFunctionOffsets, unit->functionTableSize * sizeof(quint32_le));
+ memcpy(dataPtr + unit->offsetToClassTable, blockClassAndFunctionOffsets + unit->functionTableSize, unit->classTableSize * sizeof(quint32_le));
+ memcpy(dataPtr + unit->offsetToBlockTable, blockClassAndFunctionOffsets + unit->functionTableSize + unit->classTableSize, unit->blockTableSize * sizeof(quint32_le));
for (int i = 0; i < module->functions.size(); ++i) {
Context *function = module->functions.at(i);
if (function == module->rootContext)
unit->indexOfRootFunction = i;
- writeFunction(dataPtr + blockAndFunctionOffsets[i], function);
+ writeFunction(dataPtr + blockClassAndFunctionOffsets[i], function);
+ }
+
+ for (int i = 0; i < module->classes.size(); ++i) {
+ const Class &c = module->classes.at(i);
+
+ writeClass(dataPtr + blockClassAndFunctionOffsets[i + module->functions.size()], c);
}
for (int i = 0; i < module->blocks.size(); ++i) {
Context *block = module->blocks.at(i);
- writeBlock(dataPtr + blockAndFunctionOffsets[i + module->functions.size()], block);
+ writeBlock(dataPtr + blockClassAndFunctionOffsets[i + module->classes.size() + module->functions.size()], block);
}
CompiledData::Lookup *lookupsToWrite = reinterpret_cast<CompiledData::Lookup*>(dataPtr + unit->offsetToLookupTable);
@@ -389,6 +396,45 @@ void QV4::Compiler::JSUnitGenerator::writeFunction(char *f, QV4::Compiler::Conte
memcpy(f + function->codeOffset, irFunction->code.constData(), irFunction->code.size());
}
+void QV4::Compiler::JSUnitGenerator::writeClass(char *b, const QV4::Compiler::Class &c)
+{
+ QV4::CompiledData::Class *cls = reinterpret_cast<QV4::CompiledData::Class *>(b);
+
+ quint32 currentOffset = sizeof(QV4::CompiledData::Class);
+
+ QVector<Class::Method> allMethods = c.staticMethods;
+ allMethods += c.methods;
+
+ cls->constructorFunction = c.constructorIndex;
+ cls->nameIndex = getStringId(c.name);
+ cls->nMethods = c.methods.size();
+ cls->nStaticMethods = c.staticMethods.size();
+ cls->nameTableOffset = currentOffset;
+ quint32_le *names = reinterpret_cast<quint32_le *>(b + currentOffset);
+ currentOffset += allMethods.size() * sizeof(quint32);
+ cls->methodTableOffset = currentOffset;
+ quint32_le *methods = reinterpret_cast<quint32_le *>(b + currentOffset);
+ currentOffset += cls->nMethods * sizeof(quint32);
+
+ // write methods
+ for (int i = 0; i < allMethods.size(); ++i) {
+ names[i] = getStringId(allMethods.at(i).name);
+ methods[i] = allMethods.at(i).functionIndex;
+ // ### fix getter and setter methods
+ }
+
+ static const bool showCode = qEnvironmentVariableIsSet("QV4_SHOW_BYTECODE");
+ if (showCode) {
+ qDebug() << "=== Class " << stringForIndex(cls->nameIndex) << "static methods" << cls->nStaticMethods << "methods" << cls->nMethods;
+ qDebug() << " constructor:" << cls->constructorFunction;
+ for (uint i = 0; i < cls->nStaticMethods; ++i)
+ qDebug() << " " << i << ": static" << stringForIndex(cls->nameTable()[i]);
+ for (uint i = 0; i < cls->nMethods; ++i)
+ qDebug() << " " << i << ": " << stringForIndex(cls->nameTable()[cls->nStaticMethods + i]);
+ qDebug();
+ }
+}
+
void QV4::Compiler::JSUnitGenerator::writeBlock(char *b, QV4::Compiler::Context *irBlock) const
{
QV4::CompiledData::Block *block = reinterpret_cast<QV4::CompiledData::Block *>(b);
@@ -433,6 +479,10 @@ QV4::CompiledData::Unit QV4::Compiler::JSUnitGenerator::generateHeader(QV4::Comp
unit.offsetToFunctionTable = nextOffset;
nextOffset += unit.functionTableSize * sizeof(uint);
+ unit.classTableSize = module->classes.size();
+ unit.offsetToClassTable = nextOffset;
+ nextOffset += unit.classTableSize * sizeof(uint);
+
unit.blockTableSize = module->blocks.size();
unit.offsetToBlockTable = nextOffset;
nextOffset += unit.blockTableSize * sizeof(uint);
@@ -472,6 +522,14 @@ QV4::CompiledData::Unit QV4::Compiler::JSUnitGenerator::generateHeader(QV4::Comp
}
blockAndFunctionOffsets += module->functions.size();
+ for (int i = 0; i < module->classes.size(); ++i) {
+ const Class &c = module->classes.at(i);
+ blockAndFunctionOffsets[i] = nextOffset;
+
+ nextOffset += QV4::CompiledData::Class::calculateSize(c.staticMethods.size(), c.methods.size());
+ }
+ blockAndFunctionOffsets += module->classes.size();
+
for (int i = 0; i < module->blocks.size(); ++i) {
Context *c = module->blocks.at(i);
blockAndFunctionOffsets[i] = nextOffset;