diff options
-rw-r--r-- | src/qml/compiler/qv4codegen.cpp | 22 | ||||
-rw-r--r-- | src/qml/compiler/qv4instr_moth.cpp | 9 | ||||
-rw-r--r-- | src/qml/compiler/qv4instr_moth_p.h | 14 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4vme_moth.cpp | 51 |
4 files changed, 91 insertions, 5 deletions
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp index 379db2cd9c..5a7c12d0a2 100644 --- a/src/qml/compiler/qv4codegen.cpp +++ b/src/qml/compiler/qv4codegen.cpp @@ -1064,19 +1064,33 @@ Codegen::Reference Codegen::jumpBinop(QSOperator::Op oper, Reference &left, Refe jumpTarget = _expr.iffalse(); } - if (right.isConst()) { - if (right.constant == Encode::null() || right.constant == Encode::undefined()) { + if (right.isConst() && (oper == QSOperator::Equal || oper == QSOperator::NotEqual)) { + Value c = Primitive::fromReturnedValue(right.constant); + if (c.isNull() || c.isUndefined()) { + left.loadInAccumulator(); if (oper == QSOperator::Equal) { - left.loadInAccumulator(); Instruction::CmpJmpEqNull cjump; bytecodeGenerator->addJumpInstruction(cjump).link(*jumpTarget); return Reference(); } else if (oper == QSOperator::NotEqual) { - left.loadInAccumulator(); Instruction::CmpJmpNeNull cjump; bytecodeGenerator->addJumpInstruction(cjump).link(*jumpTarget); return Reference(); } + } else if (c.isInt32()) { + left.loadInAccumulator(); + if (oper == QSOperator::Equal) { + Instruction::CmpJmpEqInt cjump; + cjump.lhs = c.int_32(); + bytecodeGenerator->addJumpInstruction(cjump).link(*jumpTarget); + return Reference(); + } else if (oper == QSOperator::NotEqual) { + Instruction::CmpJmpNeInt cjump; + cjump.lhs = c.int_32(); + bytecodeGenerator->addJumpInstruction(cjump).link(*jumpTarget); + return Reference(); + } + } } diff --git a/src/qml/compiler/qv4instr_moth.cpp b/src/qml/compiler/qv4instr_moth.cpp index c1d99162f5..f3da508266 100644 --- a/src/qml/compiler/qv4instr_moth.cpp +++ b/src/qml/compiler/qv4instr_moth.cpp @@ -398,6 +398,15 @@ void dumpBytecode(const char *code, int len, int nLocals, int nFormals) d << absoluteInstructionOffset(start, instr); MOTH_END_INSTR(CmpJmpNeNull) + MOTH_BEGIN_INSTR(CmpJmpEqInt) + d << instr.lhs << ", " << absoluteInstructionOffset(start, instr); + MOTH_END_INSTR(CmpJmpEq) + + MOTH_BEGIN_INSTR(CmpJmpNeInt) + d << instr.lhs << ", " << absoluteInstructionOffset(start, instr); + MOTH_END_INSTR(CmpJmpNe) + + MOTH_BEGIN_INSTR(CmpJmpEq) d << instr.lhs.dump(nFormals) << ", " << absoluteInstructionOffset(start, instr); MOTH_END_INSTR(CmpJmpEq) diff --git a/src/qml/compiler/qv4instr_moth_p.h b/src/qml/compiler/qv4instr_moth_p.h index cb55e84442..c7e999e2e1 100644 --- a/src/qml/compiler/qv4instr_moth_p.h +++ b/src/qml/compiler/qv4instr_moth_p.h @@ -142,6 +142,8 @@ QT_BEGIN_NAMESPACE F(JumpNe, jumpNe) \ F(CmpJmpEqNull, cmpJmpEqNull) \ F(CmpJmpNeNull, cmpJmpNeNull) \ + F(CmpJmpEqInt, cmpJmpEqInt) \ + F(CmpJmpNeInt, cmpJmpNeInt) \ F(CmpJmpEq, cmpJmpEq) \ F(CmpJmpNe, cmpJmpNe) \ F(CmpJmpGt, cmpJmpGt) \ @@ -580,6 +582,16 @@ union Instr MOTH_INSTR_HEADER ptrdiff_t offset; }; + struct instr_cmpJmpEqInt { + MOTH_INSTR_HEADER + int lhs; + ptrdiff_t offset; + }; + struct instr_cmpJmpNeInt { + MOTH_INSTR_HEADER + int lhs; + ptrdiff_t offset; + }; struct instr_cmpJmpEq { MOTH_INSTR_HEADER StackSlot lhs; @@ -800,6 +812,8 @@ union Instr instr_jumpNe jumpNe; instr_cmpJmpEqNull cmpJmpEqNull; instr_cmpJmpNeNull cmpJmpNeNull; + instr_cmpJmpEqInt cmpJmpEqInt; + instr_cmpJmpNeInt cmpJmpNeInt; instr_cmpJmpEq cmpJmpEq; instr_cmpJmpNe cmpJmpNe; instr_cmpJmpGt cmpJmpGt; diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp index 69c53aa8b6..d8d900f2bd 100644 --- a/src/qml/jsruntime/qv4vme_moth.cpp +++ b/src/qml/jsruntime/qv4vme_moth.cpp @@ -400,6 +400,7 @@ static inline const QV4::Value &constant(Function *function, int index) static bool compareEqual(Value lhs, Value rhs) { + redo: if (lhs.asReturnedValue() == rhs.asReturnedValue()) return !lhs.isNaN(); @@ -458,7 +459,7 @@ static bool compareEqual(Value lhs, Value rhs) else lhs = Primitive::fromReturnedValue(RuntimeHelpers::objectDefaultValue(&static_cast<QV4::Object &>(lhs), PREFERREDTYPE_HINT)); } - return compareEqual(lhs, rhs); + goto redo; case Value::QT_Empty: Q_UNREACHABLE(); case Value::QT_Null: @@ -485,6 +486,36 @@ static bool compareEqual(Value lhs, Value rhs) } } +static bool compareEqualInt(Value lhs, int rhs) +{ + redo: + switch (lhs.quickType()) { + case Value::QT_ManagedOrUndefined: + if (lhs.isUndefined()) + return false; + Q_FALLTHROUGH(); + case Value::QT_ManagedOrUndefined1: + case Value::QT_ManagedOrUndefined2: + case Value::QT_ManagedOrUndefined3: + // LHS: Managed + if (lhs.m()->vtable()->isString) + return RuntimeHelpers::toNumber(lhs) == rhs; + else + lhs = Primitive::fromReturnedValue(RuntimeHelpers::objectDefaultValue(&static_cast<QV4::Object &>(lhs), PREFERREDTYPE_HINT)); + goto redo; + case Value::QT_Empty: + Q_UNREACHABLE(); + case Value::QT_Null: + return false; + case Value::QT_Bool: + case Value::QT_Int: + return lhs.int_32() == rhs; + default: // double + return lhs.doubleValue() == rhs; + } +} + + QV4::ReturnedValue VME::exec(const FunctionObject *jsFunction, CallData *callData, Heap::ExecutionContext *context, QV4::Function *function) { qt_v4ResolvePendingBreakpointsHook(); @@ -906,6 +937,24 @@ QV4::ReturnedValue VME::exec(const FunctionObject *jsFunction, CallData *callDat code = reinterpret_cast<const uchar *>(&instr.offset) + instr.offset; MOTH_END_INSTR(CmpJmpNeNull) + MOTH_BEGIN_INSTR(CmpJmpEqInt) + if (accumulator.isIntOrBool()) { + if (accumulator.int_32() == instr.lhs) + code = reinterpret_cast<const uchar *>(&instr.offset) + instr.offset; + } else if (compareEqualInt(accumulator, instr.lhs)) { + code = reinterpret_cast<const uchar *>(&instr.offset) + instr.offset; + } + MOTH_END_INSTR(CmpJmpEqInt) + + MOTH_BEGIN_INSTR(CmpJmpNeInt) + if (accumulator.isIntOrBool()) { + if (accumulator.int_32() != instr.lhs) + code = reinterpret_cast<const uchar *>(&instr.offset) + instr.offset; + } else if (!compareEqualInt(accumulator, instr.lhs)) { + code = reinterpret_cast<const uchar *>(&instr.offset) + instr.offset; + } + MOTH_END_INSTR(CmpJmpNeInt) + MOTH_BEGIN_INSTR(CmpJmpEq) const Value lhs = STACK_VALUE(instr.lhs); if (Q_LIKELY(lhs.asReturnedValue() == accumulator.asReturnedValue())) { |