Ignore:
Timestamp:
Dec 9, 2013, 7:24:31 PM (11 years ago)
Author:
[email protected]
Message:

Reveal array bounds checks in DFG IR
https://bugs.webkit.org/show_bug.cgi?id=125253

Reviewed by Oliver Hunt and Mark Hahnenberg.

In SSA mode, this reveals array bounds checks and the load of array length in DFG IR,
making this a candidate for LICM.

This also fixes a long-standing performance bug where the JSObject slow paths would
always create contiguous storage, rather than type-specialized storage, when doing a
"storage creating" storage, like:

var o = {};
o[0] = 42;

  • CMakeLists.txt:
  • GNUmakefile.list.am:
  • JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
  • JavaScriptCore.xcodeproj/project.pbxproj:
  • bytecode/ExitKind.cpp:

(JSC::exitKindToString):
(JSC::exitKindIsCountable):

  • bytecode/ExitKind.h:
  • dfg/DFGAbstractInterpreterInlines.h:

(JSC::DFG::::executeEffects):

  • dfg/DFGArrayMode.cpp:

(JSC::DFG::permitsBoundsCheckLowering):
(JSC::DFG::ArrayMode::permitsBoundsCheckLowering):

  • dfg/DFGArrayMode.h:

(JSC::DFG::ArrayMode::lengthNeedsStorage):

  • dfg/DFGClobberize.h:

(JSC::DFG::clobberize):

  • dfg/DFGConstantFoldingPhase.cpp:

(JSC::DFG::ConstantFoldingPhase::foldConstants):

  • dfg/DFGFixupPhase.cpp:

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

  • dfg/DFGNodeType.h:
  • dfg/DFGPlan.cpp:

(JSC::DFG::Plan::compileInThreadImpl):

  • dfg/DFGPredictionPropagationPhase.cpp:

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

  • dfg/DFGSSALoweringPhase.cpp: Added.

(JSC::DFG::SSALoweringPhase::SSALoweringPhase):
(JSC::DFG::SSALoweringPhase::run):
(JSC::DFG::SSALoweringPhase::handleNode):
(JSC::DFG::SSALoweringPhase::lowerBoundsCheck):
(JSC::DFG::performSSALowering):

  • dfg/DFGSSALoweringPhase.h: Added.
  • dfg/DFGSafeToExecute.h:

(JSC::DFG::safeToExecute):

  • dfg/DFGSpeculativeJIT.cpp:

(JSC::DFG::SpeculativeJIT::compileDoublePutByVal):

  • dfg/DFGSpeculativeJIT32_64.cpp:

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

  • dfg/DFGSpeculativeJIT64.cpp:

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

  • ftl/FTLCapabilities.cpp:

(JSC::FTL::canCompile):

  • ftl/FTLLowerDFGToLLVM.cpp:

(JSC::FTL::LowerDFGToLLVM::compileNode):
(JSC::FTL::LowerDFGToLLVM::compileCheckInBounds):
(JSC::FTL::LowerDFGToLLVM::compileGetByVal):
(JSC::FTL::LowerDFGToLLVM::compilePutByVal):
(JSC::FTL::LowerDFGToLLVM::contiguousPutByValOutOfBounds):

  • runtime/JSObject.cpp:

(JSC::JSObject::convertUndecidedForValue):
(JSC::JSObject::createInitialForValueAndSet):
(JSC::JSObject::putByIndexBeyondVectorLength):
(JSC::JSObject::putDirectIndexBeyondVectorLength):

  • runtime/JSObject.h:
  • tests/stress/float32array-out-of-bounds.js: Added.

(make):
(foo):
(test):

  • tests/stress/int32-object-out-of-bounds.js: Added.

(make):
(foo):
(test):

  • tests/stress/int32-out-of-bounds.js: Added.

(foo):
(test):

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp

    r160295 r160347  
    356356            compileGetArrayLength();
    357357            break;
     358        case CheckInBounds:
     359            compileCheckInBounds();
     360            break;
    358361        case GetByVal:
    359362            compileGetByVal();
     
    14761479    }
    14771480   
     1481    void compileCheckInBounds()
     1482    {
     1483        speculate(
     1484            OutOfBounds, noValue(), 0,
     1485            m_out.aboveOrEqual(lowInt32(m_node->child1()), lowInt32(m_node->child2())));
     1486    }
     1487   
    14781488    void compileGetByVal()
    14791489    {
     
    14881498           
    14891499            if (m_node->arrayMode().isInBounds()) {
    1490                 speculate(
    1491                     OutOfBounds, noValue(), 0,
    1492                     m_out.aboveOrEqual(
    1493                         index, m_out.load32(storage, m_heaps.Butterfly_publicLength)));
    1494                
    14951500                LValue result = m_out.load64(baseIndex(heap, storage, index, m_node->child2()));
    14961501                speculate(LoadFromHole, noValue(), 0, m_out.isZero64(result));
     
    15331538           
    15341539            if (m_node->arrayMode().isInBounds()) {
    1535                 speculate(
    1536                     OutOfBounds, noValue(), 0,
    1537                     m_out.aboveOrEqual(
    1538                         index, m_out.load32(storage, m_heaps.Butterfly_publicLength)));
    1539                
    15401540                LValue result = m_out.loadDouble(
    15411541                    baseIndex(heap, storage, index, m_node->child2()));
     
    16011601           
    16021602            if (isTypedView(type)) {
    1603                 speculate(
    1604                     OutOfBounds, noValue(), 0,
    1605                     m_out.aboveOrEqual(
    1606                         index, typedArrayLength(m_node->child1(), m_node->arrayMode())));
    1607                
    16081603                TypedPointer pointer = TypedPointer(
    16091604                    m_heaps.typedArrayProperties,
     
    17931788           
    17941789            if (isTypedView(type)) {
    1795                 if (m_node->op() != PutByValAlias) {
    1796                     speculate(
    1797                         OutOfBounds, noValue(), 0,
    1798                         m_out.aboveOrEqual(
    1799                             index,
    1800                             typedArrayLength(child1, m_node->arrayMode(), base)));
    1801                 }
    1802                
    18031790                TypedPointer pointer = TypedPointer(
    18041791                    m_heaps.typedArrayProperties,
     
    30863073    template<typename FunctionType>
    30873074    void contiguousPutByValOutOfBounds(
    3088         FunctionType slowPathFunction,
    3089         LValue base, LValue storage, LValue index, LValue value,
     3075        FunctionType slowPathFunction, LValue base, LValue storage, LValue index, LValue value,
    30903076        LBasicBlock continuation)
    30913077    {
    30923078        LValue isNotInBounds = m_out.aboveOrEqual(
    30933079            index, m_out.load32(storage, m_heaps.Butterfly_publicLength));
    3094         if (m_node->arrayMode().isInBounds())
    3095             speculate(StoreToHoleOrOutOfBounds, noValue(), 0, isNotInBounds);
    3096         else {
     3080        if (!m_node->arrayMode().isInBounds()) {
    30973081            LBasicBlock notInBoundsCase =
    30983082                FTL_NEW_BLOCK(m_out, ("PutByVal not in bounds"));
Note: See TracChangeset for help on using the changeset viewer.