Changeset 192950 in webkit


Ignore:
Timestamp:
Dec 2, 2015 11:20:12 AM (8 years ago)
Author:
mark.lam@apple.com
Message:

Use the JITAddGenerator snippet in the FTL.
https://bugs.webkit.org/show_bug.cgi?id=151519

Reviewed by Geoffrey Garen.

One detail about how we choosing to handle operands to the binary snippets that
may be constant: the slow path call to a C++ function still needs the constant
operand loaded in a register. To simplify things, we're choosing to always tell
LLVM to load the operands into registers even if they may be constant. However,
even though a constant operand is preloaded in a register, the snippet generator
will not be made aware of it. It will continue to load the constant as an
immediate.

  • ftl/FTLCompile.cpp:
  • ftl/FTLCompileBinaryOp.cpp:

(JSC::FTL::generateArithSubFastPath):
(JSC::FTL::generateValueAddFastPath):

  • generateValueAddFastPath() currently is an exact copy of generateArithSubFastPath() except that it uses JITAddGenerator instead of JITSubGenerator. When we add support for JITMulGenerator later, the code will start to vary. We'll refactor these functions then when we have more insight into what needs to vary between the implementations.
  • ftl/FTLCompileBinaryOp.h:
  • ftl/FTLInlineCacheDescriptor.h:
  • ftl/FTLInlineCacheDescriptorInlines.h:

(JSC::FTL::ValueAddDescriptor::ValueAddDescriptor):
(JSC::FTL::ValueAddDescriptor::icSize):

  • ftl/FTLInlineCacheSize.cpp:

(JSC::FTL::sizeOfValueAdd):

  • ftl/FTLInlineCacheSize.h:
  • ftl/FTLLowerDFGToLLVM.cpp:

(JSC::FTL::DFG::LowerDFGToLLVM::lower):
(JSC::FTL::DFG::LowerDFGToLLVM::compileValueAdd):

