From 44a47106419ea4daea077320cf5f857fe6ae8b47 Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Wed, 11 Oct 2017 11:59:40 +0200 Subject: Remove Binop/BinopContext instructions and implement missing binops Change-Id: Ibefac50246045066c90c4c2dbc36d2776c5dab0e Reviewed-by: Lars Knoll --- src/qml/compiler/qv4codegen.cpp | 109 ++++++++++++++----------------------- src/qml/compiler/qv4instr_moth.cpp | 30 +++++++--- src/qml/compiler/qv4instr_moth_p.h | 18 ++++-- src/qml/jsruntime/qv4value_p.h | 7 ++- src/qml/jsruntime/qv4vme_moth.cpp | 49 ++++++++++++----- 5 files changed, 115 insertions(+), 98 deletions(-) diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp index eac107fc16..0bf043d3fc 100644 --- a/src/qml/compiler/qv4codegen.cpp +++ b/src/qml/compiler/qv4codegen.cpp @@ -67,54 +67,6 @@ using namespace QV4; using namespace QV4::Compiler; using namespace QQmlJS::AST; -static inline QV4::Runtime::RuntimeMethods aluOpFunction(QSOperator::Op op) -{ - switch (op) { - case QSOperator::Invalid: - return QV4::Runtime::InvalidRuntimeMethod; - case QSOperator::Add: - return QV4::Runtime::InvalidRuntimeMethod; - case QSOperator::Sub: - return QV4::Runtime::sub; - case QSOperator::Mul: - return QV4::Runtime::mul; - case QSOperator::Div: - return QV4::Runtime::div; - case QSOperator::Mod: - return QV4::Runtime::mod; - case QSOperator::LShift: - return QV4::Runtime::shl; - case QSOperator::RShift: - return QV4::Runtime::shr; - case QSOperator::URShift: - return QV4::Runtime::ushr; - case QSOperator::Gt: - return QV4::Runtime::greaterThan; - case QSOperator::Lt: - return QV4::Runtime::lessThan; - case QSOperator::Ge: - return QV4::Runtime::greaterEqual; - case QSOperator::Le: - return QV4::Runtime::lessEqual; - case QSOperator::Equal: - return QV4::Runtime::equal; - case QSOperator::NotEqual: - return QV4::Runtime::notEqual; - case QSOperator::StrictEqual: - return QV4::Runtime::strictEqual; - case QSOperator::StrictNotEqual: - return QV4::Runtime::strictNotEqual; - case QSOperator::BitAnd: - case QSOperator::BitOr: - case QSOperator::BitXor: - Q_UNREACHABLE(); - // fall through - default: - Q_ASSERT(!"Unknown AluOp"); - return QV4::Runtime::InvalidRuntimeMethod; - } -}; - Codegen::Codegen(QV4::Compiler::JSUnitGenerator *jsUnitGenerator, bool strict) : _module(0) , _returnAddress(0) @@ -931,6 +883,22 @@ Codegen::Reference Codegen::binopHelper(QSOperator::Op oper, Reference &left, Re bytecodeGenerator->addInstruction(mul); break; } + case QSOperator::Div: { + left = left.storeOnStack(); + right.loadInAccumulator(); + Instruction::Div div; + div.lhs = left.stackSlot(); + bytecodeGenerator->addInstruction(div); + break; + } + case QSOperator::Mod: { + left = left.storeOnStack(); + right.loadInAccumulator(); + Instruction::Mod mod; + mod.lhs = left.stackSlot(); + bytecodeGenerator->addInstruction(mod); + break; + } case QSOperator::BitAnd: if (right.isConst()) { int rightAsInt = Primitive::fromReturnedValue(right.constant).toInt32(); @@ -985,6 +953,19 @@ Codegen::Reference Codegen::binopHelper(QSOperator::Op oper, Reference &left, Re bytecodeGenerator->addInstruction(bitXor); } break; + case QSOperator::URShift: + if (right.isConst()) { + left.loadInAccumulator(); + Instruction::UShrConst ushr; + ushr.rhs = Primitive::fromReturnedValue(right.constant).toInt32() & 0x1f; + bytecodeGenerator->addInstruction(ushr); + } else { + right.loadInAccumulator(); + Instruction::UShr ushr; + ushr.lhs = left.stackSlot(); + bytecodeGenerator->addInstruction(ushr); + } + break; case QSOperator::RShift: if (right.isConst()) { left.loadInAccumulator(); @@ -1011,14 +992,16 @@ Codegen::Reference Codegen::binopHelper(QSOperator::Op oper, Reference &left, Re bytecodeGenerator->addInstruction(shl); } break; - case QSOperator::InstanceOf: + case QSOperator::InstanceOf: { + Instruction::CmpInstanceOf binop; + left = left.storeOnStack(); + right.loadInAccumulator(); + binop.lhs = left.stackSlot(); + bytecodeGenerator->addInstruction(binop); + break; + } case QSOperator::In: { - Instruction::BinopContext binop; - if (oper == QSOperator::InstanceOf) - binop.alu = QV4::Runtime::instanceof; - else - binop.alu = QV4::Runtime::in; - Q_ASSERT(binop.alu != QV4::Runtime::InvalidRuntimeMethod); + Instruction::CmpIn binop; left = left.storeOnStack(); right.loadInAccumulator(); binop.lhs = left.stackSlot(); @@ -1112,17 +1095,8 @@ Codegen::Reference Codegen::binopHelper(QSOperator::Op oper, Reference &left, Re cmp.lhs = left.stackSlot(); bytecodeGenerator->addInstruction(cmp); break; - default: { - auto binopFunc = aluOpFunction(oper); - Q_ASSERT(binopFunc != QV4::Runtime::InvalidRuntimeMethod); - left = left.storeOnStack(); - right.loadInAccumulator(); - Instruction::Binop binop; - binop.alu = binopFunc; - binop.lhs = left.stackSlot(); - bytecodeGenerator->addInstruction(binop); - break; - } + default: + Q_UNREACHABLE(); } return Reference::fromAccumulator(this); @@ -1244,7 +1218,8 @@ Codegen::Reference Codegen::jumpBinop(QSOperator::Op oper, Reference &left, Refe addCJump(); break; } - default: Q_UNIMPLEMENTED(); Q_UNREACHABLE(); + default: + Q_UNREACHABLE(); } return Reference(); } diff --git a/src/qml/compiler/qv4instr_moth.cpp b/src/qml/compiler/qv4instr_moth.cpp index 6e29c97927..ea19233a3d 100644 --- a/src/qml/compiler/qv4instr_moth.cpp +++ b/src/qml/compiler/qv4instr_moth.cpp @@ -530,10 +530,6 @@ void dumpBytecode(const char *code, int len, int nLocals, int nFormals, int /*st MOTH_BEGIN_INSTR(Decrement) MOTH_END_INSTR(PreDecrement) - MOTH_BEGIN_INSTR(Binop) - d << alu << ", " << dumpRegister(lhs, nFormals) << ", acc"; - MOTH_END_INSTR(Binop) - MOTH_BEGIN_INSTR(Add) d << dumpRegister(lhs, nFormals) << ", acc"; MOTH_END_INSTR(Add) @@ -550,6 +546,10 @@ void dumpBytecode(const char *code, int len, int nLocals, int nFormals, int /*st d << dumpRegister(lhs, nFormals) << ", acc"; MOTH_END_INSTR(BitXor) + MOTH_BEGIN_INSTR(UShr) + d << dumpRegister(lhs, nFormals) << ", acc"; + MOTH_END_INSTR(UShr) + MOTH_BEGIN_INSTR(Shr) d << dumpRegister(lhs, nFormals) << ", acc"; MOTH_END_INSTR(Shr) @@ -570,6 +570,10 @@ void dumpBytecode(const char *code, int len, int nLocals, int nFormals, int /*st d << "acc, " << rhs; MOTH_END_INSTR(BitXor) + MOTH_BEGIN_INSTR(UShrConst) + d << "acc, " << rhs; + MOTH_END_INSTR(UShrConst) + MOTH_BEGIN_INSTR(ShrConst) d << "acc, " << rhs; MOTH_END_INSTR(ShrConst) @@ -582,13 +586,25 @@ void dumpBytecode(const char *code, int len, int nLocals, int nFormals, int /*st d << dumpRegister(lhs, nFormals) << ", acc"; MOTH_END_INSTR(Mul) + MOTH_BEGIN_INSTR(Div) + d << dumpRegister(lhs, nFormals) << ", acc"; + MOTH_END_INSTR(Div) + + MOTH_BEGIN_INSTR(Mod) + d << dumpRegister(lhs, nFormals) << ", acc"; + MOTH_END_INSTR(Mod) + MOTH_BEGIN_INSTR(Sub) d << dumpRegister(lhs, nFormals) << ", acc"; MOTH_END_INSTR(Sub) - MOTH_BEGIN_INSTR(BinopContext) - d << alu << " " << dumpRegister(lhs, nFormals) << ", acc"; - MOTH_END_INSTR(BinopContext) + MOTH_BEGIN_INSTR(CmpIn) + d << dumpRegister(lhs, nFormals) << ", acc"; + MOTH_END_INSTR(CmpIn) + + MOTH_BEGIN_INSTR(CmpInstanceOf) + d << dumpRegister(lhs, nFormals) << ", acc"; + MOTH_END_INSTR(CmpInstanceOf) MOTH_BEGIN_INSTR(Ret) MOTH_END_INSTR(Ret) diff --git a/src/qml/compiler/qv4instr_moth_p.h b/src/qml/compiler/qv4instr_moth_p.h index 398970b60f..d81762f25b 100644 --- a/src/qml/compiler/qv4instr_moth_p.h +++ b/src/qml/compiler/qv4instr_moth_p.h @@ -154,6 +154,8 @@ QT_BEGIN_NAMESPACE #define INSTR_CmpLe(op) INSTRUCTION(op, CmpLe, 1, lhs) #define INSTR_CmpStrictEqual(op) INSTRUCTION(op, CmpStrictEqual, 1, lhs) #define INSTR_CmpStrictNotEqual(op) INSTRUCTION(op, CmpStrictNotEqual, 1, lhs) +#define INSTR_CmpIn(op) INSTRUCTION(op, CmpIn, 1, lhs) +#define INSTR_CmpInstanceOf(op) INSTRUCTION(op, CmpInstanceOf, 1, lhs) #define INSTR_JumpStrictEqualStackSlotInt(op) INSTRUCTION(op, JumpStrictEqualStackSlotInt, 3, lhs, rhs, offset) #define INSTR_JumpStrictNotEqualStackSlotInt(op) INSTRUCTION(op, JumpStrictNotEqualStackSlotInt, 3, lhs, rhs, offset) #define INSTR_UNot(op) INSTRUCTION(op, UNot, 0) @@ -162,23 +164,23 @@ QT_BEGIN_NAMESPACE #define INSTR_UCompl(op) INSTRUCTION(op, UCompl, 0) #define INSTR_Increment(op) INSTRUCTION(op, Increment, 0) #define INSTR_Decrement(op) INSTRUCTION(op, Decrement, 0) -// alu is QV4::Runtime::RuntimeMethods enum value -#define INSTR_Binop(op) INSTRUCTION(op, Binop, 2, alu, lhs) #define INSTR_Add(op) INSTRUCTION(op, Add, 1, lhs) #define INSTR_BitAnd(op) INSTRUCTION(op, BitAnd, 1, lhs) #define INSTR_BitOr(op) INSTRUCTION(op, BitOr, 1, lhs) #define INSTR_BitXor(op) INSTRUCTION(op, BitXor, 1, lhs) +#define INSTR_UShr(op) INSTRUCTION(op, UShr, 1, lhs) #define INSTR_Shr(op) INSTRUCTION(op, Shr, 1, lhs) #define INSTR_Shl(op) INSTRUCTION(op, Shl, 1, lhs) #define INSTR_BitAndConst(op) INSTRUCTION(op, BitAndConst, 1, rhs) #define INSTR_BitOrConst(op) INSTRUCTION(op, BitOrConst, 1, rhs) #define INSTR_BitXorConst(op) INSTRUCTION(op, BitXorConst, 1, rhs) +#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_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) #define INSTR_Sub(op) INSTRUCTION(op, Sub, 1, lhs) -// alu is offset inside the runtime methods -#define INSTR_BinopContext(op) INSTRUCTION(op, BinopContext, 2, alu, lhs) #define INSTR_LoadQmlContext(op) INSTRUCTION(op, LoadQmlContext, 1, result) #define INSTR_LoadQmlImportedScripts(op) INSTRUCTION(op, LoadQmlImportedScripts, 1, result) #define INSTR_LoadQmlSingleton(op) INSTRUCTION(op, LoadQmlSingleton, 1, name) @@ -267,6 +269,8 @@ QT_BEGIN_NAMESPACE F(CmpLe) \ F(CmpStrictEqual) \ F(CmpStrictNotEqual) \ + F(CmpIn) \ + F(CmpInstanceOf) \ F(JumpStrictEqualStackSlotInt) \ F(JumpStrictNotEqualStackSlotInt) \ F(UNot) \ @@ -275,21 +279,23 @@ QT_BEGIN_NAMESPACE F(UCompl) \ F(Increment) \ F(Decrement) \ - F(Binop) \ F(Add) \ F(BitAnd) \ F(BitOr) \ F(BitXor) \ + F(UShr) \ F(Shr) \ F(Shl) \ F(BitAndConst) \ F(BitOrConst) \ F(BitXorConst) \ + F(UShrConst) \ F(ShrConst) \ F(ShlConst) \ F(Mul) \ + F(Div) \ + F(Mod) \ F(Sub) \ - F(BinopContext) \ F(LoadQmlContext) \ F(LoadQmlImportedScripts) \ F(LoadQmlSingleton) diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h index 63433b7955..8497d47800 100644 --- a/src/qml/jsruntime/qv4value_p.h +++ b/src/qml/jsruntime/qv4value_p.h @@ -788,12 +788,13 @@ ReturnedValue value_convert(ExecutionEngine *e, const Value &v); inline int Value::toInt32() const { - if (integerCompatible()) + if (Q_LIKELY(integerCompatible())) return int_32(); - double d = isDouble() ? doubleValue() : toNumberImpl(); + if (Q_LIKELY(isDouble())) + return Double::toInt32(doubleValue()); - return Double::toInt32(d); + return Double::toInt32(toNumberImpl()); } inline unsigned int Value::toUInt32() const diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp index 4abd3582dd..6823cf0000 100644 --- a/src/qml/jsruntime/qv4vme_moth.cpp +++ b/src/qml/jsruntime/qv4vme_moth.cpp @@ -496,7 +496,6 @@ static bool compareEqualInt(Value &accumulator, Value lhs, int rhs) } \ } while (false) - QV4::ReturnedValue VME::exec(CallData *callData, QV4::Function *function) { qt_v4ResolvePendingBreakpointsHook(); @@ -1091,6 +1090,18 @@ QV4::ReturnedValue VME::exec(CallData *callData, QV4::Function *function) } MOTH_END_INSTR(CmpStrictNotEqual) + MOTH_BEGIN_INSTR(CmpIn) + STORE_ACC(); + acc = Runtime::method_in(engine, STACK_VALUE(lhs), accumulator); + CHECK_EXCEPTION; + MOTH_END_INSTR(CmpIn) + + MOTH_BEGIN_INSTR(CmpInstanceOf) + STORE_ACC(); + acc = Runtime::method_instanceof(engine, STACK_VALUE(lhs), accumulator); + CHECK_EXCEPTION; + MOTH_END_INSTR(CmpInstanceOf) + MOTH_BEGIN_INSTR(JumpStrictNotEqualStackSlotInt) if (STACK_VALUE(lhs).int_32() != rhs || STACK_VALUE(lhs).isUndefined()) code += offset; @@ -1159,13 +1170,6 @@ QV4::ReturnedValue VME::exec(CallData *callData, QV4::Function *function) } MOTH_END_INSTR(Decrement) - MOTH_BEGIN_INSTR(Binop) - QV4::Runtime::BinaryOperation op = *reinterpret_cast(reinterpret_cast(&engine->runtime.runtimeMethods[alu])); - STORE_ACC(); - acc = op(STACK_VALUE(lhs), accumulator); - CHECK_EXCEPTION; - MOTH_END_INSTR(Binop) - MOTH_BEGIN_INSTR(Add) const Value left = STACK_VALUE(lhs); if (Q_LIKELY(Value::integerCompatible(left, ACC))) { @@ -1205,6 +1209,18 @@ QV4::ReturnedValue VME::exec(CallData *callData, QV4::Function *function) } MOTH_END_INSTR(Mul) + MOTH_BEGIN_INSTR(Div) + STORE_ACC(); + acc = Runtime::method_div(STACK_VALUE(lhs), accumulator); + CHECK_EXCEPTION; + MOTH_END_INSTR(Div) + + MOTH_BEGIN_INSTR(Mod) + STORE_ACC(); + acc = Runtime::method_mod(STACK_VALUE(lhs), accumulator); + CHECK_EXCEPTION; + MOTH_END_INSTR(Mod) + MOTH_BEGIN_INSTR(BitAnd) VALUE_TO_INT(l, STACK_VALUE(lhs)); VALUE_TO_INT(a, ACC); @@ -1223,6 +1239,12 @@ QV4::ReturnedValue VME::exec(CallData *callData, QV4::Function *function) acc = Encode(l ^ a); MOTH_END_INSTR(BitXor) + MOTH_BEGIN_INSTR(UShr) + uint l = STACK_VALUE(lhs).toUInt32(); + VALUE_TO_INT(a, ACC); + acc = Encode(l >> uint(a & 0x1f)); + MOTH_END_INSTR(UShr) + MOTH_BEGIN_INSTR(Shr) VALUE_TO_INT(l, STACK_VALUE(lhs)); VALUE_TO_INT(a, ACC); @@ -1251,6 +1273,10 @@ QV4::ReturnedValue VME::exec(CallData *callData, QV4::Function *function) acc = Encode(a ^ rhs); MOTH_END_INSTR(BitXorConst) + MOTH_BEGIN_INSTR(UShrConst) + acc = Encode(ACC.toUInt32() >> uint(rhs)); + MOTH_END_INSTR(UShrConst) + MOTH_BEGIN_INSTR(ShrConst) VALUE_TO_INT(a, ACC); acc = Encode(a >> rhs); @@ -1261,13 +1287,6 @@ QV4::ReturnedValue VME::exec(CallData *callData, QV4::Function *function) acc = Encode(a << rhs); MOTH_END_INSTR(ShlConst) - MOTH_BEGIN_INSTR(BinopContext) - STORE_ACC(); - QV4::Runtime::BinaryOperationContext op = *reinterpret_cast(reinterpret_cast(&engine->runtime.runtimeMethods[alu])); - acc = op(engine, STACK_VALUE(lhs), accumulator); - CHECK_EXCEPTION; - MOTH_END_INSTR(BinopContext) - MOTH_BEGIN_INSTR(Ret) goto functionExit; MOTH_END_INSTR(Ret) -- cgit v1.2.3