From 1b30e8f94cc15352583e8e1f27139676683f62af Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Tue, 20 Mar 2018 22:40:07 +0100 Subject: Implement support for the ** and **= operators Change-Id: I58a21e70fdd040175b52465d6ba52e7fceaf6398 Reviewed-by: Simon Hausmann --- src/qml/compiler/qv4codegen.cpp | 11 +++++++++++ src/qml/compiler/qv4instr_moth.cpp | 4 ++++ src/qml/compiler/qv4instr_moth_p.h | 2 ++ src/qml/jit/qv4jit.cpp | 19 +++++++++++++++++++ src/qml/jit/qv4jit_p.h | 1 + src/qml/jsruntime/qv4vme_moth.cpp | 7 +++++++ src/qml/parser/qqmljs.g | 18 ++++++++++++++++-- src/qml/parser/qqmljsast_p.h | 2 ++ src/qml/parser/qqmljslexer.cpp | 4 ++++ tests/auto/qml/ecmascripttests/TestExpectations | 25 ------------------------- 10 files changed, 66 insertions(+), 27 deletions(-) diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp index 29a916bd7e..1feb61ce59 100644 --- a/src/qml/compiler/qv4codegen.cpp +++ b/src/qml/compiler/qv4codegen.cpp @@ -727,6 +727,7 @@ static QSOperator::Op baseOp(int op) case QSOperator::InplaceAdd: return QSOperator::Add; case QSOperator::InplaceLeftShift: return QSOperator::LShift; case QSOperator::InplaceMod: return QSOperator::Mod; + case QSOperator::InplaceExp: return QSOperator::Exp; case QSOperator::InplaceMul: return QSOperator::Mul; case QSOperator::InplaceOr: return QSOperator::BitOr; case QSOperator::InplaceRightShift: return QSOperator::RShift; @@ -836,6 +837,7 @@ bool Codegen::visit(BinaryExpression *ast) case QSOperator::InplaceAdd: case QSOperator::InplaceLeftShift: case QSOperator::InplaceMod: + case QSOperator::InplaceExp: case QSOperator::InplaceMul: case QSOperator::InplaceOr: case QSOperator::InplaceRightShift: @@ -885,6 +887,7 @@ bool Codegen::visit(BinaryExpression *ast) case QSOperator::StrictNotEqual: case QSOperator::Add: case QSOperator::Div: + case QSOperator::Exp: case QSOperator::Mod: case QSOperator::Mul: case QSOperator::Sub: @@ -937,6 +940,14 @@ Codegen::Reference Codegen::binopHelper(QSOperator::Op oper, Reference &left, Re } break; } + case QSOperator::Exp: { + left = left.storeOnStack(); + right.loadInAccumulator(); + Instruction::Exp exp; + exp.lhs = left.stackSlot(); + bytecodeGenerator->addInstruction(exp); + break; + } case QSOperator::Mul: { left = left.storeOnStack(); right.loadInAccumulator(); diff --git a/src/qml/compiler/qv4instr_moth.cpp b/src/qml/compiler/qv4instr_moth.cpp index dbdef418a0..c50e9c8379 100644 --- a/src/qml/compiler/qv4instr_moth.cpp +++ b/src/qml/compiler/qv4instr_moth.cpp @@ -608,6 +608,10 @@ void dumpBytecode(const char *code, int len, int nLocals, int nFormals, int /*st d << "acc, " << rhs; MOTH_END_INSTR(ShlConst) + MOTH_BEGIN_INSTR(Exp) + d << dumpRegister(lhs, nFormals) << ", acc"; + MOTH_END_INSTR(Exp) + MOTH_BEGIN_INSTR(Mul) d << dumpRegister(lhs, nFormals) << ", acc"; MOTH_END_INSTR(Mul) diff --git a/src/qml/compiler/qv4instr_moth_p.h b/src/qml/compiler/qv4instr_moth_p.h index 7047c74803..763e0adce1 100644 --- a/src/qml/compiler/qv4instr_moth_p.h +++ b/src/qml/compiler/qv4instr_moth_p.h @@ -171,6 +171,7 @@ QT_BEGIN_NAMESPACE #define INSTR_UShrConst(op) INSTRUCTION(op, UShrConst, 1, rhs) #define INSTR_ShrConst(op) INSTRUCTION(op, ShrConst, 1, rhs) #define INSTR_ShlConst(op) INSTRUCTION(op, ShlConst, 1, rhs) +#define INSTR_Exp(op) INSTRUCTION(op, Exp, 1, lhs) #define INSTR_Mul(op) INSTRUCTION(op, Mul, 1, lhs) #define INSTR_Div(op) INSTRUCTION(op, Div, 1, lhs) #define INSTR_Mod(op) INSTRUCTION(op, Mod, 1, lhs) @@ -290,6 +291,7 @@ QT_BEGIN_NAMESPACE F(UShrConst) \ F(ShrConst) \ F(ShlConst) \ + F(Exp) \ F(Mul) \ F(Div) \ F(Mod) \ diff --git a/src/qml/jit/qv4jit.cpp b/src/qml/jit/qv4jit.cpp index 429d721ba2..aa9c244a60 100644 --- a/src/qml/jit/qv4jit.cpp +++ b/src/qml/jit/qv4jit.cpp @@ -912,6 +912,22 @@ void BaselineJIT::generate_UShrConst(int rhs) { as->ushrConst(rhs); } void BaselineJIT::generate_ShrConst(int rhs) { as->shrConst(rhs); } void BaselineJIT::generate_ShlConst(int rhs) { as->shlConst(rhs); } +static ReturnedValue expHelper(const Value &base, const Value &exp) +{ + double b = base.toNumber(); + double e = exp.toNumber(); + return QV4::Encode(pow(b,e)); +} + +void BaselineJIT::generate_Exp(int lhs) { + STORE_IP(); + STORE_ACC(); + as->prepareCallWithArgCount(2); + as->passAccumulatorAsArg(1); + as->passRegAsArg(lhs, 0); + JIT_GENERATE_RUNTIME_CALL(expHelper, Assembler::ResultInAccumulator); + as->checkException(); +} void BaselineJIT::generate_Mul(int lhs) { as->mul(lhs); } void BaselineJIT::generate_Div(int lhs) { as->div(lhs); } void BaselineJIT::generate_Mod(int lhs) { as->mod(lhs); } @@ -1335,6 +1351,9 @@ void BaselineJIT::collectLabelsInBytecode() MOTH_BEGIN_INSTR(ShlConst) MOTH_END_INSTR(ShlConst) + MOTH_BEGIN_INSTR(Exp) + MOTH_END_INSTR(Exp) + MOTH_BEGIN_INSTR(Mul) MOTH_END_INSTR(Mul) diff --git a/src/qml/jit/qv4jit_p.h b/src/qml/jit/qv4jit_p.h index 62866895c4..7861cdec38 100644 --- a/src/qml/jit/qv4jit_p.h +++ b/src/qml/jit/qv4jit_p.h @@ -237,6 +237,7 @@ public: void generate_UShrConst(int rhs) override; void generate_ShrConst(int rhs) override; void generate_ShlConst(int rhs) override; + void generate_Exp(int lhs) override; void generate_Mul(int lhs) override; void generate_Div(int lhs) override; void generate_Mod(int lhs) override; diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp index a2a602ac58..f2c9f836ae 100644 --- a/src/qml/jsruntime/qv4vme_moth.cpp +++ b/src/qml/jsruntime/qv4vme_moth.cpp @@ -1273,6 +1273,13 @@ QV4::ReturnedValue VME::exec(const FunctionObject *fo, const Value *thisObject, } MOTH_END_INSTR(Sub) + MOTH_BEGIN_INSTR(Exp) + const Value left = STACK_VALUE(lhs); + double base = left.toNumber(); + double exp = ACC.toNumber(); + acc = QV4::Encode(pow(base,exp)); + MOTH_END_INSTR(Exp) + MOTH_BEGIN_INSTR(Mul) const Value left = STACK_VALUE(lhs); if (Q_LIKELY(Value::integerCompatible(left, ACC))) { diff --git a/src/qml/parser/qqmljs.g b/src/qml/parser/qqmljs.g index 7defdb8a08..6ee4fe2b18 100644 --- a/src/qml/parser/qqmljs.g +++ b/src/qml/parser/qqmljs.g @@ -63,7 +63,8 @@ %token T_RBRACE "}" T_RBRACKET "]" T_REMAINDER "%" %token T_REMAINDER_EQ "%=" T_RETURN "return" T_RPAREN ")" %token T_SEMICOLON ";" T_AUTOMATIC_SEMICOLON T_STAR "*" -%token T_STAR_STAR "**" T_STAR_EQ "*=" T_STRING_LITERAL "string literal" +%token T_STAR_STAR "**" T_STAR_STAR_EQ "**=" T_STAR_EQ "*=" +%token T_STRING_LITERAL "string literal" %token T_PROPERTY "property" T_SIGNAL "signal" T_READONLY "readonly" %token T_SWITCH "switch" T_THIS "this" T_THROW "throw" %token T_TILDE "~" T_TRY "try" T_TYPEOF "typeof" @@ -2186,7 +2187,13 @@ UnaryExpression: T_NOT UnaryExpression; ExponentiationExpression: UnaryExpression; ExponentiationExpression: UpdateExpression T_STAR_STAR ExponentiationExpression; -/. case $rule_number: { UNIMPLEMENTED; } ./ +/. + case $rule_number: { + AST::BinaryExpression *node = new (pool) AST::BinaryExpression(sym(1).Expression, QSOperator::Exp, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; + } break; +./ MultiplicativeExpression: ExponentiationExpression; @@ -2489,6 +2496,13 @@ AssignmentOperator: T_STAR_EQ; } break; ./ +AssignmentOperator: T_STAR_STAR_EQ; +/. + case $rule_number: { + sym(1).ival = QSOperator::InplaceExp; + } break; +./ + AssignmentOperator: T_DIVIDE_EQ; /. case $rule_number: { diff --git a/src/qml/parser/qqmljsast_p.h b/src/qml/parser/qqmljsast_p.h index cd5c3a1021..6992985097 100644 --- a/src/qml/parser/qqmljsast_p.h +++ b/src/qml/parser/qqmljsast_p.h @@ -77,6 +77,8 @@ enum Op { Div, InplaceDiv, Equal, + Exp, + InplaceExp, Ge, Gt, In, diff --git a/src/qml/parser/qqmljslexer.cpp b/src/qml/parser/qqmljslexer.cpp index 1165183483..1617f3dfa5 100644 --- a/src/qml/parser/qqmljslexer.cpp +++ b/src/qml/parser/qqmljslexer.cpp @@ -661,6 +661,10 @@ again: return T_STAR_EQ; } else if (_char == QLatin1Char('*')) { scanChar(); + if (_char == QLatin1Char('=')) { + scanChar(); + return T_STAR_STAR_EQ; + } return T_STAR_STAR; } return T_STAR; diff --git a/tests/auto/qml/ecmascripttests/TestExpectations b/tests/auto/qml/ecmascripttests/TestExpectations index 3acbee0d14..753381698f 100644 --- a/tests/auto/qml/ecmascripttests/TestExpectations +++ b/tests/auto/qml/ecmascripttests/TestExpectations @@ -5496,34 +5496,9 @@ language/expressions/equals/get-symbol-to-prim-err language/expressions/equals/symbol-abstract-equality-comparison language/expressions/equals/symbol-strict-equality-comparison language/expressions/equals/to-prim-hint -language/expressions/exponentiation/applying-the-exp-operator_A1 -language/expressions/exponentiation/applying-the-exp-operator_A11 -language/expressions/exponentiation/applying-the-exp-operator_A12 -language/expressions/exponentiation/applying-the-exp-operator_A13 -language/expressions/exponentiation/applying-the-exp-operator_A14 -language/expressions/exponentiation/applying-the-exp-operator_A15 -language/expressions/exponentiation/applying-the-exp-operator_A16 -language/expressions/exponentiation/applying-the-exp-operator_A17 -language/expressions/exponentiation/applying-the-exp-operator_A18 -language/expressions/exponentiation/applying-the-exp-operator_A19 -language/expressions/exponentiation/applying-the-exp-operator_A2 -language/expressions/exponentiation/applying-the-exp-operator_A20 -language/expressions/exponentiation/applying-the-exp-operator_A21 -language/expressions/exponentiation/applying-the-exp-operator_A22 -language/expressions/exponentiation/applying-the-exp-operator_A23 -language/expressions/exponentiation/applying-the-exp-operator_A3 -language/expressions/exponentiation/applying-the-exp-operator_A4 -language/expressions/exponentiation/applying-the-exp-operator_A5 -language/expressions/exponentiation/applying-the-exp-operator_A6 language/expressions/exponentiation/applying-the-exp-operator_A7 language/expressions/exponentiation/applying-the-exp-operator_A8 -language/expressions/exponentiation/applying-the-exp-operator_A9 -language/expressions/exponentiation/exp-assignment-operator -language/expressions/exponentiation/exp-operator -language/expressions/exponentiation/exp-operator-evaluation-order -language/expressions/exponentiation/exp-operator-precedence-unary-expression-semantics language/expressions/exponentiation/exp-operator-precedence-update-expression-semantics -language/expressions/exponentiation/int32_min-exponent language/expressions/exponentiation/order-of-evaluation language/expressions/function/arguments-with-arguments-fn language/expressions/function/arguments-with-arguments-lex -- cgit v1.2.3