aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2017-06-30 14:32:14 +0200
committerLars Knoll <lars.knoll@qt.io>2017-07-03 06:09:07 +0000
commitf4804726c30279c54b0e9354305506458b9a0c76 (patch)
tree50dca31c2c4fb235f3bf66b6bc71356a591feaf0 /src
parent62ea4f9e014d10155b898b4f68dbd98097dee276 (diff)
Mark whether arguments or local variables can escape
This helps determine whether those variables can live on the JS stack or need to go into the ExecutionContext Change-Id: I791632b7fe9fd8788af7564844b5d368c3e0b91c Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src')
-rw-r--r--src/qml/compiler/qv4codegen.cpp4
-rw-r--r--src/qml/compiler/qv4codegen_p.h23
2 files changed, 17 insertions, 10 deletions
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp
index 25622465b5..8cfdb6919d 100644
--- a/src/qml/compiler/qv4codegen.cpp
+++ b/src/qml/compiler/qv4codegen.cpp
@@ -1904,7 +1904,7 @@ Codegen::Reference Codegen::referenceForName(const QString &name, bool isLhs)
if (c->forceLookupByName() || (c->isNamedFunctionExpression && c->name == name))
goto loadByName;
- int index = c->findMember(name);
+ int index = c->findMember(name, c != _context);
Q_ASSERT (index < c->members.size());
if (index != -1) {
Reference r = Reference::fromLocal(this, index, scope);
@@ -1916,7 +1916,7 @@ Codegen::Reference Codegen::referenceForName(const QString &name, bool isLhs)
}
return r;
}
- const int argIdx = c->findArgument(name);
+ const int argIdx = c->findArgument(name, c != _context);
if (argIdx != -1)
return Reference::fromArgument(this, argIdx, scope);
diff --git a/src/qml/compiler/qv4codegen_p.h b/src/qml/compiler/qv4codegen_p.h
index 1da842b012..03a2a089d1 100644
--- a/src/qml/compiler/qv4codegen_p.h
+++ b/src/qml/compiler/qv4codegen_p.h
@@ -131,10 +131,11 @@ struct Context {
};
struct Member {
- MemberType type;
- int index;
- AST::FunctionExpression *function;
- AST::VariableDeclaration::VariableScope scope;
+ MemberType type = UndefinedMember;
+ int index = -1;
+ AST::VariableDeclaration::VariableScope scope = AST::VariableDeclaration::FunctionScope;
+ mutable bool canEscape = false;
+ AST::FunctionExpression *function = 0;
bool isLexicallyScoped() const { return this->scope != AST::VariableDeclaration::FunctionScope; }
};
@@ -157,6 +158,8 @@ struct Context {
bool usesThis = false;
bool hasTry = false;
bool hasWith = false;
+ mutable bool argumentsCanEscape = false;
+
enum UsesArgumentsObject {
ArgumentsObjectUnknown,
ArgumentsObjectNotUsed,
@@ -232,21 +235,26 @@ struct Context {
usesArgumentsObject == ArgumentsObjectNotUsed && !hasDirectEval;
}
- int findArgument(const QString &name) const
+ int findArgument(const QString &name, bool canEscape)
{
// search backwards to handle duplicate argument names correctly
for (int i = arguments.size() - 1; i >= 0; --i) {
- if (arguments.at(i) == name)
+ if (arguments.at(i) == name) {
+ if (canEscape)
+ argumentsCanEscape = true;
return i;
+ }
}
return -1;
}
- int findMember(const QString &name) const
+ int findMember(const QString &name, bool canEscape) const
{
MemberMap::const_iterator it = members.find(name);
if (it == members.end())
return -1;
+ if (canEscape)
+ (*it).canEscape = true;
Q_ASSERT((*it).index != -1 || !parent);
return (*it).index;
}
@@ -274,7 +282,6 @@ struct Context {
MemberMap::iterator it = members.find(name);
if (it == members.end()) {
Member m;
- m.index = -1;
m.type = type;
m.function = function;
m.scope = scope;