diff options
-rw-r--r-- | src/qml/compiler/qv4codegen.cpp | 12 | ||||
-rw-r--r-- | src/qml/compiler/qv4compiler.cpp | 2 | ||||
-rw-r--r-- | src/qml/compiler/qv4compilercontext.cpp | 55 | ||||
-rw-r--r-- | src/qml/compiler/qv4compilercontext_p.h | 5 | ||||
-rw-r--r-- | src/qml/compiler/qv4compilerscanfunctions.cpp | 9 |
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) { |