Support GetArrayLength on ArrayStorage in the FTL
authorutatane.tea@gmail.com <utatane.tea@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 13 Feb 2018 17:29:07 +0000 (17:29 +0000)
committerutatane.tea@gmail.com <utatane.tea@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 13 Feb 2018 17:29:07 +0000 (17:29 +0000)
https://bugs.webkit.org/show_bug.cgi?id=182625

Reviewed by Saam Barati.

JSTests:

* stress/array-storage-length.js: Added.
(shouldBe):
(testInBound):
(testUncountable):
(testSlowPutInBound):
(testSlowPutUncountable):
* stress/undecided-length.js: Added.
(shouldBe):
(test2):

Source/JavaScriptCore:

This patch adds GetArrayLength and CheckArray + ArrayStorage & SlowPutArrayStorage support for FTL.
The implementation is trivial; just porting one in DFG to FTL.

This fixes several FTL compilation failures in web-tooling-benchmarks while we still need to support
ArrayPush, ArrayPop, Arrayify, and PutByVal.

* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::checkArray):
* ftl/FTLCapabilities.cpp:
(JSC::FTL::canCompile):
* ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::compileGetArrayLength):
(JSC::FTL::DFG::LowerDFGToB3::isArrayTypeForArrayify):
(JSC::FTL::DFG::LowerDFGToB3::isArrayTypeForCheckArray):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@228421 268f45cc-cd09-0410-ab3c-d52691b4dbfc

JSTests/ChangeLog
JSTests/stress/array-storage-length.js [new file with mode: 0644]
JSTests/stress/undecided-length.js [new file with mode: 0644]
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
Source/JavaScriptCore/ftl/FTLCapabilities.cpp
Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp

index aff5c0c..aef1e27 100644 (file)
@@ -1,3 +1,20 @@
+2018-02-13  Yusuke Suzuki  <utatane.tea@gmail.com>
+
+        Support GetArrayLength on ArrayStorage in the FTL
+        https://bugs.webkit.org/show_bug.cgi?id=182625
+
+        Reviewed by Saam Barati.
+
+        * stress/array-storage-length.js: Added.
+        (shouldBe):
+        (testInBound):
+        (testUncountable):
+        (testSlowPutInBound):
+        (testSlowPutUncountable):
+        * stress/undecided-length.js: Added.
+        (shouldBe):
+        (test2):
+
 2018-02-12  Saam Barati  <sbarati@apple.com>
 
         DFG::emitCodeToGetArgumentsArrayLength needs to handle NewArrayBuffer/PhantomNewArrayBuffer
diff --git a/JSTests/stress/array-storage-length.js b/JSTests/stress/array-storage-length.js
new file mode 100644 (file)
index 0000000..4eb5800
--- /dev/null
@@ -0,0 +1,60 @@
+'use strict';
+
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+var object = { a: 10 };
+Object.defineProperties(object, {
+    "0": {
+        get: function() { return this.a; },
+        set: function(x) { this.a = x; },
+    },
+});
+
+var array = [ 0, 1, 2, 3, 4, 5 ];
+ensureArrayStorage(array);
+
+function testInBound(array)
+{
+    return array.length;
+}
+noInline(testInBound);
+for (var i = 0; i < 1e5; ++i)
+    shouldBe(testInBound(array), 6);
+
+function testUncountable(array)
+{
+    return array.length;
+}
+noInline(testUncountable);
+for (var i = 0; i < 1e5; ++i)
+    shouldBe(testUncountable(array), 6);
+array.length = 0xffffffff - 1;
+for (var i = 0; i < 1e5; ++i)
+    shouldBe(testUncountable(array), 0xffffffff - 1);
+
+
+var slowPutArray = [ 0, 1, 2, 3, 4, 5 ];
+ensureArrayStorage(slowPutArray);
+slowPutArray.__proto__ = object;
+
+function testSlowPutInBound(array)
+{
+    return array.length;
+}
+noInline(testSlowPutInBound);
+for (var i = 0; i < 1e5; ++i)
+    shouldBe(testSlowPutInBound(slowPutArray), 6);
+
+function testSlowPutUncountable(array)
+{
+    return array.length;
+}
+noInline(testSlowPutUncountable);
+for (var i = 0; i < 1e5; ++i)
+    shouldBe(testSlowPutUncountable(slowPutArray), 6);
+slowPutArray.length = 0xffffffff - 1;
+for (var i = 0; i < 1e5; ++i)
+    shouldBe(testSlowPutUncountable(slowPutArray), 0xffffffff - 1);
diff --git a/JSTests/stress/undecided-length.js b/JSTests/stress/undecided-length.js
new file mode 100644 (file)
index 0000000..8bd8e90
--- /dev/null
@@ -0,0 +1,25 @@
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+var array = [];
+
+function test1(array)
+{
+    return array.length;
+}
+noInline(test1);
+for (var i = 0; i < 1e5; ++i)
+    shouldBe(test1(array), 0);
+
+var array = [];
+array.ok = 42;
+
+function test2(array)
+{
+    return array.length;
+}
+noInline(test2);
+for (var i = 0; i < 1e5; ++i)
+    shouldBe(test2(array), 0);
index 00518f4..615686c 100644 (file)
@@ -1,3 +1,25 @@
+2018-02-13  Yusuke Suzuki  <utatane.tea@gmail.com>
+
+        Support GetArrayLength on ArrayStorage in the FTL
+        https://bugs.webkit.org/show_bug.cgi?id=182625
+
+        Reviewed by Saam Barati.
+
+        This patch adds GetArrayLength and CheckArray + ArrayStorage & SlowPutArrayStorage support for FTL.
+        The implementation is trivial; just porting one in DFG to FTL.
+
+        This fixes several FTL compilation failures in web-tooling-benchmarks while we still need to support
+        ArrayPush, ArrayPop, Arrayify, and PutByVal.
+
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::checkArray):
+        * ftl/FTLCapabilities.cpp:
+        (JSC::FTL::canCompile):
+        * ftl/FTLLowerDFGToB3.cpp:
+        (JSC::FTL::DFG::LowerDFGToB3::compileGetArrayLength):
+        (JSC::FTL::DFG::LowerDFGToB3::isArrayTypeForArrayify):
+        (JSC::FTL::DFG::LowerDFGToB3::isArrayTypeForCheckArray):
+
 2018-02-10  Filip Pizlo  <fpizlo@apple.com>
 
         Lock down JSFunction
