aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jit/qv4assembler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/jit/qv4assembler.cpp')
-rw-r--r--src/qml/jit/qv4assembler.cpp341
1 files changed, 254 insertions, 87 deletions
diff --git a/src/qml/jit/qv4assembler.cpp b/src/qml/jit/qv4assembler.cpp
index b0470ed89d..186e5952da 100644
--- a/src/qml/jit/qv4assembler.cpp
+++ b/src/qml/jit/qv4assembler.cpp
@@ -52,15 +52,6 @@
#undef ENABLE_ALL_ASSEMBLERS_FOR_REFACTORING_PURPOSES
-#ifdef Q_STATIC_ASSERT_FOR_SANE_COMPILERS
-# undef Q_STATIC_ASSERT_FOR_SANE_COMPILERS
-#endif
-#if defined(Q_CC_MSVC) && _MSC_VER < 1900
-# define Q_STATIC_ASSERT_FOR_SANE_COMPILERS(x) // insane
-#else
-# define Q_STATIC_ASSERT_FOR_SANE_COMPILERS(x) Q_STATIC_ASSERT(x)
-#endif
-
#ifdef V4_ENABLE_JIT
QT_BEGIN_NAMESPACE
@@ -70,6 +61,7 @@ namespace JIT {
#define callHelper(x) PlatformAssemblerCommon::callRuntime(#x, reinterpret_cast<void *>(&x))
const QV4::Value::ValueTypeInternal IntegerTag = QV4::Value::ValueTypeInternal::Integer;
+const int IsIntegerConvertible_Shift = QV4::Value::IsIntegerConvertible_Shift;
static ReturnedValue toNumberHelper(ReturnedValue v)
{
@@ -89,6 +81,7 @@ struct PlatformAssembler_X86_64_SysV : JSC::MacroAssembler<JSC::MacroAssemblerX8
static const RegisterID NoRegister = RegisterID(-1);
static const RegisterID ReturnValueRegister = RegisterID::eax;
+ static const RegisterID ReturnValueRegisterValue = ReturnValueRegister;
static const RegisterID AccumulatorRegister = RegisterID::eax;
static const RegisterID AccumulatorRegisterValue = AccumulatorRegister;
static const RegisterID ScratchRegister = RegisterID::r10;
@@ -125,7 +118,6 @@ struct PlatformAssembler_X86_64_SysV : JSC::MacroAssembler<JSC::MacroAssemblerX8
push(EngineRegister);
move(Arg0Reg, CppStackFrameRegister);
move(Arg1Reg, EngineRegister);
- loadPtr(Address(CppStackFrameRegister, offsetof(CppStackFrame, jsFrame)), JSStackFrameRegister);
}
void generatePlatformFunctionExit()
@@ -167,6 +159,7 @@ struct PlatformAssembler_Win64 : JSC::MacroAssembler<JSC::MacroAssemblerX86_64>
static const RegisterID NoRegister = RegisterID(-1);
static const RegisterID ReturnValueRegister = RegisterID::eax;
+ static const RegisterID ReturnValueRegisterValue = ReturnValueRegister;
static const RegisterID AccumulatorRegister = RegisterID::eax;
static const RegisterID AccumulatorRegisterValue = AccumulatorRegister;
static const RegisterID ScratchRegister = RegisterID::r10;
@@ -203,7 +196,6 @@ struct PlatformAssembler_Win64 : JSC::MacroAssembler<JSC::MacroAssemblerX86_64>
push(EngineRegister);
move(Arg0Reg, CppStackFrameRegister);
move(Arg1Reg, EngineRegister);
- loadPtr(Address(CppStackFrameRegister, offsetof(CppStackFrame, jsFrame)), JSStackFrameRegister);
}
void generatePlatformFunctionExit()
@@ -285,7 +277,6 @@ struct PlatformAssembler_X86_All : JSC::MacroAssembler<JSC::MacroAssemblerX86>
push(EngineRegister);
loadPtr(Address(FramePointerRegister, 2 * PointerSize), CppStackFrameRegister);
loadPtr(Address(FramePointerRegister, 3 * PointerSize), EngineRegister);
- loadPtr(Address(CppStackFrameRegister, offsetof(CppStackFrame, jsFrame)), JSStackFrameRegister);
}
void generatePlatformFunctionExit()
@@ -328,6 +319,7 @@ struct PlatformAssembler_ARM64 : JSC::MacroAssembler<JSC::MacroAssemblerARM64>
static const RegisterID NoRegister = RegisterID(-1);
static const RegisterID ReturnValueRegister = JSC::ARM64Registers::x0;
+ static const RegisterID ReturnValueRegisterValue = ReturnValueRegister;
static const RegisterID AccumulatorRegister = JSC::ARM64Registers::x9;
static const RegisterID AccumulatorRegisterValue = AccumulatorRegister;
static const RegisterID ScratchRegister = JSC::ARM64Registers::x10;
@@ -639,7 +631,12 @@ struct PlatformAssembler64 : PlatformAssemblerCommon
{
PlatformAssemblerCommon::callRuntime(functionName, funcPtr);
if (dest == Assembler::ResultInAccumulator)
- move(ReturnValueRegister, AccumulatorRegister);
+ saveReturnValueInAccumulator();
+ }
+
+ void saveReturnValueInAccumulator()
+ {
+ move(ReturnValueRegister, AccumulatorRegister);
}
void loadUndefined(RegisterID dest = AccumulatorRegister)
@@ -689,6 +686,11 @@ struct PlatformAssembler64 : PlatformAssemblerCommon
move(TrustedImm64(value), AccumulatorRegister);
}
+ void storeHeapObject(RegisterID source, Address addr)
+ {
+ store64(source, addr);
+ }
+
void generateCatchTrampoline()
{
PlatformAssemblerCommon::generateCatchTrampoline([this](){loadUndefined();});
@@ -715,25 +717,66 @@ struct PlatformAssembler64 : PlatformAssemblerCommon
void toNumber()
{
+ urshift64(AccumulatorRegister, TrustedImm32(Value::QuickType_Shift), ScratchRegister);
+ auto isNumber = branch32(GreaterThanOrEqual, ScratchRegister, TrustedImm32(Value::QT_Int));
+
move(AccumulatorRegister, registerForArg(0));
callHelper(toNumberHelper);
- move(ReturnValueRegister, AccumulatorRegister);
+ saveReturnValueInAccumulator();
+
+ isNumber.link(this);
+ }
+
+ void toInt32LhsAcc(Address lhs, RegisterID lhsTarget)
+ {
+ load64(lhs, lhsTarget);
+ urshift64(lhsTarget, TrustedImm32(Value::QuickType_Shift), ScratchRegister2);
+ auto lhsIsInt = branch32(Equal, TrustedImm32(Value::QT_Int), ScratchRegister2);
+
+ pushAligned(AccumulatorRegister);
+ move(lhsTarget, registerForArg(0));
+ callHelper(toInt32Helper);
+ move(ReturnValueRegister, lhsTarget);
+ popAligned(AccumulatorRegister);
+
+ lhsIsInt.link(this);
+ urshift64(AccumulatorRegister, TrustedImm32(Value::QuickType_Shift), ScratchRegister2);
+ auto isInt = branch32(Equal, TrustedImm32(Value::QT_Int), ScratchRegister2);
+
+ pushAligned(lhsTarget);
+ move(AccumulatorRegister, registerForArg(0));
+ callHelper(toInt32Helper);
+ saveReturnValueInAccumulator();
+ popAligned(lhsTarget);
+
+ isInt.link(this);
}
void toInt32()
{
+ urshift64(AccumulatorRegister, TrustedImm32(Value::QuickType_Shift), ScratchRegister2);
+ auto isInt = branch32(Equal, TrustedImm32(Value::QT_Int), ScratchRegister2);
+
move(AccumulatorRegister, registerForArg(0));
callRuntime("toInt32Helper", reinterpret_cast<void *>(&toInt32Helper),
Assembler::ResultInAccumulator);
+
+ isInt.link(this);
}
void regToInt32(Address srcReg, RegisterID targetReg)
{
+ load64(srcReg, targetReg);
+ urshift64(targetReg, TrustedImm32(Value::QuickType_Shift), ScratchRegister2);
+ auto isInt = branch32(Equal, TrustedImm32(Value::QT_Int), ScratchRegister2);
+
pushAligned(AccumulatorRegister);
- load64(srcReg, registerForArg(0));
+ move(targetReg, registerForArg(0));
callHelper(toInt32Helper);
move(ReturnValueRegister, targetReg);
popAligned(AccumulatorRegister);
+
+ isInt.link(this);
}
void isNullOrUndefined()
@@ -750,6 +793,12 @@ struct PlatformAssembler64 : PlatformAssemblerCommon
isUndef.link(this);
}
+ Jump isIntOrBool()
+ {
+ urshift64(AccumulatorRegister, TrustedImm32(Value::IsIntegerOrBool_Shift), ScratchRegister);
+ return branch32(Equal, TrustedImm32(3), ScratchRegister);
+ }
+
void jumpStrictEqualStackSlotInt(int lhs, int rhs, int offset)
{
Address lhsAddr(JSStackFrameRegister, lhs * int(sizeof(Value)));
@@ -819,8 +868,8 @@ struct PlatformAssembler64 : PlatformAssemblerCommon
Jump unopIntPath(std::function<Jump(void)> fastPath)
{
- urshift64(AccumulatorRegister, TrustedImm32(32), ScratchRegister);
- Jump accNotInt = branch32(NotEqual, TrustedImm32(int(IntegerTag)), ScratchRegister);
+ urshift64(AccumulatorRegister, TrustedImm32(IsIntegerConvertible_Shift), ScratchRegister);
+ Jump accNotIntConvertible = branch32(NotEqual, TrustedImm32(1), ScratchRegister);
// both integer
Jump failure = fastPath();
@@ -829,10 +878,16 @@ struct PlatformAssembler64 : PlatformAssemblerCommon
// all other cases
if (failure.isSet())
failure.link(this);
- accNotInt.link(this);
+ accNotIntConvertible.link(this);
return done;
}
+
+ void callWithAccumulatorByValueAsFirstArgument(std::function<void()> doCall)
+ {
+ passAsArg(AccumulatorRegister, 0);
+ doCall();
+ }
};
typedef PlatformAssembler64 PlatformAssembler;
@@ -845,10 +900,14 @@ struct PlatformAssembler32 : PlatformAssemblerCommon
Assembler::CallResultDestination dest)
{
PlatformAssemblerCommon::callRuntime(functionName, funcPtr);
- if (dest == Assembler::ResultInAccumulator) {
- move(ReturnValueRegisterValue, AccumulatorRegisterValue);
- move(ReturnValueRegisterTag, AccumulatorRegisterTag);
- }
+ if (dest == Assembler::ResultInAccumulator)
+ saveReturnValueInAccumulator();
+ }
+
+ void saveReturnValueInAccumulator()
+ {
+ move(ReturnValueRegisterValue, AccumulatorRegisterValue);
+ move(ReturnValueRegisterTag, AccumulatorRegisterTag);
}
void loadUndefined()
@@ -909,6 +968,14 @@ struct PlatformAssembler32 : PlatformAssemblerCommon
move(TrustedImm32(Value::fromReturnedValue(value).tag()), AccumulatorRegisterTag);
}
+ void storeHeapObject(RegisterID source, Address addr)
+ {
+ store32(source, addr);
+ addr.offset += 4;
+ store32(TrustedImm32(0), addr);
+ }
+
+
void generateCatchTrampoline()
{
PlatformAssemblerCommon::generateCatchTrampoline([this](){loadUndefined();});
@@ -916,6 +983,9 @@ struct PlatformAssembler32 : PlatformAssemblerCommon
void toNumber()
{
+ urshift32(AccumulatorRegisterTag, TrustedImm32(Value::QuickType_Shift - 32), ScratchRegister);
+ auto isNumber = branch32(GreaterThanOrEqual, ScratchRegister, TrustedImm32(Value::QT_Int));
+
if (ArgInRegCount < 2) {
push(AccumulatorRegisterTag);
push(AccumulatorRegisterValue);
@@ -925,14 +995,71 @@ struct PlatformAssembler32 : PlatformAssemblerCommon
}
callRuntime("toNumberHelper", reinterpret_cast<void *>(&toNumberHelper),
Assembler::ResultInAccumulator);
- move(ReturnValueRegisterValue, AccumulatorRegisterValue);
- move(ReturnValueRegisterTag, AccumulatorRegisterTag);
+ saveReturnValueInAccumulator();
if (ArgInRegCount < 2)
addPtr(TrustedImm32(2 * PointerSize), StackPointerRegister);
+
+ isNumber.link(this);
+ }
+
+ void toInt32LhsAcc(Address lhs, RegisterID lhsTarget)
+ {
+ bool accumulatorNeedsSaving = AccumulatorRegisterValue == ReturnValueRegisterValue
+ || AccumulatorRegisterTag == ReturnValueRegisterTag;
+ lhs.offset += 4;
+ load32(lhs, lhsTarget);
+ lhs.offset -= 4;
+ auto lhsIsNotInt = branch32(NotEqual, TrustedImm32(int(IntegerTag)), lhsTarget);
+ load32(lhs, lhsTarget);
+ auto lhsIsInt = jump();
+
+ lhsIsNotInt.link(this);
+ if (accumulatorNeedsSaving) {
+ push(AccumulatorRegisterTag);
+ push(AccumulatorRegisterValue);
+ }
+ if (ArgInRegCount < 2) {
+ push(lhsTarget);
+ load32(lhs, lhsTarget);
+ push(lhsTarget);
+ } else {
+ move(lhsTarget, registerForArg(1));
+ load32(lhs, registerForArg(0));
+ }
+ callHelper(toInt32Helper);
+ move(ReturnValueRegisterValue, lhsTarget);
+ if (ArgInRegCount < 2)
+ addPtr(TrustedImm32(2 * PointerSize), StackPointerRegister);
+ if (accumulatorNeedsSaving) {
+ pop(AccumulatorRegisterValue);
+ pop(AccumulatorRegisterTag);
+ }
+ lhsIsInt.link(this);
+
+ auto rhsIsInt = branch32(Equal, TrustedImm32(int(IntegerTag)), AccumulatorRegisterTag);
+
+ pushAligned(lhsTarget);
+ if (ArgInRegCount < 2) {
+ push(AccumulatorRegisterTag);
+ push(AccumulatorRegisterValue);
+ } else {
+ move(AccumulatorRegisterValue, registerForArg(0));
+ move(AccumulatorRegisterTag, registerForArg(1));
+ }
+ callRuntime("toInt32Helper", reinterpret_cast<void *>(&toInt32Helper),
+ Assembler::ResultInAccumulator);
+ if (ArgInRegCount < 2)
+ addPtr(TrustedImm32(2 * PointerSize), StackPointerRegister);
+ popAligned(lhsTarget);
+
+ rhsIsInt.link(this);
}
void toInt32()
{
+ urshift32(AccumulatorRegisterTag, TrustedImm32(Value::QuickType_Shift - 32), ScratchRegister);
+ auto isInt = branch32(Equal, TrustedImm32(Value::QT_Int), ScratchRegister);
+
if (ArgInRegCount < 2) {
push(AccumulatorRegisterTag);
push(AccumulatorRegisterValue);
@@ -944,6 +1071,8 @@ struct PlatformAssembler32 : PlatformAssemblerCommon
Assembler::ResultInAccumulator);
if (ArgInRegCount < 2)
addPtr(TrustedImm32(2 * PointerSize), StackPointerRegister);
+
+ isInt.link(this);
}
void regToInt32(Address srcReg, RegisterID targetReg)
@@ -990,6 +1119,12 @@ struct PlatformAssembler32 : PlatformAssemblerCommon
done.link(this);
}
+ Jump isIntOrBool()
+ {
+ urshift32(AccumulatorRegisterTag, TrustedImm32(Value::IsIntegerOrBool_Shift - 32), ScratchRegister);
+ return branch32(Equal, TrustedImm32(3), ScratchRegister);
+ }
+
void pushValue(ReturnedValue v)
{
push(TrustedImm32(v >> 32));
@@ -1123,6 +1258,20 @@ struct PlatformAssembler32 : PlatformAssemblerCommon
return done;
}
+
+ void callWithAccumulatorByValueAsFirstArgument(std::function<void()> doCall)
+ {
+ if (ArgInRegCount < 2) {
+ push(AccumulatorRegisterTag);
+ push(AccumulatorRegisterValue);
+ } else {
+ move(AccumulatorRegisterValue, registerForArg(0));
+ move(AccumulatorRegisterTag, registerForArg(1));
+ }
+ doCall();
+ if (ArgInRegCount < 2)
+ addPtr(TrustedImm32(2 * PointerSize), StackPointerRegister);
+ }
};
typedef PlatformAssembler32 PlatformAssembler;
@@ -1170,7 +1319,7 @@ class QIODevicePrintStream: public FilePrintStream
public:
explicit QIODevicePrintStream(QIODevice *dest)
- : FilePrintStream(0)
+ : FilePrintStream(nullptr)
, dest(dest)
, buf(4096, '0')
{
@@ -1224,7 +1373,7 @@ void Assembler::link(Function *function)
jumpTarget.jump.linkTo(pasm()->labelsByOffset[jumpTarget.offset], pasm());
JSC::JSGlobalData dummy(function->internalClass->engine->executableAllocator);
- JSC::LinkBuffer<PlatformAssembler::MacroAssembler> linkBuffer(dummy, pasm(), 0);
+ JSC::LinkBuffer<PlatformAssembler::MacroAssembler> linkBuffer(dummy, pasm(), nullptr);
for (const auto &ehTarget : pasm()->ehTargets) {
auto targetLabel = pasm()->labelsByOffset.value(ehTarget.offset);
@@ -1321,6 +1470,11 @@ void Assembler::loadValue(ReturnedValue value)
pasm()->loadValue(value);
}
+void JIT::Assembler::storeHeapObject(int reg)
+{
+ pasm()->storeHeapObject(PlatformAssembler::ReturnValueRegisterValue, regAddr(reg));
+}
+
void Assembler::toNumber()
{
pasm()->toNumber();
@@ -1342,9 +1496,14 @@ void Assembler::ucompl()
pasm()->setAccumulatorTag(IntegerTag);
}
-static ReturnedValue incHelper(const Value &v)
+static ReturnedValue incHelper(const Value v)
{
- return Encode(v.toNumber() + 1.);
+ double d;
+ if (Q_LIKELY(v.isDouble()))
+ d = v.doubleValue();
+ else
+ d = v.toNumberImpl();
+ return Encode(d + 1.);
}
void Assembler::inc()
@@ -1359,19 +1518,24 @@ void Assembler::inc()
});
// slow path:
- saveAccumulatorInFrame();
- prepareCallWithArgCount(1);
- passAccumulatorAsArg(0);
- IN_JIT_GENERATE_RUNTIME_CALL(incHelper, ResultInAccumulator);
+ pasm()->callWithAccumulatorByValueAsFirstArgument([this]() {
+ pasm()->callHelper(incHelper);
+ pasm()->saveReturnValueInAccumulator();
+ });
checkException();
// done.
done.link(pasm());
}
-static ReturnedValue decHelper(const Value &v)
+static ReturnedValue decHelper(const Value v)
{
- return Encode(v.toNumber() - 1.);
+ double d;
+ if (Q_LIKELY(v.isDouble()))
+ d = v.doubleValue();
+ else
+ d = v.toNumberImpl();
+ return Encode(d - 1.);
}
void Assembler::dec()
@@ -1386,10 +1550,10 @@ void Assembler::dec()
});
// slow path:
- saveAccumulatorInFrame();
- prepareCallWithArgCount(1);
- passAccumulatorAsArg(0);
- IN_JIT_GENERATE_RUNTIME_CALL(decHelper, ResultInAccumulator);
+ pasm()->callWithAccumulatorByValueAsFirstArgument([this]() {
+ pasm()->callHelper(decHelper);
+ pasm()->saveReturnValueInAccumulator();
+ });
checkException();
// done.
@@ -1432,10 +1596,7 @@ void Assembler::add(int lhs)
void Assembler::bitAnd(int lhs)
{
PlatformAssembler::Address lhsAddr = regAddr(lhs);
- pasm()->regToInt32(lhsAddr, PlatformAssembler::ScratchRegister);
- pasm()->pushAligned(PlatformAssembler::ScratchRegister);
- pasm()->toInt32();
- pasm()->popAligned(PlatformAssembler::ScratchRegister);
+ pasm()->toInt32LhsAcc(lhsAddr, PlatformAssembler::ScratchRegister);
pasm()->and32(PlatformAssembler::ScratchRegister, PlatformAssembler::AccumulatorRegisterValue);
pasm()->setAccumulatorTag(IntegerTag);
}
@@ -1443,10 +1604,7 @@ void Assembler::bitAnd(int lhs)
void Assembler::bitOr(int lhs)
{
PlatformAssembler::Address lhsAddr = regAddr(lhs);
- pasm()->regToInt32(lhsAddr, PlatformAssembler::ScratchRegister);
- pasm()->pushAligned(PlatformAssembler::ScratchRegister);
- pasm()->toInt32();
- pasm()->popAligned(PlatformAssembler::ScratchRegister);
+ pasm()->toInt32LhsAcc(lhsAddr, PlatformAssembler::ScratchRegister);
pasm()->or32(PlatformAssembler::ScratchRegister, PlatformAssembler::AccumulatorRegisterValue);
pasm()->setAccumulatorTag(IntegerTag);
}
@@ -1454,10 +1612,7 @@ void Assembler::bitOr(int lhs)
void Assembler::bitXor(int lhs)
{
PlatformAssembler::Address lhsAddr = regAddr(lhs);
- pasm()->regToInt32(lhsAddr, PlatformAssembler::ScratchRegister);
- pasm()->pushAligned(PlatformAssembler::ScratchRegister);
- pasm()->toInt32();
- pasm()->popAligned(PlatformAssembler::ScratchRegister);
+ pasm()->toInt32LhsAcc(lhsAddr, PlatformAssembler::ScratchRegister);
pasm()->xor32(PlatformAssembler::ScratchRegister, PlatformAssembler::AccumulatorRegisterValue);
pasm()->setAccumulatorTag(IntegerTag);
}
@@ -1465,13 +1620,10 @@ void Assembler::bitXor(int lhs)
void Assembler::ushr(int lhs)
{
PlatformAssembler::Address lhsAddr = regAddr(lhs);
- pasm()->regToInt32(lhsAddr, PlatformAssembler::ScratchRegister);
- pasm()->pushAligned(PlatformAssembler::ScratchRegister);
- pasm()->toInt32();
- pasm()->and32(TrustedImm32(0x1f), PlatformAssembler::AccumulatorRegisterValue,
- PlatformAssembler::ScratchRegister);
- pasm()->popAligned(PlatformAssembler::AccumulatorRegisterValue);
- pasm()->urshift32(PlatformAssembler::ScratchRegister, PlatformAssembler::AccumulatorRegisterValue);
+ pasm()->toInt32LhsAcc(lhsAddr, PlatformAssembler::ScratchRegister);
+ pasm()->and32(TrustedImm32(0x1f), PlatformAssembler::AccumulatorRegisterValue);
+ pasm()->urshift32(PlatformAssembler::AccumulatorRegisterValue, PlatformAssembler::ScratchRegister);
+ pasm()->move(PlatformAssembler::ScratchRegister, PlatformAssembler::AccumulatorRegisterValue);
auto doubleEncode = pasm()->branch32(PlatformAssembler::LessThan,
PlatformAssembler::AccumulatorRegisterValue,
TrustedImm32(0));
@@ -1489,26 +1641,20 @@ void Assembler::ushr(int lhs)
void Assembler::shr(int lhs)
{
PlatformAssembler::Address lhsAddr = regAddr(lhs);
- pasm()->regToInt32(lhsAddr, PlatformAssembler::ScratchRegister);
- pasm()->pushAligned(PlatformAssembler::ScratchRegister);
- pasm()->toInt32();
- pasm()->and32(TrustedImm32(0x1f), PlatformAssembler::AccumulatorRegisterValue,
- PlatformAssembler::ScratchRegister);
- pasm()->popAligned(PlatformAssembler::AccumulatorRegisterValue);
- pasm()->rshift32(PlatformAssembler::ScratchRegister, PlatformAssembler::AccumulatorRegisterValue);
+ pasm()->toInt32LhsAcc(lhsAddr, PlatformAssembler::ScratchRegister);
+ pasm()->and32(TrustedImm32(0x1f), PlatformAssembler::AccumulatorRegisterValue);
+ pasm()->rshift32(PlatformAssembler::AccumulatorRegisterValue, PlatformAssembler::ScratchRegister);
+ pasm()->move(PlatformAssembler::ScratchRegister, PlatformAssembler::AccumulatorRegisterValue);
pasm()->setAccumulatorTag(IntegerTag);
}
void Assembler::shl(int lhs)
{
PlatformAssembler::Address lhsAddr = regAddr(lhs);
- pasm()->regToInt32(lhsAddr, PlatformAssembler::ScratchRegister);
- pasm()->pushAligned(PlatformAssembler::ScratchRegister);
- pasm()->toInt32();
- pasm()->and32(TrustedImm32(0x1f), PlatformAssembler::AccumulatorRegisterValue,
- PlatformAssembler::ScratchRegister);
- pasm()->popAligned(PlatformAssembler::AccumulatorRegisterValue);
- pasm()->lshift32(PlatformAssembler::ScratchRegister, PlatformAssembler::AccumulatorRegisterValue);
+ pasm()->toInt32LhsAcc(lhsAddr, PlatformAssembler::ScratchRegister);
+ pasm()->and32(TrustedImm32(0x1f), PlatformAssembler::AccumulatorRegisterValue);
+ pasm()->lshift32(PlatformAssembler::AccumulatorRegisterValue, PlatformAssembler::ScratchRegister);
+ pasm()->move(PlatformAssembler::ScratchRegister, PlatformAssembler::AccumulatorRegisterValue);
pasm()->setAccumulatorTag(IntegerTag);
}
@@ -1537,27 +1683,32 @@ void Assembler::ushrConst(int rhs)
{
rhs &= 0x1f;
pasm()->toInt32();
- if (rhs) // shift with 0 can act weird
+ if (rhs) {
+ // a non zero shift will always give a number encodable as an int
pasm()->urshift32(TrustedImm32(rhs), PlatformAssembler::AccumulatorRegisterValue);
- auto doubleEncode = pasm()->branch32(PlatformAssembler::LessThan,
- PlatformAssembler::AccumulatorRegisterValue,
- TrustedImm32(0));
- pasm()->setAccumulatorTag(IntegerTag);
- auto done = pasm()->jump();
+ pasm()->setAccumulatorTag(IntegerTag);
+ } else {
+ // shift with 0 can lead to a negative result
+ auto doubleEncode = pasm()->branch32(PlatformAssembler::LessThan,
+ PlatformAssembler::AccumulatorRegisterValue,
+ TrustedImm32(0));
+ pasm()->setAccumulatorTag(IntegerTag);
+ auto done = pasm()->jump();
- doubleEncode.link(pasm());
- pasm()->convertUInt32ToDouble(PlatformAssembler::AccumulatorRegisterValue,
- PlatformAssembler::FPScratchRegister,
- PlatformAssembler::ScratchRegister);
- pasm()->encodeDoubleIntoAccumulator(PlatformAssembler::FPScratchRegister);
- done.link(pasm());
+ doubleEncode.link(pasm());
+ pasm()->convertUInt32ToDouble(PlatformAssembler::AccumulatorRegisterValue,
+ PlatformAssembler::FPScratchRegister,
+ PlatformAssembler::ScratchRegister);
+ pasm()->encodeDoubleIntoAccumulator(PlatformAssembler::FPScratchRegister);
+ done.link(pasm());
+ }
}
void Assembler::shrConst(int rhs)
{
rhs &= 0x1f;
pasm()->toInt32();
- if (rhs) // shift with 0 can act weird
+ if (rhs)
pasm()->rshift32(TrustedImm32(rhs), PlatformAssembler::AccumulatorRegisterValue);
pasm()->setAccumulatorTag(IntegerTag);
}
@@ -1566,7 +1717,7 @@ void Assembler::shlConst(int rhs)
{
rhs &= 0x1f;
pasm()->toInt32();
- if (rhs) // shift with 0 can act weird
+ if (rhs)
pasm()->lshift32(TrustedImm32(rhs), PlatformAssembler::AccumulatorRegisterValue);
pasm()->setAccumulatorTag(IntegerTag);
}
@@ -1652,6 +1803,7 @@ void Assembler::cmpneNull()
void Assembler::cmpeqInt(int lhs)
{
+ auto isIntOrBool = pasm()->isIntOrBool();
saveAccumulatorInFrame();
pasm()->pushValueAligned(Encode(lhs));
if (PlatformAssembler::ArgInRegCount < 2)
@@ -1663,10 +1815,18 @@ void Assembler::cmpeqInt(int lhs)
if (PlatformAssembler::ArgInRegCount < 2)
pasm()->addPtr(TrustedImm32(2 * PlatformAssembler::PointerSize), PlatformAssembler::StackPointerRegister);
pasm()->popValueAligned();
+ auto done = pasm()->jump();
+ isIntOrBool.link(pasm());
+ pasm()->compare32(PlatformAssembler::Equal, PlatformAssembler::AccumulatorRegisterValue,
+ TrustedImm32(lhs),
+ PlatformAssembler::AccumulatorRegisterValue);
+ pasm()->setAccumulatorTag(QV4::Value::ValueTypeInternal::Boolean);
+ done.link(pasm());
}
void Assembler::cmpneInt(int lhs)
{
+ auto isIntOrBool = pasm()->isIntOrBool();
saveAccumulatorInFrame();
pasm()->pushValueAligned(Encode(lhs));
if (PlatformAssembler::ArgInRegCount < 2)
@@ -1678,6 +1838,13 @@ void Assembler::cmpneInt(int lhs)
if (PlatformAssembler::ArgInRegCount < 2)
pasm()->addPtr(TrustedImm32(2 * PlatformAssembler::PointerSize), PlatformAssembler::StackPointerRegister);
pasm()->popValueAligned();
+ auto done = pasm()->jump();
+ isIntOrBool.link(pasm());
+ pasm()->compare32(PlatformAssembler::NotEqual, PlatformAssembler::AccumulatorRegisterValue,
+ TrustedImm32(lhs),
+ PlatformAssembler::AccumulatorRegisterValue);
+ pasm()->setAccumulatorTag(QV4::Value::ValueTypeInternal::Boolean);
+ done.link(pasm());
}
void Assembler::cmp(int cond, CmpFunc function, const char *functionName, int lhs)
@@ -1956,7 +2123,7 @@ void Assembler::gotoCatchException()
void Assembler::getException()
{
- Q_STATIC_ASSERT_FOR_SANE_COMPILERS(sizeof(QV4::EngineBase::hasException) == 1);
+ Q_STATIC_ASSERT(sizeof(QV4::EngineBase::hasException) == 1);
Address hasExceptionAddr(PlatformAssembler::EngineRegister,
offsetof(EngineBase, hasException));
@@ -1981,7 +2148,7 @@ void Assembler::setException()
pasm()->loadPtr(addr, PlatformAssembler::ScratchRegister);
pasm()->storeAccumulator(Address(PlatformAssembler::ScratchRegister));
addr.offset = offsetof(EngineBase, hasException);
- Q_STATIC_ASSERT_FOR_SANE_COMPILERS(sizeof(QV4::EngineBase::hasException) == 1);
+ Q_STATIC_ASSERT(sizeof(QV4::EngineBase::hasException) == 1);
pasm()->store8(TrustedImm32(1), addr);
}