aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/compiler')
-rw-r--r--src/qml/compiler/qqmlirbuilder.cpp2
-rw-r--r--src/qml/compiler/qqmlirbuilder_p.h6
-rw-r--r--src/qml/compiler/qv4codegen.cpp262
-rw-r--r--src/qml/compiler/qv4codegen_p.h120
-rw-r--r--src/qml/compiler/qv4compilerscanfunctions.cpp27
-rw-r--r--src/qml/compiler/qv4compilerscanfunctions_p.h7
6 files changed, 227 insertions, 197 deletions
diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp
index ea5efcfc66..7bd5aeb188 100644
--- a/src/qml/compiler/qqmlirbuilder.cpp
+++ b/src/qml/compiler/qqmlirbuilder.cpp
@@ -566,7 +566,7 @@ bool IRBuilder::visit(QQmlJS::AST::UiQualifiedId *id)
void IRBuilder::accept(QQmlJS::AST::Node *node)
{
- QQmlJS::AST::Node::acceptChild(node, this);
+ QQmlJS::AST::Node::accept(node, this);
}
bool IRBuilder::defineQMLObject(int *objectIndex, QQmlJS::AST::UiQualifiedId *qualifiedTypeNameId, const QQmlJS::AST::SourceLocation &location, QQmlJS::AST::UiObjectInitializer *initializer, Object *declarationsOverride)
diff --git a/src/qml/compiler/qqmlirbuilder_p.h b/src/qml/compiler/qqmlirbuilder_p.h
index fd607aee8d..7c5944931e 100644
--- a/src/qml/compiler/qqmlirbuilder_p.h
+++ b/src/qml/compiler/qqmlirbuilder_p.h
@@ -435,6 +435,12 @@ public:
bool visit(QQmlJS::AST::UiScriptBinding *ast) override;
bool visit(QQmlJS::AST::UiSourceElement *ast) override;
+ void throwRecursionDepthError() override
+ {
+ recordError(AST::SourceLocation(),
+ QStringLiteral("Maximum statement or expression depth exceeded"));
+ }
+
void accept(QQmlJS::AST::Node *node);
// returns index in _objects
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp
index ac763e592f..009545eceb 100644
--- a/src/qml/compiler/qv4codegen.cpp
+++ b/src/qml/compiler/qv4codegen.cpp
@@ -100,9 +100,10 @@ Codegen::Codegen(QV4::Compiler::JSUnitGenerator *jsUnitGenerator, bool strict)
, hasError(false)
{
jsUnitGenerator->codeGeneratorName = QStringLiteral("moth");
+ pushExpr();
}
-const char *globalNames[] = {
+const char *Codegen::s_globalNames[] = {
"isNaN",
"parseFloat",
"String",
@@ -182,7 +183,7 @@ void Codegen::generateFromProgram(const QString &fileName,
//
// Since this can be called from the loader thread we can't get the list
// directly from the engine, so let's hardcode the most important ones here
- for (const char **g = globalNames; *g != nullptr; ++g)
+ for (const char **g = s_globalNames; *g != nullptr; ++g)
m_globalNames << QString::fromLatin1(*g);
}
@@ -264,7 +265,7 @@ Context *Codegen::enterBlock(Node *node)
Codegen::Reference Codegen::unop(UnaryOperation op, const Reference &expr)
{
if (hasError)
- return _expr.result();
+ return exprResult();
if (expr.isConstant()) {
auto v = Value::fromReturnedValue(expr.constant);
@@ -310,7 +311,7 @@ Codegen::Reference Codegen::unop(UnaryOperation op, const Reference &expr)
return Reference::fromAccumulator(this);
}
case PostIncrement:
- if (!_expr.accept(nx) || requiresReturnValue) {
+ if (!exprAccept(nx) || requiresReturnValue) {
Reference e = expr.asLValue();
e.loadInAccumulator();
Instruction::UPlus uplus;
@@ -330,13 +331,13 @@ Codegen::Reference Codegen::unop(UnaryOperation op, const Reference &expr)
e.loadInAccumulator();
Instruction::Increment inc = {};
bytecodeGenerator->addTracingInstruction(inc);
- if (_expr.accept(nx))
+ if (exprAccept(nx))
return e.storeConsumeAccumulator();
else
return e.storeRetainAccumulator();
}
case PostDecrement:
- if (!_expr.accept(nx) || requiresReturnValue) {
+ if (!exprAccept(nx) || requiresReturnValue) {
Reference e = expr.asLValue();
e.loadInAccumulator();
Instruction::UPlus uplus;
@@ -356,7 +357,7 @@ Codegen::Reference Codegen::unop(UnaryOperation op, const Reference &expr)
e.loadInAccumulator();
Instruction::Decrement dec = {};
bytecodeGenerator->addTracingInstruction(dec);
- if (_expr.accept(nx))
+ if (exprAccept(nx))
return e.storeConsumeAccumulator();
else
return e.storeRetainAccumulator();
@@ -368,22 +369,13 @@ Codegen::Reference Codegen::unop(UnaryOperation op, const Reference &expr)
void Codegen::addCJump()
{
- bytecodeGenerator->addCJumpInstruction(_expr.trueBlockFollowsCondition(),
- _expr.iftrue(), _expr.iffalse());
-}
-
-void Codegen::accept(Node *node)
-{
- if (hasError)
- return;
-
- if (node)
- node->accept(this);
+ const Result &expression = currentExpr();
+ bytecodeGenerator->addCJumpInstruction(expression.trueBlockFollowsCondition(),
+ expression.iftrue(), expression.iffalse());
}
void Codegen::statement(Statement *ast)
{
- RecursionDepthCheck depthCheck(this, ast->lastSourceLocation());
RegisterScope scope(this);
bytecodeGenerator->setLocation(ast->firstSourceLocation());
@@ -399,23 +391,21 @@ void Codegen::statement(ExpressionNode *ast)
if (! ast) {
return;
} else {
- RecursionDepthCheck depthCheck(this, ast->lastSourceLocation());
RegisterScope scope(this);
- Result r(nx);
- qSwap(_expr, r);
+ pushExpr(Result(nx));
VolatileMemoryLocations vLocs = scanVolatileMemoryLocations(ast);
qSwap(_volatileMemoryLocations, vLocs);
accept(ast);
qSwap(_volatileMemoryLocations, vLocs);
- qSwap(_expr, r);
+ Reference result = popResult();
if (hasError)
return;
- if (r.result().loadTriggersSideEffect())
- r.result().loadInAccumulator(); // triggers side effects
+ if (result.loadTriggersSideEffect())
+ result.loadInAccumulator(); // triggers side effects
}
}
@@ -428,11 +418,9 @@ void Codegen::condition(ExpressionNode *ast, const BytecodeGenerator::Label *ift
if (!ast)
return;
- RecursionDepthCheck depthCheck(this, ast->lastSourceLocation());
- Result r(iftrue, iffalse, trueBlockFollowsCondition);
- qSwap(_expr, r);
+ pushExpr(Result(iftrue, iffalse, trueBlockFollowsCondition));
accept(ast);
- qSwap(_expr, r);
+ Result r = popExpr();
if (hasError)
return;
@@ -450,18 +438,6 @@ void Codegen::condition(ExpressionNode *ast, const BytecodeGenerator::Label *ift
}
}
-Codegen::Reference Codegen::expression(ExpressionNode *ast)
-{
- RecursionDepthCheck depthCheck(this, ast->lastSourceLocation());
- Result r;
- if (ast) {
- qSwap(_expr, r);
- accept(ast);
- qSwap(_expr, r);
- }
- return r.result();
-}
-
void Codegen::program(Program *ast)
{
if (ast) {
@@ -875,17 +851,13 @@ bool Codegen::visit(ExportDeclaration *ast)
Reference exportedValue;
if (auto *fdecl = AST::cast<FunctionDeclaration*>(ast->variableStatementOrDeclaration)) {
- Result r;
- qSwap(_expr, r);
+ pushExpr();
visit(static_cast<FunctionExpression*>(fdecl));
- qSwap(_expr, r);
- exportedValue = r.result();
+ exportedValue = popResult();
} else if (auto *classDecl = AST::cast<ClassDeclaration*>(ast->variableStatementOrDeclaration)) {
- Result r;
- qSwap(_expr, r);
+ pushExpr();
visit(static_cast<ClassExpression*>(classDecl));
- qSwap(_expr, r);
- exportedValue = r.result();
+ exportedValue = popResult();
} else if (ExpressionNode *expr = ast->variableStatementOrDeclaration->expressionCast()) {
exportedValue = expression(expr);
}
@@ -1068,7 +1040,7 @@ bool Codegen::visit(ClassExpression *ast)
(void) ctor.storeRetainAccumulator();
}
- _expr.setResult(Reference::fromAccumulator(this));
+ setExprResult(Reference::fromAccumulator(this));
return false;
}
@@ -1151,7 +1123,7 @@ bool Codegen::visit(ArrayPattern *ast)
}
if (!it) {
- _expr.setResult(Reference::fromAccumulator(this));
+ setExprResult(Reference::fromAccumulator(this));
return false;
}
Q_ASSERT(it->element && it->element->type == PatternElement::SpreadElement);
@@ -1245,7 +1217,7 @@ bool Codegen::visit(ArrayPattern *ast)
}
array.loadInAccumulator();
- _expr.setResult(Reference::fromAccumulator(this));
+ setExprResult(Reference::fromAccumulator(this));
return false;
}
@@ -1261,7 +1233,7 @@ bool Codegen::visit(ArrayMemberExpression *ast)
return false;
if (base.isSuper()) {
Reference index = expression(ast->expression).storeOnStack();
- _expr.setResult(Reference::fromSuperProperty(index));
+ setExprResult(Reference::fromSuperProperty(index));
return false;
}
base = base.storeOnStack();
@@ -1271,17 +1243,17 @@ bool Codegen::visit(ArrayMemberExpression *ast)
QString s = str->value.toString();
uint arrayIndex = QV4::String::toArrayIndex(s);
if (arrayIndex == UINT_MAX) {
- _expr.setResult(Reference::fromMember(base, str->value.toString()));
+ setExprResult(Reference::fromMember(base, str->value.toString()));
return false;
}
Reference index = Reference::fromConst(this, QV4::Encode(arrayIndex));
- _expr.setResult(Reference::fromSubscript(base, index));
+ setExprResult(Reference::fromSubscript(base, index));
return false;
}
Reference index = expression(ast->expression);
if (hasError)
return false;
- _expr.setResult(Reference::fromSubscript(base, index));
+ setExprResult(Reference::fromSubscript(base, index));
return false;
}
@@ -1312,12 +1284,13 @@ bool Codegen::visit(BinaryExpression *ast)
TailCallBlocker blockTailCalls(this);
if (ast->op == QSOperator::And) {
- if (_expr.accept(cx)) {
+ if (exprAccept(cx)) {
auto iftrue = bytecodeGenerator->newLabel();
- condition(ast->left, &iftrue, _expr.iffalse(), true);
+ condition(ast->left, &iftrue, currentExpr().iffalse(), true);
iftrue.link();
blockTailCalls.unblock();
- condition(ast->right, _expr.iftrue(), _expr.iffalse(), _expr.trueBlockFollowsCondition());
+ const Result &expr = currentExpr();
+ condition(ast->right, expr.iftrue(), expr.iffalse(), expr.trueBlockFollowsCondition());
} else {
auto iftrue = bytecodeGenerator->newLabel();
auto endif = bytecodeGenerator->newLabel();
@@ -1339,15 +1312,16 @@ bool Codegen::visit(BinaryExpression *ast)
endif.link();
- _expr.setResult(Reference::fromAccumulator(this));
+ setExprResult(Reference::fromAccumulator(this));
}
return false;
} else if (ast->op == QSOperator::Or) {
- if (_expr.accept(cx)) {
+ if (exprAccept(cx)) {
auto iffalse = bytecodeGenerator->newLabel();
- condition(ast->left, _expr.iftrue(), &iffalse, false);
+ condition(ast->left, currentExpr().iftrue(), &iffalse, false);
iffalse.link();
- condition(ast->right, _expr.iftrue(), _expr.iffalse(), _expr.trueBlockFollowsCondition());
+ const Result &expr = currentExpr();
+ condition(ast->right, expr.iftrue(), expr.iffalse(), expr.trueBlockFollowsCondition());
} else {
auto iffalse = bytecodeGenerator->newLabel();
auto endif = bytecodeGenerator->newLabel();
@@ -1369,7 +1343,7 @@ bool Codegen::visit(BinaryExpression *ast)
endif.link();
- _expr.setResult(Reference::fromAccumulator(this));
+ setExprResult(Reference::fromAccumulator(this));
}
return false;
} else if (ast->op == QSOperator::Assign) {
@@ -1380,9 +1354,9 @@ bool Codegen::visit(BinaryExpression *ast)
return false;
right = right.storeOnStack();
destructurePattern(p, right);
- if (!_expr.accept(nx)) {
+ if (!exprAccept(nx)) {
right.loadInAccumulator();
- _expr.setResult(Reference::fromAccumulator(this));
+ setExprResult(Reference::fromAccumulator(this));
}
return false;
}
@@ -1402,10 +1376,10 @@ bool Codegen::visit(BinaryExpression *ast)
if (hasError)
return false;
r.loadInAccumulator();
- if (_expr.accept(nx))
- _expr.setResult(left.storeConsumeAccumulator());
+ if (exprAccept(nx))
+ setExprResult(left.storeConsumeAccumulator());
else
- _expr.setResult(left.storeRetainAccumulator());
+ setExprResult(left.storeRetainAccumulator());
return false;
}
@@ -1448,7 +1422,7 @@ bool Codegen::visit(BinaryExpression *ast)
return false;
binopHelper(baseOp(ast->op), tempLeft, right).loadInAccumulator();
- _expr.setResult(left.storeRetainAccumulator());
+ setExprResult(left.storeRetainAccumulator());
break;
}
@@ -1460,7 +1434,7 @@ bool Codegen::visit(BinaryExpression *ast)
Reference right = expression(ast->right);
if (hasError)
return false;
- _expr.setResult(binopHelper(static_cast<QSOperator::Op>(ast->op), right, left));
+ setExprResult(binopHelper(static_cast<QSOperator::Op>(ast->op), right, left));
break;
}
// intentional fall-through!
@@ -1486,7 +1460,7 @@ bool Codegen::visit(BinaryExpression *ast)
Reference right;
if (AST::NumericLiteral *rhs = AST::cast<AST::NumericLiteral *>(ast->right)) {
visit(rhs);
- right = _expr.result();
+ right = exprResult();
} else {
left = left.storeOnStack(); // force any loads of the lhs, so the rhs won't clobber it
right = expression(ast->right);
@@ -1494,7 +1468,7 @@ bool Codegen::visit(BinaryExpression *ast)
if (hasError)
return false;
- _expr.setResult(binopHelper(static_cast<QSOperator::Op>(ast->op), left, right));
+ setExprResult(binopHelper(static_cast<QSOperator::Op>(ast->op), left, right));
break;
}
@@ -1671,7 +1645,7 @@ Codegen::Reference Codegen::binopHelper(QSOperator::Op oper, Reference &left, Re
break;
}
case QSOperator::StrictEqual: {
- if (_expr.accept(cx))
+ if (exprAccept(cx))
return jumpBinop(oper, left, right);
Instruction::CmpStrictEqual cmp;
@@ -1682,7 +1656,7 @@ Codegen::Reference Codegen::binopHelper(QSOperator::Op oper, Reference &left, Re
break;
}
case QSOperator::StrictNotEqual: {
- if (_expr.accept(cx))
+ if (exprAccept(cx))
return jumpBinop(oper, left, right);
Instruction::CmpStrictNotEqual cmp;
@@ -1693,7 +1667,7 @@ Codegen::Reference Codegen::binopHelper(QSOperator::Op oper, Reference &left, Re
break;
}
case QSOperator::Equal: {
- if (_expr.accept(cx))
+ if (exprAccept(cx))
return jumpBinop(oper, left, right);
Instruction::CmpEq cmp;
@@ -1704,7 +1678,7 @@ Codegen::Reference Codegen::binopHelper(QSOperator::Op oper, Reference &left, Re
break;
}
case QSOperator::NotEqual: {
- if (_expr.accept(cx))
+ if (exprAccept(cx))
return jumpBinop(oper, left, right);
Instruction::CmpNe cmp;
@@ -1715,7 +1689,7 @@ Codegen::Reference Codegen::binopHelper(QSOperator::Op oper, Reference &left, Re
break;
}
case QSOperator::Gt: {
- if (_expr.accept(cx))
+ if (exprAccept(cx))
return jumpBinop(oper, left, right);
Instruction::CmpGt cmp;
@@ -1726,7 +1700,7 @@ Codegen::Reference Codegen::binopHelper(QSOperator::Op oper, Reference &left, Re
break;
}
case QSOperator::Ge: {
- if (_expr.accept(cx))
+ if (exprAccept(cx))
return jumpBinop(oper, left, right);
Instruction::CmpGe cmp;
@@ -1737,7 +1711,7 @@ Codegen::Reference Codegen::binopHelper(QSOperator::Op oper, Reference &left, Re
break;
}
case QSOperator::Lt: {
- if (_expr.accept(cx))
+ if (exprAccept(cx))
return jumpBinop(oper, left, right);
Instruction::CmpLt cmp;
@@ -1748,7 +1722,7 @@ Codegen::Reference Codegen::binopHelper(QSOperator::Op oper, Reference &left, Re
break;
}
case QSOperator::Le:
- if (_expr.accept(cx))
+ if (exprAccept(cx))
return jumpBinop(oper, left, right);
Instruction::CmpLe cmp;
@@ -1952,7 +1926,7 @@ bool Codegen::visit(CallExpression *ast)
bytecodeGenerator->addInstruction(call);
}
- _expr.setResult(Reference::fromAccumulator(this));
+ setExprResult(Reference::fromAccumulator(this));
return false;
}
@@ -2045,7 +2019,7 @@ void Codegen::handleCall(Reference &base, Arguments calldata, int slotForFunctio
bytecodeGenerator->addTracingInstruction(call);
}
- _expr.setResult(Reference::fromAccumulator(this));
+ setExprResult(Reference::fromAccumulator(this));
}
Codegen::Arguments Codegen::pushArgs(ArgumentList *args)
@@ -2141,7 +2115,7 @@ bool Codegen::visit(ConditionalExpression *ast)
ko.loadInAccumulator();
jump_endif.link();
- _expr.setResult(Reference::fromAccumulator(this));
+ setExprResult(Reference::fromAccumulator(this));
return false;
}
@@ -2171,7 +2145,7 @@ bool Codegen::visit(DeleteExpression *ast)
throwSyntaxError(ast->deleteToken, QStringLiteral("Delete of an unqualified identifier in strict mode."));
return false;
}
- _expr.setResult(Reference::fromConst(this, QV4::Encode(false)));
+ setExprResult(Reference::fromConst(this, QV4::Encode(false)));
return false;
case Reference::Name: {
if (_context->isStrict) {
@@ -2181,7 +2155,7 @@ bool Codegen::visit(DeleteExpression *ast)
Instruction::DeleteName del;
del.name = expr.nameAsIndex();
bytecodeGenerator->addInstruction(del);
- _expr.setResult(Reference::fromAccumulator(this));
+ setExprResult(Reference::fromAccumulator(this));
return false;
}
case Reference::Member: {
@@ -2196,7 +2170,7 @@ bool Codegen::visit(DeleteExpression *ast)
del.base = expr.propertyBase.stackSlot();
del.index = index.stackSlot();
bytecodeGenerator->addInstruction(del);
- _expr.setResult(Reference::fromAccumulator(this));
+ setExprResult(Reference::fromAccumulator(this));
return false;
}
case Reference::Subscript: {
@@ -2206,14 +2180,14 @@ bool Codegen::visit(DeleteExpression *ast)
del.base = expr.elementBase;
del.index = expr.elementSubscript.stackSlot();
bytecodeGenerator->addInstruction(del);
- _expr.setResult(Reference::fromAccumulator(this));
+ setExprResult(Reference::fromAccumulator(this));
return false;
}
default:
break;
}
// [[11.4.1]] Return true if it's not a reference
- _expr.setResult(Reference::fromConst(this, QV4::Encode(true)));
+ setExprResult(Reference::fromConst(this, QV4::Encode(true)));
return false;
}
@@ -2222,7 +2196,7 @@ bool Codegen::visit(FalseLiteral *)
if (hasError)
return false;
- _expr.setResult(Reference::fromConst(this, QV4::Encode(false)));
+ setExprResult(Reference::fromConst(this, QV4::Encode(false)));
return false;
}
@@ -2231,7 +2205,7 @@ bool Codegen::visit(SuperLiteral *)
if (hasError)
return false;
- _expr.setResult(Reference::fromSuper(this));
+ setExprResult(Reference::fromSuper(this));
return false;
}
@@ -2249,12 +2223,12 @@ bool Codegen::visit(FieldMemberExpression *ast)
if (_context->isArrowFunction || _context->contextType == ContextType::Eval) {
Reference r = referenceForName(QStringLiteral("new.target"), false);
r.isReadonly = true;
- _expr.setResult(r);
+ setExprResult(r);
return false;
}
Reference r = Reference::fromStackSlot(this, CallData::NewTarget);
- _expr.setResult(r);
+ setExprResult(r);
return false;
}
}
@@ -2267,10 +2241,10 @@ bool Codegen::visit(FieldMemberExpression *ast)
load.stringId = registerString(ast->name.toString());
bytecodeGenerator->addInstruction(load);
Reference property = Reference::fromAccumulator(this).storeOnStack();
- _expr.setResult(Reference::fromSuperProperty(property));
+ setExprResult(Reference::fromSuperProperty(property));
return false;
}
- _expr.setResult(Reference::fromMember(base, ast->name.toString()));
+ setExprResult(Reference::fromMember(base, ast->name.toString()));
return false;
}
@@ -2280,12 +2254,15 @@ bool Codegen::visit(TaggedTemplate *ast)
return false;
RegisterScope scope(this);
+ return handleTaggedTemplate(expression(ast->base), ast);
+}
- int functionObject = -1, thisObject = -1;
-
- Reference base = expression(ast->base);
+bool Codegen::handleTaggedTemplate(Reference base, TaggedTemplate *ast)
+{
if (hasError)
return false;
+
+ int functionObject = -1, thisObject = -1;
switch (base.type) {
case Reference::Member:
case Reference::Subscript:
@@ -2346,7 +2323,7 @@ bool Codegen::visit(FunctionExpression *ast)
if (hasError)
return false;
loadClosure(function);
- _expr.setResult(Reference::fromAccumulator(this));
+ setExprResult(Reference::fromAccumulator(this));
return false;
}
@@ -2412,7 +2389,7 @@ bool Codegen::visit(IdentifierExpression *ast)
if (hasError)
return false;
- _expr.setResult(referenceForName(ast->name.toString(), false, ast->firstSourceLocation()));
+ setExprResult(referenceForName(ast->name.toString(), false, ast->firstSourceLocation()));
return false;
}
@@ -2462,7 +2439,7 @@ void Codegen::handleConstruct(const Reference &base, ArgumentList *arguments)
// set the result up as the thisObject
Reference::fromAccumulator(this).storeOnStack(CallData::This);
- _expr.setResult(Reference::fromAccumulator(this));
+ setExprResult(Reference::fromAccumulator(this));
}
bool Codegen::visit(NewExpression *ast)
@@ -2511,7 +2488,7 @@ bool Codegen::visit(NotExpression *ast)
return false;
TailCallBlocker blockTailCalls(this);
- _expr.setResult(unop(Not, expression(ast->expression)));
+ setExprResult(unop(Not, expression(ast->expression)));
return false;
}
@@ -2520,10 +2497,10 @@ bool Codegen::visit(NullExpression *)
if (hasError)
return false;
- if (_expr.accept(cx))
- bytecodeGenerator->jump().link(*_expr.iffalse());
+ if (exprAccept(cx))
+ bytecodeGenerator->jump().link(*currentExpr().iffalse());
else
- _expr.setResult(Reference::fromConst(this, Encode::null()));
+ setExprResult(Reference::fromConst(this, Encode::null()));
return false;
}
@@ -2533,7 +2510,7 @@ bool Codegen::visit(NumericLiteral *ast)
if (hasError)
return false;
- _expr.setResult(Reference::fromConst(this, QV4::Encode::smallestNumber(ast->value)));
+ setExprResult(Reference::fromConst(this, QV4::Encode::smallestNumber(ast->value)));
return false;
}
@@ -2645,8 +2622,7 @@ bool Codegen::visit(ObjectPattern *ast)
call.argc = argc;
call.args = Moth::StackSlot::createRegister(args);
bytecodeGenerator->addInstruction(call);
- Reference result = Reference::fromAccumulator(this);
- _expr.setResult(result);
+ setExprResult(Reference::fromAccumulator(this));
return false;
}
@@ -2665,7 +2641,7 @@ bool Codegen::visit(PostDecrementExpression *ast)
if (throwSyntaxErrorOnEvalOrArgumentsInStrictMode(expr, ast->decrementToken))
return false;
- _expr.setResult(unop(PostDecrement, expr));
+ setExprResult(unop(PostDecrement, expr));
return false;
}
@@ -2685,7 +2661,7 @@ bool Codegen::visit(PostIncrementExpression *ast)
if (throwSyntaxErrorOnEvalOrArgumentsInStrictMode(expr, ast->incrementToken))
return false;
- _expr.setResult(unop(PostIncrement, expr));
+ setExprResult(unop(PostIncrement, expr));
return false;
}
@@ -2703,7 +2679,7 @@ bool Codegen::visit(PreDecrementExpression *ast)
if (throwSyntaxErrorOnEvalOrArgumentsInStrictMode(expr, ast->decrementToken))
return false;
- _expr.setResult(unop(PreDecrement, expr));
+ setExprResult(unop(PreDecrement, expr));
return false;
}
@@ -2722,7 +2698,7 @@ bool Codegen::visit(PreIncrementExpression *ast)
if (throwSyntaxErrorOnEvalOrArgumentsInStrictMode(expr, ast->incrementToken))
return false;
- _expr.setResult(unop(PreIncrement, expr));
+ setExprResult(unop(PreIncrement, expr));
return false;
}
@@ -2733,7 +2709,7 @@ bool Codegen::visit(RegExpLiteral *ast)
auto r = Reference::fromStackSlot(this);
r.isReadonly = true;
- _expr.setResult(r);
+ setExprResult(r);
Instruction::MoveRegExp instr;
instr.regExpId = jsUnitGenerator->registerRegExp(ast);
@@ -2749,7 +2725,7 @@ bool Codegen::visit(StringLiteral *ast)
auto r = Reference::fromAccumulator(this);
r.isReadonly = true;
- _expr.setResult(r);
+ setExprResult(r);
Instruction::LoadRuntimeString instr;
instr.stringId = registerString(ast->value.toString());
@@ -2799,7 +2775,7 @@ bool Codegen::visit(TemplateLiteral *ast)
auto r = Reference::fromAccumulator(this);
r.isReadonly = true;
- _expr.setResult(r);
+ setExprResult(r);
return false;
}
@@ -2812,10 +2788,10 @@ bool Codegen::visit(ThisExpression *)
if (_context->isArrowFunction) {
Reference r = referenceForName(QStringLiteral("this"), false);
r.isReadonly = true;
- _expr.setResult(r);
+ setExprResult(r);
return false;
}
- _expr.setResult(Reference::fromThis(this));
+ setExprResult(Reference::fromThis(this));
return false;
}
@@ -2825,7 +2801,7 @@ bool Codegen::visit(TildeExpression *ast)
return false;
TailCallBlocker blockTailCalls(this);
- _expr.setResult(unop(Compl, expression(ast->expression)));
+ setExprResult(unop(Compl, expression(ast->expression)));
return false;
}
@@ -2834,7 +2810,7 @@ bool Codegen::visit(TrueLiteral *)
if (hasError)
return false;
- _expr.setResult(Reference::fromConst(this, QV4::Encode(true)));
+ setExprResult(Reference::fromConst(this, QV4::Encode(true)));
return false;
}
@@ -2860,7 +2836,7 @@ bool Codegen::visit(TypeOfExpression *ast)
Instruction::TypeofValue instr;
bytecodeGenerator->addInstruction(instr);
}
- _expr.setResult(Reference::fromAccumulator(this));
+ setExprResult(Reference::fromAccumulator(this));
return false;
}
@@ -2871,7 +2847,7 @@ bool Codegen::visit(UnaryMinusExpression *ast)
return false;
TailCallBlocker blockTailCalls(this);
- _expr.setResult(unop(UMinus, expression(ast->expression)));
+ setExprResult(unop(UMinus, expression(ast->expression)));
return false;
}
@@ -2881,7 +2857,7 @@ bool Codegen::visit(UnaryPlusExpression *ast)
return false;
TailCallBlocker blockTailCalls(this);
- _expr.setResult(unop(UPlus, expression(ast->expression)));
+ setExprResult(unop(UPlus, expression(ast->expression)));
return false;
}
@@ -2894,7 +2870,7 @@ bool Codegen::visit(VoidExpression *ast)
TailCallBlocker blockTailCalls(this);
statement(ast->expression);
- _expr.setResult(Reference::fromConst(this, Encode::undefined()));
+ setExprResult(Reference::fromConst(this, Encode::undefined()));
return false;
}
@@ -2908,7 +2884,7 @@ bool Codegen::visit(FunctionDeclaration * ast)
if (_functionContext->contextType == ContextType::Binding)
referenceForName(ast->name.toString(), true).loadInAccumulator();
- _expr.accept(nx);
+ exprAccept(nx);
return false;
}
@@ -2964,7 +2940,7 @@ bool Codegen::visit(YieldExpression *ast)
done.link();
lhsValue.loadInAccumulator();
- _expr.setResult(acc);
+ setExprResult(acc);
return false;
}
@@ -2975,7 +2951,7 @@ bool Codegen::visit(YieldExpression *ast)
BytecodeGenerator::Jump jump = bytecodeGenerator->addJumpInstruction(resume);
emitReturn(acc);
jump.link();
- _expr.setResult(acc);
+ setExprResult(acc);
return false;
}
@@ -3850,8 +3826,14 @@ QQmlRefPointer<CompiledData::CompilationUnit> Codegen::createUnitForLoading()
class Codegen::VolatileMemoryLocationScanner: protected QQmlJS::AST::Visitor
{
VolatileMemoryLocations locs;
+ Codegen *parent;
public:
+ VolatileMemoryLocationScanner(Codegen *parent) :
+ QQmlJS::AST::Visitor(parent->recursionDepth()),
+ parent(parent)
+ {}
+
Codegen::VolatileMemoryLocations scan(AST::Node *s)
{
s->accept(this);
@@ -3916,25 +3898,41 @@ public:
}
}
+ void throwRecursionDepthError() override
+ {
+ parent->throwRecursionDepthError();
+ }
+
private:
- void collectIdentifiers(QVector<QStringView> &ids, AST::Node *node) const {
+ void collectIdentifiers(QVector<QStringView> &ids, AST::Node *node) {
class Collector: public QQmlJS::AST::Visitor {
+ private:
QVector<QStringView> &ids;
+ VolatileMemoryLocationScanner *parent;
+
public:
- Collector(QVector<QStringView> &ids): ids(ids) {}
- virtual bool visit(IdentifierExpression *ie) {
+ Collector(QVector<QStringView> &ids, VolatileMemoryLocationScanner *parent) :
+ QQmlJS::AST::Visitor(parent->recursionDepth()), ids(ids), parent(parent)
+ {}
+
+ bool visit(IdentifierExpression *ie) final {
ids.append(ie->name);
return false;
}
+
+ void throwRecursionDepthError() final
+ {
+ parent->throwRecursionDepthError();
+ }
};
- Collector collector(ids);
+ Collector collector(ids, this);
node->accept(&collector);
}
};
-Codegen::VolatileMemoryLocations Codegen::scanVolatileMemoryLocations(AST::Node *ast) const
+Codegen::VolatileMemoryLocations Codegen::scanVolatileMemoryLocations(AST::Node *ast)
{
- VolatileMemoryLocationScanner scanner;
+ VolatileMemoryLocationScanner scanner(this);
return scanner.scan(ast);
}
diff --git a/src/qml/compiler/qv4codegen_p.h b/src/qml/compiler/qv4codegen_p.h
index 4d7001fe64..0b25d9c53d 100644
--- a/src/qml/compiler/qv4codegen_p.h
+++ b/src/qml/compiler/qv4codegen_p.h
@@ -192,8 +192,24 @@ public:
bool isLValue() const { return !isReadonly && type > Accumulator; }
- Reference(Codegen *cg, Type type = Invalid) : type(type), constant(0), codegen(cg) {}
- Reference(): constant(0) {}
+ Reference(Codegen *cg, Type t = Invalid) : Reference()
+ {
+ type = t;
+ codegen = cg;
+ }
+
+ Reference() :
+ constant(0),
+ isArgOrEval(false),
+ isReadonly(false),
+ isReferenceToConst(false),
+ requiresTDZCheck(false),
+ subscriptRequiresTDZCheck(false),
+ stackSlotIsLocalOrArgument(false),
+ isVolatile(false),
+ global(false)
+ {}
+
Reference(const Reference &) = default;
Reference(Reference &&) = default;
Reference &operator =(const Reference &) = default;
@@ -395,16 +411,17 @@ public:
Moth::StackSlot property; // super property
};
QString name;
- mutable bool isArgOrEval = false;
- bool isReadonly = false;
- bool isReferenceToConst = false;
- bool requiresTDZCheck = false;
- bool subscriptRequiresTDZCheck = false;
- bool stackSlotIsLocalOrArgument = false;
- bool isVolatile = false;
- bool global = false;
Codegen *codegen = nullptr;
+ quint32 isArgOrEval:1;
+ quint32 isReadonly:1;
+ quint32 isReferenceToConst:1;
+ quint32 requiresTDZCheck:1;
+ quint32 subscriptRequiresTDZCheck:1;
+ quint32 stackSlotIsLocalOrArgument:1;
+ quint32 isVolatile:1;
+ quint32 global:1;
+
private:
void storeAccumulator() const;
Reference doStoreOnStack(int tempIndex) const;
@@ -499,6 +516,10 @@ protected:
void setResult(const Reference &result) {
_result = result;
}
+
+ void setResult(Reference &&result) {
+ _result = std::move(result);
+ }
};
void enterContext(AST::Node *node);
@@ -544,9 +565,22 @@ protected:
void condition(AST::ExpressionNode *ast, const BytecodeGenerator::Label *iftrue,
const BytecodeGenerator::Label *iffalse,
bool trueBlockFollowsCondition);
- Reference expression(AST::ExpressionNode *ast);
- void accept(AST::Node *node);
+ inline Reference expression(AST::ExpressionNode *ast)
+ {
+ if (!ast || hasError)
+ return Reference();
+
+ pushExpr();
+ ast->accept(this);
+ return popResult();
+ }
+
+ inline void accept(AST::Node *node)
+ {
+ if (!hasError && node)
+ node->accept(this);
+ }
void program(AST::Program *ast);
void statementList(AST::StatementList *ast);
@@ -670,6 +704,11 @@ protected:
bool throwSyntaxErrorOnEvalOrArgumentsInStrictMode(const Reference &r, const AST::SourceLocation &loc);
virtual void throwSyntaxError(const AST::SourceLocation &loc, const QString &detail);
virtual void throwReferenceError(const AST::SourceLocation &loc, const QString &detail);
+ void throwRecursionDepthError() override
+ {
+ throwSyntaxError(AST::SourceLocation(),
+ QStringLiteral("Maximum statement or expression depth exceeded"));
+ }
public:
QList<DiagnosticMessage> errors() const;
@@ -684,6 +723,7 @@ public:
void handleCall(Reference &base, Arguments calldata, int slotForFunction, int slotForThisObject);
Arguments pushTemplateArgs(AST::TemplateLiteral *args);
+ bool handleTaggedTemplate(Reference base, AST::TaggedTemplate *ast);
void createTemplateObject(AST::TemplateLiteral *t);
void setUseFastLookups(bool b) { useFastLookups = b; }
@@ -714,13 +754,40 @@ public:
m_globalNames = globalNames;
}
+ static const char *s_globalNames[];
protected:
friend class ScanFunctions;
friend struct ControlFlow;
friend struct ControlFlowCatch;
friend struct ControlFlowFinally;
- Result _expr;
+
+ inline void setExprResult(const Reference &result) { m_expressions.back().setResult(result); }
+ inline void setExprResult(Reference &&result) { m_expressions.back().setResult(std::move(result)); }
+ inline Reference exprResult() const { return m_expressions.back().result(); }
+
+ inline bool exprAccept(Format f) { return m_expressions.back().accept(f); }
+
+ inline const Result &currentExpr() const { return m_expressions.back(); }
+
+ inline void pushExpr(Result &&expr) { m_expressions.push_back(std::move(expr)); }
+ inline void pushExpr(const Result &expr) { m_expressions.push_back(expr); }
+ inline void pushExpr() { m_expressions.emplace_back(); }
+
+ inline Result popExpr()
+ {
+ const Result result = m_expressions.back();
+ m_expressions.pop_back();
+ return result;
+ }
+
+ inline Reference popResult() {
+ const Reference result = m_expressions.back().result();
+ m_expressions.pop_back();
+ return result;
+ }
+
+ std::vector<Result> m_expressions;
VolatileMemoryLocations _volatileMemoryLocations;
Module *_module;
int _returnAddress;
@@ -769,33 +836,8 @@ protected:
bool _onoff;
};
- class RecursionDepthCheck {
- public:
- RecursionDepthCheck(Codegen *cg, const AST::SourceLocation &loc)
- : _cg(cg)
- {
-#ifdef QT_NO_DEBUG
- const int depthLimit = 4000; // limit to ~1000 deep
-#else
- const int depthLimit = 1000; // limit to ~250 deep
-#endif // QT_NO_DEBUG
-
- ++_cg->_recursionDepth;
- if (_cg->_recursionDepth > depthLimit)
- _cg->throwSyntaxError(loc, QStringLiteral("Maximum statement or expression depth exceeded"));
- }
-
- ~RecursionDepthCheck()
- { --_cg->_recursionDepth; }
-
- private:
- Codegen *_cg;
- };
- int _recursionDepth = 0;
- friend class RecursionDepthCheck;
-
private:
- VolatileMemoryLocations scanVolatileMemoryLocations(AST::Node *ast) const;
+ VolatileMemoryLocations scanVolatileMemoryLocations(AST::Node *ast);
void handleConstruct(const Reference &base, AST::ArgumentList *args);
};
diff --git a/src/qml/compiler/qv4compilerscanfunctions.cpp b/src/qml/compiler/qv4compilerscanfunctions.cpp
index e0eaa8867b..04593f202a 100644
--- a/src/qml/compiler/qv4compilerscanfunctions.cpp
+++ b/src/qml/compiler/qv4compilerscanfunctions.cpp
@@ -57,7 +57,8 @@ using namespace QV4::Compiler;
using namespace QQmlJS::AST;
ScanFunctions::ScanFunctions(Codegen *cg, const QString &sourceCode, ContextType defaultProgramType)
- : _cg(cg)
+ : QQmlJS::AST::Visitor(cg->recursionDepth())
+ , _cg(cg)
, _sourceCode(sourceCode)
, _context(nullptr)
, _allowFuncDecls(true)
@@ -96,25 +97,6 @@ void ScanFunctions::leaveEnvironment()
_context = _contextStack.isEmpty() ? nullptr : _contextStack.top();
}
-bool ScanFunctions::preVisit(Node *ast)
-{
- if (_cg->hasError)
- return false;
- ++_recursionDepth;
-
- if (_recursionDepth > 1000) {
- _cg->throwSyntaxError(ast->lastSourceLocation(), QStringLiteral("Maximum statement or expression depth exceeded"));
- return false;
- }
-
- return true;
-}
-
-void ScanFunctions::postVisit(Node *)
-{
- --_recursionDepth;
-}
-
void ScanFunctions::checkDirectivePrologue(StatementList *ast)
{
for (StatementList *it = ast; it; it = it->next) {
@@ -893,3 +875,8 @@ void ScanFunctions::calcEscapingVariables()
}
}
}
+
+void ScanFunctions::throwRecursionDepthError()
+{
+ _cg->throwRecursionDepthError();
+}
diff --git a/src/qml/compiler/qv4compilerscanfunctions_p.h b/src/qml/compiler/qv4compilerscanfunctions_p.h
index 28ad846bcd..0f7bf1818a 100644
--- a/src/qml/compiler/qv4compilerscanfunctions_p.h
+++ b/src/qml/compiler/qv4compilerscanfunctions_p.h
@@ -96,9 +96,6 @@ protected:
using Visitor::visit;
using Visitor::endVisit;
- bool preVisit(AST::Node *ast) override;
- void postVisit(AST::Node *) override;
-
void checkDirectivePrologue(AST::StatementList *ast);
void checkName(const QStringRef &name, const AST::SourceLocation &loc);
@@ -160,6 +157,8 @@ protected:
bool visit(AST::WithStatement *ast) override;
void endVisit(AST::WithStatement *ast) override;
+ void throwRecursionDepthError() override;
+
protected:
bool enterFunction(AST::Node *ast, const QString &name, AST::FormalParameterList *formals, AST::StatementList *body, bool enterName);
@@ -173,8 +172,6 @@ protected:
bool _allowFuncDecls;
ContextType defaultProgramType;
- unsigned _recursionDepth = 0;
-
private:
static constexpr AST::Node *astNodeForGlobalEnvironment = nullptr;
};