Ignore:
Timestamp:
Dec 2, 2015, 9:42:56 PM (10 years ago)
Author:
[email protected]
Message:

Polymorphic operand types for DFG and FTL mul.
https://bugs.webkit.org/show_bug.cgi?id=151746

Reviewed by Filip Pizlo.

Source/JavaScriptCore:

Perf on benchmarks is neutral except for the newly added JSRegress ftl-object-mul
test which shows a 2.16x speed up on x86_64 FTL, 1.27x speed up on x86_64 DFG,
and 1.56x on x86 DFG.

The speed up comes not from the mul operator itself, but from the fact that the
polymorphic operand types support now allow the test function to run without OSR
exiting, thereby realizing the DFG and FTL's speed up on other work that the test
function does.

This patch has passed the layout tests on x86_64 with a debug build.
It passed the JSC tests with x86 and x86_64 debug builds.

  • dfg/DFGAbstractInterpreterInlines.h:

(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):

  • dfg/DFGClobberize.h:

(JSC::DFG::clobberize):

  • dfg/DFGFixupPhase.cpp:

(JSC::DFG::FixupPhase::fixupNode):

  • dfg/DFGOperations.cpp:
  • dfg/DFGOperations.h:
  • dfg/DFGPredictionPropagationPhase.cpp:

(JSC::DFG::PredictionPropagationPhase::propagate):

  • dfg/DFGSpeculativeJIT.cpp:

(JSC::DFG::SpeculativeJIT::compileArithMul):

  • ftl/FTLCompile.cpp:
  • Changed to call generateBinaryOpFastPath() instead now, and let it dispatch to the appropriate snippet generator.
  • ftl/FTLCompileBinaryOp.cpp:

(JSC::FTL::generateBinaryArithOpFastPath):
(JSC::FTL::generateBinaryOpFastPath):
(JSC::FTL::generateArithSubFastPath): Deleted.
(JSC::FTL::generateValueAddFastPath): Deleted.

  • Refactored these functions to eliminate the need for copy-pasting every time we add support for another binary arithmetic snippet.
  • ftl/FTLCompileBinaryOp.h:
  • ftl/FTLInlineCacheDescriptor.h:
  • ftl/FTLInlineCacheDescriptorInlines.h:

(JSC::FTL::ArithMulDescriptor::ArithMulDescriptor):
(JSC::FTL::ArithMulDescriptor::icSize):

  • ftl/FTLInlineCacheSize.cpp:

(JSC::FTL::sizeOfArithMul):

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

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

  • jit/JITMulGenerator.h:

(JSC::JITMulGenerator::JITMulGenerator):

  • tests/stress/op_mul.js:
  • Updated a test value: the interesting value for imminent overflow from an int32 is 0x7fffffff, not 0x7ffffff.

LayoutTests:

  • js/regress/ftl-object-mul-expected.txt: Added.
  • js/regress/ftl-object-mul.html: Added.
  • js/regress/script-tests/ftl-object-mul.js: Added.

