Title: [264750] trunk
Revision
264750
Author
shvaikal...@gmail.com
Date
2020-07-23 01:25:12 -0700 (Thu, 23 Jul 2020)

Log Message

Remove ArrayNode::m_optional
https://bugs.webkit.org/show_bug.cgi?id=214294

Reviewed by Darin Adler.

JSTests:

* microbenchmarks/destructuring-array-literal.js: Added.
* microbenchmarks/function-dot-apply-array-literal.js: Added.
* stress/apply-second-argument-must-be-array-like.js:
* stress/destructuring-assignment-syntax.js:

Source/_javascript_Core:

m_optional, which dates back to KJS era, means "is this an array with optional trailing comma,
with elision, or an empty array". It was used by ArrayNode::streamTo() to preserve a trailing
comma when converting array node to source string, as well as in few other places,
before ECMA-262 clarified trailing comma in array literals [1].

Currently, m_optional is used only by ArrayNode::isSimpleArray(), along with m_elision.
Checking m_elision is enough since trailing comma doesn't add extra `undefined` element.

This patch completely removes m_optional, speeding up destructuring and function.apply()
with empty arrays and arrays with trailing commas by ~55% and a factor of 11 respectively.
Reflect.apply() optimization (https://webkit.org/b/190668) will also benefit from this change.

Also, this change converts isSpreadExpression() check to an ASSERT (was enabled by r196323).

[1]: https://tc39.es/ecma262/#sec-array-initializer

* bytecompiler/NodesCodegen.cpp:
(JSC::ArrayNode::isSimpleArray const):
(JSC::ArrayNode::toArgumentList const):
(JSC::ArrayNode::emitDirectBinding):
* parser/NodeConstructors.h:
(JSC::ArrayNode::ArrayNode):
* parser/Nodes.h:

Modified Paths

Added Paths

Diff

Modified: trunk/JSTests/ChangeLog (264749 => 264750)


--- trunk/JSTests/ChangeLog	2020-07-23 07:50:11 UTC (rev 264749)
+++ trunk/JSTests/ChangeLog	2020-07-23 08:25:12 UTC (rev 264750)
@@ -1,3 +1,15 @@
+2020-07-23  Alexey Shvayka  <shvaikal...@gmail.com>
+
+        Remove ArrayNode::m_optional
+        https://bugs.webkit.org/show_bug.cgi?id=214294
+
+        Reviewed by Darin Adler.
+
+        * microbenchmarks/destructuring-array-literal.js: Added.
+        * microbenchmarks/function-dot-apply-array-literal.js: Added.
+        * stress/apply-second-argument-must-be-array-like.js:
+        * stress/destructuring-assignment-syntax.js:
+
 2020-07-22  Angelos Oikonomopoulos  <ange...@igalia.com>
 
         Skip failing intl tests on ARM

Added: trunk/JSTests/microbenchmarks/destructuring-array-literal.js (0 => 264750)


--- trunk/JSTests/microbenchmarks/destructuring-array-literal.js	                        (rev 0)
+++ trunk/JSTests/microbenchmarks/destructuring-array-literal.js	2020-07-23 08:25:12 UTC (rev 264750)
@@ -0,0 +1,5 @@
+for (var i = 0; i < 1e6; ++i) {
+    var [] = [];
+    var [a] = [1,];
+    var [b, c] = [1, 2,];
+}

Added: trunk/JSTests/microbenchmarks/function-dot-apply-array-literal.js (0 => 264750)


--- trunk/JSTests/microbenchmarks/function-dot-apply-array-literal.js	                        (rev 0)
+++ trunk/JSTests/microbenchmarks/function-dot-apply-array-literal.js	2020-07-23 08:25:12 UTC (rev 264750)
@@ -0,0 +1,8 @@
+function fn() {}
+noInline(Function.prototype.apply);
+
+for (var i = 0; i < 1e7; ++i) {
+    fn.apply(null, []);
+    fn.apply(null, [1,]);
+    fn.apply(null, [1, 2,]);
+}

Modified: trunk/JSTests/stress/apply-second-argument-must-be-array-like.js (264749 => 264750)


--- trunk/JSTests/stress/apply-second-argument-must-be-array-like.js	2020-07-23 07:50:11 UTC (rev 264749)
+++ trunk/JSTests/stress/apply-second-argument-must-be-array-like.js	2020-07-23 08:25:12 UTC (rev 264750)
@@ -18,19 +18,6 @@
     }
 }
 
-function shouldNotThrow(expr) {
-    let testFunc = new Function(expr);
-    for (let i = 0; i < 10000; i++) {
-        let error;
-        try {
-            testFunc();
-        } catch (e) {
-            error = e;
-        }
-        assert(!error);
-    }
-}
-
 function foo() { }
 
 shouldThrow("foo.apply(undefined, true)");
@@ -42,8 +29,16 @@
 shouldThrow("foo.apply(undefined, 'hello')");
 shouldThrow("foo.apply(undefined, Symbol())");
 
-shouldNotThrow("foo.apply(undefined, undefined)");
-shouldNotThrow("foo.apply(undefined, null)");
-shouldNotThrow("foo.apply(undefined, {})");
-shouldNotThrow("foo.apply(undefined, [])");
-shouldNotThrow("foo.apply(undefined, function(){})");
+function bar() {
+    return arguments.length;
+}
+
+for (let i = 0; i < 10000; i++) {
+    new Function(`
+        assert(bar.apply(undefined, undefined) === 0);
+        assert(bar.apply(undefined, null) === 0);
+        assert(bar.apply(undefined, {}) === 0);
+        assert(bar.apply(undefined, []) === 0);
+        assert(bar.apply(undefined, function() {}) === 0);
+    `)();
+}

