⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 264750 in webkit


Ignore:
Timestamp:
Jul 23, 2020, 1:25:12 AM (6 years ago)
Author:
Alexey Shvayka
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/JavaScriptCore:

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:
Location:
trunk
Files:
2 added
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/JSTests/ChangeLog

    r264703 r264750  
     12020-07-23  Alexey Shvayka  <shvaikalesh@gmail.com>
     2
     3        Remove ArrayNode::m_optional
     4        https://bugs.webkit.org/show_bug.cgi?id=214294
     5
     6        Reviewed by Darin Adler.
     7
     8        * microbenchmarks/destructuring-array-literal.js: Added.
     9        * microbenchmarks/function-dot-apply-array-literal.js: Added.
     10        * stress/apply-second-argument-must-be-array-like.js:
     11        * stress/destructuring-assignment-syntax.js:
     12
    1132020-07-22  Angelos Oikonomopoulos  <angelos@igalia.com>
    214
  • trunk/JSTests/stress/apply-second-argument-must-be-array-like.js

    r203790 r264750  
    1919}
    2020
    21 function shouldNotThrow(expr) {
    22     let testFunc = new Function(expr);
    23     for (let i = 0; i < 10000; i++) {
    24         let error;
    25         try {
    26             testFunc();
    27         } catch (e) {
    28             error = e;
    29         }
    30         assert(!error);
    31     }
    32 }
    33 
    3421function foo() { }
    3522
     
    4330shouldThrow("foo.apply(undefined, Symbol())");
    4431
    45 shouldNotThrow("foo.apply(undefined, undefined)");
    46 shouldNotThrow("foo.apply(undefined, null)");
    47 shouldNotThrow("foo.apply(undefined, {})");
    48 shouldNotThrow("foo.apply(undefined, [])");
    49 shouldNotThrow("foo.apply(undefined, function(){})");
     32function bar() {
     33    return arguments.length;
     34}
     35
     36for (let i = 0; i < 10000; i++) {
     37    new Function(`
     38        assert(bar.apply(undefined, undefined) === 0);
     39        assert(bar.apply(undefined, null) === 0);
     40        assert(bar.apply(undefined, {}) === 0);
     41        assert(bar.apply(undefined, []) === 0);
     42        assert(bar.apply(undefined, function() {}) === 0);
     43    `)();
     44}
  • trunk/JSTests/stress/destructuring-assignment-syntax.js

    r231142 r264750  
    2222        throw new Error("Bad error: " + String(error));
    2323}
     24
     25testSyntax("[] = []");
     26testSyntax("[] = [,]");
     27testSyntax("[,] = [,]");
     28testSyntax("[,] = []");
    2429
    2530testSyntax("({ a: this.a } = {})");
  • trunk/Source/JavaScriptCore/ChangeLog

    r264748 r264750  
     12020-07-23  Alexey Shvayka  <shvaikalesh@gmail.com>
     2
     3        Remove ArrayNode::m_optional
     4        https://bugs.webkit.org/show_bug.cgi?id=214294
     5
     6        Reviewed by Darin Adler.
     7
     8        m_optional, which dates back to KJS era, means "is this an array with optional trailing comma,
     9        with elision, or an empty array". It was used by ArrayNode::streamTo() to preserve a trailing
     10        comma when converting array node to source string, as well as in few other places,
     11        before ECMA-262 clarified trailing comma in array literals [1].
     12
     13        Currently, m_optional is used only by ArrayNode::isSimpleArray(), along with m_elision.
     14        Checking m_elision is enough since trailing comma doesn't add extra `undefined` element.
     15
     16        This patch completely removes m_optional, speeding up destructuring and function.apply()
     17        with empty arrays and arrays with trailing commas by ~55% and a factor of 11 respectively.
     18        Reflect.apply() optimization (https://webkit.org/b/190668) will also benefit from this change.
     19
     20        Also, this change converts isSpreadExpression() check to an ASSERT (was enabled by r196323).
     21
     22        [1]: https://tc39.es/ecma262/#sec-array-initializer
     23
     24        * bytecompiler/NodesCodegen.cpp:
     25        (JSC::ArrayNode::isSimpleArray const):
     26        (JSC::ArrayNode::toArgumentList const):
     27        (JSC::ArrayNode::emitDirectBinding):
     28        * parser/NodeConstructors.h:
     29        (JSC::ArrayNode::ArrayNode):
     30        * parser/Nodes.h:
     31
    1322020-07-23  Alexey Shvayka  <shvaikalesh@gmail.com>
    233
  • trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp

    r264748 r264750  
    507507bool ArrayNode::isSimpleArray() const
    508508{
    509     if (m_elision || m_optional)
     509    if (m_elision)
    510510        return false;
    511511    for (ElementNode* ptr = m_element; ptr; ptr = ptr->next()) {
     
    520520ArgumentListNode* ArrayNode::toArgumentList(ParserArena& parserArena, int lineNumber, int startPosition) const
    521521{
    522     ASSERT(!m_elision && !m_optional);
     522    ASSERT(!m_elision);
    523523    ElementNode* ptr = m_element;
    524524    if (!ptr)
     
    51045104    for (; elementNodes; elementNodes = elementNodes->next()) {
    51055105        ExpressionNode* value = elementNodes->value();
    5106         if (value->isSpreadExpression())
    5107             return nullptr;
     5106        ASSERT(!value->isSpreadExpression());
    51085107        elements.append(value);
    51095108    }
  • trunk/Source/JavaScriptCore/parser/NodeConstructors.h

    r262613 r264750  
    227227        , m_element(nullptr)
    228228        , m_elision(elision)
    229         , m_optional(true)
    230229    {
    231230    }
     
    235234        , m_element(element)
    236235        , m_elision(0)
    237         , m_optional(false)
    238236    {
    239237    }
     
    243241        , m_element(element)
    244242        , m_elision(elision)
    245         , m_optional(true)
    246243    {
    247244    }
  • trunk/Source/JavaScriptCore/parser/Nodes.h

    r264304 r264750  
    717717        ElementNode* m_element;
    718718        int m_elision;
    719         bool m_optional;
    720719    };
    721720
Note: See TracChangeset for help on using the changeset viewer.