Modified: trunk/Source/_javascript_Core/ChangeLog (197654 => 197655)
--- trunk/Source/_javascript_Core/ChangeLog 2016-03-07 02:43:09 UTC (rev 197654)
+++ trunk/Source/_javascript_Core/ChangeLog 2016-03-07 03:21:08 UTC (rev 197655)
@@ -1,5 +1,29 @@
2016-03-06 Benjamin Poulain <benja...@webkit.org>
+ [JSC] Improve DFG's Int32 ArithMul if one operand is a constant
+ https://bugs.webkit.org/show_bug.cgi?id=155066
+
+ Reviewed by Filip Pizlo.
+
+ When multiplying an integer by a constant, DFG was doing quite
+ a bit worse than baseline JIT.
+ We were loading the constant into a register, doing the multiply,
+ the checking the result and both operands for negative zero.
+
+ This patch changes:
+ -Use the multiply-by-immediate form on x86.
+ -Do as few checks as possible to detect negative-zero.
+
+ In most cases, this reduce the negative-zero checks
+ to zero or one TEST+JUMP.
+
+ * assembler/MacroAssembler.h:
+ (JSC::MacroAssembler::mul32):
+ * dfg/DFGSpeculativeJIT.cpp:
+ (JSC::DFG::SpeculativeJIT::compileArithMul):
+
+2016-03-06 Benjamin Poulain <benja...@webkit.org>
+
[JSC] Remove a superfluous Move in front of every double unboxing
https://bugs.webkit.org/show_bug.cgi?id=155064
Modified: trunk/Source/_javascript_Core/assembler/MacroAssembler.h (197654 => 197655)
--- trunk/Source/_javascript_Core/assembler/MacroAssembler.h 2016-03-07 02:43:09 UTC (rev 197654)
+++ trunk/Source/_javascript_Core/assembler/MacroAssembler.h 2016-03-07 03:21:08 UTC (rev 197655)
@@ -115,6 +115,7 @@
using MacroAssemblerBase::compare32;
using MacroAssemblerBase::move;
using MacroAssemblerBase::add32;
+ using MacroAssemblerBase::mul32;
using MacroAssemblerBase::and32;
using MacroAssemblerBase::branchAdd32;
using MacroAssemblerBase::branchMul32;
@@ -1488,6 +1489,27 @@
addPtr(imm.asTrustedImm32(), dest);
}
+ void mul32(Imm32 imm, RegisterID src, RegisterID dest)
+ {
+ if (shouldBlind(imm)) {
+ if (src != dest || haveScratchRegisterForBlinding()) {
+ if (src == dest) {
+ move(src, scratchRegisterForBlinding());
+ src = ""
+ }
+ loadXorBlindedConstant(xorBlindConstant(imm), dest);
+ mul32(src, dest);
+ return;
+ }
+ // If we don't have a scratch register available for use, we'll just
+ // place a random number of nops.
+ uint32_t nopCount = random() & 3;
+ while (nopCount--)
+ nop();
+ }
+ mul32(imm.asTrustedImm32(), src, dest);
+ }
+
void and32(Imm32 imm, RegisterID dest)
{
if (shouldBlind(imm)) {
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (197654 => 197655)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2016-03-07 02:43:09 UTC (rev 197654)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2016-03-07 03:21:08 UTC (rev 197655)
@@ -3671,6 +3671,38 @@
{
switch (node->binaryUseKind()) {
case Int32Use: {
+ if (node->child2()->isInt32Constant()) {
+ SpeculateInt32Operand op1(this, node->child1());
+ GPRTemporary result(this);
+
+ int32_t imm = node->child2()->asInt32();
+ GPRReg op1GPR = op1.gpr();
+ GPRReg resultGPR = result.gpr();
+
+ if (!shouldCheckOverflow(node->arithMode()))
+ m_jit.mul32(Imm32(imm), op1GPR, resultGPR);
+ else {
+ speculationCheck(Overflow, JSValueRegs(), 0,
+ m_jit.branchMul32(MacroAssembler::Overflow, op1GPR, Imm32(imm), resultGPR));
+ }
+
+ // The only way to create negative zero with a constant is:
+ // -negative-op1 * 0.
+ // -zero-op1 * negative constant.
+ if (shouldCheckNegativeZero(node->arithMode())) {
+ if (!imm)
+ speculationCheck(NegativeZero, JSValueRegs(), 0, m_jit.branchTest32(MacroAssembler::Signed, op1GPR));
+ else if (imm < 0) {
+ if (shouldCheckOverflow(node->arithMode()))
+ speculationCheck(NegativeZero, JSValueRegs(), 0, m_jit.branchTest32(MacroAssembler::Zero, resultGPR));
+ else
+ speculationCheck(NegativeZero, JSValueRegs(), 0, m_jit.branchTest32(MacroAssembler::Zero, op1GPR));
+ }
+ }
+
+ int32Result(resultGPR, node);
+ return;
+ }
SpeculateInt32Operand op1(this, node->child1());
SpeculateInt32Operand op2(this, node->child2());
GPRTemporary result(this);
@@ -3693,16 +3725,16 @@
// Check for negative zero, if the users of this node care about such things.
if (shouldCheckNegativeZero(node->arithMode())) {
MacroAssembler::Jump resultNonZero = m_jit.branchTest32(MacroAssembler::NonZero, result.gpr());
- speculationCheck(NegativeZero, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::LessThan, reg1, TrustedImm32(0)));
- speculationCheck(NegativeZero, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::LessThan, reg2, TrustedImm32(0)));
+ speculationCheck(NegativeZero, JSValueRegs(), 0, m_jit.branchTest32(MacroAssembler::Signed, reg1));
+ speculationCheck(NegativeZero, JSValueRegs(), 0, m_jit.branchTest32(MacroAssembler::Signed, reg2));
resultNonZero.link(&m_jit);
}
int32Result(result.gpr(), node);
return;
}
-
-#if USE(JSVALUE64)
+
+#if USE(JSVALUE64)
case Int52RepUse: {
ASSERT(shouldCheckOverflow(node->arithMode()));