aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/compiler
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2018-04-03 21:15:18 +0200
committerLars Knoll <lars.knoll@qt.io>2018-05-02 14:17:25 +0000
commit9934514db7ec46f1c57d82e54e61c02b35bfd357 (patch)
tree422d1db77b9c65b52e559a38a4cf3e84adc9613c /src/qml/compiler
parent851c28d140c398990513640047a20aab36ccc655 (diff)
Split out the generation of indices for locals and registers
Change-Id: I0e98ccba9ae3026cd8bfdc4cae100f280b5aa22c Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src/qml/compiler')
-rw-r--r--src/qml/compiler/qv4codegen.cpp12
-rw-r--r--src/qml/compiler/qv4compiler.cpp2
-rw-r--r--src/qml/compiler/qv4compilercontext.cpp55
-rw-r--r--src/qml/compiler/qv4compilercontext_p.h5
-rw-r--r--src/qml/compiler/qv4compilerscanfunctions.cpp9
5 files changed, 51 insertions, 32 deletions
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp
index 6a409edc58..d0b84c7463 100644
--- a/src/qml/compiler/qv4codegen.cpp
+++ b/src/qml/compiler/qv4codegen.cpp
@@ -2318,6 +2318,7 @@ int Codegen::defineFunction(const QString &name, AST::Node *ast,
returnAddress = bytecodeGenerator->newRegister();
qSwap(_returnAddress, returnAddress);
+ RegisterScope registerScope(this);
_context->emitHeaderBytecode(this);
for (const Context::Member &member : qAsConst(_context->members)) {
@@ -2328,9 +2329,10 @@ int Codegen::defineFunction(const QString &name, AST::Node *ast,
if (! _context->parent) {
Reference::fromName(this, member.function->name.toString()).storeConsumeAccumulator();
} else {
- Q_ASSERT(member.index >= 0);
- Reference local = member.canEscape ? Reference::fromScopedLocal(this, member.index, 0)
- : Reference::fromStackSlot(this, member.index, true);
+ int idx = member.index;
+ Q_ASSERT(idx >= 0);
+ Reference local = member.canEscape ? Reference::fromScopedLocal(this, idx, 0)
+ : Reference::fromStackSlot(this, idx, true);
local.storeConsumeAccumulator();
}
}
@@ -2380,11 +2382,11 @@ int Codegen::defineFunction(const QString &name, AST::Node *ast,
}
bytecodeGenerator->finalize(_context);
- _context->registerCount = bytecodeGenerator->registerCount();
+ _context->registerCountInFunction = bytecodeGenerator->registerCount();
static const bool showCode = qEnvironmentVariableIsSet("QV4_SHOW_BYTECODE");
if (showCode) {
qDebug() << "=== Bytecode for" << _context->name << "strict mode" << _context->isStrict
- << "register count" << _context->registerCount;
+ << "register count" << _context->registerCountInFunction;
QV4::Moth::dumpBytecode(_context->code, _context->locals.size(), _context->arguments.size(),
_context->line, _context->lineNumberMapping);
qDebug();
diff --git a/src/qml/compiler/qv4compiler.cpp b/src/qml/compiler/qv4compiler.cpp
index d870c34101..d9f37b542f 100644
--- a/src/qml/compiler/qv4compiler.cpp
+++ b/src/qml/compiler/qv4compiler.cpp
@@ -329,7 +329,7 @@ void QV4::Compiler::JSUnitGenerator::writeFunction(char *f, QV4::Compiler::Conte
currentOffset += function->nLineNumbers * sizeof(CompiledData::CodeOffsetToLine);
- function->nRegisters = irFunction->registerCount;
+ function->nRegisters = irFunction->registerCountInFunction;
function->nDependingIdObjects = 0;
function->nDependingContextProperties = 0;
diff --git a/src/qml/compiler/qv4compilercontext.cpp b/src/qml/compiler/qv4compilercontext.cpp
index 1c583b5cf2..e2e978be7c 100644
--- a/src/qml/compiler/qv4compilercontext.cpp
+++ b/src/qml/compiler/qv4compilercontext.cpp
@@ -163,10 +163,12 @@ Context::ResolvedName Context::resolveName(const QString &name)
void Context::emitHeaderBytecode(Codegen *codegen)
{
+
using Instruction = Moth::Instruction;
Moth::BytecodeGenerator *bytecodeGenerator = codegen->generator();
- bool allVarsEscape = hasWith || hasTry || hasDirectEval;
+ setupFunctionIndices(bytecodeGenerator);
+
if (requiresExecutionContext ||
type == ContextType::Binding) { // we don't really need this for bindings, but we do for signal handlers, and we don't know if the code is a signal handler or not.
Instruction::CreateCallContext createContext;
@@ -181,26 +183,14 @@ void Context::emitHeaderBytecode(Codegen *codegen)
// variables in global code are properties of the global context object, not locals as with other functions.
if (type == ContextType::Function || type == ContextType::Binding) {
for (Context::MemberMap::iterator it = members.begin(), end = members.end(); it != end; ++it) {
- const QString &local = it.key();
- if (allVarsEscape)
- it->canEscape = true;
- if (it->canEscape) {
- it->index = locals.size();
- locals.append(local);
- if (it->type == Context::ThisFunctionName) {
- // move the name from the stack to the call context
- Instruction::LoadReg load;
- load.reg = CallData::Function;
- bytecodeGenerator->addInstruction(load);
- Instruction::StoreLocal store;
- store.index = it->index;
- bytecodeGenerator->addInstruction(store);
- }
- } else {
- if (it->type == Context::ThisFunctionName)
- it->index = CallData::Function;
- else
- it->index = bytecodeGenerator->newRegister();
+ if (it->canEscape && it->type == Context::ThisFunctionName) {
+ // move the function from the stack to the call context
+ Instruction::LoadReg load;
+ load.reg = CallData::Function;
+ bytecodeGenerator->addInstruction(load);
+ Instruction::StoreLocal store;
+ store.index = it->index;
+ bytecodeGenerator->addInstruction(store);
}
}
} else {
@@ -226,4 +216,27 @@ void Context::emitHeaderBytecode(Codegen *codegen)
}
}
+void Context::setupFunctionIndices(Moth::BytecodeGenerator *bytecodeGenerator)
+{
+ Q_ASSERT(locals.size() == 0);
+ Q_ASSERT(nRegisters == 0);
+ registerOffset = bytecodeGenerator->registerCount();
+
+ if (type == ContextType::Function || type == ContextType::Binding) {
+ for (Context::MemberMap::iterator it = members.begin(), end = members.end(); it != end; ++it) {
+ const QString &local = it.key();
+ if (it->canEscape) {
+ it->index = locals.size();
+ locals.append(local);
+ } else {
+ if (it->type == Context::ThisFunctionName)
+ it->index = CallData::Function;
+ else
+ it->index = bytecodeGenerator->newRegister();
+ }
+ }
+ }
+ nRegisters = bytecodeGenerator->registerCount() - registerOffset;
+}
+
QT_END_NAMESPACE
diff --git a/src/qml/compiler/qv4compilercontext_p.h b/src/qml/compiler/qv4compilercontext_p.h
index 1047af973d..65091bb67e 100644
--- a/src/qml/compiler/qv4compilercontext_p.h
+++ b/src/qml/compiler/qv4compilercontext_p.h
@@ -105,7 +105,7 @@ struct Context {
QString name;
int line = 0;
int column = 0;
- int registerCount = 0;
+ int registerCountInFunction = 0;
int functionIndex = -1;
enum MemberType {
@@ -139,6 +139,8 @@ struct Context {
QVector<CompiledData::CodeOffsetToLine> lineNumberMapping;
int maxNumberOfArguments = 0;
+ int nRegisters = 0;
+ int registerOffset = -1;
bool hasDirectEval = false;
bool hasNestedFunctions = false;
bool isStrict = false;
@@ -283,6 +285,7 @@ struct Context {
};
ResolvedName resolveName(const QString &name);
void emitHeaderBytecode(Compiler::Codegen *codegen);
+ void setupFunctionIndices(Moth::BytecodeGenerator *bytecodeGenerator);
};
diff --git a/src/qml/compiler/qv4compilerscanfunctions.cpp b/src/qml/compiler/qv4compilerscanfunctions.cpp
index 0feba7bb61..4fa35f3adb 100644
--- a/src/qml/compiler/qv4compilerscanfunctions.cpp
+++ b/src/qml/compiler/qv4compilerscanfunctions.cpp
@@ -502,9 +502,6 @@ void ScanFunctions::calcEscapingVariables()
if (allVarsEscape) {
c->requiresExecutionContext = true;
c->argumentsCanEscape = true;
- for (auto &m : c->members) {
- m.canEscape = true;
- }
}
// ### for now until we have lexically scoped vars that'll require it
if (c->type == ContextType::Global)
@@ -522,13 +519,17 @@ void ScanFunctions::calcEscapingVariables()
c->requiresExecutionContext = true;
}
}
+ if (allVarsEscape) {
+ for (auto &m : c->members)
+ m.canEscape = true;
+ }
}
static const bool showEscapingVars = qEnvironmentVariableIsSet("QV4_SHOW_ESCAPING_VARS");
if (showEscapingVars) {
qDebug() << "==== escaping variables ====";
for (Context *c : qAsConst(m->contextMap)) {
- qDebug() << "Context" << c->name << ":";
+ qDebug() << "Context" << c << c->name << ":";
if (c->argumentsCanEscape)
qDebug() << " Arguments escape";
for (auto it = c->members.constBegin(); it != c->members.constEnd(); ++it) {