DFG should optimize aliased uses of the Arguments object of the current call frame
https://bugs.webkit.org/show_bug.cgi?id=86552

Source/JavaScriptCore: 

Reviewed by Geoff Garen.
        
Merged r117542 and r117543 from dfgopt.
        
Performs must-alias and escape analysis on uses of CreateArguments, and if
a variable is must-aliased to CreateArguments and does not escape, then we
turn all uses of that variable into direct arguments accesses.
        
36% speed-up on V8/earley leading to a 2.3% speed-up overall in V8.

* bytecode/CodeBlock.h:
(JSC::CodeBlock::uncheckedArgumentsRegister):
* bytecode/ValueRecovery.h:
(JSC::ValueRecovery::argumentsThatWereNotCreated):
(ValueRecovery):
(JSC::ValueRecovery::dump):
* dfg/DFGAbstractState.cpp:
(JSC::DFG::AbstractState::execute):
* dfg/DFGAdjacencyList.h:
(AdjacencyList):
(JSC::DFG::AdjacencyList::removeEdgeFromBag):
* dfg/DFGArgumentsSimplificationPhase.cpp:
(JSC::DFG::ArgumentsSimplificationPhase::run):
(ArgumentsSimplificationPhase):
(JSC::DFG::ArgumentsSimplificationPhase::observeBadArgumentsUse):
(JSC::DFG::ArgumentsSimplificationPhase::observeBadArgumentsUses):
(JSC::DFG::ArgumentsSimplificationPhase::observeProperArgumentsUse):
(JSC::DFG::ArgumentsSimplificationPhase::isOKToOptimize):
(JSC::DFG::ArgumentsSimplificationPhase::removeArgumentsReferencingPhantomChild):
* dfg/DFGAssemblyHelpers.h:
(JSC::DFG::AssemblyHelpers::argumentsRegisterFor):
(AssemblyHelpers):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::parseBlock):
* dfg/DFGCFGSimplificationPhase.cpp:
(JSC::DFG::CFGSimplificationPhase::removePotentiallyDeadPhiReference):
* dfg/DFGGPRInfo.h:
(GPRInfo):
* dfg/DFGGraph.cpp:
(JSC::DFG::Graph::collectGarbage):
(DFG):
* dfg/DFGGraph.h:
(Graph):
(JSC::DFG::Graph::executableFor):
(JSC::DFG::Graph::argumentsRegisterFor):
(JSC::DFG::Graph::uncheckedArgumentsRegisterFor):
(JSC::DFG::Graph::clobbersWorld):
* dfg/DFGNode.h:
(JSC::DFG::Node::hasHeapPrediction):
* dfg/DFGNodeType.h:
(DFG):
* dfg/DFGOSRExitCompiler.cpp:
* dfg/DFGOSRExitCompiler.h:
(JSC::DFG::OSRExitCompiler::OSRExitCompiler):
(OSRExitCompiler):
* dfg/DFGOSRExitCompiler32_64.cpp:
(JSC::DFG::OSRExitCompiler::compileExit):
* dfg/DFGOSRExitCompiler64.cpp:
(JSC::DFG::OSRExitCompiler::compileExit):
* dfg/DFGOperations.cpp:
* dfg/DFGPredictionPropagationPhase.cpp:
(JSC::DFG::PredictionPropagationPhase::propagate):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::ValueSource::dump):
(JSC::DFG::SpeculativeJIT::compile):
(JSC::DFG::SpeculativeJIT::computeValueRecoveryFor):
* dfg/DFGSpeculativeJIT.h:
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGVariableAccessData.h:
(JSC::DFG::VariableAccessData::VariableAccessData):
(JSC::DFG::VariableAccessData::mergeIsArgumentsAlias):
(VariableAccessData):
(JSC::DFG::VariableAccessData::isArgumentsAlias):
* jit/JITOpcodes.cpp:
(JSC::JIT::emitSlow_op_get_argument_by_val):

LayoutTests: 

Rubber stamped by Geoff Garen.
        
Merged r117542 from dfgopt.
        
Added a bunch of tests that check that our optimizations for aliased uses of the
'arguments' object are robust against various forms of JavaScript crazy.
        