(o1.valueOf):
(foo):

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp

    r192882 r192993  
    4040#include "DirectArguments.h"
    4141#include "JITAddGenerator.h"
     42#include "JITMulGenerator.h"
    4243#include "JITSubGenerator.h"
    4344#include "JSArrowFunction.h"
     
    34443445        return;
    34453446    }
    3446        
     3447
     3448    case UntypedUse: {
     3449        Edge& leftChild = node->child1();
     3450        Edge& rightChild = node->child2();
     3451
     3452        if (isKnownNotNumber(leftChild.node()) || isKnownNotNumber(rightChild.node())) {
     3453            JSValueOperand left(this, leftChild);
     3454            JSValueOperand right(this, rightChild);
     3455            JSValueRegs leftRegs = left.jsValueRegs();
     3456            JSValueRegs rightRegs = right.jsValueRegs();
     3457#if USE(JSVALUE64)
     3458            GPRTemporary result(this);
     3459            JSValueRegs resultRegs = JSValueRegs(result.gpr());
     3460#else
     3461            GPRTemporary resultTag(this);
     3462            GPRTemporary resultPayload(this);
     3463            JSValueRegs resultRegs = JSValueRegs(resultPayload.gpr(), resultTag.gpr());
     3464#endif
     3465            flushRegisters();
     3466            callOperation(operationValueMul, resultRegs, leftRegs, rightRegs);
     3467            m_jit.exceptionCheck();
     3468
     3469            jsValueResult(resultRegs, node);
     3470            return;
     3471        }
     3472
     3473        Optional<JSValueOperand> left;
     3474        Optional<JSValueOperand> right;
     3475
     3476        JSValueRegs leftRegs;
     3477        JSValueRegs rightRegs;
     3478
     3479        FPRTemporary leftNumber(this);
     3480        FPRTemporary rightNumber(this);
     3481        FPRReg leftFPR = leftNumber.fpr();
     3482        FPRReg rightFPR = rightNumber.fpr();
     3483
     3484#if USE(JSVALUE64)
     3485        GPRTemporary result(this);
     3486        JSValueRegs resultRegs = JSValueRegs(result.gpr());
     3487        GPRTemporary scratch(this);
     3488        GPRReg scratchGPR = scratch.gpr();
     3489        FPRReg scratchFPR = InvalidFPRReg;
     3490#else
     3491        GPRTemporary resultTag(this);
     3492        GPRTemporary resultPayload(this);
     3493        JSValueRegs resultRegs = JSValueRegs(resultPayload.gpr(), resultTag.gpr());
     3494        GPRReg scratchGPR = resultTag.gpr();
     3495        FPRTemporary fprScratch(this);
     3496        FPRReg scratchFPR = fprScratch.fpr();
     3497#endif
     3498
     3499        SnippetOperand leftOperand(m_state.forNode(leftChild).resultType());
     3500        SnippetOperand rightOperand(m_state.forNode(rightChild).resultType());
     3501
     3502        if (leftChild->isInt32Constant())
     3503            leftOperand.setConstInt32(leftChild->asInt32());
     3504        if (rightChild->isInt32Constant())
     3505            rightOperand.setConstInt32(rightChild->asInt32());
     3506
     3507        RELEASE_ASSERT(!leftOperand.isConst() || !rightOperand.isConst());
     3508
     3509        if (!leftOperand.isPositiveConstInt32()) {
     3510            left = JSValueOperand(this, leftChild);
     3511            leftRegs = left->jsValueRegs();
     3512        }
     3513        if (!rightOperand.isPositiveConstInt32()) {
     3514            right = JSValueOperand(this, rightChild);
     3515            rightRegs = right->jsValueRegs();
     3516        }
     3517
     3518        JITMulGenerator gen(leftOperand, rightOperand, resultRegs, leftRegs, rightRegs,
     3519            leftFPR, rightFPR, scratchGPR, scratchFPR);
     3520        gen.generateFastPath(m_jit);
     3521
     3522        ASSERT(gen.didEmitFastPath());
     3523        gen.endJumpList().append(m_jit.jump());
     3524
     3525        gen.slowPathJumpList().link(&m_jit);
     3526        silentSpillAllRegisters(resultRegs);
     3527
     3528        if (leftOperand.isPositiveConstInt32()) {
     3529            leftRegs = resultRegs;
     3530            int64_t leftConst = leftOperand.asConstInt32();
     3531            m_jit.moveValue(JSValue(leftConst), leftRegs);
     3532        }
     3533        if (rightOperand.isPositiveConstInt32()) {
     3534            rightRegs = resultRegs;
     3535            int64_t rightConst = rightOperand.asConstInt32();
     3536            m_jit.moveValue(JSValue(rightConst), rightRegs);
     3537        }
     3538
     3539        callOperation(operationValueMul, resultRegs, leftRegs, rightRegs);
     3540
     3541        silentFillAllRegisters(resultRegs);
     3542        m_jit.exceptionCheck();
     3543
     3544        gen.endJumpList().link(&m_jit);
     3545        jsValueResult(resultRegs, node);
     3546        return;
     3547    }
     3548
    34473549    default:
    34483550        RELEASE_ASSERT_NOT_REACHED();
Note: See TracChangeset for help on using the changeset viewer.