+ JSValue getIndexQuickly(unsigned i)
+ {
+ switch (indexingType()) {
+ case ALL_INT32_INDEXING_TYPES:
+ return jsNumber(m_butterfly->contiguous()[i].get().asInt32());
+ case ALL_CONTIGUOUS_INDEXING_TYPES:
+ return m_butterfly->contiguous()[i].get();
+ case ALL_DOUBLE_INDEXING_TYPES:
+ return JSValue(JSValue::EncodeAsDouble, m_butterfly->contiguousDouble()[i]);
+ case ALL_ARRAY_STORAGE_INDEXING_TYPES:
+ return m_butterfly->arrayStorage()->m_vector[i].get();
+ default:
+ RELEASE_ASSERT_NOT_REACHED();
+ return JSValue();
+ }
+ }
+
+ JSValue tryGetIndexQuickly(unsigned i)
+ {
+ switch (indexingType()) {
+ case ALL_BLANK_INDEXING_TYPES:
+ case ALL_UNDECIDED_INDEXING_TYPES:
+ break;
+ case ALL_INT32_INDEXING_TYPES:
+ if (i < m_butterfly->publicLength()) {
+ JSValue result = m_butterfly->contiguous()[i].get();
+ ASSERT(result.isInt32() || !result);
+ return result;
+ }
+ break;
+ case ALL_CONTIGUOUS_INDEXING_TYPES:
+ if (i < m_butterfly->publicLength())
+ return m_butterfly->contiguous()[i].get();
+ break;
+ case ALL_DOUBLE_INDEXING_TYPES: {
+ if (i >= m_butterfly->publicLength())
+ break;
+ double result = m_butterfly->contiguousDouble()[i];
+ if (result != result)
+ break;
+ return JSValue(JSValue::EncodeAsDouble, result);
+ }
+ case ALL_ARRAY_STORAGE_INDEXING_TYPES:
+ if (i < m_butterfly->arrayStorage()->vectorLength())
+ return m_butterfly->arrayStorage()->m_vector[i].get();
+ break;
+ default:
+ RELEASE_ASSERT_NOT_REACHED();
+ break;
+ }
+ return JSValue();
+ }
+
+ JSValue getDirectIndex(ExecState* exec, unsigned i)
+ {
+ if (JSValue result = tryGetIndexQuickly(i))
+ return result;
+ PropertySlot slot(this);
+ if (methodTable(exec->vm())->getOwnPropertySlotByIndex(this, exec, i, slot))
+ return slot.getValue(exec, i);
+ return JSValue();
+ }
+
+ JSValue getIndex(ExecState* exec, unsigned i)
+ {
+ if (JSValue result = tryGetIndexQuickly(i))
+ return result;
+ return get(exec, i);
+ }
+
+ bool canSetIndexQuickly(unsigned i)
+ {
+ switch (indexingType()) {
+ case ALL_BLANK_INDEXING_TYPES:
+ case ALL_UNDECIDED_INDEXING_TYPES:
+ return false;
+ case ALL_INT32_INDEXING_TYPES:
+ case ALL_DOUBLE_INDEXING_TYPES:
+ case ALL_CONTIGUOUS_INDEXING_TYPES:
+ case NonArrayWithArrayStorage:
+ case ArrayWithArrayStorage:
+ return i < m_butterfly->vectorLength();
+ case NonArrayWithSlowPutArrayStorage:
+ case ArrayWithSlowPutArrayStorage:
+ return i < m_butterfly->arrayStorage()->vectorLength()
+ && !!m_butterfly->arrayStorage()->m_vector[i];
+ default:
+ RELEASE_ASSERT_NOT_REACHED();
+ return false;
+ }
+ }
+
+ bool canSetIndexQuicklyForPutDirect(unsigned i)
+ {
+ switch (indexingType()) {
+ case ALL_BLANK_INDEXING_TYPES:
+ case ALL_UNDECIDED_INDEXING_TYPES:
+ return false;
+ case ALL_INT32_INDEXING_TYPES:
+ case ALL_DOUBLE_INDEXING_TYPES:
+ case ALL_CONTIGUOUS_INDEXING_TYPES:
+ case ALL_ARRAY_STORAGE_INDEXING_TYPES:
+ return i < m_butterfly->vectorLength();
+ default:
+ RELEASE_ASSERT_NOT_REACHED();
+ return false;
+ }
+ }
+
+ void setIndexQuickly(VM& vm, unsigned i, JSValue v)
+ {
+ switch (indexingType()) {
+ case ALL_INT32_INDEXING_TYPES: {
+ ASSERT(i < m_butterfly->vectorLength());
+ if (!v.isInt32()) {
+ convertInt32ToDoubleOrContiguousWhilePerformingSetIndex(vm, i, v);
+ return;
+ }
+ FALLTHROUGH;
+ }
+ case ALL_CONTIGUOUS_INDEXING_TYPES: {
+ ASSERT(i < m_butterfly->vectorLength());
+ m_butterfly->contiguous()[i].set(vm, this, v);
+ if (i >= m_butterfly->publicLength())
+ m_butterfly->setPublicLength(i + 1);
+ break;
+ }
+ case ALL_DOUBLE_INDEXING_TYPES: {
+ ASSERT(i < m_butterfly->vectorLength());
+ if (!v.isNumber()) {
+ convertDoubleToContiguousWhilePerformingSetIndex(vm, i, v);
+ return;
+ }
+ double value = v.asNumber();
+ if (value != value) {
+ convertDoubleToContiguousWhilePerformingSetIndex(vm, i, v);
+ return;
+ }
+ m_butterfly->contiguousDouble()[i] = value;
+ if (i >= m_butterfly->publicLength())
+ m_butterfly->setPublicLength(i + 1);
+ break;
+ }
+ case ALL_ARRAY_STORAGE_INDEXING_TYPES: {
+ ArrayStorage* storage = m_butterfly->arrayStorage();
+ WriteBarrier<Unknown>& x = storage->m_vector[i];
+ JSValue old = x.get();
+ x.set(vm, this, v);
+ if (!old) {
+ ++storage->m_numValuesInVector;
+ if (i >= storage->length())
+ storage->setLength(i + 1);
+ }
+ break;
+ }
+ default:
+ RELEASE_ASSERT_NOT_REACHED();
+ }
+ }