Diff
Modified: releases/WebKitGTK/webkit-2.20/JSTests/ChangeLog (228992 => 228993)
--- releases/WebKitGTK/webkit-2.20/JSTests/ChangeLog 2018-02-26 10:03:26 UTC (rev 228992)
+++ releases/WebKitGTK/webkit-2.20/JSTests/ChangeLog 2018-02-26 10:03:34 UTC (rev 228993)
@@ -1,5 +1,27 @@
2018-02-14 Yusuke Suzuki <[email protected]>
+ [FTL] Support ArrayPush for ArrayStorage
+ https://bugs.webkit.org/show_bug.cgi?id=182782
+
+ Reviewed by Saam Barati.
+
+ Existing array-push-multiple-storage.js covers ArrayPush(ArrayStorage) multiple arguments case.
+
+ * stress/array-push-array-storage-beyond-int32.js: Added.
+ (shouldBe):
+ (test):
+ * stress/array-push-array-storage.js: Added.
+ (shouldBe):
+ (test):
+ * stress/array-push-multiple-array-storage-beyond-int32.js: Added.
+ (shouldBe):
+ (test):
+ * stress/array-push-multiple-storage-continuous.js: Added.
+ (shouldBe):
+ (test):
+
+2018-02-14 Yusuke Suzuki <[email protected]>
+
[FTL] Support ArrayPop for ArrayStorage
https://bugs.webkit.org/show_bug.cgi?id=182783
Added: releases/WebKitGTK/webkit-2.20/JSTests/stress/array-push-array-storage-beyond-int32.js (0 => 228993)
--- releases/WebKitGTK/webkit-2.20/JSTests/stress/array-push-array-storage-beyond-int32.js (rev 0)
+++ releases/WebKitGTK/webkit-2.20/JSTests/stress/array-push-array-storage-beyond-int32.js 2018-02-26 10:03:34 UTC (rev 228993)
@@ -0,0 +1,27 @@
+function shouldBe(actual, expected)
+{
+ if (actual !== expected)
+ throw new Error('bad value: ' + actual);
+}
+
+function test(array, val1)
+{
+ return array.push(val1);
+}
+noInline(test);
+
+for (var i = 0; i < 1e5; ++i) {
+ var array = ["Cocoa"];
+ ensureArrayStorage(array);
+ array.length = 2;
+ shouldBe(test(array, "Cocoa"), 3);
+ shouldBe(array[0], "Cocoa");
+ shouldBe(array[1], undefined);
+ shouldBe(array[2], "Cocoa");
+}
+
+var array = ["Cocoa"];
+ensureArrayStorage(array);
+array.length = 0x7fffffff;
+shouldBe(test(array, "Cocoa"), 0x7fffffff + 1);
+shouldBe(array[0x7fffffff], "Cocoa");
Added: releases/WebKitGTK/webkit-2.20/JSTests/stress/array-push-array-storage.js (0 => 228993)
--- releases/WebKitGTK/webkit-2.20/JSTests/stress/array-push-array-storage.js (rev 0)
+++ releases/WebKitGTK/webkit-2.20/JSTests/stress/array-push-array-storage.js 2018-02-26 10:03:34 UTC (rev 228993)
@@ -0,0 +1,40 @@
+function shouldBe(actual, expected)
+{
+ if (actual !== expected)
+ throw new Error('bad value: ' + actual);
+}
+
+function test(array, val1)
+{
+ return array.push(val1);
+}
+noInline(test);
+
+for (var i = 0; i < 1e5; ++i) {
+ var array = ["Cocoa"];
+ ensureArrayStorage(array);
+ shouldBe(test(array, "Cocoa"), 2);
+ shouldBe(array[0], "Cocoa");
+ shouldBe(array[1], "Cocoa");
+ shouldBe(array[2], undefined);
+ shouldBe(array[3], undefined);
+ shouldBe(array[4], undefined);
+ shouldBe(test(array, "Cappuccino"), 3);
+ shouldBe(array[0], "Cocoa");
+ shouldBe(array[1], "Cocoa");
+ shouldBe(array[2], "Cappuccino");
+ shouldBe(array[3], undefined);
+ shouldBe(array[4], undefined);
+ shouldBe(test(array, "Matcha"), 4);
+ shouldBe(array[0], "Cocoa");
+ shouldBe(array[1], "Cocoa");
+ shouldBe(array[2], "Cappuccino");
+ shouldBe(array[3], "Matcha");
+ shouldBe(array[4], undefined);
+ shouldBe(test(array, "Matcha"), 5);
+ shouldBe(array[0], "Cocoa");
+ shouldBe(array[1], "Cocoa");
+ shouldBe(array[2], "Cappuccino");
+ shouldBe(array[3], "Matcha");
+ shouldBe(array[4], "Matcha");
+}
Added: releases/WebKitGTK/webkit-2.20/JSTests/stress/array-push-multiple-array-storage-beyond-int32.js (0 => 228993)
--- releases/WebKitGTK/webkit-2.20/JSTests/stress/array-push-multiple-array-storage-beyond-int32.js (rev 0)
+++ releases/WebKitGTK/webkit-2.20/JSTests/stress/array-push-multiple-array-storage-beyond-int32.js 2018-02-26 10:03:34 UTC (rev 228993)
@@ -0,0 +1,29 @@
+function shouldBe(actual, expected)
+{
+ if (actual !== expected)
+ throw new Error('bad value: ' + actual);
+}
+
+function test(array, val1, val2)
+{
+ return array.push(val1, val2);
+}
+noInline(test);
+
+for (var i = 0; i < 1e5; ++i) {
+ var array = ["Cocoa"];
+ ensureArrayStorage(array);
+ array.length = 2;
+ shouldBe(test(array, "Cocoa", "Cappuccino"), 4);
+ shouldBe(array[0], "Cocoa");
+ shouldBe(array[1], undefined);
+ shouldBe(array[2], "Cocoa");
+ shouldBe(array[3], "Cappuccino");
+}
+
+var array = ["Cocoa"];
+ensureArrayStorage(array);
+array.length = 0x7fffffff - 1;
+shouldBe(test(array, "Cocoa", "Cappuccino"), 0x7fffffff + 1);
+shouldBe(array[0x7fffffff - 1], "Cocoa");
+shouldBe(array[0x7fffffff - 0], "Cappuccino");
Added: releases/WebKitGTK/webkit-2.20/JSTests/stress/array-push-multiple-storage-continuous.js (0 => 228993)
--- releases/WebKitGTK/webkit-2.20/JSTests/stress/array-push-multiple-storage-continuous.js (rev 0)
+++ releases/WebKitGTK/webkit-2.20/JSTests/stress/array-push-multiple-storage-continuous.js 2018-02-26 10:03:34 UTC (rev 228993)
@@ -0,0 +1,31 @@
+function shouldBe(actual, expected)
+{
+ if (actual !== expected)
+ throw new Error('bad value: ' + actual);
+}
+
+function test(array, val1, val2, val3)
+{
+ return array.push(val1, val2, val3);
+}
+noInline(test);
+
+for (var i = 0; i < 1e5; ++i) {
+ var array = [];
+ ensureArrayStorage(array);
+ shouldBe(test(array, "Cocoa", "Cappuccino", "Matcha"), 3);
+ shouldBe(array[0], "Cocoa");
+ shouldBe(array[1], "Cappuccino");
+ shouldBe(array[2], "Matcha");
+}
+
+var array = [];
+ensureArrayStorage(array);
+for (var i = 0; i < 1e3; ++i) {
+ shouldBe(test(array, "Cocoa", "Cappuccino", "Matcha"), 3 * (i + 1));
+}
+for (var i = 0; i < 1e3; ++i) {
+ shouldBe(array[3 * i + 0], "Cocoa");
+ shouldBe(array[3 * i + 1], "Cappuccino");
+ shouldBe(array[3 * i + 2], "Matcha");
+}
Modified: releases/WebKitGTK/webkit-2.20/Source/_javascript_Core/ChangeLog (228992 => 228993)
--- releases/WebKitGTK/webkit-2.20/Source/_javascript_Core/ChangeLog 2018-02-26 10:03:26 UTC (rev 228992)
+++ releases/WebKitGTK/webkit-2.20/Source/_javascript_Core/ChangeLog 2018-02-26 10:03:34 UTC (rev 228993)
@@ -1,5 +1,20 @@
2018-02-14 Yusuke Suzuki <[email protected]>
+ [FTL] Support ArrayPush for ArrayStorage
+ https://bugs.webkit.org/show_bug.cgi?id=182782
+
+ Reviewed by Saam Barati.
+
+ This patch adds support for ArrayPush(ArrayStorage). We just port ArrayPush(ArrayStorage) in DFG to FTL.
+
+ * ftl/FTLAbstractHeapRepository.h:
+ * ftl/FTLCapabilities.cpp:
+ (JSC::FTL::canCompile):
+ * ftl/FTLLowerDFGToB3.cpp:
+ (JSC::FTL::DFG::LowerDFGToB3::compileArrayPush):
+
+2018-02-14 Yusuke Suzuki <[email protected]>
+
[FTL] Support ArrayPop for ArrayStorage
https://bugs.webkit.org/show_bug.cgi?id=182783
Modified: releases/WebKitGTK/webkit-2.20/Source/_javascript_Core/ftl/FTLCapabilities.cpp (228992 => 228993)
--- releases/WebKitGTK/webkit-2.20/Source/_javascript_Core/ftl/FTLCapabilities.cpp 2018-02-26 10:03:26 UTC (rev 228992)
+++ releases/WebKitGTK/webkit-2.20/Source/_javascript_Core/ftl/FTLCapabilities.cpp 2018-02-26 10:03:34 UTC (rev 228993)
@@ -319,6 +319,7 @@
case ArraySlice:
case ArrayIndexOf:
case ArrayPop:
+ case ArrayPush:
case ParseInt:
case AtomicsAdd:
case AtomicsAnd:
@@ -437,16 +438,6 @@
break;
case PutByValWithThis:
break;
- case ArrayPush:
- switch (node->arrayMode().type()) {
- case Array::Int32:
- case Array::Contiguous:
- case Array::Double:
- break;
- default:
- return CannotCompile;
- }
- break;
default:
// Don't know how to handle anything else.
return CannotCompile;
Modified: releases/WebKitGTK/webkit-2.20/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp (228992 => 228993)
--- releases/WebKitGTK/webkit-2.20/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp 2018-02-26 10:03:26 UTC (rev 228992)
+++ releases/WebKitGTK/webkit-2.20/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp 2018-02-26 10:03:34 UTC (rev 228993)
@@ -4475,6 +4475,100 @@
return;
}
+ case Array::ArrayStorage: {
+ // This ensures that the result of ArrayPush is Int32 in AI.
+ int32_t largestPositiveInt32Length = 0x7fffffff - elementCount;
+
+ LValue prevLength = m_out.load32(storage, m_heaps.Butterfly_publicLength);
+ // Refuse to handle bizarre lengths.
+ speculate(Uncountable, noValue(), nullptr, m_out.above(prevLength, m_out.constInt32(largestPositiveInt32Length)));
+
+ if (elementCount == 1) {
+ Edge& element = m_graph.varArgChild(m_node, elementOffset);
+
+ LValue value = lowJSValue(element);
+
+ LBasicBlock fastPath = m_out.newBlock();
+ LBasicBlock slowPath = m_out.newBlock();
+ LBasicBlock continuation = m_out.newBlock();
+
+ m_out.branch(
+ m_out.aboveOrEqual(
+ prevLength, m_out.load32(storage, m_heaps.Butterfly_vectorLength)),
+ rarely(slowPath), usually(fastPath));
+
+ LBasicBlock lastNext = m_out.appendTo(fastPath, slowPath);
+ m_out.store64(
+ value, m_out.baseIndex(m_heaps.ArrayStorage_vector, storage, m_out.zeroExtPtr(prevLength)));
+ LValue newLength = m_out.add(prevLength, m_out.int32One);
+ m_out.store32(newLength, storage, m_heaps.Butterfly_publicLength);
+ m_out.store32(
+ m_out.add(m_out.load32(storage, m_heaps.ArrayStorage_numValuesInVector), m_out.int32One),
+ storage, m_heaps.ArrayStorage_numValuesInVector);
+
+ ValueFromBlock fastResult = m_out.anchor(boxInt32(newLength));
+ m_out.jump(continuation);
+
+ m_out.appendTo(slowPath, continuation);
+ ValueFromBlock slowResult = m_out.anchor(
+ vmCall(Int64, m_out.operation(operationArrayPush), m_callFrame, value, base));
+ m_out.jump(continuation);
+
+ m_out.appendTo(continuation, lastNext);
+ setJSValue(m_out.phi(Int64, fastResult, slowResult));
+ return;
+ }
+
+ LValue newLength = m_out.add(prevLength, m_out.constInt32(elementCount));
+
+ LBasicBlock fastPath = m_out.newBlock();
+ LBasicBlock slowPath = m_out.newBlock();
+ LBasicBlock setup = m_out.newBlock();
+ LBasicBlock slowCallPath = m_out.newBlock();
+ LBasicBlock continuation = m_out.newBlock();
+
+ LValue beyondVectorLength = m_out.above(newLength, m_out.load32(storage, m_heaps.Butterfly_vectorLength));
+
+ m_out.branch(beyondVectorLength, rarely(slowPath), usually(fastPath));
+
+ LBasicBlock lastNext = m_out.appendTo(fastPath, slowPath);
+ m_out.store32(newLength, storage, m_heaps.Butterfly_publicLength);
+ m_out.store32(
+ m_out.add(m_out.load32(storage, m_heaps.ArrayStorage_numValuesInVector), m_out.constInt32(elementCount)),
+ storage, m_heaps.ArrayStorage_numValuesInVector);
+ ValueFromBlock fastBufferResult = m_out.anchor(m_out.baseIndex(storage, m_out.zeroExtPtr(prevLength), ScaleEight, ArrayStorage::vectorOffset()));
+ m_out.jump(setup);
+
+ m_out.appendTo(slowPath, setup);
+ size_t scratchSize = sizeof(EncodedJSValue) * elementCount;
+ ASSERT(scratchSize);
+ ScratchBuffer* scratchBuffer = vm().scratchBufferForSize(scratchSize);
+ m_out.storePtr(m_out.constIntPtr(scratchSize), m_out.absolute(scratchBuffer->addressOfActiveLength()));
+ ValueFromBlock slowBufferResult = m_out.anchor(m_out.constIntPtr(static_cast<EncodedJSValue*>(scratchBuffer->dataBuffer())));
+ m_out.jump(setup);
+
+ m_out.appendTo(setup, slowCallPath);
+ LValue buffer = m_out.phi(pointerType(), fastBufferResult, slowBufferResult);
+ for (unsigned elementIndex = 0; elementIndex < elementCount; ++elementIndex) {
+ Edge& element = m_graph.varArgChild(m_node, elementIndex + elementOffset);
+
+ LValue value = lowJSValue(element);
+ m_out.store64(value, m_out.baseIndex(m_heaps.variables, buffer, m_out.constInt32(elementIndex), jsNumber(elementIndex)));
+ }
+ ValueFromBlock fastResult = m_out.anchor(boxInt32(newLength));
+
+ m_out.branch(beyondVectorLength, rarely(slowCallPath), usually(continuation));
+
+ m_out.appendTo(slowCallPath, continuation);
+ ValueFromBlock slowResult = m_out.anchor(vmCall(Int64, m_out.operation(operationArrayPushMultiple), m_callFrame, base, buffer, m_out.constInt32(elementCount)));
+ m_out.storePtr(m_out.constIntPtr(0), m_out.absolute(scratchBuffer->addressOfActiveLength()));
+ m_out.jump(continuation);
+
+ m_out.appendTo(continuation, lastNext);
+ setJSValue(m_out.phi(Int64, fastResult, slowResult));
+ return;
+ }
+
default:
DFG_CRASH(m_graph, m_node, "Bad array type");
return;
@@ -14635,7 +14729,7 @@
m_out.bitAnd(indexingType, m_out.constInt32(IndexingShapeMask)),
m_out.constInt32(ArrayStorageShape)),
m_out.constInt32(SlowPutArrayStorageShape - ArrayStorageShape));
- m_out.branch(isAnArrayStorageShape, usually(checkCase), usually(continuation));
+ m_out.branch(isAnArrayStorageShape, unsure(checkCase), unsure(continuation));
LBasicBlock lastNext = m_out.appendTo(checkCase, trueCase);
switch (arrayMode.arrayClass()) {
@@ -14646,7 +14740,7 @@
case Array::Array:
m_out.branch(
m_out.testNonZero32(indexingType, m_out.constInt32(IsArray)),
- usually(trueCase), usually(continuation));
+ unsure(trueCase), unsure(continuation));
break;
case Array::NonArray:
@@ -14653,7 +14747,7 @@
case Array::OriginalNonArray:
m_out.branch(
m_out.testIsZero32(indexingType, m_out.constInt32(IsArray)),
- usually(trueCase), usually(continuation));
+ unsure(trueCase), unsure(continuation));
break;
case Array::PossiblyArray: