Changeset 222384 in webkit for trunk/Source/JavaScriptCore


Ignore:
Timestamp:
Sep 22, 2017, 5:19:54 AM (8 years ago)
Author:
Yusuke Suzuki
Message:

[DFG][FTL] Profile array vector length for array allocation
https://bugs.webkit.org/show_bug.cgi?id=177051

Reviewed by Saam Barati.

JSTests:

  • microbenchmarks/new-array-buffer-vector-profile.js: Added.

(target):

Source/JavaScriptCore:

Currently, NewArrayBuffer allocation is penalized by JSC: While empty array gets 25 vector size (BASE_CONTIGUOUS_VECTOR_LEN),
new_array_buffer case gets 3 vector size (BASE_CONTIGUOUS_VECTOR_LEN). Surely, new_array_buffer can get larger vector size
if the number of its constant elements is larger than 3. But these created array may be grown by push() operation after
the allocation. In this case, new_array_buffer is penalized compared to empty array allocation.

empty array allocation,

var array = [];
array.push(0);
array.push(1);
array.push(2);
array.push(3);
array.push(4);

v.s. new_array_buffer case,

var array = [0];
array.push(1);
array.push(2);
array.push(3);
array.push(4);

In this case, the latter becomes slow. While we have a chance to reduce memory usage if new_array_buffer is not grown (and a bit likely),
we should allocate 3 to 25 vector size if it is likely grown. So we should get profile on the resulted array.

We select 25 to make it fit to one of size classes.

In this patch, we extend ArrayAllocationProfile to record vector length. And use this information when allocating array for new_array_buffer.
If the number of new_array_buffer constants is <= 25, array vector size would become 3 to 25 based on profiling. If the number of its constants
is larger than 25, we just use it for allocation as before.

Added microbenchmark and SixSpeed spread-literal.es5 shows improvement.

new-array-buffer-vector-profile 67.4706+-3.7625 28.4249+-1.9025 definitely 2.3736x faster
spread-literal.es5 133.1443+-9.2253 95.2667+-0.5740 definitely 1.3976x faster

  • bytecode/ArrayAllocationProfile.cpp:

(JSC::ArrayAllocationProfile::updateProfile):
(JSC::ArrayAllocationProfile::updateIndexingType): Deleted.

  • bytecode/ArrayAllocationProfile.h:

(JSC::ArrayAllocationProfile::selectIndexingType):
(JSC::ArrayAllocationProfile::vectorLengthHint):
(JSC::ArrayAllocationProfile::ArrayAllocationProfile): Deleted.

  • bytecode/CodeBlock.cpp:

(JSC::CodeBlock::updateAllArrayPredictions):

  • dfg/DFGByteCodeParser.cpp:

(JSC::DFG::ByteCodeParser::parseBlock):

  • dfg/DFGGraph.cpp:

(JSC::DFG::Graph::dump):

  • dfg/DFGNode.h:

(JSC::DFG::Node::vectorLengthHint):

  • dfg/DFGOperations.cpp:
  • dfg/DFGOperations.h:
  • dfg/DFGSpeculativeJIT64.cpp:

(JSC::DFG::SpeculativeJIT::compile):

  • ftl/FTLLowerDFGToB3.cpp:

(JSC::FTL::DFG::LowerDFGToB3::compileArraySlice):
(JSC::FTL::DFG::LowerDFGToB3::compileNewArrayBuffer):
(JSC::FTL::DFG::LowerDFGToB3::compileNewArrayWithSize):
(JSC::FTL::DFG::LowerDFGToB3::allocateJSArray):
(JSC::FTL::DFG::LowerDFGToB3::allocateUninitializedContiguousJSArrayInternal):
(JSC::FTL::DFG::LowerDFGToB3::allocateUninitializedContiguousJSArray):

  • runtime/ArrayConventions.h:
  • runtime/JSArray.h:

(JSC::JSArray::tryCreate):

