Diff
Modified: releases/WebKitGTK/webkit-2.20/JSTests/ChangeLog (229005 => 229006)
--- releases/WebKitGTK/webkit-2.20/JSTests/ChangeLog 2018-02-26 13:14:00 UTC (rev 229005)
+++ releases/WebKitGTK/webkit-2.20/JSTests/ChangeLog 2018-02-26 13:14:10 UTC (rev 229006)
@@ -1,3 +1,12 @@
+2018-02-20 Saam Barati <[email protected]>
+
+ DFG::VarargsForwardingPhase should eliminate getting argument length
+ https://bugs.webkit.org/show_bug.cgi?id=182959
+
+ Reviewed by Keith Miller.
+
+ * microbenchmarks/forward-arguments-dont-escape-on-arguments-length.js: Added.
+
2018-02-14 Yusuke Suzuki <[email protected]>
[FTL] Support ArrayPush for ArrayStorage
Added: releases/WebKitGTK/webkit-2.20/JSTests/microbenchmarks/forward-arguments-dont-escape-on-arguments-length.js (0 => 229006)
--- releases/WebKitGTK/webkit-2.20/JSTests/microbenchmarks/forward-arguments-dont-escape-on-arguments-length.js (rev 0)
+++ releases/WebKitGTK/webkit-2.20/JSTests/microbenchmarks/forward-arguments-dont-escape-on-arguments-length.js 2018-02-26 13:14:10 UTC (rev 229006)
@@ -0,0 +1,35 @@
+function f1() {
+ 'use strict';
+ if (arguments.length === 1)
+ return 25;
+ return 42;
+}
+noFTL(f1);
+noInline(f1);
+
+function f2() {
+ if (arguments.length === 1)
+ return 25;
+ return 42;
+}
+noFTL(f2);
+noInline(f2);
+
+class C {
+ construct() {
+ let x = 1;
+ if (arguments.length === 2)
+ --x;
+ if (x)
+ this.x = x;
+ }
+}
+noFTL(C);
+noInline(C);
+
+for (let i = 0; i < 1000000; ++i)
+ f1(10, 20);
+for (let i = 0; i < 1000000; ++i)
+ f2(10, 20);
+for (let i = 0; i < 1000000; ++i)
+ new C(10, 20);
Modified: releases/WebKitGTK/webkit-2.20/Source/_javascript_Core/ChangeLog (229005 => 229006)
--- releases/WebKitGTK/webkit-2.20/Source/_javascript_Core/ChangeLog 2018-02-26 13:14:00 UTC (rev 229005)
+++ releases/WebKitGTK/webkit-2.20/Source/_javascript_Core/ChangeLog 2018-02-26 13:14:10 UTC (rev 229006)
@@ -1,3 +1,40 @@
+2018-02-20 Saam Barati <[email protected]>
+
+ DFG::VarargsForwardingPhase should eliminate getting argument length
+ https://bugs.webkit.org/show_bug.cgi?id=182959
+
+ Reviewed by Keith Miller.
+
+ This patch teaches the DFG VarargsForwardingPhase to not treat
+ length accesses on Cloned/Direct Arguments objects as escapes.
+ It teaches this phase to materialize the length in the same
+ way the ArgumentsEliminationPhase does.
+
+ This is around a 0.5-1% speedup on ARES6 on my iMac. It speeds
+ up the ML subtest by 2-4%.
+
+ This patch also extends compileGetArgumentCountIncludingThis to take
+ a parameter that is the inline call frame to load from (in the case
+ where the inline call frame is a varargs frame). This allows the
+ the emitCodeToGetArgumentsArrayLength helper function to just emit
+ a GetArgumentCountIncludingThis node instead of a GetLocal. If we
+ emitted a GetLocal, we'd need to rerun CPS rethreading.
+
+ * dfg/DFGArgumentsEliminationPhase.cpp:
+ * dfg/DFGArgumentsUtilities.cpp:
+ (JSC::DFG::emitCodeToGetArgumentsArrayLength):
+ * dfg/DFGByteCodeParser.cpp:
+ (JSC::DFG::ByteCodeParser::getArgumentCount):
+ * dfg/DFGClobberize.h:
+ (JSC::DFG::clobberize):
+ * dfg/DFGNode.h:
+ (JSC::DFG::Node::argumentsInlineCallFrame):
+ * dfg/DFGSpeculativeJIT.cpp:
+ (JSC::DFG::SpeculativeJIT::compileGetArgumentCountIncludingThis):
+ * dfg/DFGVarargsForwardingPhase.cpp:
+ * ftl/FTLLowerDFGToB3.cpp:
+ (JSC::FTL::DFG::LowerDFGToB3::compileGetArgumentCountIncludingThis):
+
2018-02-14 Yusuke Suzuki <[email protected]>
[FTL] Support ArrayPush for ArrayStorage
Modified: releases/WebKitGTK/webkit-2.20/Source/_javascript_Core/dfg/DFGArgumentsEliminationPhase.cpp (229005 => 229006)
--- releases/WebKitGTK/webkit-2.20/Source/_javascript_Core/dfg/DFGArgumentsEliminationPhase.cpp 2018-02-26 13:14:00 UTC (rev 229005)
+++ releases/WebKitGTK/webkit-2.20/Source/_javascript_Core/dfg/DFGArgumentsEliminationPhase.cpp 2018-02-26 13:14:10 UTC (rev 229006)
@@ -708,6 +708,8 @@
if (!isEliminatedAllocation(candidate))
break;
+ // FIXME: This should be an assert:
+ // https://bugs.webkit.org/show_bug.cgi?id=182982
if (node->child2()->op() != PhantomClonedArguments)
break;
Modified: releases/WebKitGTK/webkit-2.20/Source/_javascript_Core/dfg/DFGArgumentsUtilities.cpp (229005 => 229006)
--- releases/WebKitGTK/webkit-2.20/Source/_javascript_Core/dfg/DFGArgumentsUtilities.cpp 2018-02-26 13:14:00 UTC (rev 229005)
+++ releases/WebKitGTK/webkit-2.20/Source/_javascript_Core/dfg/DFGArgumentsUtilities.cpp 2018-02-26 13:14:10 UTC (rev 229006)
@@ -91,16 +91,8 @@
nodeIndex, origin, jsNumber(argumentsSize));
}
- Node* argumentCount;
- if (!inlineCallFrame)
- argumentCount = insertionSet.insertNode(nodeIndex, SpecInt32Only, GetArgumentCountIncludingThis, origin);
- else {
- VirtualRegister argumentCountRegister(inlineCallFrame->stackOffset + CallFrameSlot::argumentCount);
-
- argumentCount = insertionSet.insertNode(
- nodeIndex, SpecInt32Only, GetStack, origin,
- OpInfo(graph.m_stackAccessData.add(argumentCountRegister, FlushedInt32)));
- }
+ Node* argumentCount = insertionSet.insertNode(nodeIndex,
+ SpecInt32Only, GetArgumentCountIncludingThis, origin, OpInfo(inlineCallFrame));
Node* result = insertionSet.insertNode(
nodeIndex, SpecInt32Only, ArithSub, origin, OpInfo(Arith::Unchecked),
Modified: releases/WebKitGTK/webkit-2.20/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp (229005 => 229006)
--- releases/WebKitGTK/webkit-2.20/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp 2018-02-26 13:14:00 UTC (rev 229005)
+++ releases/WebKitGTK/webkit-2.20/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp 2018-02-26 13:14:10 UTC (rev 229006)
@@ -1352,13 +1352,10 @@
Node* ByteCodeParser::getArgumentCount()
{
Node* argumentCount;
- if (m_inlineStackTop->m_inlineCallFrame) {
- if (m_inlineStackTop->m_inlineCallFrame->isVarargs())
- argumentCount = get(VirtualRegister(CallFrameSlot::argumentCount));
- else
- argumentCount = jsConstant(m_graph.freeze(jsNumber(m_inlineStackTop->m_inlineCallFrame->argumentCountIncludingThis))->value());
- } else
- argumentCount = addToGraph(GetArgumentCountIncludingThis, OpInfo(0), OpInfo(SpecInt32Only));
+ if (m_inlineStackTop->m_inlineCallFrame && !m_inlineStackTop->m_inlineCallFrame->isVarargs())
+ argumentCount = jsConstant(m_graph.freeze(jsNumber(m_inlineStackTop->m_inlineCallFrame->argumentCountIncludingThis))->value());
+ else
+ argumentCount = addToGraph(GetArgumentCountIncludingThis, OpInfo(m_inlineStackTop->m_inlineCallFrame), OpInfo(SpecInt32Only));
return argumentCount;
}
Modified: releases/WebKitGTK/webkit-2.20/Source/_javascript_Core/dfg/DFGClobberize.h (229005 => 229006)
--- releases/WebKitGTK/webkit-2.20/Source/_javascript_Core/dfg/DFGClobberize.h 2018-02-26 13:14:00 UTC (rev 229005)
+++ releases/WebKitGTK/webkit-2.20/Source/_javascript_Core/dfg/DFGClobberize.h 2018-02-26 13:14:10 UTC (rev 229006)
@@ -35,6 +35,7 @@
#include "DFGPureValue.h"
#include "DOMJITCallDOMGetterSnippet.h"
#include "DOMJITSignature.h"
+#include "InlineCallFrame.h"
#include "JSFixedArray.h"
namespace JSC { namespace DFG {
@@ -702,10 +703,12 @@
def(HeapLocation(StackLoc, AbstractHeap(Stack, CallFrameSlot::callee)), LazyNode(node));
return;
- case GetArgumentCountIncludingThis:
- read(AbstractHeap(Stack, CallFrameSlot::argumentCount));
- def(HeapLocation(StackPayloadLoc, AbstractHeap(Stack, CallFrameSlot::argumentCount)), LazyNode(node));
+ case GetArgumentCountIncludingThis: {
+ auto heap = AbstractHeap(Stack, remapOperand(node->argumentsInlineCallFrame(), VirtualRegister(CallFrameSlot::argumentCount)));
+ read(heap);
+ def(HeapLocation(StackPayloadLoc, heap), LazyNode(node));
return;
+ }
case SetArgumentCountIncludingThis:
write(AbstractHeap(Stack, CallFrameSlot::argumentCount));
Modified: releases/WebKitGTK/webkit-2.20/Source/_javascript_Core/dfg/DFGNode.h (229005 => 229006)
--- releases/WebKitGTK/webkit-2.20/Source/_javascript_Core/dfg/DFGNode.h 2018-02-26 13:14:00 UTC (rev 229005)
+++ releases/WebKitGTK/webkit-2.20/Source/_javascript_Core/dfg/DFGNode.h 2018-02-26 13:14:10 UTC (rev 229006)
@@ -1265,6 +1265,12 @@
return m_opInfo.as<LoadVarargsData*>();
}
+ InlineCallFrame* argumentsInlineCallFrame()
+ {
+ ASSERT(op() == GetArgumentCountIncludingThis);
+ return m_opInfo.as<InlineCallFrame*>();
+ }
+
bool hasQueriedType()
{
return op() == IsCellWithType;
Modified: releases/WebKitGTK/webkit-2.20/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (229005 => 229006)
--- releases/WebKitGTK/webkit-2.20/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2018-02-26 13:14:00 UTC (rev 229005)
+++ releases/WebKitGTK/webkit-2.20/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2018-02-26 13:14:10 UTC (rev 229006)
@@ -11337,7 +11337,12 @@
void SpeculativeJIT::compileGetArgumentCountIncludingThis(Node* node)
{
GPRTemporary result(this);
- m_jit.load32(JITCompiler::payloadFor(CallFrameSlot::argumentCount), result.gpr());
+ VirtualRegister argumentCountRegister;
+ if (InlineCallFrame* inlineCallFrame = node->argumentsInlineCallFrame())
+ argumentCountRegister = inlineCallFrame->argumentCountRegister;
+ else
+ argumentCountRegister = VirtualRegister(CallFrameSlot::argumentCount);
+ m_jit.load32(JITCompiler::payloadFor(argumentCountRegister), result.gpr());
int32Result(result.gpr(), node);
}
Modified: releases/WebKitGTK/webkit-2.20/Source/_javascript_Core/dfg/DFGValidate.cpp (229005 => 229006)
--- releases/WebKitGTK/webkit-2.20/Source/_javascript_Core/dfg/DFGValidate.cpp 2018-02-26 13:14:00 UTC (rev 229005)
+++ releases/WebKitGTK/webkit-2.20/Source/_javascript_Core/dfg/DFGValidate.cpp 2018-02-26 13:14:10 UTC (rev 229006)
@@ -346,6 +346,11 @@
}
break;
}
+ case GetArgumentCountIncludingThis: {
+ if (InlineCallFrame* inlineCallFrame = node->argumentsInlineCallFrame())
+ VALIDATE((node), inlineCallFrame->isVarargs());
+ break;
+ }
default:
break;
}
Modified: releases/WebKitGTK/webkit-2.20/Source/_javascript_Core/dfg/DFGVarargsForwardingPhase.cpp (229005 => 229006)
--- releases/WebKitGTK/webkit-2.20/Source/_javascript_Core/dfg/DFGVarargsForwardingPhase.cpp 2018-02-26 13:14:00 UTC (rev 229005)
+++ releases/WebKitGTK/webkit-2.20/Source/_javascript_Core/dfg/DFGVarargsForwardingPhase.cpp 2018-02-26 13:14:10 UTC (rev 229006)
@@ -28,6 +28,7 @@
#if ENABLE(DFG_JIT)
+#include "ClonedArguments.h"
#include "DFGArgumentsUtilities.h"
#include "DFGClobberize.h"
#include "DFGForAllKills.h"
@@ -90,6 +91,11 @@
if (DFGVarargsForwardingPhaseInternal::verbose)
dataLog("Handling candidate ", candidate, "\n");
+ // We eliminate GetButterfly over CreateClonedArguments if the butterfly is only
+ // used by a GetByOffset that loads the CreateClonedArguments's length. We also
+ // eliminate it if the GetButterfly node is totally unused.
+ Vector<Node*, 1> candidateButterflies;
+
// Find the index of the last node in this block to use the candidate, and look for escaping
// sites.
unsigned lastUserIndex = candidateNodeIndex;
@@ -96,7 +102,17 @@
Vector<VirtualRegister, 2> relevantLocals; // This is a set. We expect it to be a small set.
for (unsigned nodeIndex = candidateNodeIndex + 1; nodeIndex < block->size(); ++nodeIndex) {
Node* node = block->at(nodeIndex);
-
+
+ auto defaultEscape = [&] {
+ if (m_graph.uses(node, candidate)) {
+ if (DFGVarargsForwardingPhaseInternal::verbose)
+ dataLog(" Escape at ", node, "\n");
+ return true;
+ }
+ return false;
+ };
+
+ bool validGetByOffset = false;
switch (node->op()) {
case MovHint:
if (node->child1() != candidate)
@@ -156,15 +172,61 @@
return;
}
break;
-
+
+ case GetArrayLength: {
+ if (node->arrayMode().type() == Array::DirectArguments && node->child1() == candidate && node->child1()->op() == CreateDirectArguments) {
+ lastUserIndex = nodeIndex;
+ break;
+ }
+ if (defaultEscape())
+ return;
+ break;
+ }
+
+ case GetButterfly: {
+ if (node->child1() == candidate && candidate->op() == CreateClonedArguments) {
+ lastUserIndex = nodeIndex;
+ candidateButterflies.append(node);
+ break;
+ }
+ if (defaultEscape())
+ return;
+ break;
+ }
+
+ case GetByOffset: {
+ if (node->child1()->op() == GetButterfly
+ && candidateButterflies.contains(node->child1().node())
+ && node->child2() == candidate
+ && node->storageAccessData().offset == clonedArgumentsLengthPropertyOffset) {
+ ASSERT(node->child1()->child1() == candidate);
+ ASSERT(isOutOfLineOffset(clonedArgumentsLengthPropertyOffset));
+ // We're good to go. This is getting the length of the arguments.
+ lastUserIndex = nodeIndex;
+ validGetByOffset = true;
+ break;
+ }
+ if (defaultEscape())
+ return;
+ break;
+ }
+
default:
- if (m_graph.uses(node, candidate)) {
- if (DFGVarargsForwardingPhaseInternal::verbose)
- dataLog(" Escape at ", node, "\n");
+ if (defaultEscape())
return;
+ break;
+ }
+
+ if (!validGetByOffset) {
+ for (Node* butterfly : candidateButterflies) {
+ if (m_graph.uses(node, butterfly)) {
+ if (DFGVarargsForwardingPhaseInternal::verbose)
+ dataLog(" Butterfly escaped at ", node, "\n");
+ return;
+ }
}
}
-
+
forAllKilledOperands(
m_graph, node, block->tryAt(nodeIndex + 1),
[&] (VirtualRegister reg) {
@@ -261,6 +323,8 @@
DFG_CRASH(m_graph, candidate, "bad node type");
break;
}
+
+ InsertionSet insertionSet(m_graph);
for (unsigned nodeIndex = candidateNodeIndex + 1; nodeIndex <= lastUserIndex; ++nodeIndex) {
Node* node = block->at(nodeIndex);
switch (node->op()) {
@@ -308,7 +372,33 @@
// soon, since it has no real users. DCE will surely kill it. If we make it to SSA, then
// SSA conversion will kill it.
break;
-
+
+ case GetButterfly: {
+ if (node->child1().node() == candidate) {
+ ASSERT(candidateButterflies.contains(node));
+ node->child1() = Edge();
+ node->remove(m_graph);
+ }
+ break;
+ }
+
+ case GetByOffset: {
+ if (node->child2() == candidate) {
+ ASSERT(candidateButterflies.contains(node->child1().node())); // It's no longer a GetButterfly node, but it should've been a candidate butterfly.
+ ASSERT(node->storageAccessData().offset == clonedArgumentsLengthPropertyOffset);
+ node->convertToIdentityOn(
+ emitCodeToGetArgumentsArrayLength(insertionSet, candidate, nodeIndex, node->origin));
+ }
+ break;
+ }
+
+ case GetArrayLength:
+ if (node->arrayMode().type() == Array::DirectArguments && node->child1() == candidate) {
+ node->convertToIdentityOn(
+ emitCodeToGetArgumentsArrayLength(insertionSet, candidate, nodeIndex, node->origin));
+ }
+ break;
+
default:
if (ASSERT_DISABLED)
break;
@@ -320,6 +410,8 @@
break;
}
}
+
+ insertionSet.execute(block);
}
bool m_changed;
Modified: releases/WebKitGTK/webkit-2.20/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp (229005 => 229006)
--- releases/WebKitGTK/webkit-2.20/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp 2018-02-26 13:14:00 UTC (rev 229005)
+++ releases/WebKitGTK/webkit-2.20/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp 2018-02-26 13:14:10 UTC (rev 229006)
@@ -6550,7 +6550,12 @@
void compileGetArgumentCountIncludingThis()
{
- setInt32(m_out.load32(payloadFor(CallFrameSlot::argumentCount)));
+ VirtualRegister argumentCountRegister;
+ if (InlineCallFrame* inlineCallFrame = m_node->argumentsInlineCallFrame())
+ argumentCountRegister = inlineCallFrame->argumentCountRegister;
+ else
+ argumentCountRegister = VirtualRegister(CallFrameSlot::argumentCount);
+ setInt32(m_out.load32(payloadFor(argumentCountRegister)));
}
void compileSetArgumentCountIncludingThis()