* fast/js/dfg-arguments-alias-escape-expected.txt: Added.
* fast/js/dfg-arguments-alias-escape.html: Added.
* fast/js/dfg-arguments-alias-expected.txt: Added.
* fast/js/dfg-arguments-alias.html: Added.
* fast/js/dfg-arguments-cross-code-origin-expected.txt: Added.
* fast/js/dfg-arguments-cross-code-origin.html: Added.
* fast/js/dfg-arguments-mixed-alias-expected.txt: Added.
* fast/js/dfg-arguments-mixed-alias.html: Added.
* fast/js/dfg-arguments-osr-exit-expected.txt: Added.
* fast/js/dfg-arguments-osr-exit.html: Added.
* fast/js/dfg-arguments-unexpected-escape-expected.txt: Added.
* fast/js/dfg-arguments-unexpected-escape.html: Added.
* fast/js/jsc-test-list:
* fast/js/script-tests/dfg-arguments-alias-escape.js: Added.
(foo):
(bar):
* fast/js/script-tests/dfg-arguments-alias.js: Added.
(foo):
(bar):
* fast/js/script-tests/dfg-arguments-cross-code-origin.js: Added.
(foo):
(bar):
(baz):
* fast/js/script-tests/dfg-arguments-mixed-alias.js: Added.
(foo):
(bar):
* fast/js/script-tests/dfg-arguments-osr-exit.js: Added.
(baz):
(foo):
(bar):
* fast/js/script-tests/dfg-arguments-unexpected-escape.js: Added.
(baz):
(foo):
(bar):



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@118323 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/dfg/DFGAbstractState.cpp b/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
index 5c5b7ab..a0cffca 100644
--- a/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
+++ b/Source/JavaScriptCore/dfg/DFGAbstractState.cpp
@@ -1094,19 +1094,18 @@
         break;
         
     case GetMyArgumentsLength:
-        if (!m_graph.m_executablesWhoseArgumentsEscaped.contains(
-                m_graph.executableFor(node.codeOrigin))) {
-            // We know that this executable does not escape its arguments, so we can optimize
-            // the arguments a bit. Note that this is not sufficient to force constant folding
-            // of GetMyArgumentsLength, because GetMyArgumentsLength is a clobbering operation.
-            // We perform further optimizations on this later on.
-            if (node.codeOrigin.inlineCallFrame) {
-                forNode(nodeIndex).set(jsNumber(node.codeOrigin.inlineCallFrame->arguments.size() - 1));
-                break;
-            }
-            forNode(nodeIndex).set(PredictInt32);
+        // We know that this executable does not escape its arguments, so we can optimize
+        // the arguments a bit. Note that this is not sufficient to force constant folding
+        // of GetMyArgumentsLength, because GetMyArgumentsLength is a clobbering operation.
+        // We perform further optimizations on this later on.
+        if (node.codeOrigin.inlineCallFrame) {
+            forNode(nodeIndex).set(jsNumber(node.codeOrigin.inlineCallFrame->arguments.size() - 1));
             break;
         }
+        forNode(nodeIndex).set(PredictInt32);
+        break;
+        
+    case GetMyArgumentsLengthSafe:
         // This potentially clobbers all structures if the arguments object had a getter
         // installed on the length property.
         clobberStructures(indexInBlock);
@@ -1116,15 +1115,14 @@
         break;
         
     case GetMyArgumentByVal:
-        if (!m_graph.m_executablesWhoseArgumentsEscaped.contains(
-                m_graph.executableFor(node.codeOrigin))) {
-            // We know that this executable does not escape its arguments, so we can optimize
-            // the arguments a bit. Note that this ends up being further optimized by the
-            // ArgumentsSimplificationPhase.
-            forNode(node.child1()).filter(PredictInt32);
-            forNode(nodeIndex).makeTop();
-            break;
-        }
+        // We know that this executable does not escape its arguments, so we can optimize
+        // the arguments a bit. Note that this ends up being further optimized by the
+        // ArgumentsSimplificationPhase.
+        forNode(node.child1()).filter(PredictInt32);
+        forNode(nodeIndex).makeTop();
+        break;
+        
+    case GetMyArgumentByValSafe:
         // This potentially clobbers all structures if the property we're accessing has
         // a getter. We don't speculate against this.
         clobberStructures(indexInBlock);