Location:
trunk/Source/JavaScriptCore
Files:
13 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r222382 r222384  
     12017-09-22  Yusuke Suzuki  <[email protected]>
     2
     3        [DFG][FTL] Profile array vector length for array allocation
     4        https://bugs.webkit.org/show_bug.cgi?id=177051
     5
     6        Reviewed by Saam Barati.
     7
     8        Currently, NewArrayBuffer allocation is penalized by JSC: While empty array gets 25 vector size (BASE_CONTIGUOUS_VECTOR_LEN),
     9        new_array_buffer case gets 3 vector size (BASE_CONTIGUOUS_VECTOR_LEN). Surely, new_array_buffer can get larger vector size
     10        if the number of its constant elements is larger than 3. But these created array may be grown by `push()` operation after
     11        the allocation. In this case, new_array_buffer is penalized compared to empty array allocation.
     12
     13            empty array allocation,
     14
     15            var array = [];
     16            array.push(0);
     17            array.push(1);
     18            array.push(2);
     19            array.push(3);
     20            array.push(4);
     21
     22            v.s. new_array_buffer case,
     23
     24            var array = [0];
     25            array.push(1);
     26            array.push(2);
     27            array.push(3);
     28            array.push(4);
     29
     30        In this case, the latter becomes slow. While we have a chance to reduce memory usage if new_array_buffer is not grown (and a bit likely),
     31        we should allocate 3 to 25 vector size if it is likely grown. So we should get profile on the resulted array.
     32
     33        We select 25 to make it fit to one of size classes.
     34
     35        In this patch, we extend ArrayAllocationProfile to record vector length. And use this information when allocating array for new_array_buffer.
     36        If the number of new_array_buffer constants is <= 25, array vector size would become 3 to 25 based on profiling. If the number of its constants
     37        is larger than 25, we just use it for allocation as before.
     38
     39        Added microbenchmark and SixSpeed spread-literal.es5 shows improvement.
     40
     41            new-array-buffer-vector-profile       67.4706+-3.7625     ^     28.4249+-1.9025        ^ definitely 2.3736x faster
     42            spread-literal.es5                   133.1443+-9.2253     ^     95.2667+-0.5740        ^ definitely 1.3976x faster
     43
     44        * bytecode/ArrayAllocationProfile.cpp:
     45        (JSC::ArrayAllocationProfile::updateProfile):
     46        (JSC::ArrayAllocationProfile::updateIndexingType): Deleted.
     47        * bytecode/ArrayAllocationProfile.h:
     48        (JSC::ArrayAllocationProfile::selectIndexingType):
     49        (JSC::ArrayAllocationProfile::vectorLengthHint):
     50        (JSC::ArrayAllocationProfile::ArrayAllocationProfile): Deleted.
     51        * bytecode/CodeBlock.cpp:
     52        (JSC::CodeBlock::updateAllArrayPredictions):
     53        * dfg/DFGByteCodeParser.cpp:
     54        (JSC::DFG::ByteCodeParser::parseBlock):
     55        * dfg/DFGGraph.cpp:
     56        (JSC::DFG::Graph::dump):
     57        * dfg/DFGNode.h:
     58        (JSC::DFG::Node::vectorLengthHint):
     59        * dfg/DFGOperations.cpp:
     60        * dfg/DFGOperations.h:
     61        * dfg/DFGSpeculativeJIT64.cpp:
     62        (JSC::DFG::SpeculativeJIT::compile):
     63        * ftl/FTLLowerDFGToB3.cpp:
     64        (JSC::FTL::DFG::LowerDFGToB3::compileArraySlice):
     65        (JSC::FTL::DFG::LowerDFGToB3::compileNewArrayBuffer):
     66        (JSC::FTL::DFG::LowerDFGToB3::compileNewArrayWithSize):
     67        (JSC::FTL::DFG::LowerDFGToB3::allocateJSArray):
     68        (JSC::FTL::DFG::LowerDFGToB3::allocateUninitializedContiguousJSArrayInternal):
     69        (JSC::FTL::DFG::LowerDFGToB3::allocateUninitializedContiguousJSArray):
     70        * runtime/ArrayConventions.h:
     71        * runtime/JSArray.h:
     72        (JSC::JSArray::tryCreate):
     73
    1742017-09-22  Commit Queue  <[email protected]>
    275
  • trunk/Source/JavaScriptCore/bytecode/ArrayAllocationProfile.cpp

    r222382 r222384  
    3131namespace JSC {
    3232
    33 void ArrayAllocationProfile::updateIndexingType()
     33void ArrayAllocationProfile::updateProfile()
    3434{
    3535    // This is awkwardly racy but totally sound even when executed concurrently. The
     
    5050    if (!lastArray)
    5151        return;
    52     if (LIKELY(Options::useArrayAllocationProfiling()))
     52    if (LIKELY(Options::useArrayAllocationProfiling())) {
    5353        m_currentIndexingType = leastUpperBoundOfIndexingTypes(m_currentIndexingType, lastArray->indexingType());
    54     m_lastArray = 0;
     54        m_largestSeenVectorLength = std::min(std::max(m_largestSeenVectorLength, lastArray->getVectorLength()), BASE_CONTIGUOUS_VECTOR_LEN_MAX);
     55    }
     56    m_lastArray = nullptr;
    5557}
    5658
  • trunk/Source/JavaScriptCore/bytecode/ArrayAllocationProfile.h

    r222382 r222384  
    3333class ArrayAllocationProfile {
    3434public:
    35     ArrayAllocationProfile()
    36         : m_currentIndexingType(ArrayWithUndecided)
    37         , m_lastArray(0)
    38     {
    39     }
    40    
    4135    IndexingType selectIndexingType()
    4236    {
    4337        JSArray* lastArray = m_lastArray;
    4438        if (lastArray && UNLIKELY(lastArray->indexingType() != m_currentIndexingType))
    45             updateIndexingType();
     39            updateProfile();
    4640        return m_currentIndexingType;
     41    }
     42
     43    // vector length hint becomes [0, BASE_CONTIGUOUS_VECTOR_LEN_MAX].
     44    unsigned vectorLengthHint()
     45    {
     46        JSArray* lastArray = m_lastArray;
     47        if (lastArray && (m_largestSeenVectorLength != BASE_CONTIGUOUS_VECTOR_LEN_MAX) && UNLIKELY(lastArray->getVectorLength() > m_largestSeenVectorLength))
     48            updateProfile();
     49        return m_largestSeenVectorLength;
    4750    }
    4851   
     
    5356    }
    5457   
    55     JS_EXPORT_PRIVATE void updateIndexingType();
     58    JS_EXPORT_PRIVATE void updateProfile();
    5659   
    5760    static IndexingType selectIndexingTypeFor(ArrayAllocationProfile* profile)
     
    7174private:
    7275   
    73     IndexingType m_currentIndexingType;
    74     JSArray* m_lastArray;
     76    IndexingType m_currentIndexingType { ArrayWithUndecided };
     77    unsigned m_largestSeenVectorLength { 0 };
     78    JSArray* m_lastArray { nullptr };
    7579};
    7680
  • trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp

    r222382 r222384  
    25692569    // Don't count these either, for similar reasons.
    25702570    for (unsigned i = m_arrayAllocationProfiles.size(); i--;)
    2571         m_arrayAllocationProfiles[i].updateIndexingType();
     2571        m_arrayAllocationProfiles[i].updateProfile();
    25722572}
    25732573
  • trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp

    r222382 r222384  
    44004400            data.numConstants = numConstants;
    44014401            data.indexingType = profile->selectIndexingType();
     4402            data.vectorLengthHint = std::max<unsigned>(profile->vectorLengthHint(), numConstants);
    44024403
    44034404            // If this statement has never executed, we'll have the wrong indexing type in the profile.
     
    44094410            }
    44104411           
    4411             m_graph.m_newArrayBufferData.append(data);
     4412            m_graph.m_newArrayBufferData.append(WTFMove(data));
    44124413            set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(NewArrayBuffer, OpInfo(&m_graph.m_newArrayBufferData.last())));
    44134414            NEXT_OPCODE(op_new_array_buffer);
  • trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp

    r222382 r222384  
    322322            out.print(anotherComma, pointerDumpInContext(freeze(m_codeBlock->constantBuffer(node->startConstant())[i]), context));
    323323        out.print("]");
     324        out.print(comma, "vectorLengthHint = ", node->vectorLengthHint());
    324325    }
    325326    if (node->hasLazyJSValue())
  • trunk/Source/JavaScriptCore/dfg/DFGNode.h

    r222382 r222384  
    100100    unsigned startConstant;
    101101    unsigned numConstants;
     102    unsigned vectorLengthHint;
    102103    IndexingType indexingType;
    103104};
     
    11151116    {
    11161117        return newArrayBufferData()->numConstants;
     1118    }
     1119
     1120    unsigned vectorLengthHint()
     1121    {
     1122        return newArrayBufferData()->vectorLengthHint;
    11171123    }
    11181124   
  • trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp

    r222382 r222384  
    13121312}
    13131313
     1314char* JIT_OPERATION operationNewArrayWithSizeAndHint(ExecState* exec, Structure* arrayStructure, int32_t size, int32_t vectorLengthHint, Butterfly* butterfly)
     1315{
     1316    VM& vm = exec->vm();
     1317    NativeCallFrameTracer tracer(&vm, exec);
     1318    auto scope = DECLARE_THROW_SCOPE(vm);
     1319
     1320    if (UNLIKELY(size < 0))
     1321        return bitwise_cast<char*>(throwException(exec, scope, createRangeError(exec, ASCIILiteral("Array size is not a small enough positive integer."))));
     1322
     1323    JSArray* result;
     1324    if (butterfly)
     1325        result = JSArray::createWithButterfly(vm, nullptr, arrayStructure, butterfly);
     1326    else {
     1327        result = JSArray::tryCreate(vm, arrayStructure, size, vectorLengthHint);
     1328        ASSERT(result);
     1329    }
     1330    return bitwise_cast<char*>(result);
     1331}
     1332
    13141333char* JIT_OPERATION operationNewArrayBuffer(ExecState* exec, Structure* arrayStructure, size_t start, size_t size)
    13151334{
  • trunk/Source/JavaScriptCore/dfg/DFGOperations.h

    r222382 r222384  
    8282char* JIT_OPERATION operationNewEmptyArray(ExecState*, Structure*) WTF_INTERNAL;
    8383char* JIT_OPERATION operationNewArrayWithSize(ExecState*, Structure*, int32_t, Butterfly*) WTF_INTERNAL;
     84char* JIT_OPERATION operationNewArrayWithSizeAndHint(ExecState*, Structure*, int32_t, int32_t, Butterfly*) WTF_INTERNAL;
    8485char* JIT_OPERATION operationNewInt8ArrayWithSize(ExecState*, Structure*, int32_t, char*) WTF_INTERNAL;
    8586char* JIT_OPERATION operationNewInt8ArrayWithOneArgument(ExecState*, Structure*, EncodedJSValue) WTF_INTERNAL;
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp

    r222382 r222384  
    42394239        if (!globalObject->isHavingABadTime() && !hasAnyArrayStorage(indexingType)) {
    42404240            unsigned numElements = node->numConstants();
     4241            unsigned vectorLengthHint = node->vectorLengthHint();
     4242            ASSERT(vectorLengthHint >= numElements);
    42414243           
    42424244            GPRTemporary result(this);
     
    42464248            GPRReg storageGPR = storage.gpr();
    42474249
    4248             emitAllocateRawObject(resultGPR, m_jit.graph().registerStructure(globalObject->arrayStructureForIndexingTypeDuringAllocation(indexingType)), storageGPR, numElements, numElements);
     4250            emitAllocateRawObject(resultGPR, m_jit.graph().registerStructure(globalObject->arrayStructureForIndexingTypeDuringAllocation(indexingType)), storageGPR, numElements, vectorLengthHint);
    42494251           
    42504252            DFG_ASSERT(m_jit.graph(), node, indexingType & IsArray);
  • trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp

    r222382 r222384  
    41904190                    weakStructure(m_graph.registerStructure(globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous))),
    41914191                    weakStructure(m_graph.registerStructure(globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithDouble)))));
    4192             arrayResult = allocateJSArray(resultLength, structure, indexingType, false, false);
     4192            arrayResult = allocateJSArray(resultLength, resultLength, structure, indexingType, false, false);
    41934193        }
    41944194
     
    51155115        if (!globalObject->isHavingABadTime() && !hasAnyArrayStorage(m_node->indexingType())) {
    51165116            unsigned numElements = m_node->numConstants();
    5117            
     5117            unsigned vectorLengthHint = m_node->vectorLengthHint();
     5118           
     5119            ASSERT(vectorLengthHint >= numElements);
    51185120            ArrayValues arrayValues =
    5119                 allocateUninitializedContiguousJSArray(m_out.constInt32(numElements), structure);
     5121                allocateUninitializedContiguousJSArray(numElements, vectorLengthHint, structure);
    51205122           
    51215123            JSValue* data = codeBlock()->constantBuffer(m_node->startConstant());
     
    51565158            setJSValue(
    51575159                allocateJSArray(
    5158                     publicLength, weakPointer(globalObject->arrayStructureForIndexingTypeDuringAllocation(indexingType)), m_out.constInt32(indexingType)).array);
     5160                    publicLength, publicLength, weakPointer(globalObject->arrayStructureForIndexingTypeDuringAllocation(indexingType)), m_out.constInt32(indexingType)).array);
    51595161            mutatorFence();
    51605162            return;
     
    1144211444    };
    1144311445
    11444     ArrayValues allocateJSArray(LValue publicLength, LValue structure, LValue indexingType, bool shouldInitializeElements = true, bool shouldLargeArraySizeCreateArrayStorage = true)
     11446    ArrayValues allocateJSArray(LValue publicLength, LValue vectorLength, LValue structure, LValue indexingType, bool shouldInitializeElements = true, bool shouldLargeArraySizeCreateArrayStorage = true)
    1144511447    {
    1144611448        JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node->origin.semantic);
     
    1146111463       
    1146211464        LBasicBlock lastNext = m_out.insertNewBlocksBefore(fastCase);
     11465
     11466        std::optional<unsigned> staticVectorLength;
     11467        std::optional<unsigned> staticVectorLengthFromPublicLength;
     11468        if (structure->hasIntPtr()) {
     11469            if (publicLength->hasInt32()) {
     11470                unsigned publicLengthConst = static_cast<unsigned>(publicLength->asInt32());
     11471                if (publicLengthConst <= MAX_STORAGE_VECTOR_LENGTH) {
     11472                    publicLengthConst = Butterfly::optimalContiguousVectorLength(
     11473                        bitwise_cast<Structure*>(structure->asIntPtr())->outOfLineCapacity(), publicLengthConst);
     11474                    staticVectorLengthFromPublicLength = publicLengthConst;
     11475                }
     11476
     11477            }
     11478            if (vectorLength->hasInt32()) {
     11479                unsigned vectorLengthConst = static_cast<unsigned>(vectorLength->asInt32());
     11480                if (vectorLengthConst <= MAX_STORAGE_VECTOR_LENGTH) {
     11481                    vectorLengthConst = Butterfly::optimalContiguousVectorLength(
     11482                        bitwise_cast<Structure*>(structure->asIntPtr())->outOfLineCapacity(), vectorLengthConst);
     11483                    vectorLength = m_out.constInt32(vectorLengthConst);
     11484                    staticVectorLength = vectorLengthConst;
     11485                }
     11486            }
     11487        } else {
     11488            // We don't compute the optimal vector length for new Array(blah) where blah is not
     11489            // statically known, since the compute effort of doing it here is probably not worth it.
     11490        }
    1146311491       
    1146411492        ValueFromBlock noButterfly = m_out.anchor(m_out.intPtrZero);
     
    1147311501       
    1147411502        m_out.appendTo(fastCase, largeCase);
    11475 
    11476         LValue vectorLength = nullptr;
    11477         if (publicLength->hasInt32() && structure->hasIntPtr()) {
    11478             unsigned publicLengthConst = static_cast<unsigned>(publicLength->asInt32());
    11479             if (publicLengthConst <= MAX_STORAGE_VECTOR_LENGTH) {
    11480                 vectorLength = m_out.constInt32(
    11481                     Butterfly::optimalContiguousVectorLength(
    11482                         bitwise_cast<Structure*>(structure->asIntPtr())->outOfLineCapacity(), publicLengthConst));
    11483             }
    11484         }
    11485        
    11486         if (!vectorLength) {
    11487             // We don't compute the optimal vector length for new Array(blah) where blah is not
    11488             // statically known, since the compute effort of doing it here is probably not worth it.
    11489             vectorLength = publicLength;
    11490         }
    1149111503           
    1149211504        LValue payloadSize =
     
    1153111543
    1153211544        VM& vm = this->vm();
    11533         LValue slowResultValue = lazySlowPath(
    11534             [=, &vm] (const Vector<Location>& locations) -> RefPtr<LazySlowPath::Generator> {
    11535                 return createLazyCallGenerator(vm,
    11536                     operationNewArrayWithSize, locations[0].directGPR(),
    11537                     locations[1].directGPR(), locations[2].directGPR(), locations[3].directGPR());
    11538             },
    11539             structureValue, publicLength, butterflyValue);
     11545        LValue slowResultValue = nullptr;
     11546        if (vectorLength == publicLength
     11547            || (staticVectorLengthFromPublicLength && staticVectorLength && staticVectorLength.value() == staticVectorLengthFromPublicLength.value())) {
     11548            slowResultValue = lazySlowPath(
     11549                [=, &vm] (const Vector<Location>& locations) -> RefPtr<LazySlowPath::Generator> {
     11550                    return createLazyCallGenerator(vm,
     11551                        operationNewArrayWithSize, locations[0].directGPR(),
     11552                        locations[1].directGPR(), locations[2].directGPR(), locations[3].directGPR());
     11553                },
     11554                structureValue, publicLength, butterflyValue);
     11555        } else {
     11556            slowResultValue = lazySlowPath(
     11557                [=, &vm] (const Vector<Location>& locations) -> RefPtr<LazySlowPath::Generator> {
     11558                    return createLazyCallGenerator(vm,
     11559                        operationNewArrayWithSizeAndHint, locations[0].directGPR(),
     11560                        locations[1].directGPR(), locations[2].directGPR(), locations[3].directGPR(), locations[4].directGPR());
     11561                },
     11562                structureValue, publicLength, vectorLength, butterflyValue);
     11563        }
     11564
    1154011565        ValueFromBlock slowResult = m_out.anchor(slowResultValue);
    1154111566        ValueFromBlock slowButterfly = m_out.anchor(
     
    1154911574    }
    1155011575   
    11551     ArrayValues allocateUninitializedContiguousJSArray(LValue publicLength, RegisteredStructure structure)
     11576    ArrayValues allocateUninitializedContiguousJSArrayInternal(LValue publicLength, LValue vectorLength, RegisteredStructure structure)
    1155211577    {
    1155311578        bool shouldInitializeElements = false;
    1155411579        bool shouldLargeArraySizeCreateArrayStorage = false;
    1155511580        return allocateJSArray(
    11556             publicLength, weakStructure(structure), m_out.constInt32(structure->indexingType()), shouldInitializeElements,
     11581            publicLength, vectorLength, weakStructure(structure), m_out.constInt32(structure->indexingType()), shouldInitializeElements,
    1155711582            shouldLargeArraySizeCreateArrayStorage);
     11583    }
     11584
     11585    ArrayValues allocateUninitializedContiguousJSArray(LValue publicLength, RegisteredStructure structure)
     11586    {
     11587        return allocateUninitializedContiguousJSArrayInternal(publicLength, publicLength, structure);
     11588    }
     11589
     11590    ArrayValues allocateUninitializedContiguousJSArray(unsigned publicLength, unsigned vectorLength, RegisteredStructure structure)
     11591    {
     11592        ASSERT(vectorLength >= publicLength);
     11593        return allocateUninitializedContiguousJSArrayInternal(m_out.constInt32(publicLength), m_out.constInt32(vectorLength), structure);
    1155811594    }
    1155911595   
  • trunk/Source/JavaScriptCore/runtime/ArrayConventions.h

    r222382 r222384  
    7878#define BASE_CONTIGUOUS_VECTOR_LEN 3U
    7979#define BASE_CONTIGUOUS_VECTOR_LEN_EMPTY 5U
     80#define BASE_CONTIGUOUS_VECTOR_LEN_MIN 3U
     81#define BASE_CONTIGUOUS_VECTOR_LEN_MAX 25U
    8082#define BASE_ARRAY_STORAGE_VECTOR_LEN 4U
    8183
  • trunk/Source/JavaScriptCore/runtime/JSArray.h

    r222382 r222384  
    5555public:
    5656    static JSArray* tryCreate(VM&, Structure*, unsigned initialLength = 0);
     57    static JSArray* tryCreate(VM&, Structure*, unsigned initialLength, unsigned vectorLengthHint);
    5758    static JSArray* create(VM&, Structure*, unsigned initialLength = 0);
    5859    static JSArray* createWithButterfly(VM&, GCDeferralContext*, Structure*, Butterfly*);
     
    216217    VM&, JSCell* intendedOwner, unsigned initialLength);
    217218
    218 inline JSArray* JSArray::tryCreate(VM& vm, Structure* structure, unsigned initialLength)
    219 {
     219inline JSArray* JSArray::tryCreate(VM& vm, Structure* structure, unsigned initialLength, unsigned vectorLengthHint)
     220{
     221    ASSERT(vectorLengthHint >= initialLength);
    220222    unsigned outOfLineStorage = structure->outOfLineCapacity();
    221223
     
    229231            || hasContiguous(indexingType));
    230232
    231         if (UNLIKELY(initialLength > MAX_STORAGE_VECTOR_LENGTH))
     233        if (UNLIKELY(vectorLengthHint > MAX_STORAGE_VECTOR_LENGTH))
    232234            return nullptr;
    233235
    234         unsigned vectorLength = Butterfly::optimalContiguousVectorLength(structure, initialLength);
     236        unsigned vectorLength = Butterfly::optimalContiguousVectorLength(structure, vectorLengthHint);
    235237        void* temp = vm.jsValueGigacageAuxiliarySpace.tryAllocate(nullptr, Butterfly::totalSize(0, outOfLineStorage, true, vectorLength * sizeof(EncodedJSValue)));
    236238        if (!temp)
     
    257259}
    258260
     261inline JSArray* JSArray::tryCreate(VM& vm, Structure* structure, unsigned initialLength)
     262{
     263    return tryCreate(vm, structure, initialLength, initialLength);
     264}
     265
    259266inline JSArray* JSArray::create(VM& vm, Structure* structure, unsigned initialLength)
    260267{
Note: See TracChangeset for help on using the changeset viewer.