Diff
Modified: trunk/JSTests/ChangeLog (222379 => 222380)
--- trunk/JSTests/ChangeLog 2017-09-22 06:36:20 UTC (rev 222379)
+++ trunk/JSTests/ChangeLog 2017-09-22 08:22:44 UTC (rev 222380)
@@ -1,3 +1,13 @@
+2017-09-21 Yusuke Suzuki <[email protected]>
+
+ [DFG][FTL] Profile array vector length for array allocation
+ https://bugs.webkit.org/show_bug.cgi?id=177051
+
+ Reviewed by Saam Barati.
+
+ * microbenchmarks/new-array-buffer-vector-profile.js: Added.
+ (target):
+
2017-09-21 Joseph Pecoraro <[email protected]>
Skip new hanging test262 tests.
Added: trunk/JSTests/microbenchmarks/new-array-buffer-vector-profile.js (0 => 222380)
--- trunk/JSTests/microbenchmarks/new-array-buffer-vector-profile.js (rev 0)
+++ trunk/JSTests/microbenchmarks/new-array-buffer-vector-profile.js 2017-09-22 08:22:44 UTC (rev 222380)
@@ -0,0 +1,12 @@
+function target()
+{
+ var array = [0];
+ array.push(1);
+ array.push(2);
+ array.push(3);
+ array.push(4);
+ return array;
+}
+noInline(target);
+for (var i = 0; i < 1e6; ++i)
+ target();
Modified: trunk/Source/_javascript_Core/ChangeLog (222379 => 222380)
--- trunk/Source/_javascript_Core/ChangeLog 2017-09-22 06:36:20 UTC (rev 222379)
+++ trunk/Source/_javascript_Core/ChangeLog 2017-09-22 08:22:44 UTC (rev 222380)
@@ -1,3 +1,76 @@
+2017-09-21 Yusuke Suzuki <[email protected]>
+
+ [DFG][FTL] Profile array vector length for array allocation
+ https://bugs.webkit.org/show_bug.cgi?id=177051
+
+ Reviewed by Saam Barati.
+
+ 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):
+
2017-09-21 Joseph Pecoraro <[email protected]>
Web Inspector: Remove support for CSS Regions
Modified: trunk/Source/_javascript_Core/bytecode/ArrayAllocationProfile.cpp (222379 => 222380)
--- trunk/Source/_javascript_Core/bytecode/ArrayAllocationProfile.cpp 2017-09-22 06:36:20 UTC (rev 222379)
+++ trunk/Source/_javascript_Core/bytecode/ArrayAllocationProfile.cpp 2017-09-22 08:22:44 UTC (rev 222380)
@@ -30,7 +30,7 @@
namespace JSC {
-void ArrayAllocationProfile::updateIndexingType()
+void ArrayAllocationProfile::updateProfile()
{
// This is awkwardly racy but totally sound even when executed concurrently. The
// worst cases go something like this:
@@ -49,9 +49,11 @@
JSArray* lastArray = m_lastArray;
if (!lastArray)
return;
- if (LIKELY(Options::useArrayAllocationProfiling()))
+ if (LIKELY(Options::useArrayAllocationProfiling())) {
m_currentIndexingType = leastUpperBoundOfIndexingTypes(m_currentIndexingType, lastArray->indexingType());
- m_lastArray = 0;
+ m_largestSeenVectorLength = std::min(std::max(m_largestSeenVectorLength, lastArray->getVectorLength()), BASE_CONTIGUOUS_VECTOR_LEN_MAX);
+ }
+ m_lastArray = nullptr;
}
} // namespace JSC
Modified: trunk/Source/_javascript_Core/bytecode/ArrayAllocationProfile.h (222379 => 222380)
--- trunk/Source/_javascript_Core/bytecode/ArrayAllocationProfile.h 2017-09-22 06:36:20 UTC (rev 222379)
+++ trunk/Source/_javascript_Core/bytecode/ArrayAllocationProfile.h 2017-09-22 08:22:44 UTC (rev 222380)
@@ -32,19 +32,22 @@
class ArrayAllocationProfile {
public:
- ArrayAllocationProfile()
- : m_currentIndexingType(ArrayWithUndecided)
- , m_lastArray(0)
- {
- }
-
IndexingType selectIndexingType()
{
JSArray* lastArray = m_lastArray;
if (lastArray && UNLIKELY(lastArray->indexingType() != m_currentIndexingType))
- updateIndexingType();
+ updateProfile();
return m_currentIndexingType;
}
+
+ // vector length hint becomes [0, BASE_CONTIGUOUS_VECTOR_LEN_MAX].
+ unsigned vectorLengthHint()
+ {
+ JSArray* lastArray = m_lastArray;
+ if (lastArray && (m_largestSeenVectorLength != BASE_CONTIGUOUS_VECTOR_LEN_MAX) && UNLIKELY(lastArray->getVectorLength() > m_largestSeenVectorLength))
+ updateProfile();
+ return m_largestSeenVectorLength;
+ }
JSArray* updateLastAllocation(JSArray* lastArray)
{
@@ -52,7 +55,7 @@
return lastArray;
}
- JS_EXPORT_PRIVATE void updateIndexingType();
+ JS_EXPORT_PRIVATE void updateProfile();
static IndexingType selectIndexingTypeFor(ArrayAllocationProfile* profile)
{
@@ -70,8 +73,9 @@
private:
- IndexingType m_currentIndexingType;
- JSArray* m_lastArray;
+ IndexingType m_currentIndexingType { ArrayWithUndecided };
+ unsigned m_largestSeenVectorLength { 0 };
+ JSArray* m_lastArray { nullptr };
};
} // namespace JSC
Modified: trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp (222379 => 222380)
--- trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp 2017-09-22 06:36:20 UTC (rev 222379)
+++ trunk/Source/_javascript_Core/bytecode/CodeBlock.cpp 2017-09-22 08:22:44 UTC (rev 222380)
@@ -2568,7 +2568,7 @@
// Don't count these either, for similar reasons.
for (unsigned i = m_arrayAllocationProfiles.size(); i--;)
- m_arrayAllocationProfiles[i].updateIndexingType();
+ m_arrayAllocationProfiles[i].updateProfile();
}
void CodeBlock::updateAllPredictions()
Modified: trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp (222379 => 222380)
--- trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp 2017-09-22 06:36:20 UTC (rev 222379)
+++ trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp 2017-09-22 08:22:44 UTC (rev 222380)
@@ -4399,6 +4399,7 @@
data.startConstant = m_inlineStackTop->m_constantBufferRemap[startConstant];
data.numConstants = numConstants;
data.indexingType = profile->selectIndexingType();
+ data.vectorLengthHint = std::max<unsigned>(profile->vectorLengthHint(), numConstants);
// If this statement has never executed, we'll have the wrong indexing type in the profile.
for (int i = 0; i < numConstants; ++i) {
@@ -4408,7 +4409,7 @@
m_codeBlock->constantBuffer(data.startConstant)[i]);
}
- m_graph.m_newArrayBufferData.append(data);
+ m_graph.m_newArrayBufferData.append(WTFMove(data));
set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(NewArrayBuffer, OpInfo(&m_graph.m_newArrayBufferData.last())));
NEXT_OPCODE(op_new_array_buffer);
}
Modified: trunk/Source/_javascript_Core/dfg/DFGGraph.cpp (222379 => 222380)
--- trunk/Source/_javascript_Core/dfg/DFGGraph.cpp 2017-09-22 06:36:20 UTC (rev 222379)
+++ trunk/Source/_javascript_Core/dfg/DFGGraph.cpp 2017-09-22 08:22:44 UTC (rev 222380)
@@ -321,6 +321,7 @@
for (unsigned i = 0; i < node->numConstants(); ++i)
out.print(anotherComma, pointerDumpInContext(freeze(m_codeBlock->constantBuffer(node->startConstant())[i]), context));
out.print("]");
+ out.print(comma, "vectorLengthHint = ", node->vectorLengthHint());
}
if (node->hasLazyJSValue())
out.print(comma, node->lazyJSValue());
Modified: trunk/Source/_javascript_Core/dfg/DFGNode.h (222379 => 222380)
--- trunk/Source/_javascript_Core/dfg/DFGNode.h 2017-09-22 06:36:20 UTC (rev 222379)
+++ trunk/Source/_javascript_Core/dfg/DFGNode.h 2017-09-22 08:22:44 UTC (rev 222380)
@@ -99,6 +99,7 @@
struct NewArrayBufferData {
unsigned startConstant;
unsigned numConstants;
+ unsigned vectorLengthHint;
IndexingType indexingType;
};
@@ -1115,6 +1116,11 @@
{
return newArrayBufferData()->numConstants;
}
+
+ unsigned vectorLengthHint()
+ {
+ return newArrayBufferData()->vectorLengthHint;
+ }
bool hasIndexingType()
{
Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.cpp (222379 => 222380)
--- trunk/Source/_javascript_Core/dfg/DFGOperations.cpp 2017-09-22 06:36:20 UTC (rev 222379)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.cpp 2017-09-22 08:22:44 UTC (rev 222380)
@@ -1311,6 +1311,25 @@
return bitwise_cast<char*>(result);
}
+char* JIT_OPERATION operationNewArrayWithSizeAndHint(ExecState* exec, Structure* arrayStructure, int32_t size, int32_t vectorLengthHint, Butterfly* butterfly)
+{
+ VM& vm = exec->vm();
+ NativeCallFrameTracer tracer(&vm, exec);
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ if (UNLIKELY(size < 0))
+ return bitwise_cast<char*>(throwException(exec, scope, createRangeError(exec, ASCIILiteral("Array size is not a small enough positive integer."))));
+
+ JSArray* result;
+ if (butterfly)
+ result = JSArray::createWithButterfly(vm, nullptr, arrayStructure, butterfly);
+ else {
+ result = JSArray::tryCreate(vm, arrayStructure, size, vectorLengthHint);
+ ASSERT(result);
+ }
+ return bitwise_cast<char*>(result);
+}
+
char* JIT_OPERATION operationNewArrayBuffer(ExecState* exec, Structure* arrayStructure, size_t start, size_t size)
{
VM& vm = exec->vm();
Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.h (222379 => 222380)
--- trunk/Source/_javascript_Core/dfg/DFGOperations.h 2017-09-22 06:36:20 UTC (rev 222379)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.h 2017-09-22 08:22:44 UTC (rev 222380)
@@ -81,6 +81,7 @@
char* JIT_OPERATION operationNewArrayBuffer(ExecState*, Structure*, size_t, size_t) WTF_INTERNAL;
char* JIT_OPERATION operationNewEmptyArray(ExecState*, Structure*) WTF_INTERNAL;
char* JIT_OPERATION operationNewArrayWithSize(ExecState*, Structure*, int32_t, Butterfly*) WTF_INTERNAL;
+char* JIT_OPERATION operationNewArrayWithSizeAndHint(ExecState*, Structure*, int32_t, int32_t, Butterfly*) WTF_INTERNAL;
char* JIT_OPERATION operationNewInt8ArrayWithSize(ExecState*, Structure*, int32_t, char*) WTF_INTERNAL;
char* JIT_OPERATION operationNewInt8ArrayWithOneArgument(ExecState*, Structure*, EncodedJSValue) WTF_INTERNAL;
char* JIT_OPERATION operationNewInt16ArrayWithSize(ExecState*, Structure*, int32_t, char*) WTF_INTERNAL;
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp (222379 => 222380)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp 2017-09-22 06:36:20 UTC (rev 222379)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp 2017-09-22 08:22:44 UTC (rev 222380)
@@ -4238,6 +4238,8 @@
IndexingType indexingType = node->indexingType();
if (!globalObject->isHavingABadTime() && !hasAnyArrayStorage(indexingType)) {
unsigned numElements = node->numConstants();
+ unsigned vectorLengthHint = node->vectorLengthHint();
+ ASSERT(vectorLengthHint >= numElements);
GPRTemporary result(this);
GPRTemporary storage(this);
@@ -4245,7 +4247,7 @@
GPRReg resultGPR = result.gpr();
GPRReg storageGPR = storage.gpr();
- emitAllocateRawObject(resultGPR, m_jit.graph().registerStructure(globalObject->arrayStructureForIndexingTypeDuringAllocation(indexingType)), storageGPR, numElements, numElements);
+ emitAllocateRawObject(resultGPR, m_jit.graph().registerStructure(globalObject->arrayStructureForIndexingTypeDuringAllocation(indexingType)), storageGPR, numElements, vectorLengthHint);
DFG_ASSERT(m_jit.graph(), node, indexingType & IsArray);
JSValue* data = ""
Modified: trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp (222379 => 222380)
--- trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp 2017-09-22 06:36:20 UTC (rev 222379)
+++ trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp 2017-09-22 08:22:44 UTC (rev 222380)
@@ -4189,7 +4189,7 @@
m_out.select(m_out.equal(indexingType, m_out.constInt32(ArrayWithContiguous)),
weakStructure(m_graph.registerStructure(globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithContiguous))),
weakStructure(m_graph.registerStructure(globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithDouble)))));
- arrayResult = allocateJSArray(resultLength, structure, indexingType, false, false);
+ arrayResult = allocateJSArray(resultLength, resultLength, structure, indexingType, false, false);
}
LBasicBlock loop = m_out.newBlock();
@@ -5114,9 +5114,11 @@
if (!globalObject->isHavingABadTime() && !hasAnyArrayStorage(m_node->indexingType())) {
unsigned numElements = m_node->numConstants();
-
+ unsigned vectorLengthHint = m_node->vectorLengthHint();
+
+ ASSERT(vectorLengthHint >= numElements);
ArrayValues arrayValues =
- allocateUninitializedContiguousJSArray(m_out.constInt32(numElements), structure);
+ allocateUninitializedContiguousJSArray(numElements, vectorLengthHint, structure);
JSValue* data = ""
for (unsigned index = 0; index < m_node->numConstants(); ++index) {
@@ -5155,7 +5157,7 @@
IndexingType indexingType = m_node->indexingType();
setJSValue(
allocateJSArray(
- publicLength, weakPointer(globalObject->arrayStructureForIndexingTypeDuringAllocation(indexingType)), m_out.constInt32(indexingType)).array);
+ publicLength, publicLength, weakPointer(globalObject->arrayStructureForIndexingTypeDuringAllocation(indexingType)), m_out.constInt32(indexingType)).array);
mutatorFence();
return;
}
@@ -11441,7 +11443,7 @@
LValue butterfly;
};
- ArrayValues allocateJSArray(LValue publicLength, LValue structure, LValue indexingType, bool shouldInitializeElements = true, bool shouldLargeArraySizeCreateArrayStorage = true)
+ ArrayValues allocateJSArray(LValue publicLength, LValue vectorLength, LValue structure, LValue indexingType, bool shouldInitializeElements = true, bool shouldLargeArraySizeCreateArrayStorage = true)
{
JSGlobalObject* globalObject = m_graph.globalObjectFor(m_node->origin.semantic);
if (indexingType->hasInt32()) {
@@ -11460,6 +11462,18 @@
LBasicBlock slowCase = m_out.newBlock();
LBasicBlock lastNext = m_out.insertNewBlocksBefore(fastCase);
+
+ if (vectorLength->hasInt32() && structure->hasIntPtr()) {
+ unsigned vectorLengthConst = static_cast<unsigned>(vectorLength->asInt32());
+ if (vectorLengthConst <= MAX_STORAGE_VECTOR_LENGTH) {
+ vectorLength = m_out.constInt32(
+ Butterfly::optimalContiguousVectorLength(
+ bitwise_cast<Structure*>(structure->asIntPtr())->outOfLineCapacity(), vectorLengthConst));
+ }
+ } else {
+ // We don't compute the optimal vector length for new Array(blah) where blah is not
+ // statically known, since the compute effort of doing it here is probably not worth it.
+ }
ValueFromBlock noButterfly = m_out.anchor(m_out.intPtrZero);
@@ -11472,22 +11486,6 @@
m_out.branch(predicate, rarely(largeCase), usually(fastCase));
m_out.appendTo(fastCase, largeCase);
-
- LValue vectorLength = nullptr;
- if (publicLength->hasInt32() && structure->hasIntPtr()) {
- unsigned publicLengthConst = static_cast<unsigned>(publicLength->asInt32());
- if (publicLengthConst <= MAX_STORAGE_VECTOR_LENGTH) {
- vectorLength = m_out.constInt32(
- Butterfly::optimalContiguousVectorLength(
- bitwise_cast<Structure*>(structure->asIntPtr())->outOfLineCapacity(), publicLengthConst));
- }
- }
-
- if (!vectorLength) {
- // We don't compute the optimal vector length for new Array(blah) where blah is not
- // statically known, since the compute effort of doing it here is probably not worth it.
- vectorLength = publicLength;
- }
LValue payloadSize =
m_out.shl(m_out.zeroExt(vectorLength, pointerType()), m_out.constIntPtr(3));
@@ -11533,10 +11531,10 @@
LValue slowResultValue = lazySlowPath(
[=, &vm] (const Vector<Location>& locations) -> RefPtr<LazySlowPath::Generator> {
return createLazyCallGenerator(vm,
- operationNewArrayWithSize, locations[0].directGPR(),
- locations[1].directGPR(), locations[2].directGPR(), locations[3].directGPR());
+ operationNewArrayWithSizeAndHint, locations[0].directGPR(),
+ locations[1].directGPR(), locations[2].directGPR(), locations[3].directGPR(), locations[4].directGPR());
},
- structureValue, publicLength, butterflyValue);
+ structureValue, publicLength, vectorLength, butterflyValue);
ValueFromBlock slowResult = m_out.anchor(slowResultValue);
ValueFromBlock slowButterfly = m_out.anchor(
m_out.loadPtr(slowResultValue, m_heaps.JSObject_butterfly));
@@ -11548,14 +11546,25 @@
m_out.phi(pointerType(), fastButterfly, slowButterfly));
}
- ArrayValues allocateUninitializedContiguousJSArray(LValue publicLength, RegisteredStructure structure)
+ ArrayValues allocateUninitializedContiguousJSArrayInternal(LValue publicLength, LValue vectorLength, RegisteredStructure structure)
{
bool shouldInitializeElements = false;
bool shouldLargeArraySizeCreateArrayStorage = false;
return allocateJSArray(
- publicLength, weakStructure(structure), m_out.constInt32(structure->indexingType()), shouldInitializeElements,
+ publicLength, vectorLength, weakStructure(structure), m_out.constInt32(structure->indexingType()), shouldInitializeElements,
shouldLargeArraySizeCreateArrayStorage);
}
+
+ ArrayValues allocateUninitializedContiguousJSArray(LValue publicLength, RegisteredStructure structure)
+ {
+ return allocateUninitializedContiguousJSArrayInternal(publicLength, publicLength, structure);
+ }
+
+ ArrayValues allocateUninitializedContiguousJSArray(unsigned publicLength, unsigned vectorLength, RegisteredStructure structure)
+ {
+ ASSERT(vectorLength >= publicLength);
+ return allocateUninitializedContiguousJSArrayInternal(m_out.constInt32(publicLength), m_out.constInt32(vectorLength), structure);
+ }
LValue ensureShadowChickenPacket()
{
Modified: trunk/Source/_javascript_Core/runtime/ArrayConventions.h (222379 => 222380)
--- trunk/Source/_javascript_Core/runtime/ArrayConventions.h 2017-09-22 06:36:20 UTC (rev 222379)
+++ trunk/Source/_javascript_Core/runtime/ArrayConventions.h 2017-09-22 08:22:44 UTC (rev 222380)
@@ -77,6 +77,8 @@
// for an array that was created with a sepcified length (e.g. a = new Array(123))
#define BASE_CONTIGUOUS_VECTOR_LEN 3U
#define BASE_CONTIGUOUS_VECTOR_LEN_EMPTY 5U
+#define BASE_CONTIGUOUS_VECTOR_LEN_MIN 3U
+#define BASE_CONTIGUOUS_VECTOR_LEN_MAX 25U
#define BASE_ARRAY_STORAGE_VECTOR_LEN 4U
// The upper bound to the size we'll grow a zero length array when the first element
Modified: trunk/Source/_javascript_Core/runtime/JSArray.h (222379 => 222380)
--- trunk/Source/_javascript_Core/runtime/JSArray.h 2017-09-22 06:36:20 UTC (rev 222379)
+++ trunk/Source/_javascript_Core/runtime/JSArray.h 2017-09-22 08:22:44 UTC (rev 222380)
@@ -54,6 +54,7 @@
public:
static JSArray* tryCreate(VM&, Structure*, unsigned initialLength = 0);
+ static JSArray* tryCreate(VM&, Structure*, unsigned initialLength, unsigned vectorLengthHint);
static JSArray* create(VM&, Structure*, unsigned initialLength = 0);
static JSArray* createWithButterfly(VM&, GCDeferralContext*, Structure*, Butterfly*);
@@ -215,8 +216,9 @@
Butterfly* createArrayButterflyInDictionaryIndexingMode(
VM&, JSCell* intendedOwner, unsigned initialLength);
-inline JSArray* JSArray::tryCreate(VM& vm, Structure* structure, unsigned initialLength)
+inline JSArray* JSArray::tryCreate(VM& vm, Structure* structure, unsigned initialLength, unsigned vectorLengthHint)
{
+ ASSERT(vectorLengthHint >= initialLength);
unsigned outOfLineStorage = structure->outOfLineCapacity();
Butterfly* butterfly;
@@ -228,10 +230,10 @@
|| hasDouble(indexingType)
|| hasContiguous(indexingType));
- if (UNLIKELY(initialLength > MAX_STORAGE_VECTOR_LENGTH))
+ if (UNLIKELY(vectorLengthHint > MAX_STORAGE_VECTOR_LENGTH))
return nullptr;
- unsigned vectorLength = Butterfly::optimalContiguousVectorLength(structure, initialLength);
+ unsigned vectorLength = Butterfly::optimalContiguousVectorLength(structure, vectorLengthHint);
void* temp = vm.jsValueGigacageAuxiliarySpace.tryAllocate(nullptr, Butterfly::totalSize(0, outOfLineStorage, true, vectorLength * sizeof(EncodedJSValue)));
if (!temp)
return nullptr;
@@ -256,6 +258,11 @@
return createWithButterfly(vm, nullptr, structure, butterfly);
}
+inline JSArray* JSArray::tryCreate(VM& vm, Structure* structure, unsigned initialLength)
+{
+ return tryCreate(vm, structure, initialLength, initialLength);
+}
+
inline JSArray* JSArray::create(VM& vm, Structure* structure, unsigned initialLength)
{
JSArray* result = JSArray::tryCreate(vm, structure, initialLength);