Ignore:
Timestamp:
Mar 27, 2018, 1:49:41 AM (7 years ago)
Author:
Yusuke Suzuki
Message:

[JSC] Remove repeated iteration of ElementNode
https://bugs.webkit.org/show_bug.cgi?id=183987

Reviewed by Keith Miller.

BytecodeGenerator repeatedly iterates ElementNode to emit the efficient code.
While it is OK for small arrays, this repeated iteration takes much time
if the array is very large. For example, Kraken's initialization code includes
very large array with numeric literals. This makes bytecode compiling so long.

This patch carefully removes unnecessary iteration when emitting arrays.
This reduces one of Kraken/imaging-darkroom's bytecode compiling from 13.169856 ms
to 9.988050 ms.

  • bytecompiler/BytecodeGenerator.cpp:

(JSC::BytecodeGenerator::emitNewArrayBuffer):
(JSC::BytecodeGenerator::emitNewArray):

  • bytecompiler/BytecodeGenerator.h:
  • bytecompiler/NodesCodegen.cpp:

(JSC::ArrayNode::emitBytecode):
(JSC::ArrayPatternNode::bindValue const):
(JSC::ArrayPatternNode::emitDirectBinding):

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp

    r229852 r229993  
    385385RegisterID* ArrayNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    386386{
    387     // FIXME: Should we put all of this code into emitNewArray?
    388 
     387    bool hadVariableExpression = false;
    389388    unsigned length = 0;
    390389    ElementNode* firstPutElement;
     
    392391        if (firstPutElement->elision() || firstPutElement->value()->isSpreadExpression())
    393392            break;
     393        if (!firstPutElement->value()->isConstant())
     394            hadVariableExpression = true;
    394395        ++length;
    395396    }
    396397
     398    auto newArray = [&generator] (RegisterID* dst, ElementNode* elements, unsigned length, bool hadVariableExpression) {
     399        if (length && !hadVariableExpression) {
     400            auto* array = JSFixedArray::create(*generator.vm(), length);
     401            unsigned index = 0;
     402            for (ElementNode* element = elements; index < length; element = element->next()) {
     403                ASSERT(element->value()->isConstant());
     404                array->set(*generator.vm(), index++, static_cast<ConstantNode*>(element->value())->jsValue(generator));
     405            }
     406            return generator.emitNewArrayBuffer(dst, array);
     407        }
     408        return generator.emitNewArray(dst, elements, length);
     409    };
     410
    397411    if (!firstPutElement && !m_elision)
    398         return generator.emitNewArray(generator.finalDestination(dst), m_element, length);
     412        return newArray(generator.finalDestination(dst), m_element, length, hadVariableExpression);
    399413
    400414    if (firstPutElement && firstPutElement->value()->isSpreadExpression()) {
    401         bool hasElision = false;
    402         for (ElementNode* node = m_element; node; node = node->next()) {
    403             if (!!node->elision()) {
    404                 hasElision = true;
    405                 break;
     415        bool hasElision = m_elision;
     416        if (!hasElision) {
     417            for (ElementNode* node = firstPutElement; node; node = node->next()) {
     418                if (node->elision()) {
     419                    hasElision = true;
     420                    break;
     421                }
    406422            }
    407423        }
    408         if (!!m_elision)
    409             hasElision = true;
    410424
    411425        if (!hasElision)
     
    413427    }
    414428
    415     RefPtr<RegisterID> array = generator.emitNewArray(generator.tempDestination(dst), m_element, length);
     429    RefPtr<RegisterID> array = newArray(generator.tempDestination(dst), m_element, length, hadVariableExpression);
    416430    ElementNode* n = firstPutElement;
    417431    for (; n; n = n->next()) {
     
    40824096
    40834097        case BindingType::RestElement: {
    4084             RefPtr<RegisterID> array = generator.emitNewArray(generator.newTemporary(), 0, 0);
     4098            RefPtr<RegisterID> array = generator.emitNewArray(generator.newTemporary(), nullptr, 0);
    40854099
    40864100            Ref<Label> iterationDone = generator.newLabel();
     
    41344148    RefPtr<RegisterID> resultRegister;
    41354149    if (dst && dst != generator.ignoredResult())
    4136         resultRegister = generator.emitNewArray(generator.newTemporary(), 0, 0);
     4150        resultRegister = generator.emitNewArray(generator.newTemporary(), nullptr, 0);
    41374151    if (m_targetPatterns.size() != elements.size())
    41384152        return nullptr;
Note: See TracChangeset for help on using the changeset viewer.