diff options
Diffstat (limited to 'src/qml/compiler/qv4jsir_p.h')
-rw-r--r-- | src/qml/compiler/qv4jsir_p.h | 445 |
1 files changed, 296 insertions, 149 deletions
diff --git a/src/qml/compiler/qv4jsir_p.h b/src/qml/compiler/qv4jsir_p.h index 94fa65cf71..51b8797862 100644 --- a/src/qml/compiler/qv4jsir_p.h +++ b/src/qml/compiler/qv4jsir_p.h @@ -192,7 +192,7 @@ enum AluOp { AluOp binaryOperator(int op); const char *opname(IR::AluOp op); -enum Type { +enum Type : quint16 { UnknownType = 0, MissingType = 1 << 0, @@ -217,34 +217,6 @@ inline bool strictlyEqualTypes(Type t1, Type t2) QString typeName(Type t); -struct ExprVisitor { - virtual ~ExprVisitor() {} - virtual void visitConst(Const *) = 0; - virtual void visitString(String *) = 0; - virtual void visitRegExp(RegExp *) = 0; - virtual void visitName(Name *) = 0; - virtual void visitTemp(Temp *) = 0; - virtual void visitArgLocal(ArgLocal *) = 0; - virtual void visitClosure(Closure *) = 0; - virtual void visitConvert(Convert *) = 0; - virtual void visitUnop(Unop *) = 0; - virtual void visitBinop(Binop *) = 0; - virtual void visitCall(Call *) = 0; - virtual void visitNew(New *) = 0; - virtual void visitSubscript(Subscript *) = 0; - virtual void visitMember(Member *) = 0; -}; - -struct StmtVisitor { - virtual ~StmtVisitor() {} - virtual void visitExp(Exp *) = 0; - virtual void visitMove(Move *) = 0; - virtual void visitJump(Jump *) = 0; - virtual void visitCJump(CJump *) = 0; - virtual void visitRet(Ret *) = 0; - virtual void visitPhi(Phi *) = 0; -}; - struct MemberExpressionResolver; struct DiscoveredType { @@ -288,28 +260,129 @@ struct MemberExpressionResolver }; struct Q_AUTOTEST_EXPORT Expr { + enum ExprKind : quint8 { + NameExpr, + TempExpr, + ArgLocalExpr, + SubscriptExpr, + MemberExpr, + + LastLValue = MemberExpr, + + ConstExpr, + StringExpr, + RegExpExpr, + ClosureExpr, + ConvertExpr, + UnopExpr, + BinopExpr, + CallExpr, + NewExpr + }; + Type type; + const ExprKind exprKind; + + Expr &operator=(const Expr &other) { + Q_ASSERT(exprKind == other.exprKind); + type = other.type; + return *this; + } + + template <typename To> + inline bool isa() const { + return To::classof(this); + } - Expr(): type(UnknownType) {} - virtual ~Expr() {} - virtual void accept(ExprVisitor *) = 0; - virtual bool isLValue() { return false; } - virtual Const *asConst() { return 0; } - virtual String *asString() { return 0; } - virtual RegExp *asRegExp() { return 0; } - virtual Name *asName() { return 0; } - virtual Temp *asTemp() { return 0; } - virtual ArgLocal *asArgLocal() { return 0; } - virtual Closure *asClosure() { return 0; } - virtual Convert *asConvert() { return 0; } - virtual Unop *asUnop() { return 0; } - virtual Binop *asBinop() { return 0; } - virtual Call *asCall() { return 0; } - virtual New *asNew() { return 0; } - virtual Subscript *asSubscript() { return 0; } - virtual Member *asMember() { return 0; } + template <typename To> + inline To *as() { + if (isa<To>()) { + return static_cast<To *>(this); + } else { + return nullptr; + } + } + + template <typename To> + inline const To *as() const { + if (isa<To>()) { + return static_cast<const To *>(this); + } else { + return nullptr; + } + } + + Expr(ExprKind exprKind): type(UnknownType), exprKind(exprKind) {} + bool isLValue() const; + + Const *asConst() { return as<Const>(); } + String *asString() { return as<String>(); } + RegExp *asRegExp() { return as<RegExp>(); } + Name *asName() { return as<Name>(); } + Temp *asTemp() { return as<Temp>(); } + ArgLocal *asArgLocal() { return as<ArgLocal>(); } + Closure *asClosure() { return as<Closure>(); } + Convert *asConvert() { return as<Convert>(); } + Unop *asUnop() { return as<Unop>(); } + Binop *asBinop() { return as<Binop>(); } + Call *asCall() { return as<Call>(); } + New *asNew() { return as<New>(); } + Subscript *asSubscript() { return as<Subscript>(); } + Member *asMember() { return as<Member>(); } }; +#define EXPR_VISIT_ALL_KINDS(e) \ + switch (e->exprKind) { \ + case QV4::IR::Expr::ConstExpr: \ + break; \ + case QV4::IR::Expr::StringExpr: \ + break; \ + case QV4::IR::Expr::RegExpExpr: \ + break; \ + case QV4::IR::Expr::NameExpr: \ + break; \ + case QV4::IR::Expr::TempExpr: \ + break; \ + case QV4::IR::Expr::ArgLocalExpr: \ + break; \ + case QV4::IR::Expr::ClosureExpr: \ + break; \ + case QV4::IR::Expr::ConvertExpr: { \ + auto casted = e->asConvert(); \ + visit(casted->expr); \ + } break; \ + case QV4::IR::Expr::UnopExpr: { \ + auto casted = e->asUnop(); \ + visit(casted->expr); \ + } break; \ + case QV4::IR::Expr::BinopExpr: { \ + auto casted = e->asBinop(); \ + visit(casted->left); \ + visit(casted->right); \ + } break; \ + case QV4::IR::Expr::CallExpr: { \ + auto casted = e->asCall(); \ + visit(casted->base); \ + for (QV4::IR::ExprList *it = casted->args; it; it = it->next) \ + visit(it->expr); \ + } break; \ + case QV4::IR::Expr::NewExpr: { \ + auto casted = e->asNew(); \ + visit(casted->base); \ + for (QV4::IR::ExprList *it = casted->args; it; it = it->next) \ + visit(it->expr); \ + } break; \ + case QV4::IR::Expr::SubscriptExpr: { \ + auto casted = e->asSubscript(); \ + visit(casted->base); \ + visit(casted->index); \ + } break; \ + case QV4::IR::Expr::MemberExpr: { \ + auto casted = e->asMember(); \ + visit(casted->base); \ + } break; \ + } + struct ExprList { Expr *expr; ExprList *next; @@ -326,26 +399,28 @@ struct ExprList { struct Const: Expr { double value; + Const(): Expr(ConstExpr) {} + void init(Type type, double value) { this->type = type; this->value = value; } - virtual void accept(ExprVisitor *v) { v->visitConst(this); } - virtual Const *asConst() { return this; } + static bool classof(const Expr *c) { return c->exprKind == ConstExpr; } }; struct String: Expr { const QString *value; + String(): Expr(StringExpr) {} + void init(const QString *value) { this->value = value; } - virtual void accept(ExprVisitor *v) { v->visitString(this); } - virtual String *asString() { return this; } + static bool classof(const Expr *c) { return c->exprKind == StringExpr; } }; struct RegExp: Expr { @@ -359,14 +434,15 @@ struct RegExp: Expr { const QString *value; int flags; + RegExp(): Expr(RegExpExpr) {} + void init(const QString *value, int flags) { this->value = value; this->flags = flags; } - virtual void accept(ExprVisitor *v) { v->visitRegExp(this); } - virtual RegExp *asRegExp() { return this; } + static bool classof(const Expr *c) { return c->exprKind == RegExpExpr; } }; struct Name: Expr { @@ -399,13 +475,13 @@ struct Name: Expr { quint32 line; quint32 column; + Name(): Expr(NameExpr) {} + void initGlobal(const QString *id, quint32 line, quint32 column); void init(const QString *id, quint32 line, quint32 column); void init(Builtin builtin, quint32 line, quint32 column); - virtual void accept(ExprVisitor *v) { v->visitName(this); } - virtual bool isLValue() { return true; } - virtual Name *asName() { return this; } + static bool classof(const Expr *c) { return c->exprKind == NameExpr; } }; struct Q_AUTOTEST_EXPORT Temp: Expr { @@ -424,7 +500,8 @@ struct Q_AUTOTEST_EXPORT Temp: Expr { MemberExpressionResolver *memberResolver; Temp() - : index((1 << 28) - 1) + : Expr(TempExpr) + , index((1 << 28) - 1) , isReadOnly(0) , kind(Invalid) , memberResolver(0) @@ -438,9 +515,8 @@ struct Q_AUTOTEST_EXPORT Temp: Expr { } bool isInvalid() const { return kind == Invalid; } - virtual void accept(ExprVisitor *v) { v->visitTemp(this); } - virtual bool isLValue() { return !isReadOnly; } - virtual Temp *asTemp() { return this; } + + static bool classof(const Expr *c) { return c->exprKind == TempExpr; } }; inline bool operator==(const Temp &t1, const Temp &t2) Q_DECL_NOTHROW @@ -479,44 +555,48 @@ struct Q_AUTOTEST_EXPORT ArgLocal: Expr { this->isArgumentsOrEval = false; } - virtual void accept(ExprVisitor *v) { v->visitArgLocal(this); } - virtual bool isLValue() { return true; } - virtual ArgLocal *asArgLocal() { return this; } + ArgLocal(): Expr(ArgLocalExpr) {} bool operator==(const ArgLocal &other) const { return index == other.index && scope == other.scope && kind == other.kind; } + + static bool classof(const Expr *c) { return c->exprKind == ArgLocalExpr; } }; struct Closure: Expr { int value; // index in _module->functions const QString *functionName; + Closure(): Expr(ClosureExpr) {} + void init(int functionInModule, const QString *functionName) { this->value = functionInModule; this->functionName = functionName; } - virtual void accept(ExprVisitor *v) { v->visitClosure(this); } - virtual Closure *asClosure() { return this; } + static bool classof(const Expr *c) { return c->exprKind == ClosureExpr; } }; struct Convert: Expr { Expr *expr; + Convert(): Expr(ConvertExpr) {} + void init(Expr *expr, Type type) { this->expr = expr; this->type = type; } - virtual void accept(ExprVisitor *v) { v->visitConvert(this); } - virtual Convert *asConvert() { return this; } + static bool classof(const Expr *c) { return c->exprKind == ConvertExpr; } }; struct Unop: Expr { - AluOp op; Expr *expr; + AluOp op; + + Unop(): Expr(UnopExpr) {} void init(AluOp op, Expr *expr) { @@ -524,14 +604,15 @@ struct Unop: Expr { this->expr = expr; } - virtual void accept(ExprVisitor *v) { v->visitUnop(this); } - virtual Unop *asUnop() { return this; } + static bool classof(const Expr *c) { return c->exprKind == UnopExpr; } }; struct Binop: Expr { - AluOp op; Expr *left; // Temp or Const Expr *right; // Temp or Const + AluOp op; + + Binop(): Expr(BinopExpr) {} void init(AluOp op, Expr *left, Expr *right) { @@ -540,14 +621,15 @@ struct Binop: Expr { this->right = right; } - virtual void accept(ExprVisitor *v) { v->visitBinop(this); } - virtual Binop *asBinop() { return this; } + static bool classof(const Expr *c) { return c->exprKind == BinopExpr; } }; struct Call: Expr { Expr *base; // Name, Member, Temp ExprList *args; // List of Temps + Call(): Expr(CallExpr) {} + void init(Expr *base, ExprList *args) { this->base = base; @@ -560,14 +642,15 @@ struct Call: Expr { return 0; } - virtual void accept(ExprVisitor *v) { v->visitCall(this); } - virtual Call *asCall() { return this; } + static bool classof(const Expr *c) { return c->exprKind == CallExpr; } }; struct New: Expr { Expr *base; // Name, Member, Temp ExprList *args; // List of Temps + New(): Expr(NewExpr) {} + void init(Expr *base, ExprList *args) { this->base = base; @@ -580,23 +663,22 @@ struct New: Expr { return 0; } - virtual void accept(ExprVisitor *v) { v->visitNew(this); } - virtual New *asNew() { return this; } + static bool classof(const Expr *c) { return c->exprKind == NewExpr; } }; struct Subscript: Expr { Expr *base; Expr *index; + Subscript(): Expr(SubscriptExpr) {} + void init(Expr *base, Expr *index) { this->base = base; this->index = index; } - virtual void accept(ExprVisitor *v) { v->visitSubscript(this); } - virtual bool isLValue() { return true; } - virtual Subscript *asSubscript() { return this; } + static bool classof(const Expr *c) { return c->exprKind == SubscriptExpr; } }; struct Member: Expr { @@ -628,6 +710,8 @@ struct Member: Expr { uchar kind: 3; // MemberKind + Member(): Expr(MemberExpr) {} + void setEnumValue(int value) { kind = MemberOfEnum; enumValue = value; @@ -649,35 +733,52 @@ struct Member: Expr { this->kind = kind; } - virtual void accept(ExprVisitor *v) { v->visitMember(this); } - virtual bool isLValue() { return true; } - virtual Member *asMember() { return this; } + static bool classof(const Expr *c) { return c->exprKind == MemberExpr; } }; +inline bool Expr::isLValue() const { + if (auto t = as<Temp>()) + return !t->isReadOnly; + return exprKind <= LastLValue; +} + struct Stmt { + enum StmtKind: quint8 { + MoveStmt, + ExpStmt, + JumpStmt, + CJumpStmt, + RetStmt, + PhiStmt + }; + + template <typename To> + inline bool isa() const { + return To::classof(this); + } + + template <typename To> + inline To *as() { + if (isa<To>()) + return static_cast<To *>(this); + else + return nullptr; + } + enum { InvalidId = -1 }; QQmlJS::AST::SourceLocation location; - explicit Stmt(int id): _id(id) {} + explicit Stmt(int id, StmtKind stmtKind): _id(id), stmtKind(stmtKind) {} - virtual ~Stmt() - { -#ifdef Q_CC_MSVC - // MSVC complains about potential memory leaks if a destructor never returns. -#else - Q_UNREACHABLE(); -#endif - } - virtual Stmt *asTerminator() { return 0; } + Stmt *asTerminator(); - virtual void accept(StmtVisitor *) = 0; - virtual Exp *asExp() { return 0; } - virtual Move *asMove() { return 0; } - virtual Jump *asJump() { return 0; } - virtual CJump *asCJump() { return 0; } - virtual Ret *asRet() { return 0; } - virtual Phi *asPhi() { return 0; } + Exp *asExp() { return as<Exp>(); } + Move *asMove() { return as<Move>(); } + Jump *asJump() { return as<Jump>(); } + CJump *asCJump() { return as<CJump>(); } + Ret *asRet() { return as<Ret>(); } + Phi *asPhi() { return as<Phi>(); } int id() const { return _id; } @@ -687,21 +788,52 @@ private: // For memory management in BasicBlock private: friend struct Function; int _id; + +public: + const StmtKind stmtKind; }; +#define STMT_VISIT_ALL_KINDS(s) \ + switch (s->stmtKind) { \ + case QV4::IR::Stmt::MoveStmt: { \ + auto casted = s->asMove(); \ + visit(casted->target); \ + visit(casted->source); \ + } break; \ + case QV4::IR::Stmt::ExpStmt: { \ + auto casted = s->asExp(); \ + visit(casted->expr); \ + } break; \ + case QV4::IR::Stmt::JumpStmt: \ + break; \ + case QV4::IR::Stmt::CJumpStmt: { \ + auto casted = s->asCJump(); \ + visit(casted->cond); \ + } break; \ + case QV4::IR::Stmt::RetStmt: { \ + auto casted = s->asRet(); \ + visit(casted->expr); \ + } break; \ + case QV4::IR::Stmt::PhiStmt: { \ + auto casted = s->asPhi(); \ + visit(casted->targetTemp); \ + for (auto *e : casted->incoming) { \ + visit(e); \ + } \ + } break; \ + } + struct Exp: Stmt { Expr *expr; - Exp(int id): Stmt(id) {} + Exp(int id): Stmt(id, ExpStmt) {} void init(Expr *expr) { this->expr = expr; } - virtual void accept(StmtVisitor *v) { v->visitExp(this); } - virtual Exp *asExp() { return this; } - + static bool classof(const Stmt *c) { return c->stmtKind == ExpStmt; } }; struct Move: Stmt { @@ -709,7 +841,7 @@ struct Move: Stmt { Expr *source; bool swap; - Move(int id): Stmt(id) {} + Move(int id): Stmt(id, MoveStmt) {} void init(Expr *target, Expr *source) { @@ -718,25 +850,20 @@ struct Move: Stmt { this->swap = false; } - virtual void accept(StmtVisitor *v) { v->visitMove(this); } - virtual Move *asMove() { return this; } - + static bool classof(const Stmt *c) { return c->stmtKind == MoveStmt; } }; struct Jump: Stmt { BasicBlock *target; - Jump(int id): Stmt(id) {} + Jump(int id): Stmt(id, JumpStmt) {} void init(BasicBlock *target) { this->target = target; } - virtual Stmt *asTerminator() { return this; } - - virtual void accept(StmtVisitor *v) { v->visitJump(this); } - virtual Jump *asJump() { return this; } + static bool classof(const Stmt *c) { return c->stmtKind == JumpStmt; } }; struct CJump: Stmt { @@ -745,7 +872,7 @@ struct CJump: Stmt { BasicBlock *iffalse; BasicBlock *parent; - CJump(int id): Stmt(id) {} + CJump(int id): Stmt(id, CJumpStmt) {} void init(Expr *cond, BasicBlock *iftrue, BasicBlock *iffalse, BasicBlock *parent) { @@ -755,26 +882,20 @@ struct CJump: Stmt { this->parent = parent; } - virtual Stmt *asTerminator() { return this; } - - virtual void accept(StmtVisitor *v) { v->visitCJump(this); } - virtual CJump *asCJump() { return this; } + static bool classof(const Stmt *c) { return c->stmtKind == CJumpStmt; } }; struct Ret: Stmt { Expr *expr; - Ret(int id): Stmt(id) {} + Ret(int id): Stmt(id, RetStmt) {} void init(Expr *expr) { this->expr = expr; } - virtual Stmt *asTerminator() { return this; } - - virtual void accept(StmtVisitor *v) { v->visitRet(this); } - virtual Ret *asRet() { return this; } + static bool classof(const Stmt *c) { return c->stmtKind == RetStmt; } }; // Phi nodes can only occur at the start of a basic block. If there are any, they need to be @@ -785,30 +906,52 @@ struct Phi: Stmt { Temp *targetTemp; VarLengthArray<Expr *, 4> incoming; - Phi(int id): Stmt(id) {} + Phi(int id): Stmt(id, PhiStmt) {} - virtual void accept(StmtVisitor *v) { v->visitPhi(this); } - virtual Phi *asPhi() { return this; } + static bool classof(const Stmt *c) { return c->stmtKind == PhiStmt; } void destroyData() { incoming.~VarLengthArray(); } }; +inline Stmt *Stmt::asTerminator() +{ + if (auto s = asJump()) { + return s; + } else if (auto s = asCJump()) { + return s; + } else if (auto s = asRet()) { + return s; + } else { + return nullptr; + } +} + struct Q_QML_PRIVATE_EXPORT Module { QQmlJS::MemoryPool pool; QVector<Function *> functions; Function *rootFunction; QString fileName; + qint64 sourceTimeStamp; bool isQmlModule; // implies rootFunction is always 0 +#ifdef QT_NO_QML_DEBUGGER + static const bool debugMode = false; +#else bool debugMode; +#endif Function *newFunction(const QString &name, Function *outer); Module(bool debugMode) : rootFunction(0) + , sourceTimeStamp(0) , isQmlModule(false) +#ifndef QT_NO_QML_DEBUGGER , debugMode(debugMode) {} +#else + { Q_UNUSED(debugMode); } +#endif ~Module(); void setFileName(const QString &name); @@ -1060,6 +1203,20 @@ private: unsigned _isRemoved : 1; }; +template <typename T> +class SmallSet: public QVarLengthArray<T, 8> +{ +public: + void insert(int value) + { + for (auto it : *this) { + if (it == value) + return; + } + this->append(value); + } +}; + // Map from meta property index (existence implies dependency) to notify signal index struct KeyValuePair { @@ -1125,14 +1282,15 @@ struct Function { uint isNamedExpression : 1; uint hasTry: 1; uint hasWith: 1; - uint unused : 25; + uint isQmlBinding: 1; + uint unused : 24; - // Location of declaration in source code (-1 if not specified) - int line; - int column; + // Location of declaration in source code (0 if not specified) + uint line; + uint column; // Qml extension: - QSet<int> idObjectDependencies; + SmallSet<int> idObjectDependencies; PropertyDependencyMap contextObjectPropertyDependencies; PropertyDependencyMap scopeObjectPropertyDependencies; @@ -1192,7 +1350,7 @@ private: int _statementCount; }; -class CloneExpr: protected IR::ExprVisitor +class CloneExpr { public: explicit CloneExpr(IR::BasicBlock *block = 0); @@ -1210,7 +1368,7 @@ public: { Expr *c = expr; qSwap(cloned, c); - expr->accept(this); + visit(expr); qSwap(cloned, c); return static_cast<ExprSubclass *>(c); } @@ -1253,23 +1411,10 @@ public: return newArgLocal; } -protected: +private: IR::ExprList *clone(IR::ExprList *list); - virtual void visitConst(Const *); - virtual void visitString(String *); - virtual void visitRegExp(RegExp *); - virtual void visitName(Name *); - virtual void visitTemp(Temp *); - virtual void visitArgLocal(ArgLocal *); - virtual void visitClosure(Closure *); - virtual void visitConvert(Convert *); - virtual void visitUnop(Unop *); - virtual void visitBinop(Binop *); - virtual void visitCall(Call *); - virtual void visitNew(New *); - virtual void visitSubscript(Subscript *); - virtual void visitMember(Member *); + void visit(Expr *e); protected: IR::BasicBlock *block; @@ -1278,7 +1423,7 @@ private: IR::Expr *cloned; }; -class Q_AUTOTEST_EXPORT IRPrinter: public StmtVisitor, public ExprVisitor +class Q_AUTOTEST_EXPORT IRPrinter { public: IRPrinter(QTextStream *out); @@ -1291,6 +1436,7 @@ public: virtual void print(Function *f); virtual void print(BasicBlock *bb); + void visit(Stmt *s); virtual void visitExp(Exp *s); virtual void visitMove(Move *s); virtual void visitJump(Jump *s); @@ -1298,6 +1444,7 @@ public: virtual void visitRet(Ret *s); virtual void visitPhi(Phi *s); + void visit(Expr *e); virtual void visitConst(Const *e); virtual void visitString(String *e); virtual void visitRegExp(RegExp *e); |