aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/compiler/qv4codegen.cpp
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2017-06-19 14:04:37 +0200
committerErik Verbruggen <erik.verbruggen@qt.io>2017-06-20 10:08:36 +0000
commit2a612d76550e37d292e724a6873ef31fbb2f6710 (patch)
tree67a9b8c1ae41998de7bcb2f9720fd2029eff863e /src/qml/compiler/qv4codegen.cpp
parent809d624d0f70874e9acc4617b29f3d97cb27d131 (diff)
Handle loads/stores of References better
This is still not ideal and creates too many move instructions, but at least it avoids repeated loads and stores into temps to the largest part. Change-Id: I5286a6598461b229aa12cf88b711922e69f46b70 Reviewed-by: Erik Verbruggen <erik.verbruggen@qt.io>
Diffstat (limited to 'src/qml/compiler/qv4codegen.cpp')
-rw-r--r--src/qml/compiler/qv4codegen.cpp143
1 files changed, 94 insertions, 49 deletions
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp
index a484892b7c..52bffa53bc 100644
--- a/src/qml/compiler/qv4codegen.cpp
+++ b/src/qml/compiler/qv4codegen.cpp
@@ -2320,6 +2320,7 @@ bool Codegen::visit(TypeOfExpression *ast)
instr.result = _expr.result.asLValue();
bytecodeGenerator->addInstruction(instr);
}
+
return false;
}
@@ -3202,6 +3203,47 @@ void RuntimeCodegen::throwReferenceError(const AST::SourceLocation &loc, const Q
#endif // V4_BOOTSTRAP
+Codegen::Reference::Reference(const Codegen::Reference &other)
+{
+ *this = other;
+}
+
+Codegen::Reference &Codegen::Reference::operator =(const Reference &other)
+{
+ other.writeBack();
+
+ type = other.type;
+ base = other.base;
+
+ switch (type) {
+ case Invalid:
+ break;
+ case Temp:
+ case Local:
+ case Argument:
+ break;
+ case Name:
+ case Member:
+ nameIndex = other.nameIndex;
+ break;
+ case Subscript:
+ subscript = other.subscript;
+ break;
+ case Const:
+ constant = other.constant;
+ break;
+ case Closure:
+ closureId = other.closureId;
+ break;
+ }
+
+ // keep loaded reference
+ tempIndex = other.tempIndex;
+ needsWriteBack = false;
+ codegen = other.codegen;
+ return *this;
+}
+
Codegen::Reference::~Reference()
{
writeBack();
@@ -3253,20 +3295,17 @@ void Codegen::Reference::storeConsume(Reference &r) const
void Codegen::Reference::store(const Reference &r) const
{
Q_ASSERT(type != Const);
+ Q_ASSERT(!needsWriteBack);
if (*this == r)
return;
- writeBack();
-
Moth::Param b = base;
if (!isSimple()) {
if (tempIndex < 0)
tempIndex = codegen->bytecodeGenerator->newTemp();
if (!r.isSimple() && r.tempIndex == -1) {
- r.tempIndex = tempIndex;
- r.asRValue(); // trigger load
- r.tempIndex = -1;
+ r.load(tempIndex);
needsWriteBack = true;
return;
}
@@ -3291,56 +3330,18 @@ void Codegen::Reference::store(const Reference &r) const
Moth::Param Codegen::Reference::asRValue() const
{
- writeBack(); // because of possible side effects
+ Q_ASSERT(!needsWriteBack);
Q_ASSERT(type != Invalid);
if (type <= Argument)
return base;
// need a temp to hold the value
- if (tempIndex < 0)
- tempIndex = codegen->bytecodeGenerator->newTemp();
- Moth::Param temp = Moth::Param::createTemp(tempIndex);
- if (type == Const) {
- Instruction::MoveConst move;
- move.source = constant;
- move.result = temp;
- codegen->bytecodeGenerator->addInstruction(move);
- } else if (type == Name) {
- Instruction::LoadName load;
- load.name = nameIndex;
- load.result = temp;
- codegen->bytecodeGenerator->addInstruction(load);
- } else if (type == Member) {
-// if (useFastLookups) {
-// Instruction::GetLookup load;
-// load.base = getParam(base);
-// load.index = registerGetterLookup(name);
-// load.result = getResultParam(target);
-// addInstruction(load);
-// return;
-// }
- Instruction::LoadProperty load;
- load.base = base;
- load.name = nameIndex;
- load.result = temp;
- codegen->bytecodeGenerator->addInstruction(load);
- } else if (type == Subscript) {
- Instruction::LoadElement load;
- load.base = base;
- load.index = subscript;
- load.result = temp;
- codegen->bytecodeGenerator->addInstruction(load);
- } else if (type == Closure) {
- Instruction::LoadClosure load;
- load.value = closureId;
- load.result = temp;
- codegen->bytecodeGenerator->addInstruction(load);
- } else {
- Q_ASSERT(false);
- Q_UNREACHABLE();
- }
- return temp;
+ if (tempIndex >= 0)
+ return Moth::Param::createTemp(tempIndex);
+ tempIndex = codegen->bytecodeGenerator->newTemp();
+ load(tempIndex);
+ return Moth::Param::createTemp(tempIndex);
}
Moth::Param Codegen::Reference::asLValue() const
@@ -3396,3 +3397,47 @@ void Codegen::Reference::writeBack() const
Q_UNREACHABLE();
}
}
+
+void Codegen::Reference::load(uint tmp) const
+{
+ Moth::Param temp = Moth::Param::createTemp(tmp);
+ if (type == Const) {
+ Instruction::MoveConst move;
+ move.source = constant;
+ move.result = temp;
+ codegen->bytecodeGenerator->addInstruction(move);
+ } else if (type == Name) {
+ Instruction::LoadName load;
+ load.name = nameIndex;
+ load.result = temp;
+ codegen->bytecodeGenerator->addInstruction(load);
+ } else if (type == Member) {
+// if (useFastLookups) {
+// Instruction::GetLookup load;
+// load.base = getParam(base);
+// load.index = registerGetterLookup(name);
+// load.result = getResultParam(target);
+// addInstruction(load);
+// return;
+// }
+ Instruction::LoadProperty load;
+ load.base = base;
+ load.name = nameIndex;
+ load.result = temp;
+ codegen->bytecodeGenerator->addInstruction(load);
+ } else if (type == Subscript) {
+ Instruction::LoadElement load;
+ load.base = base;
+ load.index = subscript;
+ load.result = temp;
+ codegen->bytecodeGenerator->addInstruction(load);
+ } else if (type == Closure) {
+ Instruction::LoadClosure load;
+ load.value = closureId;
+ load.result = temp;
+ codegen->bytecodeGenerator->addInstruction(load);
+ } else {
+ Q_ASSERT(false);
+ Q_UNREACHABLE();
+ }
+}