[JSC] Add support for GetByVal on arrays of Undecided shape
https://bugs.webkit.org/show_bug.cgi?id=147814
Patch by Benjamin Poulain <bpoulain@apple.com> 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.
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@188432 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
index d6a9790..da76e7a 100644
--- a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
@@ -625,7 +625,6 @@
switch (arrayMode.type()) {
case Array::SelectUsingPredictions:
case Array::Unprofiled:
- case Array::Undecided:
RELEASE_ASSERT_NOT_REACHED();
break;
case Array::Generic:
@@ -686,6 +685,7 @@
switch (node->arrayMode().modeForPut().type()) {
case Array::SelectUsingPredictions:
+ case Array::SelectUsingArguments:
case Array::Unprofiled:
case Array::Undecided:
RELEASE_ASSERT_NOT_REACHED();