diff options
author | Simon Hausmann <simon.hausmann@digia.com> | 2012-11-09 12:15:52 +0100 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@digia.com> | 2012-11-09 12:16:06 +0100 |
commit | de4f791e30be4e4239b381c11745ffa4d87ddb8b (patch) | |
tree | 885e3a5d6670828b454cf676b4d42f78e28b1f0e /Source/JavaScriptCore/runtime/JSObject.cpp | |
parent | b022df48697d40cdabdeafb2c29bb14fe489b6fe (diff) | |
download | qtwebkit-de4f791e30be4e4239b381c11745ffa4d87ddb8b.tar.gz |
Imported WebKit commit e2c32e2f53e02d388e70b9db88b91d8d9d28fc84 (http://svn.webkit.org/repository/webkit/trunk@133952)
Revert back to an older snapshot that should build on ARM
Diffstat (limited to 'Source/JavaScriptCore/runtime/JSObject.cpp')
-rw-r--r-- | Source/JavaScriptCore/runtime/JSObject.cpp | 661 |
1 files changed, 67 insertions, 594 deletions
diff --git a/Source/JavaScriptCore/runtime/JSObject.cpp b/Source/JavaScriptCore/runtime/JSObject.cpp index a67896b1a..6a3fb84e4 100644 --- a/Source/JavaScriptCore/runtime/JSObject.cpp +++ b/Source/JavaScriptCore/runtime/JSObject.cpp @@ -24,14 +24,14 @@ #include "config.h" #include "JSObject.h" -#include "ButterflyInlines.h" -#include "CopiedSpaceInlines.h" +#include "ButterflyInlineMethods.h" +#include "CopiedSpaceInlineMethods.h" #include "CopyVisitor.h" -#include "CopyVisitorInlines.h" +#include "CopyVisitorInlineMethods.h" #include "DatePrototype.h" #include "ErrorConstructor.h" #include "GetterSetter.h" -#include "IndexingHeaderInlines.h" +#include "IndexingHeaderInlineMethods.h" #include "JSFunction.h" #include "JSGlobalObject.h" #include "Lookup.h" @@ -42,7 +42,7 @@ #include "PropertyDescriptor.h" #include "PropertyNameArray.h" #include "Reject.h" -#include "SlotVisitorInlines.h" +#include "SlotVisitorInlineMethods.h" #include <math.h> #include <wtf/Assertions.h> @@ -129,16 +129,7 @@ ALWAYS_INLINE void JSObject::copyButterfly(CopyVisitor& visitor, Butterfly* butt size_t count; switch (structure->indexingType()) { - case ALL_UNDECIDED_INDEXING_TYPES: { - currentTarget = 0; - currentSource = 0; - count = 0; - break; - } - - case ALL_CONTIGUOUS_INDEXING_TYPES: - case ALL_INT32_INDEXING_TYPES: - case ALL_DOUBLE_INDEXING_TYPES: { + case ALL_CONTIGUOUS_INDEXING_TYPES: { currentTarget = newButterfly->contiguous(); currentSource = butterfly->contiguous(); ASSERT(newButterfly->publicLength() <= newButterfly->vectorLength()); @@ -161,7 +152,8 @@ ALWAYS_INLINE void JSObject::copyButterfly(CopyVisitor& visitor, Butterfly* butt break; } - memcpy(currentTarget, currentSource, count * sizeof(EncodedJSValue)); + while (count--) + (currentTarget++)->setWithoutWriteBarrier((currentSource++)->get()); } m_butterfly = newButterfly; @@ -280,10 +272,8 @@ bool JSObject::getOwnPropertySlotByIndex(JSCell* cell, ExecState* exec, unsigned switch (thisObject->structure()->indexingType()) { case ALL_BLANK_INDEXING_TYPES: - case ALL_UNDECIDED_INDEXING_TYPES: break; - case ALL_INT32_INDEXING_TYPES: case ALL_CONTIGUOUS_INDEXING_TYPES: { Butterfly* butterfly = thisObject->m_butterfly; if (i >= butterfly->vectorLength()) @@ -298,20 +288,6 @@ bool JSObject::getOwnPropertySlotByIndex(JSCell* cell, ExecState* exec, unsigned return false; } - case ALL_DOUBLE_INDEXING_TYPES: { - Butterfly* butterfly = thisObject->m_butterfly; - if (i >= butterfly->vectorLength()) - return false; - - double value = butterfly->contiguousDouble()[i]; - if (value == value) { - slot.setValue(JSValue(JSValue::EncodeAsDouble, value)); - return true; - } - - return false; - } - case ALL_ARRAY_STORAGE_INDEXING_TYPES: { ArrayStorage* storage = thisObject->m_butterfly->arrayStorage(); if (i >= storage->length()) @@ -429,22 +405,6 @@ void JSObject::putByIndex(JSCell* cell, ExecState* exec, unsigned propertyName, case ALL_BLANK_INDEXING_TYPES: break; - case ALL_UNDECIDED_INDEXING_TYPES: { - thisObject->convertUndecidedForValue(exec->globalData(), value); - // Reloop. - putByIndex(cell, exec, propertyName, value, shouldThrow); - return; - } - - case ALL_INT32_INDEXING_TYPES: { - if (!value.isInt32()) { - thisObject->convertInt32ForValue(exec->globalData(), value); - putByIndex(cell, exec, propertyName, value, shouldThrow); - return; - } - // Fall through. - } - case ALL_CONTIGUOUS_INDEXING_TYPES: { Butterfly* butterfly = thisObject->m_butterfly; if (propertyName >= butterfly->vectorLength()) @@ -455,29 +415,6 @@ void JSObject::putByIndex(JSCell* cell, ExecState* exec, unsigned propertyName, return; } - case ALL_DOUBLE_INDEXING_TYPES: { - if (!value.isNumber()) { - thisObject->convertDoubleToContiguous(exec->globalData()); - // Reloop. - putByIndex(cell, exec, propertyName, value, shouldThrow); - return; - } - double valueAsDouble = value.asNumber(); - if (valueAsDouble != valueAsDouble) { - thisObject->convertDoubleToContiguous(exec->globalData()); - // Reloop. - putByIndex(cell, exec, propertyName, value, shouldThrow); - return; - } - Butterfly* butterfly = thisObject->m_butterfly; - if (propertyName >= butterfly->vectorLength()) - break; - butterfly->contiguousDouble()[propertyName] = valueAsDouble; - if (propertyName >= butterfly->publicLength()) - butterfly->setPublicLength(propertyName + 1); - return; - } - case NonArrayWithArrayStorage: case ArrayWithArrayStorage: { ArrayStorage* storage = thisObject->m_butterfly->arrayStorage(); @@ -570,13 +507,10 @@ ArrayStorage* JSObject::enterDictionaryIndexingModeWhenArrayStorageAlreadyExists void JSObject::enterDictionaryIndexingMode(JSGlobalData& globalData) { switch (structure()->indexingType()) { - case ALL_UNDECIDED_INDEXING_TYPES: - case ALL_INT32_INDEXING_TYPES: - case ALL_DOUBLE_INDEXING_TYPES: case ALL_CONTIGUOUS_INDEXING_TYPES: // NOTE: this is horribly inefficient, as it will perform two conversions. We could optimize // this case if we ever cared. - enterDictionaryIndexingModeWhenArrayStorageAlreadyExists(globalData, ensureArrayStorageSlow(globalData)); + enterDictionaryIndexingModeWhenArrayStorageAlreadyExists(globalData, convertContiguousToArrayStorage(globalData)); break; case ALL_ARRAY_STORAGE_INDEXING_TYPES: enterDictionaryIndexingModeWhenArrayStorageAlreadyExists(globalData, m_butterfly->arrayStorage()); @@ -600,7 +534,7 @@ void JSObject::notifyPresenceOfIndexedAccessors(JSGlobalData& globalData) globalObject()->haveABadTime(globalData); } -Butterfly* JSObject::createInitialIndexedStorage(JSGlobalData& globalData, unsigned length, size_t elementSize) +WriteBarrier<Unknown>* JSObject::createInitialContiguous(JSGlobalData& globalData, unsigned length) { ASSERT(length < MAX_ARRAY_INDEX); IndexingType oldType = structure()->indexingType(); @@ -610,41 +544,9 @@ Butterfly* JSObject::createInitialIndexedStorage(JSGlobalData& globalData, unsig unsigned vectorLength = std::max(length, BASE_VECTOR_LEN); Butterfly* newButterfly = m_butterfly->growArrayRight( globalData, structure(), structure()->outOfLineCapacity(), false, 0, - elementSize * vectorLength); + sizeof(EncodedJSValue) * vectorLength); newButterfly->setPublicLength(length); newButterfly->setVectorLength(vectorLength); - return newButterfly; -} - -Butterfly* JSObject::createInitialUndecided(JSGlobalData& globalData, unsigned length) -{ - Butterfly* newButterfly = createInitialIndexedStorage(globalData, length, sizeof(EncodedJSValue)); - Structure* newStructure = Structure::nonPropertyTransition(globalData, structure(), AllocateUndecided); - setButterfly(globalData, newButterfly, newStructure); - return newButterfly; -} - -WriteBarrier<Unknown>* JSObject::createInitialInt32(JSGlobalData& globalData, unsigned length) -{ - Butterfly* newButterfly = createInitialIndexedStorage(globalData, length, sizeof(EncodedJSValue)); - Structure* newStructure = Structure::nonPropertyTransition(globalData, structure(), AllocateInt32); - setButterfly(globalData, newButterfly, newStructure); - return newButterfly->contiguousInt32(); -} - -double* JSObject::createInitialDouble(JSGlobalData& globalData, unsigned length) -{ - Butterfly* newButterfly = createInitialIndexedStorage(globalData, length, sizeof(double)); - for (unsigned i = newButterfly->vectorLength(); i--;) - newButterfly->contiguousDouble()[i] = QNaN; - Structure* newStructure = Structure::nonPropertyTransition(globalData, structure(), AllocateDouble); - setButterfly(globalData, newButterfly, newStructure); - return newButterfly->contiguousDouble(); -} - -WriteBarrier<Unknown>* JSObject::createInitialContiguous(JSGlobalData& globalData, unsigned length) -{ - Butterfly* newButterfly = createInitialIndexedStorage(globalData, length, sizeof(EncodedJSValue)); Structure* newStructure = Structure::nonPropertyTransition(globalData, structure(), AllocateContiguous); setButterfly(globalData, newButterfly, newStructure); return newButterfly->contiguous(); @@ -675,33 +577,10 @@ ArrayStorage* JSObject::createInitialArrayStorage(JSGlobalData& globalData) return createArrayStorage(globalData, 0, BASE_VECTOR_LEN); } -WriteBarrier<Unknown>* JSObject::convertUndecidedToInt32(JSGlobalData& globalData) -{ - ASSERT(hasUndecided(structure()->indexingType())); - setStructure(globalData, Structure::nonPropertyTransition(globalData, structure(), AllocateInt32)); - return m_butterfly->contiguousInt32(); -} - -double* JSObject::convertUndecidedToDouble(JSGlobalData& globalData) +ArrayStorage* JSObject::convertContiguousToArrayStorage(JSGlobalData& globalData, NonPropertyTransition transition, unsigned neededLength) { - ASSERT(hasUndecided(structure()->indexingType())); - - for (unsigned i = m_butterfly->vectorLength(); i--;) - m_butterfly->contiguousDouble()[i] = QNaN; + ASSERT(hasContiguous(structure()->indexingType())); - setStructure(globalData, Structure::nonPropertyTransition(globalData, structure(), AllocateDouble)); - return m_butterfly->contiguousDouble(); -} - -WriteBarrier<Unknown>* JSObject::convertUndecidedToContiguous(JSGlobalData& globalData) -{ - ASSERT(hasUndecided(structure()->indexingType())); - setStructure(globalData, Structure::nonPropertyTransition(globalData, structure(), AllocateContiguous)); - return m_butterfly->contiguous(); -} - -ArrayStorage* JSObject::constructConvertedArrayStorageWithoutCopyingElements(JSGlobalData& globalData, unsigned neededLength) -{ unsigned publicLength = m_butterfly->publicLength(); unsigned propertyCapacity = structure()->outOfLineCapacity(); unsigned propertySize = structure()->outOfLineSize(); @@ -720,141 +599,7 @@ ArrayStorage* JSObject::constructConvertedArrayStorageWithoutCopyingElements(JSG newStorage->m_sparseMap.clear(); newStorage->m_indexBias = 0; newStorage->m_numValuesInVector = 0; - - return newStorage; -} - -ArrayStorage* JSObject::convertUndecidedToArrayStorage(JSGlobalData& globalData, NonPropertyTransition transition, unsigned neededLength) -{ - ASSERT(hasUndecided(structure()->indexingType())); - - ArrayStorage* storage = constructConvertedArrayStorageWithoutCopyingElements(globalData, neededLength); - // No need to copy elements. - - Structure* newStructure = Structure::nonPropertyTransition(globalData, structure(), transition); - setButterfly(globalData, storage->butterfly(), newStructure); - return storage; -} - -ArrayStorage* JSObject::convertUndecidedToArrayStorage(JSGlobalData& globalData, NonPropertyTransition transition) -{ - return convertUndecidedToArrayStorage(globalData, transition, m_butterfly->vectorLength()); -} - -ArrayStorage* JSObject::convertUndecidedToArrayStorage(JSGlobalData& globalData) -{ - return convertUndecidedToArrayStorage(globalData, structure()->suggestedArrayStorageTransition()); -} - -double* JSObject::convertInt32ToDouble(JSGlobalData& globalData) -{ - ASSERT(hasInt32(structure()->indexingType())); - - for (unsigned i = m_butterfly->vectorLength(); i--;) { - WriteBarrier<Unknown>* current = &m_butterfly->contiguousInt32()[i]; - double* currentAsDouble = bitwise_cast<double*>(current); - JSValue v = current->get(); - if (!v) { - *currentAsDouble = QNaN; - continue; - } - ASSERT(v.isInt32()); - *currentAsDouble = v.asInt32(); - } - - setStructure(globalData, Structure::nonPropertyTransition(globalData, structure(), AllocateDouble)); - return m_butterfly->contiguousDouble(); -} - -WriteBarrier<Unknown>* JSObject::convertInt32ToContiguous(JSGlobalData& globalData) -{ - ASSERT(hasInt32(structure()->indexingType())); - - setStructure(globalData, Structure::nonPropertyTransition(globalData, structure(), AllocateContiguous)); - return m_butterfly->contiguous(); -} - -ArrayStorage* JSObject::convertInt32ToArrayStorage(JSGlobalData& globalData, NonPropertyTransition transition, unsigned neededLength) -{ - ASSERT(hasInt32(structure()->indexingType())); - - ArrayStorage* newStorage = constructConvertedArrayStorageWithoutCopyingElements(globalData, neededLength); - for (unsigned i = m_butterfly->publicLength(); i--;) { - JSValue v = m_butterfly->contiguous()[i].get(); - if (!v) - continue; - newStorage->m_vector[i].setWithoutWriteBarrier(v); - newStorage->m_numValuesInVector++; - } - - Structure* newStructure = Structure::nonPropertyTransition(globalData, structure(), transition); - setButterfly(globalData, newStorage->butterfly(), newStructure); - return newStorage; -} - -ArrayStorage* JSObject::convertInt32ToArrayStorage(JSGlobalData& globalData, NonPropertyTransition transition) -{ - return convertInt32ToArrayStorage(globalData, transition, m_butterfly->vectorLength()); -} - -ArrayStorage* JSObject::convertInt32ToArrayStorage(JSGlobalData& globalData) -{ - return convertInt32ToArrayStorage(globalData, structure()->suggestedArrayStorageTransition()); -} - -WriteBarrier<Unknown>* JSObject::convertDoubleToContiguous(JSGlobalData& globalData) -{ - ASSERT(hasDouble(structure()->indexingType())); - - for (unsigned i = m_butterfly->vectorLength(); i--;) { - double* current = &m_butterfly->contiguousDouble()[i]; - WriteBarrier<Unknown>* currentAsValue = bitwise_cast<WriteBarrier<Unknown>*>(current); - double value = *current; - if (value != value) { - currentAsValue->clear(); - continue; - } - currentAsValue->setWithoutWriteBarrier(JSValue(JSValue::EncodeAsDouble, value)); - } - - setStructure(globalData, Structure::nonPropertyTransition(globalData, structure(), AllocateContiguous)); - return m_butterfly->contiguous(); -} - -ArrayStorage* JSObject::convertDoubleToArrayStorage(JSGlobalData& globalData, NonPropertyTransition transition, unsigned neededLength) -{ - ASSERT(hasDouble(structure()->indexingType())); - - ArrayStorage* newStorage = constructConvertedArrayStorageWithoutCopyingElements(globalData, neededLength); - for (unsigned i = m_butterfly->publicLength(); i--;) { - double value = m_butterfly->contiguousDouble()[i]; - if (value != value) - continue; - newStorage->m_vector[i].setWithoutWriteBarrier(JSValue(JSValue::EncodeAsDouble, value)); - newStorage->m_numValuesInVector++; - } - - Structure* newStructure = Structure::nonPropertyTransition(globalData, structure(), transition); - setButterfly(globalData, newStorage->butterfly(), newStructure); - return newStorage; -} - -ArrayStorage* JSObject::convertDoubleToArrayStorage(JSGlobalData& globalData, NonPropertyTransition transition) -{ - return convertDoubleToArrayStorage(globalData, transition, m_butterfly->vectorLength()); -} - -ArrayStorage* JSObject::convertDoubleToArrayStorage(JSGlobalData& globalData) -{ - return convertDoubleToArrayStorage(globalData, structure()->suggestedArrayStorageTransition()); -} - -ArrayStorage* JSObject::convertContiguousToArrayStorage(JSGlobalData& globalData, NonPropertyTransition transition, unsigned neededLength) -{ - ASSERT(hasContiguous(structure()->indexingType())); - - ArrayStorage* newStorage = constructConvertedArrayStorageWithoutCopyingElements(globalData, neededLength); - for (unsigned i = m_butterfly->publicLength(); i--;) { + for (unsigned i = publicLength; i--;) { JSValue v = m_butterfly->contiguous()[i].get(); if (!v) continue; @@ -863,7 +608,7 @@ ArrayStorage* JSObject::convertContiguousToArrayStorage(JSGlobalData& globalData } Structure* newStructure = Structure::nonPropertyTransition(globalData, structure(), transition); - setButterfly(globalData, newStorage->butterfly(), newStructure); + setButterfly(globalData, newButterfly, newStructure); return newStorage; } @@ -877,154 +622,48 @@ ArrayStorage* JSObject::convertContiguousToArrayStorage(JSGlobalData& globalData return convertContiguousToArrayStorage(globalData, structure()->suggestedArrayStorageTransition()); } -void JSObject::convertUndecidedForValue(JSGlobalData& globalData, JSValue value) -{ - if (value.isInt32()) { - convertUndecidedToInt32(globalData); - return; - } - - if (value.isDouble()) { - convertUndecidedToDouble(globalData); - return; - } - - convertUndecidedToContiguous(globalData); -} - -void JSObject::convertInt32ForValue(JSGlobalData& globalData, JSValue value) -{ - ASSERT(!value.isInt32()); - - if (value.isDouble()) { - convertInt32ToDouble(globalData); - return; - } - - convertInt32ToContiguous(globalData); -} - -void JSObject::setIndexQuicklyToUndecided(JSGlobalData& globalData, unsigned index, JSValue value) -{ - ASSERT(index < m_butterfly->publicLength()); - ASSERT(index < m_butterfly->vectorLength()); - convertUndecidedForValue(globalData, value); - setIndexQuickly(globalData, index, value); -} - -void JSObject::convertInt32ToDoubleOrContiguousWhilePerformingSetIndex(JSGlobalData& globalData, unsigned index, JSValue value) -{ - ASSERT(!value.isInt32()); - convertInt32ForValue(globalData, value); - setIndexQuickly(globalData, index, value); -} - -void JSObject::convertDoubleToContiguousWhilePerformingSetIndex(JSGlobalData& globalData, unsigned index, JSValue value) -{ - ASSERT(!value.isNumber() || value.asNumber() != value.asNumber()); - convertDoubleToContiguous(globalData); - setIndexQuickly(globalData, index, value); -} - -WriteBarrier<Unknown>* JSObject::ensureInt32Slow(JSGlobalData& globalData) +WriteBarrier<Unknown>* JSObject::ensureContiguousSlow(JSGlobalData& globalData) { switch (structure()->indexingType()) { case ALL_BLANK_INDEXING_TYPES: if (UNLIKELY(indexingShouldBeSparse() || structure()->needsSlowPutIndexing())) return 0; - return createInitialInt32(globalData, 0); - - case ALL_UNDECIDED_INDEXING_TYPES: - return convertUndecidedToInt32(globalData); - - case ALL_DOUBLE_INDEXING_TYPES: - case ALL_CONTIGUOUS_INDEXING_TYPES: - case ALL_ARRAY_STORAGE_INDEXING_TYPES: - return 0; + return createInitialContiguous(globalData, 0); default: - CRASH(); + ASSERT_NOT_REACHED(); return 0; } } -double* JSObject::ensureDoubleSlow(JSGlobalData& globalData) +ArrayStorage* JSObject::ensureArrayStorageSlow(JSGlobalData& globalData) { switch (structure()->indexingType()) { - case ALL_BLANK_INDEXING_TYPES: - if (UNLIKELY(indexingShouldBeSparse() || structure()->needsSlowPutIndexing())) - return 0; - return createInitialDouble(globalData, 0); - - case ALL_UNDECIDED_INDEXING_TYPES: - return convertUndecidedToDouble(globalData); - - case ALL_INT32_INDEXING_TYPES: - return convertInt32ToDouble(globalData); - case ALL_CONTIGUOUS_INDEXING_TYPES: - case ALL_ARRAY_STORAGE_INDEXING_TYPES: - return 0; + ASSERT(!indexingShouldBeSparse()); + ASSERT(!structure()->needsSlowPutIndexing()); + return convertContiguousToArrayStorage(globalData); - default: - CRASH(); - return 0; - } -} - -WriteBarrier<Unknown>* JSObject::ensureContiguousSlow(JSGlobalData& globalData) -{ - switch (structure()->indexingType()) { case ALL_BLANK_INDEXING_TYPES: - if (UNLIKELY(indexingShouldBeSparse() || structure()->needsSlowPutIndexing())) - return 0; - return createInitialContiguous(globalData, 0); - - case ALL_UNDECIDED_INDEXING_TYPES: - return convertUndecidedToContiguous(globalData); - - case ALL_INT32_INDEXING_TYPES: - return convertInt32ToContiguous(globalData); - - case ALL_DOUBLE_INDEXING_TYPES: - return convertDoubleToContiguous(globalData); - - case ALL_ARRAY_STORAGE_INDEXING_TYPES: - return 0; + if (UNLIKELY(indexingShouldBeSparse())) + return ensureArrayStorageExistsAndEnterDictionaryIndexingMode(globalData); + return createInitialArrayStorage(globalData); default: - CRASH(); + ASSERT_NOT_REACHED(); return 0; } } -ArrayStorage* JSObject::ensureArrayStorageSlow(JSGlobalData& globalData) +Butterfly* JSObject::ensureIndexedStorageSlow(JSGlobalData& globalData) { switch (structure()->indexingType()) { case ALL_BLANK_INDEXING_TYPES: + if (UNLIKELY(structure()->needsSlowPutIndexing())) + return createInitialArrayStorage(globalData)->butterfly(); if (UNLIKELY(indexingShouldBeSparse())) - return ensureArrayStorageExistsAndEnterDictionaryIndexingMode(globalData); - return createInitialArrayStorage(globalData); - - case ALL_UNDECIDED_INDEXING_TYPES: - ASSERT(!indexingShouldBeSparse()); - ASSERT(!structure()->needsSlowPutIndexing()); - return convertUndecidedToArrayStorage(globalData); - - case ALL_INT32_INDEXING_TYPES: - ASSERT(!indexingShouldBeSparse()); - ASSERT(!structure()->needsSlowPutIndexing()); - return convertInt32ToArrayStorage(globalData); - - case ALL_DOUBLE_INDEXING_TYPES: - ASSERT(!indexingShouldBeSparse()); - ASSERT(!structure()->needsSlowPutIndexing()); - return convertDoubleToArrayStorage(globalData); - - case ALL_CONTIGUOUS_INDEXING_TYPES: - ASSERT(!indexingShouldBeSparse()); - ASSERT(!structure()->needsSlowPutIndexing()); - return convertContiguousToArrayStorage(globalData); + return ensureArrayStorageExistsAndEnterDictionaryIndexingMode(globalData)->butterfly(); + return Butterfly::fromContiguous(createInitialContiguous(globalData, 0)); default: ASSERT_NOT_REACHED(); @@ -1035,6 +674,13 @@ ArrayStorage* JSObject::ensureArrayStorageSlow(JSGlobalData& globalData) ArrayStorage* JSObject::ensureArrayStorageExistsAndEnterDictionaryIndexingMode(JSGlobalData& globalData) { switch (structure()->indexingType()) { + case ALL_CONTIGUOUS_INDEXING_TYPES: + // FIXME: This could be made way more efficient, if we cared. + return enterDictionaryIndexingModeWhenArrayStorageAlreadyExists(globalData, convertContiguousToArrayStorage(globalData)); + + case ALL_ARRAY_STORAGE_INDEXING_TYPES: + return enterDictionaryIndexingModeWhenArrayStorageAlreadyExists(globalData, m_butterfly->arrayStorage()); + case ALL_BLANK_INDEXING_TYPES: { createArrayStorage(globalData, 0, 0); SparseArrayValueMap* map = allocateSparseIndexMap(globalData); @@ -1042,23 +688,8 @@ ArrayStorage* JSObject::ensureArrayStorageExistsAndEnterDictionaryIndexingMode(J return arrayStorage(); } - case ALL_UNDECIDED_INDEXING_TYPES: - return enterDictionaryIndexingModeWhenArrayStorageAlreadyExists(globalData, convertUndecidedToArrayStorage(globalData)); - - case ALL_INT32_INDEXING_TYPES: - return enterDictionaryIndexingModeWhenArrayStorageAlreadyExists(globalData, convertInt32ToArrayStorage(globalData)); - - case ALL_DOUBLE_INDEXING_TYPES: - return enterDictionaryIndexingModeWhenArrayStorageAlreadyExists(globalData, convertDoubleToArrayStorage(globalData)); - - case ALL_CONTIGUOUS_INDEXING_TYPES: - return enterDictionaryIndexingModeWhenArrayStorageAlreadyExists(globalData, convertContiguousToArrayStorage(globalData)); - - case ALL_ARRAY_STORAGE_INDEXING_TYPES: - return enterDictionaryIndexingModeWhenArrayStorageAlreadyExists(globalData, m_butterfly->arrayStorage()); - default: - CRASH(); + ASSERT_NOT_REACHED(); return 0; } } @@ -1066,21 +697,10 @@ ArrayStorage* JSObject::ensureArrayStorageExistsAndEnterDictionaryIndexingMode(J void JSObject::switchToSlowPutArrayStorage(JSGlobalData& globalData) { switch (structure()->indexingType()) { - case ALL_UNDECIDED_INDEXING_TYPES: - convertUndecidedToArrayStorage(globalData, AllocateSlowPutArrayStorage); - break; - - case ALL_INT32_INDEXING_TYPES: - convertInt32ToArrayStorage(globalData, AllocateSlowPutArrayStorage); - break; - - case ALL_DOUBLE_INDEXING_TYPES: - convertDoubleToArrayStorage(globalData, AllocateSlowPutArrayStorage); - break; - - case ALL_CONTIGUOUS_INDEXING_TYPES: + case ALL_CONTIGUOUS_INDEXING_TYPES: { convertContiguousToArrayStorage(globalData, AllocateSlowPutArrayStorage); break; + } case NonArrayWithArrayStorage: case ArrayWithArrayStorage: { @@ -1090,7 +710,7 @@ void JSObject::switchToSlowPutArrayStorage(JSGlobalData& globalData) } default: - CRASH(); + ASSERT_NOT_REACHED(); break; } } @@ -1257,10 +877,8 @@ bool JSObject::deletePropertyByIndex(JSCell* cell, ExecState* exec, unsigned i) switch (thisObject->structure()->indexingType()) { case ALL_BLANK_INDEXING_TYPES: - case ALL_UNDECIDED_INDEXING_TYPES: return true; - case ALL_INT32_INDEXING_TYPES: case ALL_CONTIGUOUS_INDEXING_TYPES: { Butterfly* butterfly = thisObject->m_butterfly; if (i >= butterfly->vectorLength()) @@ -1269,14 +887,6 @@ bool JSObject::deletePropertyByIndex(JSCell* cell, ExecState* exec, unsigned i) return true; } - case ALL_DOUBLE_INDEXING_TYPES: { - Butterfly* butterfly = thisObject->m_butterfly; - if (i >= butterfly->vectorLength()) - return true; - butterfly->contiguousDouble()[i] = QNaN; - return true; - } - case ALL_ARRAY_STORAGE_INDEXING_TYPES: { ArrayStorage* storage = thisObject->m_butterfly->arrayStorage(); @@ -1448,10 +1058,8 @@ void JSObject::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNa // which almost certainly means a different structure for PropertyNameArray. switch (object->structure()->indexingType()) { case ALL_BLANK_INDEXING_TYPES: - case ALL_UNDECIDED_INDEXING_TYPES: break; - case ALL_INT32_INDEXING_TYPES: case ALL_CONTIGUOUS_INDEXING_TYPES: { Butterfly* butterfly = object->m_butterfly; unsigned usedLength = butterfly->publicLength(); @@ -1463,18 +1071,6 @@ void JSObject::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNa break; } - case ALL_DOUBLE_INDEXING_TYPES: { - Butterfly* butterfly = object->m_butterfly; - unsigned usedLength = butterfly->publicLength(); - for (unsigned i = 0; i < usedLength; ++i) { - double value = butterfly->contiguousDouble()[i]; - if (value != value) - continue; - propertyNames.add(Identifier::from(exec, i)); - } - break; - } - case ALL_ARRAY_STORAGE_INDEXING_TYPES: { ArrayStorage* storage = object->m_butterfly->arrayStorage(); @@ -1864,10 +1460,9 @@ bool JSObject::attemptToInterceptPutByIndexOnHole(ExecState* exec, unsigned i, J return asObject(prototypeValue)->attemptToInterceptPutByIndexOnHoleForPrototype(exec, this, i, value, shouldThrow); } -template<IndexingType indexingShape> -void JSObject::putByIndexBeyondVectorLengthWithoutAttributes(ExecState* exec, unsigned i, JSValue value) +void JSObject::putByIndexBeyondVectorLengthContiguousWithoutAttributes(ExecState* exec, unsigned i, JSValue value) { - ASSERT((structure()->indexingType() & IndexingShapeMask) == indexingShape); + ASSERT(hasContiguous(structure()->indexingType())); ASSERT(!indexingShouldBeSparse()); // For us to get here, the index is either greater than the public length, or greater than @@ -1878,9 +1473,9 @@ void JSObject::putByIndexBeyondVectorLengthWithoutAttributes(ExecState* exec, un if (i >= MAX_ARRAY_INDEX - 1 || (i >= MIN_SPARSE_ARRAY_INDEX - && !isDenseEnoughForVector(i, countElements<indexingShape>(m_butterfly)))) { + && !isDenseEnoughForVector(i, countElementsInContiguous(m_butterfly)))) { ASSERT(i <= MAX_ARRAY_INDEX); - ensureArrayStorageSlow(globalData); + convertContiguousToArrayStorage(globalData, AllocateArrayStorage); SparseArrayValueMap* map = allocateSparseIndexMap(globalData); map->putEntry(exec, this, i, value, false); ASSERT(i >= arrayStorage()->length()); @@ -1888,30 +1483,10 @@ void JSObject::putByIndexBeyondVectorLengthWithoutAttributes(ExecState* exec, un return; } - ensureLength(globalData, i + 1); + ensureContiguousLength(globalData, i + 1); ASSERT(i < m_butterfly->vectorLength()); - switch (indexingShape) { - case Int32Shape: - ASSERT(value.isInt32()); - m_butterfly->contiguousInt32()[i].setWithoutWriteBarrier(value); - break; - - case DoubleShape: { - ASSERT(value.isNumber()); - double valueAsDouble = value.asNumber(); - ASSERT(valueAsDouble == valueAsDouble); - m_butterfly->contiguousDouble()[i] = valueAsDouble; - break; - } - - case ContiguousShape: - m_butterfly->contiguous()[i].set(globalData, this, value); - break; - - default: - CRASH(); - } + m_butterfly->contiguous()[i].set(globalData, this, value); } void JSObject::putByIndexBeyondVectorLengthWithArrayStorage(ExecState* exec, unsigned i, JSValue value, bool shouldThrow, ArrayStorage* storage) @@ -2017,23 +1592,8 @@ void JSObject::putByIndexBeyondVectorLength(ExecState* exec, unsigned i, JSValue break; } - case ALL_UNDECIDED_INDEXING_TYPES: { - CRASH(); - break; - } - - case ALL_INT32_INDEXING_TYPES: { - putByIndexBeyondVectorLengthWithoutAttributes<Int32Shape>(exec, i, value); - break; - } - - case ALL_DOUBLE_INDEXING_TYPES: { - putByIndexBeyondVectorLengthWithoutAttributes<DoubleShape>(exec, i, value); - break; - } - case ALL_CONTIGUOUS_INDEXING_TYPES: { - putByIndexBeyondVectorLengthWithoutAttributes<ContiguousShape>(exec, i, value); + putByIndexBeyondVectorLengthContiguousWithoutAttributes(exec, i, value); break; } @@ -2164,49 +1724,12 @@ bool JSObject::putDirectIndexBeyondVectorLength(ExecState* exec, unsigned i, JSV return true; } - case ALL_UNDECIDED_INDEXING_TYPES: { - convertUndecidedForValue(exec->globalData(), value); - // Reloop. - return putDirectIndex(exec, i, value, attributes, mode); - } - - case ALL_INT32_INDEXING_TYPES: { - if (attributes & (ReadOnly | Accessor)) { - return putDirectIndexBeyondVectorLengthWithArrayStorage( - exec, i, value, attributes, mode, convertInt32ToArrayStorage(globalData)); - } - if (!value.isInt32()) { - convertInt32ForValue(globalData, value); - return putDirectIndexBeyondVectorLength(exec, i, value, attributes, mode); - } - putByIndexBeyondVectorLengthWithoutAttributes<Int32Shape>(exec, i, value); - return true; - } - - case ALL_DOUBLE_INDEXING_TYPES: { - if (attributes & (ReadOnly | Accessor)) { - return putDirectIndexBeyondVectorLengthWithArrayStorage( - exec, i, value, attributes, mode, convertDoubleToArrayStorage(globalData)); - } - if (!value.isNumber()) { - convertDoubleToContiguous(globalData); - return putDirectIndexBeyondVectorLength(exec, i, value, attributes, mode); - } - double valueAsDouble = value.asNumber(); - if (valueAsDouble != valueAsDouble) { - convertDoubleToContiguous(globalData); - return putDirectIndexBeyondVectorLength(exec, i, value, attributes, mode); - } - putByIndexBeyondVectorLengthWithoutAttributes<DoubleShape>(exec, i, value); - return true; - } - case ALL_CONTIGUOUS_INDEXING_TYPES: { if (attributes & (ReadOnly | Accessor)) { return putDirectIndexBeyondVectorLengthWithArrayStorage( exec, i, value, attributes, mode, convertContiguousToArrayStorage(globalData)); } - putByIndexBeyondVectorLengthWithoutAttributes<ContiguousShape>(exec, i, value); + putByIndexBeyondVectorLengthContiguousWithoutAttributes(exec, i, value); return true; } @@ -2246,65 +1769,33 @@ ALWAYS_INLINE unsigned JSObject::getNewVectorLength(unsigned desiredLength) unsigned vectorLength; unsigned length; - if (hasIndexedProperties(structure()->indexingType())) { - vectorLength = m_butterfly->vectorLength(); - length = m_butterfly->publicLength(); - } else { + switch (structure()->indexingType()) { + case ALL_BLANK_INDEXING_TYPES: vectorLength = 0; length = 0; + break; + case ALL_CONTIGUOUS_INDEXING_TYPES: + case ALL_ARRAY_STORAGE_INDEXING_TYPES: + vectorLength = m_butterfly->vectorLength(); + length = m_butterfly->publicLength(); + break; + default: + CRASH(); + return 0; } - return getNewVectorLength(vectorLength, length, desiredLength); } -template<IndexingType indexingShape> -unsigned JSObject::countElements(Butterfly* butterfly) +unsigned JSObject::countElementsInContiguous(Butterfly* butterfly) { unsigned numValues = 0; for (unsigned i = butterfly->publicLength(); i--;) { - switch (indexingShape) { - case Int32Shape: - case ContiguousShape: - if (butterfly->contiguous()[i]) - numValues++; - break; - - case DoubleShape: { - double value = butterfly->contiguousDouble()[i]; - if (value == value) - numValues++; - break; - } - - default: - CRASH(); - } + if (butterfly->contiguous()[i]) + numValues++; } return numValues; } -unsigned JSObject::countElements() -{ - switch (structure()->indexingType()) { - case ALL_BLANK_INDEXING_TYPES: - case ALL_UNDECIDED_INDEXING_TYPES: - return 0; - - case ALL_INT32_INDEXING_TYPES: - return countElements<Int32Shape>(m_butterfly); - - case ALL_DOUBLE_INDEXING_TYPES: - return countElements<DoubleShape>(m_butterfly); - - case ALL_CONTIGUOUS_INDEXING_TYPES: - return countElements<ContiguousShape>(m_butterfly); - - default: - CRASH(); - return 0; - } -} - bool JSObject::increaseVectorLength(JSGlobalData& globalData, unsigned newLength) { // This function leaves the array in an internally inconsistent state, because it does not move any values from sparse value map @@ -2348,24 +1839,19 @@ bool JSObject::increaseVectorLength(JSGlobalData& globalData, unsigned newLength return true; } -void JSObject::ensureLengthSlow(JSGlobalData& globalData, unsigned length) +void JSObject::ensureContiguousLengthSlow(JSGlobalData& globalData, unsigned length) { ASSERT(length < MAX_ARRAY_INDEX); - ASSERT(hasContiguous(structure()->indexingType()) || hasInt32(structure()->indexingType()) || hasDouble(structure()->indexingType()) || hasUndecided(structure()->indexingType())); + ASSERT(hasContiguous(structure()->indexingType())); ASSERT(length > m_butterfly->vectorLength()); unsigned newVectorLength = std::min( length << 1, MAX_STORAGE_VECTOR_LENGTH); - unsigned oldVectorLength = m_butterfly->vectorLength(); m_butterfly = m_butterfly->growArrayRight( globalData, structure(), structure()->outOfLineCapacity(), true, - oldVectorLength * sizeof(EncodedJSValue), + m_butterfly->vectorLength() * sizeof(EncodedJSValue), newVectorLength * sizeof(EncodedJSValue)); - if (hasDouble(structure()->indexingType())) { - for (unsigned i = oldVectorLength; i < newVectorLength; ++i) - m_butterfly->contiguousDouble()[i] = QNaN; - } m_butterfly->setVectorLength(newVectorLength); } @@ -2395,10 +1881,8 @@ bool JSObject::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, Prope switch (object->structure()->indexingType()) { case ALL_BLANK_INDEXING_TYPES: - case ALL_UNDECIDED_INDEXING_TYPES: return false; - case ALL_INT32_INDEXING_TYPES: case ALL_CONTIGUOUS_INDEXING_TYPES: { Butterfly* butterfly = object->m_butterfly; if (i >= butterfly->vectorLength()) @@ -2410,17 +1894,6 @@ bool JSObject::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, Prope return true; } - case ALL_DOUBLE_INDEXING_TYPES: { - Butterfly* butterfly = object->m_butterfly; - if (i >= butterfly->vectorLength()) - return false; - double value = butterfly->contiguousDouble()[i]; - if (value != value) - return false; - descriptor.setDescriptor(JSValue(JSValue::EncodeAsDouble, value), 0); - return true; - } - case ALL_ARRAY_STORAGE_INDEXING_TYPES: { ArrayStorage* storage = object->m_butterfly->arrayStorage(); if (i >= storage->length()) |