Ignore:
Timestamp:
Aug 13, 2015, 8:54:32 PM (10 years ago)
Author:
[email protected]
Message:

[JSC] Add support for GetByVal on arrays of Undecided shape
https://bugs.webkit.org/show_bug.cgi?id=147814

Patch by Benjamin Poulain <[email protected]> on 2015-08-13
Reviewed by Filip Pizlo.

Previously, GetByVal on Array::Undecided would just take
the generic path. The problem is the generic path is so
slow that it could take a significant amount of time
even for unfrequent accesses.

With this patch, if the following conditions are met,
the GetByVal just returns a "undefined" constant:
-The object is an OriginalArray.
-The prototype chain is sane.
-The index is an integer.
-The integer is positive (runtime check).

Ideally, the 4th conditions should be removed
deducing a compile-time constant gives us so much better
opportunities at getting rid of this code.

There are two cases where this patch removes the runtime
check:
-If the index is constant (uncommon but easy)
-If the index is within a range known to be positive.

(common case and made possible with DFGIntegerRangeOptimizationPhase).

When we get into those cases, DFG just nukes everything
and all we have left is a structure check :)

This patch is a 14% improvement on audio-beat-detection,
a few percent faster here and there and no regression.

  • dfg/DFGAbstractInterpreterInlines.h:

(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
If the index is a positive constant, we can get rid of the GetByVal
entirely. :)

  • dfg/DFGArrayMode.cpp:

(JSC::DFG::ArrayMode::fromObserved):
The returned type is now Array::Undecided + profiling information.
The useful type is set in ArrayMode::refine().

(JSC::DFG::ArrayMode::refine):
If we meet the particular set conditions, we speculate an Undecided
array type with sane chain. Anything else comes back to Generic.

(JSC::DFG::ArrayMode::originalArrayStructure):
To enable the structure check for Undecided array.

(JSC::DFG::ArrayMode::alreadyChecked):

  • dfg/DFGArrayMode.h:

(JSC::DFG::ArrayMode::withProfile):
(JSC::DFG::ArrayMode::canCSEStorage):
(JSC::DFG::ArrayMode::benefitsFromOriginalArray):
(JSC::DFG::ArrayMode::lengthNeedsStorage): Deleted.
(JSC::DFG::ArrayMode::isSpecific): Deleted.A

  • dfg/DFGByteCodeParser.cpp:

(JSC::DFG::ByteCodeParser::handleIntrinsic): Deleted.
This is somewhat unrelated.

Having Array::Undecided on ArrayPush was impossible before
since ArrayMode::fromObserved() used to return Array::Generic.

Now that Array::Undecided is possible, we must make sure not
to provide it to ArrayPush since there is no code to handle it
properly.

  • dfg/DFGClobberize.h:

(JSC::DFG::clobberize):
The operation only depends on the index, it is pure.

  • dfg/DFGFixupPhase.cpp:

(JSC::DFG::FixupPhase::fixupNode): Deleted.

  • dfg/DFGIntegerRangeOptimizationPhase.cpp:
  • dfg/DFGSpeculativeJIT.cpp:

(JSC::DFG::SpeculativeJIT::jumpSlowForUnwantedArrayMode):
(JSC::DFG::SpeculativeJIT::checkArray):

  • dfg/DFGSpeculativeJIT32_64.cpp:

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

  • dfg/DFGSpeculativeJIT64.cpp:

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

  • ftl/FTLCapabilities.cpp:

(JSC::FTL::canCompile):

  • ftl/FTLLowerDFGToLLVM.cpp:

(JSC::FTL::DFG::LowerDFGToLLVM::compileGetByVal):

  • tests/stress/get-by-val-on-undecided-array-type.js: Added.
  • tests/stress/get-by-val-on-undecided-sane-chain-1.js: Added.
  • tests/stress/get-by-val-on-undecided-sane-chain-2.js: Added.
  • tests/stress/get-by-val-on-undecided-sane-chain-3.js: Added.
  • tests/stress/get-by-val-on-undecided-sane-chain-4.js: Added.
  • tests/stress/get-by-val-on-undecided-sane-chain-5.js: Added.
  • tests/stress/get-by-val-on-undecided-sane-chain-6.js: Added.
File:
1 edited

Legend:

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

    r188040 r188432  
    959959                    break;
    960960                }
    961                    
     961
     962                case GetByVal: {
     963                    if (node->arrayMode().type() != Array::Undecided)
     964                        break;
     965
     966                    auto iter = m_relationships.find(node->child2().node());
     967                    if (iter == m_relationships.end())
     968                        break;
     969
     970                    int minValue = std::numeric_limits<int>::min();
     971                    for (Relationship relationship : iter->value)
     972                        minValue = std::max(minValue, relationship.minValueOfLeft());
     973
     974                    if (minValue < 0)
     975                        break;
     976
     977                    executeNode(block->at(nodeIndex));
     978                    m_graph.convertToConstant(node, jsUndefined());
     979                    changed = true;
     980                    break;
     981                }
     982
    962983                default:
    963984                    break;
Note: See TracChangeset for help on using the changeset viewer.