Location:
trunk/Source/JavaScriptCore
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r192949 r192950  
     12015-12-02  Mark Lam  <mark.lam@apple.com>
     2
     3        Use the JITAddGenerator snippet in the FTL.
     4        https://bugs.webkit.org/show_bug.cgi?id=151519
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        One detail about how we choosing to handle operands to the binary snippets that
     9        may be constant: the slow path call to a C++ function still needs the constant
     10        operand loaded in a register.  To simplify things, we're choosing to always tell
     11        LLVM to load the operands into registers even if they may be constant.  However,
     12        even though a constant operand is preloaded in a register, the snippet generator
     13        will not be made aware of it.  It will continue to load the constant as an
     14        immediate.
     15
     16        * ftl/FTLCompile.cpp:
     17        * ftl/FTLCompileBinaryOp.cpp:
     18        (JSC::FTL::generateArithSubFastPath):
     19        (JSC::FTL::generateValueAddFastPath):
     20        - generateValueAddFastPath() currently is an exact copy of generateArithSubFastPath()
     21          except that it uses JITAddGenerator instead of JITSubGenerator.  When we add
     22          support for JITMulGenerator later, the code will start to vary.  We'll refactor
     23          these functions then when we have more insight into what needs to vary between
     24          the implementations.
     25
     26        * ftl/FTLCompileBinaryOp.h:
     27        * ftl/FTLInlineCacheDescriptor.h:
     28        * ftl/FTLInlineCacheDescriptorInlines.h:
     29        (JSC::FTL::ValueAddDescriptor::ValueAddDescriptor):
     30        (JSC::FTL::ValueAddDescriptor::icSize):
     31        * ftl/FTLInlineCacheSize.cpp:
     32        (JSC::FTL::sizeOfValueAdd):
     33        * ftl/FTLInlineCacheSize.h:
     34        * ftl/FTLLowerDFGToLLVM.cpp:
     35        (JSC::FTL::DFG::LowerDFGToLLVM::lower):
     36        (JSC::FTL::DFG::LowerDFGToLLVM::compileValueAdd):
     37
    1382015-12-02  Mark Lam  <mark.lam@apple.com>
    239
  • trunk/Source/JavaScriptCore/ftl/FTLCompile.cpp

    r192896 r192950  
    341341            generateArithSubFastPath(ic, fastPathJIT, result, left, right, usedRegisters, done, slowPathStart);
    342342            break;
     343        case ValueAdd:
     344            generateValueAddFastPath(ic, fastPathJIT, result, left, right, usedRegisters, done, slowPathStart);
     345            break;
    343346        default:
    344347            RELEASE_ASSERT_NOT_REACHED();
  • trunk/Source/JavaScriptCore/ftl/FTLCompileBinaryOp.cpp

    r192896 r192950  
    3232#include "FTLInlineCacheDescriptor.h"
    3333#include "GPRInfo.h"
     34#include "JITAddGenerator.h"
    3435#include "JITSubGenerator.h"
    3536#include "ScratchRegisterAllocator.h"
     
    189190}
    190191
     192void generateValueAddFastPath(BinaryOpDescriptor& ic, CCallHelpers& jit,
     193    GPRReg result, GPRReg left, GPRReg right, RegisterSet usedRegisters,
     194    CCallHelpers::Jump& done, CCallHelpers::Jump& slowPathStart)
     195{
     196    ASSERT(ic.nodeType() == ValueAdd);
     197    ScratchRegisterAllocator allocator(usedRegisters);
     198
     199    BinarySnippetRegisterContext context(allocator, result, left, right);
     200
     201    GPRReg scratchGPR = allocator.allocateScratchGPR();
     202    FPRReg leftFPR = allocator.allocateScratchFPR();
     203    FPRReg rightFPR = allocator.allocateScratchFPR();
     204    FPRReg scratchFPR = InvalidFPRReg;
     205
     206    JITAddGenerator gen(ic.leftOperand(), ic.rightOperand(), JSValueRegs(result),
     207        JSValueRegs(left), JSValueRegs(right), leftFPR, rightFPR, scratchGPR, scratchFPR);
     208
     209    auto numberOfBytesUsedToPreserveReusedRegisters =
     210    allocator.preserveReusedRegistersByPushing(jit, ScratchRegisterAllocator::ExtraStackSpace::NoExtraSpace);
     211
     212    context.initializeRegisters(jit);
     213    gen.generateFastPath(jit);
     214
     215    ASSERT(gen.didEmitFastPath());
     216    gen.endJumpList().link(&jit);
     217    context.restoreRegisters(jit);
     218    allocator.restoreReusedRegistersByPopping(jit, numberOfBytesUsedToPreserveReusedRegisters,
     219        ScratchRegisterAllocator::ExtraStackSpace::SpaceForCCall);
     220    done = jit.jump();
     221
     222    gen.slowPathJumpList().link(&jit);
     223    context.restoreRegisters(jit);
     224    allocator.restoreReusedRegistersByPopping(jit, numberOfBytesUsedToPreserveReusedRegisters,
     225        ScratchRegisterAllocator::ExtraStackSpace::SpaceForCCall);
     226    slowPathStart = jit.jump();
     227}
     228
    191229} } // namespace JSC::FTL
    192230
  • trunk/Source/JavaScriptCore/ftl/FTLCompileBinaryOp.h

    r192896 r192950  
    4040    CCallHelpers::Jump& done, CCallHelpers::Jump& slowPathStart);
    4141
     42void generateValueAddFastPath(BinaryOpDescriptor&, CCallHelpers&,
     43    GPRReg result, GPRReg left, GPRReg right, RegisterSet usedRegisters,
     44    CCallHelpers::Jump& done, CCallHelpers::Jump& slowPathStart);
     45
    4246} // namespace FTL
    4347} // namespace JSC
  • trunk/Source/JavaScriptCore/ftl/FTLInlineCacheDescriptor.h

    r192896 r192950  
    172172};
    173173
     174class ValueAddDescriptor : public BinaryOpDescriptor {
     175public:
     176    ValueAddDescriptor(unsigned stackmapID, CodeOrigin, const SnippetOperand& leftOperand, const SnippetOperand& rightOperand);
     177    static size_t icSize();
     178};
     179
    174180// You can create a lazy slow path call in lowerDFGToLLVM by doing:
    175181// m_ftlState.lazySlowPaths.append(
  • trunk/Source/JavaScriptCore/ftl/FTLInlineCacheDescriptorInlines.h

    r192896 r192950  
    4848}
    4949
     50ValueAddDescriptor::ValueAddDescriptor(unsigned stackmapID, CodeOrigin codeOrigin,
     51    const SnippetOperand& leftOperand, const SnippetOperand& rightOperand)
     52    : BinaryOpDescriptor(DFG::ValueAdd, stackmapID, codeOrigin, icSize(),
     53        "ValueAdd", "ValueAdd IC fast path", DFG::operationValueAdd, leftOperand, rightOperand)
     54{
     55}
     56
     57size_t ValueAddDescriptor::icSize()
     58{
     59    return sizeOfValueAdd();
     60}
     61
    5062} } // namespace JSC::FTL
    5163
  • trunk/Source/JavaScriptCore/ftl/FTLInlineCacheSize.cpp

    r192353 r192950  
    142142#else
    143143    return 298; // X86_64 debug.
     144#endif
     145#endif
     146}
     147
     148size_t sizeOfValueAdd()
     149{
     150#if CPU(ARM64)
     151#ifdef NDEBUG
     152    return 180; // ARM64 release.
     153#else
     154    return 276; // ARM64 debug.
     155#endif
     156#else // CPU(X86_64)
     157#ifdef NDEBUG
     158    return 199; // X86_64 release.
     159#else
     160    return 286; // X86_64 debug.
    144161#endif
    145162#endif
  • trunk/Source/JavaScriptCore/ftl/FTLInlineCacheSize.h

    r192334 r192950  
    4848size_t sizeOfIn();
    4949size_t sizeOfArithSub();
     50size_t sizeOfValueAdd();
    5051#if ENABLE(MASM_PROBE)
    5152size_t sizeOfProbe();
  • trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp

    r192912 r192950  
    235235                    case ArithSub:
    236236                    case GetById:
    237                     case GetByIdFlush: {
     237                    case GetByIdFlush:
     238                    case ValueAdd: {
    238239                        // We may have to flush one thing for GetByIds/ArithSubs when the base and result or the left/right and the result
    239240                        // are assigned the same register. For a more comprehensive overview, look at the comment in FTLCompile.cpp
     
    244245                        bool willCatchException = m_graph.willCatchExceptionInMachineFrame(node->origin.forExit, opCatchOrigin, exceptionHandler);
    245246                        if (willCatchException) {
    246                             static const size_t numberOfGetByIdOrSubSpills = 1;
    247                             maxNumberOfCatchSpills = std::max(maxNumberOfCatchSpills, numberOfGetByIdOrSubSpills);
     247                            static const size_t numberOfGetByIdOrBinaryOpSpills = 1;
     248                            maxNumberOfCatchSpills = std::max(maxNumberOfCatchSpills, numberOfGetByIdOrBinaryOpSpills);
    248249                        }
    249250                        break;
     
    14851486    void compileValueAdd()
    14861487    {
    1487         J_JITOperation_EJJ operation;
    1488         if (!(provenType(m_node->child1()) & SpecFullNumber)
    1489             && !(provenType(m_node->child2()) & SpecFullNumber))
    1490             operation = operationValueAddNotNumber;
    1491         else
    1492             operation = operationValueAdd;
    1493         setJSValue(vmCall(
    1494             m_out.int64, m_out.operation(operation), m_callFrame,
    1495             lowJSValue(m_node->child1()), lowJSValue(m_node->child2())));
     1488        auto leftChild = m_node->child1();
     1489        auto rightChild = m_node->child2();
     1490
     1491        if (!(provenType(leftChild) & SpecFullNumber) || !(provenType(rightChild) & SpecFullNumber)) {
     1492            setJSValue(vmCall(m_out.int64, m_out.operation(operationValueAddNotNumber), m_callFrame,
     1493                lowJSValue(leftChild), lowJSValue(rightChild)));
     1494            return;
     1495        }
     1496
     1497        unsigned stackmapID = m_stackmapIDs++;
     1498
     1499        if (Options::verboseCompilation())
     1500            dataLog("    Emitting ValueAdd patchpoint with stackmap #", stackmapID, "\n");
     1501
     1502#if FTL_USES_B3
     1503        CRASH();
     1504#else
     1505        LValue left = lowJSValue(leftChild);
     1506        LValue right = lowJSValue(rightChild);
     1507
     1508        SnippetOperand leftOperand(abstractValue(leftChild).resultType());
     1509        SnippetOperand rightOperand(abstractValue(rightChild).resultType());
     1510
     1511        // The DFG does not always fold the sum of 2 constant int operands together.
     1512        // Because the snippet does not support both operands being constant, if the left
     1513        // operand is already a constant, we'll just pretend the right operand is not.
     1514        if (leftChild->isInt32Constant())
     1515            leftOperand.setConstInt32(leftChild->asInt32());
     1516        if (!leftOperand.isConst() && rightChild->isInt32Constant())
     1517            rightOperand.setConstInt32(rightChild->asInt32());
     1518
     1519        // Arguments: id, bytes, target, numArgs, args...
     1520        StackmapArgumentList arguments;
     1521        arguments.append(m_out.constInt64(stackmapID));
     1522        arguments.append(m_out.constInt32(ValueAddDescriptor::icSize()));
     1523        arguments.append(constNull(m_out.ref8));
     1524        arguments.append(m_out.constInt32(2));
     1525        arguments.append(left);
     1526        arguments.append(right);
     1527
     1528        appendOSRExitArgumentsForPatchpointIfWillCatchException(arguments,
     1529            ExceptionType::BinaryOpGenerator, 3); // left, right, and result show up in the stackmap locations.
     1530
     1531        LValue call = m_out.call(m_out.int64, m_out.patchpointInt64Intrinsic(), arguments);
     1532        setInstructionCallingConvention(call, LLVMAnyRegCallConv);
     1533
     1534        m_ftlState.binaryOps.append(ValueAddDescriptor(stackmapID, m_node->origin.semantic, leftOperand, rightOperand));
     1535
     1536        setJSValue(call);
     1537#endif
    14961538    }
    14971539   
Note: See TracChangeset for help on using the changeset viewer.