index 42efc29..6db949c 100644 (file)
@@ -822,13 +822,11 @@ void SpeculativeJIT::checkArray(Node* node)
         return;
     }
     
-    const ClassInfo* expectedClassInfo = 0;
-    
     switch (node->arrayMode().type()) {
     case Array::AnyTypedArray:
     case Array::String:
         RELEASE_ASSERT_NOT_REACHED(); // Should have been a Phantom(String:)
-        break;
+        return;
     case Array::Int32:
     case Array::Double:
     case Array::Contiguous:
@@ -860,20 +858,6 @@ void SpeculativeJIT::checkArray(Node* node)
         noResult(m_currentNode);
         return;
     }
-    
-    RELEASE_ASSERT(expectedClassInfo);
-    
-    GPRTemporary temp(this);
-    GPRTemporary temp2(this);
-    m_jit.emitLoadStructure(*m_jit.vm(), baseReg, temp.gpr(), temp2.gpr());
-    speculationCheck(
-        BadType, JSValueSource::unboxedCell(baseReg), node,
-        m_jit.branchPtr(
-            MacroAssembler::NotEqual,
-            MacroAssembler::Address(temp.gpr(), Structure::classInfoOffset()),
-            TrustedImmPtr(PoisonedClassInfoPtr(expectedClassInfo).bits())));
-
-    noResult(m_currentNode);
 }
 
 void SpeculativeJIT::arrayify(Node* node, GPRReg baseReg, GPRReg propertyReg)
index a450f89..4995e3d 100644 (file)
@@ -355,6 +355,9 @@ inline CapabilityLevel canCompile(Node* node)
         case Array::Int32:
         case Array::Double:
         case Array::Contiguous:
+        case Array::Undecided:
+        case Array::ArrayStorage:
+        case Array::SlowPutArrayStorage:
         case Array::DirectArguments:
         case Array::ScopedArguments:
             break;
@@ -370,6 +373,8 @@ inline CapabilityLevel canCompile(Node* node)
         case Array::Int32:
         case Array::Double:
         case Array::Contiguous:
+        case Array::ArrayStorage:
+        case Array::SlowPutArrayStorage:
         case Array::String:
         case Array::DirectArguments:
         case Array::ScopedArguments:
index 765d52d..d0f25c7 100644 (file)
@@ -3644,6 +3644,14 @@ private:
             setInt32(m_out.load32NonNegative(lowStorage(m_node->child2()), m_heaps.Butterfly_publicLength));
             return;
         }
+
+        case Array::ArrayStorage:
+        case Array::SlowPutArrayStorage: {
+            LValue length = m_out.load32(lowStorage(m_node->child2()), m_heaps.Butterfly_publicLength);
+            speculate(Uncountable, noValue(), nullptr, m_out.lessThan(length, m_out.int32Zero));
+            setInt32(length);
+            return;
+        }
             
         case Array::String: {
             LValue string = lowCell(m_node->child1());
@@ -14540,7 +14548,10 @@ private:
         switch (arrayMode.type()) {
         case Array::Int32:
         case Array::Double:
-        case Array::Contiguous: {
+        case Array::Contiguous:
+        case Array::Undecided:
+        case Array::ArrayStorage:
+        case Array::SlowPutArrayStorage: {
             IndexingType shape = arrayMode.shapeMask();
             LValue indexingType = m_out.load8ZeroExt32(cell, m_heaps.JSCell_indexingTypeAndMisc);
 
@@ -14580,6 +14591,9 @@ private:
         case Array::Int32:
         case Array::Double:
         case Array::Contiguous:
+        case Array::Undecided:
+        case Array::ArrayStorage:
+        case Array::SlowPutArrayStorage:
             return isArrayTypeForArrayify(cell, arrayMode);
             
         case Array::DirectArguments: