Changeset 95754 in webkit


Ignore:
Timestamp:
Sep 22, 2011 3:02:24 PM (13 years ago)
Author:
fpizlo@apple.com
Message:

DFG JIT should support integer division
https://bugs.webkit.org/show_bug.cgi?id=68597

Reviewed by Darin Adler.

This adds support for ArithDiv speculating integer, and speculating
that the result is integer (i.e. remainder = 0).

This is a 4% win on Kraken and a 1% loss on V8.

  • bytecode/CodeBlock.h:
  • dfg/DFGByteCodeParser.cpp:

(JSC::DFG::ByteCodeParser::makeDivSafe):
(JSC::DFG::ByteCodeParser::parseBlock):

  • dfg/DFGNode.h:

(JSC::DFG::Node::hasArithNodeFlags):

  • dfg/DFGPropagator.cpp:

(JSC::DFG::Propagator::propagateArithNodeFlags):
(JSC::DFG::Propagator::propagateNodePredictions):
(JSC::DFG::Propagator::fixupNode):

  • dfg/DFGSpeculativeJIT.cpp:

(JSC::DFG::SpeculativeJIT::compile):

  • jit/JITArithmetic.cpp:

(JSC::JIT::emit_op_div):

Location:
trunk/Source/JavaScriptCore
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r95753 r95754  
     12011-09-22  Filip Pizlo  <fpizlo@apple.com>
     2
     3        DFG JIT should support integer division
     4        https://bugs.webkit.org/show_bug.cgi?id=68597
     5
     6        Reviewed by Darin Adler.
     7       
     8        This adds support for ArithDiv speculating integer, and speculating
     9        that the result is integer (i.e. remainder = 0).
     10       
     11        This is a 4% win on Kraken and a 1% loss on V8.
     12
     13        * bytecode/CodeBlock.h:
     14        * dfg/DFGByteCodeParser.cpp:
     15        (JSC::DFG::ByteCodeParser::makeDivSafe):
     16        (JSC::DFG::ByteCodeParser::parseBlock):
     17        * dfg/DFGNode.h:
     18        (JSC::DFG::Node::hasArithNodeFlags):
     19        * dfg/DFGPropagator.cpp:
     20        (JSC::DFG::Propagator::propagateArithNodeFlags):
     21        (JSC::DFG::Propagator::propagateNodePredictions):
     22        (JSC::DFG::Propagator::fixupNode):
     23        * dfg/DFGSpeculativeJIT.cpp:
     24        (JSC::DFG::SpeculativeJIT::compile):
     25        * jit/JITArithmetic.cpp:
     26        (JSC::JIT::emit_op_div):
     27
    1282011-09-22  Oliver Hunt  <oliver@apple.com>
    229
  • trunk/Source/JavaScriptCore/bytecode/CodeBlock.h

    r95681 r95754  
    538538        }
    539539       
     540        bool likelyToTakeSpecialFastCase(int bytecodeOffset)
     541        {
     542            unsigned specialFastCaseCount = specialFastCaseProfileForBytecodeOffset(bytecodeOffset)->m_counter;
     543            return specialFastCaseCount >= slowCaseThreshold();
     544        }
     545       
    540546        bool likelyToTakeDeepestSlowCase(int bytecodeOffset)
    541547        {
     
    543549            unsigned specialFastCaseCount = specialFastCaseProfileForBytecodeOffset(bytecodeOffset)->m_counter;
    544550            return (slowCaseCount - specialFastCaseCount) >= slowCaseThreshold();
     551        }
     552       
     553        bool likelyToTakeAnySlowCase(int bytecodeOffset)
     554        {
     555            unsigned slowCaseCount = rareCaseProfileForBytecodeOffset(bytecodeOffset)->m_counter;
     556            unsigned specialFastCaseCount = specialFastCaseProfileForBytecodeOffset(bytecodeOffset)->m_counter;
     557            return (slowCaseCount + specialFastCaseCount) >= slowCaseThreshold();
    545558        }
    546559       
  • trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp

    r95753 r95754  
    537537            break;
    538538        }
     539       
     540        return nodeIndex;
     541    }
     542   
     543    NodeIndex makeDivSafe(NodeIndex nodeIndex)
     544    {
     545        ASSERT(m_graph[nodeIndex].op == ArithDiv);
     546       
     547        // The main slow case counter for op_div in the old JIT counts only when
     548        // the operands are not numbers. We don't care about that since we already
     549        // have speculations in place that take care of that separately. We only
     550        // care about when the outcome of the division is not an integer, which
     551        // is what the special fast case counter tells us.
     552       
     553        if (!m_profiledBlock->likelyToTakeSpecialFastCase(m_currentIndex))
     554            return nodeIndex;
     555       
     556        m_graph[nodeIndex].mergeArithNodeFlags(NodeMayOverflow | NodeMayNegZero);
    539557       
    540558        return nodeIndex;
     
    917935            NodeIndex op1 = getToNumber(currentInstruction[2].u.operand);
    918936            NodeIndex op2 = getToNumber(currentInstruction[3].u.operand);
    919             set(currentInstruction[1].u.operand, addToGraph(ArithDiv, op1, op2));
     937            set(currentInstruction[1].u.operand, makeDivSafe(addToGraph(ArithDiv, OpInfo(NodeUseBottom), op1, op2)));
    920938            NEXT_OPCODE(op_div);
    921939        }
  • trunk/Source/JavaScriptCore/dfg/DFGNode.h

    r95753 r95754  
    491491        case ArithMax:
    492492        case ArithMod:
     493        case ArithDiv:
    493494        case ValueAdd:
    494495            return true;
  • trunk/Source/JavaScriptCore/dfg/DFGPropagator.cpp

    r95753 r95754  
    212212        }
    213213           
    214         case ArithMul: {
     214        case ArithMul:
     215        case ArithDiv: {
    215216            // As soon as a multiply happens, we can easily end up in the part
    216217            // of the double domain where the point at which you do truncation
     
    423424        case ArithMul:
    424425        case ArithMin:
    425         case ArithMax: {
     426        case ArithMax:
     427        case ArithDiv: {
    426428            PredictedType left = m_predictions[node.child1()];
    427429            PredictedType right = m_predictions[node.child2()];
     
    436438        }
    437439           
    438         case ArithDiv:
    439440        case ArithSqrt: {
    440441            changed |= setPrediction(makePrediction(PredictDouble, StrongPrediction));
     
    650651        case ArithMin:
    651652        case ArithMax:
    652         case ArithMod: {
     653        case ArithMod:
     654        case ArithDiv: {
    653655            if (!nodeCanSpeculateInteger(node.arithNodeFlags())) {
    654656                toDouble(node.child1());
     
    666668                    toDouble(node.child1());
    667669            }
    668             break;
    669         }
    670            
    671         case ArithDiv: {
    672             toDouble(node.child1());
    673             toDouble(node.child2());
    674670            break;
    675671        }
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp

    r95753 r95754  
    10991099
    11001100    case ArithDiv: {
     1101        if (shouldSpeculateInteger(node.child1(), node.child2()) && nodeCanSpeculateInteger(node.arithNodeFlags())) {
     1102            SpeculateIntegerOperand op1(this, node.child1());
     1103            SpeculateIntegerOperand op2(this, node.child2());
     1104            GPRTemporary eax(this, X86Registers::eax);
     1105            GPRTemporary edx(this, X86Registers::edx);
     1106            GPRReg op1GPR = op1.gpr();
     1107            GPRReg op2GPR = op2.gpr();
     1108           
     1109            speculationCheck(m_jit.branchTest32(JITCompiler::Zero, op2GPR));
     1110           
     1111            // If the user cares about negative zero, then speculate that we're not about
     1112            // to produce negative zero.
     1113            if (!nodeCanIgnoreNegativeZero(node.arithNodeFlags())) {
     1114                MacroAssembler::Jump numeratorNonZero = m_jit.branchTest32(MacroAssembler::NonZero, op1GPR);
     1115                speculationCheck(m_jit.branch32(MacroAssembler::LessThan, op2GPR, TrustedImm32(0)));
     1116                numeratorNonZero.link(&m_jit);
     1117            }
     1118           
     1119            GPRReg temp2 = InvalidGPRReg;
     1120            if (op2GPR == X86Registers::eax || op2GPR == X86Registers::edx) {
     1121                temp2 = allocate();
     1122                m_jit.move(op2GPR, temp2);
     1123                op2GPR = temp2;
     1124            }
     1125           
     1126            m_jit.move(op1GPR, eax.gpr());
     1127            m_jit.assembler().cdq();
     1128            m_jit.assembler().idivl_r(op2GPR);
     1129           
     1130            // Check that there was no remainder. If there had been, then we'd be obligated to
     1131            // produce a double result instead.
     1132            speculationCheck(m_jit.branchTest32(JITCompiler::NonZero, edx.gpr()));
     1133           
     1134            integerResult(eax.gpr(), m_compileIndex);
     1135            break;
     1136        }
     1137       
    11011138        SpeculateDoubleOperand op1(this, node.child1());
    11021139        SpeculateDoubleOperand op2(this, node.child2());
  • trunk/Source/JavaScriptCore/jit/JITArithmetic.cpp

    r95563 r95754  
    10481048    }
    10491049    divDouble(fpRegT1, fpRegT0);
    1050 
     1050   
     1051#if ENABLE(DFG_JIT)
     1052    // Is the result actually an integer? The DFG JIT would really like to know. If it's
     1053    // not an integer, we increment a count. If this together with the slow case counter
     1054    // are below threshold then the DFG JIT will compile this division with a specualtion
     1055    // that the remainder is zero.
     1056   
     1057    // As well, there are cases where a double result here would cause an important field
     1058    // in the heap to sometimes have doubles in it, resulting in double predictions getting
     1059    // propagated to a use site where it might cause damage (such as the index to an array
     1060    // access). So if we are DFG compiling anything in the program, we want this code to
     1061    // ensure that it produces integers whenever possible.
     1062   
     1063    // FIXME: This will fail to convert to integer if the result is zero. We should
     1064    // distinguish between positive zero and negative zero here.
     1065   
     1066    JumpList notInteger;
     1067    branchConvertDoubleToInt32(fpRegT0, regT0, notInteger, fpRegT1);
     1068    // If we've got an integer, we might as well make that the result of the division.
     1069    emitFastArithReTagImmediate(regT0, regT0);
     1070    Jump isInteger = jump();
     1071    notInteger.link(this);
     1072    add32(Imm32(1), AbsoluteAddress(&m_codeBlock->addSpecialFastCaseProfile(m_bytecodeOffset)->m_counter));
     1073    moveDoubleToPtr(fpRegT0, regT0);
     1074    subPtr(tagTypeNumberRegister, regT0);
     1075    isInteger.link(this);
     1076#else
    10511077    // Double result.
    10521078    moveDoubleToPtr(fpRegT0, regT0);
    10531079    subPtr(tagTypeNumberRegister, regT0);
     1080#endif
    10541081
    10551082    emitPutVirtualRegister(dst, regT0);
Note: See TracChangeset for help on using the changeset viewer.