Skip to content
  • fpizlo@apple.com's avatar
    DFG should be able to emit effectful structure checks · 99f3762d
    fpizlo@apple.com authored
    https://bugs.webkit.org/show_bug.cgi?id=99260
    
    Reviewed by Oliver Hunt.
    
    This change allows us to find out if an array access that has gone polymorphic
    is operating over known structures - i.e. the primordial array structures of the
    global object that the code block containing the array access belongs to. We
    term this state "OriginalArray" for short. The fact that the access has gone
    polymorphic means that the array profile will not be able to report the set of
    structures it had seen - but if it can tell us that all of the structures were
    primordial then it just so happens that we can deduce what the structure set
    would have been by just querying the code block's global object. This allows us
    to emit an ArrayifyToStructure instead of an Arrayify if we find that we need to
    do conversions. The fast path of an ArrayifyToStructure is exactly like the fast
    path of a CheckStructure and is mostly subject to the same optimizations. It
    also burns one fewer registers.
            
    Essentially the notion of OriginalArray is a super cheap way of getting the
    array profile to tell us a structure set instead of a singleton structure.
    Currently, the array profile can only tell us the structure seen at an array
    access if there was exactly one structure. If there were multiple structures, it
    won't tell us anything other than the array modes and other auxiliary profiling
    data (whether there were stores to holes, for example). With OriginalArray, we
    cheaply get a structure set if all of the structures were primordial for the
    code block's global object, since in that case the array mode set (ArrayModes)
    can directly tell us the structure set. In the future, we might consider adding
    complete structure sets to the array profiles, but I suspect that we would hit
    diminishing returns if we did so - it would only help if we have array accesses
    that are both polymorphic and are cross-global-object accesses (rare) or if the
    arrays had named properties or other structure transitions that are unrelated to
    indexing type (also rare).
            
    This also does away with Arrayify (and the new ArrayifyToStructure) returning
    the butterfly pointer. This turns out to be faster and easier to CSE.
            
    And, this also changes constant folding to be able to eliminate CheckStructure,
    ForwardCheckStructure, and ArrayifyToStructure in addition to being able to
    transform them into structure transition watchpoints. This is great for
    ArrayifyToStructure because then CSE and CFA know that there is no side effect.
    Converting CheckStructure and ForwardCheckStructure to also behave this way is
    just a matter of elegance.
            
    This has no performance impact right now. It's intended to alleviate some of the
    regressions seen in the early implementation of
    https://bugs.webkit.org/show_bug.cgi?id=98606.
    
    * bytecode/ArrayProfile.cpp:
    (JSC::ArrayProfile::computeUpdatedPrediction):
    * bytecode/ArrayProfile.h:
    (JSC):
    (JSC::ArrayProfile::ArrayProfile):
    (ArrayProfile):
    (JSC::ArrayProfile::usesOriginalArrayStructures):
    * bytecode/CodeBlock.cpp:
    (JSC::CodeBlock::updateAllPredictionsAndCountLiveness):
    * dfg/DFGAbstractState.cpp:
    (JSC::DFG::AbstractState::execute):
    * dfg/DFGArrayMode.cpp:
    (JSC::DFG::ArrayMode::fromObserved):
    (JSC::DFG::ArrayMode::alreadyChecked):
    (JSC::DFG::arrayClassToString):
    * dfg/DFGArrayMode.h:
    (JSC::DFG::ArrayMode::withProfile):
    (JSC::DFG::ArrayMode::isJSArray):
    (ArrayMode):
    (JSC::DFG::ArrayMode::isJSArrayWithOriginalStructure):
    (JSC::DFG::ArrayMode::supportsLength):
    (JSC::DFG::ArrayMode::arrayModesWithIndexingShape):
    * dfg/DFGByteCodeParser.cpp:
    (JSC::DFG::ByteCodeParser::getArrayMode):
    (JSC::DFG::ByteCodeParser::getArrayModeAndEmitChecks):
    (JSC::DFG::ByteCodeParser::handleGetByOffset):
    * dfg/DFGCSEPhase.cpp:
    (JSC::DFG::CSEPhase::checkStructureElimination):
    (JSC::DFG::CSEPhase::structureTransitionWatchpointElimination):
    (JSC::DFG::CSEPhase::getPropertyStorageLoadElimination):
    (JSC::DFG::CSEPhase::checkArrayElimination):
    (JSC::DFG::CSEPhase::getScopeRegistersLoadElimination):
    * dfg/DFGConstantFoldingPhase.cpp:
    (JSC::DFG::ConstantFoldingPhase::foldConstants):
    * dfg/DFGFixupPhase.cpp:
    (JSC::DFG::FixupPhase::fixupNode):
    (JSC::DFG::FixupPhase::checkArray):
    * dfg/DFGNode.h:
    (JSC::DFG::Node::hasStructure):
    (JSC::DFG::Node::hasArrayMode):
    (JSC::DFG::Node::arrayMode):
    * dfg/DFGNodeType.h:
    (DFG):
    * dfg/DFGPredictionPropagationPhase.cpp:
    (JSC::DFG::PredictionPropagationPhase::propagate):
    * dfg/DFGSpeculativeJIT.cpp:
    (JSC::DFG::SpeculativeJIT::jumpSlowForUnwantedArrayMode):
    (JSC::DFG::SpeculativeJIT::arrayify):
    * dfg/DFGSpeculativeJIT.h:
    (SpeculativeJIT):
    * dfg/DFGSpeculativeJIT32_64.cpp:
    (JSC::DFG::SpeculativeJIT::compile):
    * dfg/DFGSpeculativeJIT64.cpp:
    (JSC::DFG::SpeculativeJIT::compile):
    * runtime/JSGlobalObject.h:
    (JSC::JSGlobalObject::isOriginalArrayStructure):
    * runtime/Structure.cpp:
    (JSC::Structure::nonPropertyTransition):
    
    
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@132759 268f45cc-cd09-0410-ab3c-d52691b4dbfc
    99f3762d