Ignore:
Timestamp:
Aug 17, 2020, 3:10:14 PM (5 years ago)
Author:
[email protected]
Message:

Have an OOB+SaneChain Array::Speculation
https://bugs.webkit.org/show_bug.cgi?id=215487

Reviewed by Yusuke Suzuki.

JSTests:

  • microbenchmarks/oob-sane-chain-contiguous.js: Added.
  • microbenchmarks/oob-sane-chain-double-read-undefined.js: Added.
  • microbenchmarks/oob-sane-chain-double.js: Added.
  • microbenchmarks/oob-sane-chain-int32.js: Added.
  • stress/oob-sane-chain-negative-index.js: Added.

Source/JavaScriptCore:

This patch adds a new ArrayMode speculation in the DFG/FTL called OutOfBoundsSaneChain.
It allows us to do fast things when we go OOB, like simply return undefined.
This is because we install watchpoints on the prototype chain to ensure they
have no indexed properties. This patch implements OutOfBoundsSaneChain on
GetByVal over Int32/Double/Contiguous original JS arrays. We can extend it in
the future to non original JS arrays if we prove their prototype is Array.prototype.
To implement this properly, we also need to ensure that the index isn't negative,
as Array.prototype/Object.prototype may have negative indexed accessors. We
do this via speculation, and if we ever recompile, and see an exit because of
this, we will stop speculating OutOfBoundsSaneChain.

This is about 20% faster on crypto-md5-SP. And ~3-4x faster on the
microbenchmarks I created.

  • dfg/DFGAbstractInterpreterInlines.h:

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

  • dfg/DFGArrayMode.cpp:

(JSC::DFG::ArrayMode::refine const):
(JSC::DFG::arraySpeculationToString):

  • dfg/DFGArrayMode.h:

(JSC::DFG::ArrayMode::isInBoundsSaneChain const):
(JSC::DFG::ArrayMode::isOutOfBoundsSaneChain const):
(JSC::DFG::ArrayMode::isOutOfBounds const):
(JSC::DFG::ArrayMode::isEffectfulOutOfBounds const):
(JSC::DFG::ArrayMode::isInBounds const):
(JSC::DFG::ArrayMode::isSaneChain const): Deleted.

  • dfg/DFGCSEPhase.cpp:
  • dfg/DFGClobberize.h:

(JSC::DFG::clobberize):

  • dfg/DFGFixupPhase.cpp:

(JSC::DFG::FixupPhase::fixupNode):
(JSC::DFG::FixupPhase::checkArray):
(JSC::DFG::FixupPhase::setSaneChainIfPossible):
(JSC::DFG::FixupPhase::convertToHasIndexedProperty):

  • dfg/DFGSpeculativeJIT.cpp:

(JSC::DFG::SpeculativeJIT::compileGetByValOnString):
(JSC::DFG::SpeculativeJIT::compileHasIndexedProperty):

  • dfg/DFGSpeculativeJIT32_64.cpp:

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

  • dfg/DFGSpeculativeJIT64.cpp:

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

  • dfg/DFGValidate.cpp:
  • ftl/FTLLowerDFGToB3.cpp:

(JSC::FTL::DFG::LowerDFGToB3::compileGetByVal):
(JSC::FTL::DFG::LowerDFGToB3::compileStringCharAt):
(JSC::FTL::DFG::LowerDFGToB3::compileHasIndexedProperty):

File:
1 edited

Legend:

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

    r261895 r265775  
    261261            graph.registerAndWatchStructureTransition(objectPrototypeStructure);
    262262            if (globalObject->arrayPrototypeChainIsSane())
    263                 return withSpeculation(Array::SaneChain);
     263                return withSpeculation(Array::InBoundsSaneChain);
    264264        }
    265265        return ArrayMode(Array::Generic, action());
     
    714714{
    715715    switch (speculation) {
    716     case Array::SaneChain:
    717         return "SaneChain";
     716    case Array::InBoundsSaneChain:
     717        return "InBoundsSaneChain";
    718718    case Array::InBounds:
    719719        return "InBounds";
     
    722722    case Array::OutOfBounds:
    723723        return "OutOfBounds";
     724    case Array::OutOfBoundsSaneChain:
     725        return "OutOfBoundsSaneChain";
    724726    default:
    725727        return "Unknown!";
Note: See TracChangeset for help on using the changeset viewer.