Title: [229743] trunk
Revision
229743
Author
[email protected]
Date
2018-03-20 00:58:22 -0700 (Tue, 20 Mar 2018)

Log Message

[DFG][FTL] Add vectorLengthHint for NewArray
https://bugs.webkit.org/show_bug.cgi?id=183694

Reviewed by Saam Barati.

JSTests:

* stress/vector-length-hint-array-constructor.js: Added.
(shouldBe):
(test):
* stress/vector-length-hint-new-array.js: Added.
(shouldBe):
(test):

Source/_javascript_Core:

While the following code is a common, it is not so efficient.

var array = [];
for (...) {
    ...
    array.push(...);
}

The array is always allocated with 0 vector length. And it is eventually grown.

We have ArrayAllocationProfile, and it tells us that the vector length hint for
the allocated arrays. This hint is already used for NewArrayBuffer. This patch
extends this support for NewArray DFG node.

This patch improves Kraken/stanford-crypto-aes 4%.

                              baseline                  patched

stanford-crypto-aes        64.069+-1.352             61.589+-1.274           might be 1.0403x faster

NewArray can be optimized.

                                               baseline                  patched

vector-length-hint-new-array               21.8157+-0.0882     ^     13.1764+-0.0942        ^ definitely 1.6557x faster
vector-length-hint-array-constructor       21.9076+-0.0987     ?     22.1168+-0.4814        ?

* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::handleConstantInternalFunction):
(JSC::DFG::ByteCodeParser::parseBlock):
* dfg/DFGNode.h:
(JSC::DFG::Node::hasVectorLengthHint):
(JSC::DFG::Node::vectorLengthHint):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::compileNewArray):

Modified Paths

Added Paths

Diff

Modified: trunk/JSTests/ChangeLog (229742 => 229743)


--- trunk/JSTests/ChangeLog	2018-03-20 07:12:56 UTC (rev 229742)
+++ trunk/JSTests/ChangeLog	2018-03-20 07:58:22 UTC (rev 229743)
@@ -1,3 +1,17 @@
+2018-03-16  Yusuke Suzuki  <[email protected]>
+
+        [DFG][FTL] Add vectorLengthHint for NewArray
+        https://bugs.webkit.org/show_bug.cgi?id=183694
+
+        Reviewed by Saam Barati.
+
+        * stress/vector-length-hint-array-constructor.js: Added.
+        (shouldBe):
+        (test):
+        * stress/vector-length-hint-new-array.js: Added.
+        (shouldBe):
+        (test):
+
 2018-03-13  Yusuke Suzuki  <[email protected]>
 
         [DFG][FTL] Make ArraySlice(0) code tight

Added: trunk/JSTests/microbenchmarks/vector-length-hint-array-constructor.js (0 => 229743)


--- trunk/JSTests/microbenchmarks/vector-length-hint-array-constructor.js	                        (rev 0)
+++ trunk/JSTests/microbenchmarks/vector-length-hint-array-constructor.js	2018-03-20 07:58:22 UTC (rev 229743)
@@ -0,0 +1,11 @@
+function test(constructor)
+{
+    var array = new constructor(1, 2);
+    for (var i = 0; i < 20; ++i)
+        array.push(i);
+    return array;
+}
+noInline(test);
+
+for (var i = 0; i < 1e5; ++i)
+    var result = test(Array);

Added: trunk/JSTests/microbenchmarks/vector-length-hint-new-array.js (0 => 229743)


--- trunk/JSTests/microbenchmarks/vector-length-hint-new-array.js	                        (rev 0)
+++ trunk/JSTests/microbenchmarks/vector-length-hint-new-array.js	2018-03-20 07:58:22 UTC (rev 229743)
@@ -0,0 +1,11 @@
+function test(v0, v1)
+{
+    var array = [v0, v1];
+    for (var i = 0; i < 20; ++i)
+        array.push(i);
+    return array;
+}
+noInline(test);
+
+for (var i = 0; i < 1e5; ++i)
+    test(1, 2);

Added: trunk/JSTests/stress/vector-length-hint-array-constructor.js (0 => 229743)