Modified: trunk/JSTests/stress/destructuring-assignment-syntax.js (264749 => 264750)


--- trunk/JSTests/stress/destructuring-assignment-syntax.js	2020-07-23 07:50:11 UTC (rev 264749)
+++ trunk/JSTests/stress/destructuring-assignment-syntax.js	2020-07-23 08:25:12 UTC (rev 264750)
@@ -22,6 +22,11 @@
         throw new Error("Bad error: " + String(error));
 }
 
+testSyntax("[] = []");
+testSyntax("[] = [,]");
+testSyntax("[,] = [,]");
+testSyntax("[,] = []");
+
 testSyntax("({ a: this.a } = {})");
 testSyntax("({ a: this['a'] } = {})");
 testSyntax("({ a: this[\"a\"] } = {})");

Modified: trunk/Source/_javascript_Core/ChangeLog (264749 => 264750)


--- trunk/Source/_javascript_Core/ChangeLog	2020-07-23 07:50:11 UTC (rev 264749)
+++ trunk/Source/_javascript_Core/ChangeLog	2020-07-23 08:25:12 UTC (rev 264750)
@@ -1,5 +1,36 @@
 2020-07-23  Alexey Shvayka  <shvaikal...@gmail.com>
 
+        Remove ArrayNode::m_optional
+        https://bugs.webkit.org/show_bug.cgi?id=214294
+
+        Reviewed by Darin Adler.
+
+        m_optional, which dates back to KJS era, means "is this an array with optional trailing comma,
+        with elision, or an empty array". It was used by ArrayNode::streamTo() to preserve a trailing
+        comma when converting array node to source string, as well as in few other places,
+        before ECMA-262 clarified trailing comma in array literals [1].
+
+        Currently, m_optional is used only by ArrayNode::isSimpleArray(), along with m_elision.
+        Checking m_elision is enough since trailing comma doesn't add extra `undefined` element.
+
+        This patch completely removes m_optional, speeding up destructuring and function.apply()
+        with empty arrays and arrays with trailing commas by ~55% and a factor of 11 respectively.
+        Reflect.apply() optimization (https://webkit.org/b/190668) will also benefit from this change.
+
+        Also, this change converts isSpreadExpression() check to an ASSERT (was enabled by r196323).
+
+        [1]: https://tc39.es/ecma262/#sec-array-initializer
+
+        * bytecompiler/NodesCodegen.cpp:
+        (JSC::ArrayNode::isSimpleArray const):
+        (JSC::ArrayNode::toArgumentList const):
+        (JSC::ArrayNode::emitDirectBinding):
+        * parser/NodeConstructors.h:
+        (JSC::ArrayNode::ArrayNode):
+        * parser/Nodes.h:
+
+2020-07-23  Alexey Shvayka  <shvaikal...@gmail.com>
+
         Remove emitIsUndefined() from ClassExprNode::emitBytecode()
         https://bugs.webkit.org/show_bug.cgi?id=214645
 

Modified: trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp (264749 => 264750)


--- trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp	2020-07-23 07:50:11 UTC (rev 264749)
+++ trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp	2020-07-23 08:25:12 UTC (rev 264750)
@@ -506,7 +506,7 @@
 
 bool ArrayNode::isSimpleArray() const
 {
-    if (m_elision || m_optional)
+    if (m_elision)
         return false;
     for (ElementNode* ptr = m_element; ptr; ptr = ptr->next()) {
         if (ptr->elision())
@@ -519,7 +519,7 @@
 
 ArgumentListNode* ArrayNode::toArgumentList(ParserArena& parserArena, int lineNumber, int startPosition) const
 {
-    ASSERT(!m_elision && !m_optional);
+    ASSERT(!m_elision);
     ElementNode* ptr = m_element;
     if (!ptr)
         return nullptr;
@@ -5103,8 +5103,7 @@
     Vector<ExpressionNode*> elements;
     for (; elementNodes; elementNodes = elementNodes->next()) {
         ExpressionNode* value = elementNodes->value();
-        if (value->isSpreadExpression())
-            return nullptr;
+        ASSERT(!value->isSpreadExpression());
         elements.append(value);
     }
 

Modified: trunk/Source/_javascript_Core/parser/NodeConstructors.h (264749 => 264750)


--- trunk/Source/_javascript_Core/parser/NodeConstructors.h	2020-07-23 07:50:11 UTC (rev 264749)
+++ trunk/Source/_javascript_Core/parser/NodeConstructors.h	2020-07-23 08:25:12 UTC (rev 264750)
@@ -226,7 +226,6 @@
         : ExpressionNode(location)
         , m_element(nullptr)
         , m_elision(elision)
-        , m_optional(true)
     {
     }
 
@@ -234,7 +233,6 @@
         : ExpressionNode(location)
         , m_element(element)
         , m_elision(0)
-        , m_optional(false)
     {
     }
 
@@ -242,7 +240,6 @@
         : ExpressionNode(location)
         , m_element(element)
         , m_elision(elision)
-        , m_optional(true)
     {
     }
 

Modified: trunk/Source/_javascript_Core/parser/Nodes.h (264749 => 264750)


--- trunk/Source/_javascript_Core/parser/Nodes.h	2020-07-23 07:50:11 UTC (rev 264749)
+++ trunk/Source/_javascript_Core/parser/Nodes.h	2020-07-23 08:25:12 UTC (rev 264750)
@@ -716,7 +716,6 @@
 
         ElementNode* m_element;
         int m_elision;
-        bool m_optional;
     };
 
     enum class ClassElementTag : uint8_t { No, Instance, Static, LastTag };
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to