--- trunk/JSTests/stress/vector-length-hint-array-constructor.js	                        (rev 0)
+++ trunk/JSTests/stress/vector-length-hint-array-constructor.js	2018-03-20 07:58:22 UTC (rev 229743)
@@ -0,0 +1,18 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + String(actual) + ' ' + String(expected));
+}
+
+function test(constructor)
+{
+    var array = new constructor(1, 2);
+    for (var i = 0; i < 20; ++i)
+        array.push(i);
+    return array;
+}
+noInline(test);
+
+for (var i = 0; i < 1e5; ++i) {
+    var result = test(Array);
+    shouldBe(JSON.stringify(result), `[1,2,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]`);
+}

Added: trunk/JSTests/stress/vector-length-hint-new-array.js (0 => 229743)


--- trunk/JSTests/stress/vector-length-hint-new-array.js	                        (rev 0)
+++ trunk/JSTests/stress/vector-length-hint-new-array.js	2018-03-20 07:58:22 UTC (rev 229743)
@@ -0,0 +1,18 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + String(actual) + ' ' + String(expected));
+}
+
+function test(v0, v1)
+{
+    var array = [v0, v1];
+    for (var i = 0; i < 20; ++i)
+        array.push(i);
+    return array;
+}
+noInline(test);
+
+for (var i = 0; i < 1e5; ++i) {
+    var result = test(1, 2);
+    shouldBe(JSON.stringify(result), `[1,2,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]`);
+}

Modified: trunk/Source/_javascript_Core/ChangeLog (229742 => 229743)


--- trunk/Source/_javascript_Core/ChangeLog	2018-03-20 07:12:56 UTC (rev 229742)
+++ trunk/Source/_javascript_Core/ChangeLog	2018-03-20 07:58:22 UTC (rev 229743)
@@ -1,3 +1,48 @@
+2018-03-16  Yusuke Suzuki  <[email protected]>
+
+        [DFG][FTL] Add vectorLengthHint for NewArray
+        https://bugs.webkit.org/show_bug.cgi?id=183694
+
+        Reviewed by Saam Barati.
+
+        While the following code is a common, it is not so efficient.
+
+        var array = [];
+        for (...) {
+            ...
+            array.push(...);
+        }
+
+        The array is always allocated with 0 vector length. And it is eventually grown.
+
+        We have ArrayAllocationProfile, and it tells us that the vector length hint for
+        the allocated arrays. This hint is already used for NewArrayBuffer. This patch
+        extends this support for NewArray DFG node.
+
+        This patch improves Kraken/stanford-crypto-aes 4%.
+
+                                      baseline                  patched
+
+        stanford-crypto-aes        64.069+-1.352             61.589+-1.274           might be 1.0403x faster
+
+        NewArray can be optimized.
+
+                                                       baseline                  patched
+
+        vector-length-hint-new-array               21.8157+-0.0882     ^     13.1764+-0.0942        ^ definitely 1.6557x faster
+        vector-length-hint-array-constructor       21.9076+-0.0987     ?     22.1168+-0.4814        ?
+
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::handleConstantInternalFunction):
+        (JSC::DFG::ByteCodeParser::parseBlock):
+        * dfg/DFGNode.h:
+        (JSC::DFG::Node::hasVectorLengthHint):
+        (JSC::DFG::Node::vectorLengthHint):
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * ftl/FTLLowerDFGToB3.cpp:
+        (JSC::FTL::DFG::LowerDFGToB3::compileNewArray):
+
 2018-03-13  Yusuke Suzuki  <[email protected]>
 
         [DFG][FTL] Make ArraySlice(0) code tight

Modified: trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp (229742 => 229743)


--- trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2018-03-20 07:12:56 UTC (rev 229742)
+++ trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2018-03-20 07:58:22 UTC (rev 229743)
@@ -3455,7 +3455,7 @@
         for (int i = 1; i < argumentCountIncludingThis; ++i)
             addVarArgChild(get(virtualRegisterForArgument(i, registerOffset)));
         set(VirtualRegister(resultOperand),
-            addToGraph(Node::VarArg, NewArray, OpInfo(ArrayWithUndecided), OpInfo(0)));
+            addToGraph(Node::VarArg, NewArray, OpInfo(ArrayWithUndecided), OpInfo(argumentCountIncludingThis - 1)));
         return true;
     }
 
@@ -4510,7 +4510,8 @@
             ArrayAllocationProfile* profile = ""
             for (int operandIdx = startOperand; operandIdx > startOperand - numOperands; --operandIdx)
                 addVarArgChild(get(VirtualRegister(operandIdx)));
-            set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(Node::VarArg, NewArray, OpInfo(profile->selectIndexingType()), OpInfo(0)));
+            unsigned vectorLengthHint = std::max<unsigned>(profile->vectorLengthHint(), numOperands);
+            set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(Node::VarArg, NewArray, OpInfo(profile->selectIndexingType()), OpInfo(vectorLengthHint)));
             NEXT_OPCODE(op_new_array);
         }
 

Modified: trunk/Source/_javascript_Core/dfg/DFGNode.h (229742 => 229743)


--- trunk/Source/_javascript_Core/dfg/DFGNode.h	2018-03-20 07:12:56 UTC (rev 229742)
+++ trunk/Source/_javascript_Core/dfg/DFGNode.h	2018-03-20 07:58:22 UTC (rev 229743)
@@ -1121,12 +1121,21 @@
 
     unsigned hasVectorLengthHint()
     {
-        return op() == NewArrayBuffer || op() == PhantomNewArrayBuffer;
+        switch (op()) {
+        case NewArray:
+        case NewArrayBuffer:
+        case PhantomNewArrayBuffer:
+            return true;
+        default:
+            return false;
+        }
     }
     
     unsigned vectorLengthHint()
     {
         ASSERT(hasVectorLengthHint());
+        if (op() == NewArray)
+            return m_opInfo2.as<unsigned>();
         return newArrayBufferData().vectorLengthHint;
     }
     

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp (229742 => 229743)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp	2018-03-20 07:12:56 UTC (rev 229742)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp	2018-03-20 07:58:22 UTC (rev 229743)
@@ -3730,6 +3730,8 @@
                 || hasContiguous(structure->indexingType()));
             
             unsigned numElements = node->numChildren();
+            unsigned vectorLengthHint = node->vectorLengthHint();
+            ASSERT(vectorLengthHint >= numElements);
             
             GPRTemporary result(this);
             GPRTemporary storage(this);
@@ -3737,7 +3739,7 @@
             GPRReg resultGPR = result.gpr();
             GPRReg storageGPR = storage.gpr();
 
-            emitAllocateRawObject(resultGPR, structure, storageGPR, numElements, numElements);
+            emitAllocateRawObject(resultGPR, structure, storageGPR, numElements, vectorLengthHint);
             
             // At this point, one way or another, resultGPR and storageGPR have pointers to
             // the JSArray and the Butterfly, respectively.

Modified: trunk/Source/_javascript_Core/dfg/DFGValidate.cpp (229742 => 229743)


--- trunk/Source/_javascript_Core/dfg/DFGValidate.cpp	2018-03-20 07:12:56 UTC (rev 229742)
+++ trunk/Source/_javascript_Core/dfg/DFGValidate.cpp	2018-03-20 07:58:22 UTC (rev 229743)
@@ -351,6 +351,12 @@
                         VALIDATE((node), inlineCallFrame->isVarargs());
                     break;
                 }
+                case NewArray:
+                    VALIDATE((node), node->vectorLengthHint() >= node->numChildren());
+                    break;
+                case NewArrayBuffer:
+                    VALIDATE((node), node->vectorLengthHint() >= node->castOperand<JSFixedArray*>()->length());
+                    break;
                 default:
                     break;
                 }
@@ -787,6 +793,7 @@
 
                 case PhantomNewArrayBuffer:
                     VALIDATE((node), m_graph.m_form == SSA);
+                    VALIDATE((node), node->vectorLengthHint() >= node->castOperand<JSFixedArray*>()->length());
                     break;
 
                 case NewArrayWithSpread: {

Modified: trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp (229742 => 229743)


--- trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp	2018-03-20 07:12:56 UTC (rev 229742)
+++ trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp	2018-03-20 07:58:22 UTC (rev 229743)
@@ -5411,9 +5411,11 @@
 
         if (!globalObject->isHavingABadTime() && !hasAnyArrayStorage(m_node->indexingType())) {
             unsigned numElements = m_node->numChildren();
+            unsigned vectorLengthHint = m_node->vectorLengthHint();
+            ASSERT(vectorLengthHint >= numElements);
             
             ArrayValues arrayValues =
-                allocateUninitializedContiguousJSArray(m_out.constInt32(numElements), structure);
+                allocateUninitializedContiguousJSArray(numElements, vectorLengthHint, structure);
             
             for (unsigned operandIndex = 0; operandIndex < m_node->numChildren(); ++operandIndex) {
                 Edge edge = m_graph.varArgChild(m_node, operandIndex);
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to