Force debug builds to do bounds checks on contiguous property storage
authoroliver@apple.com <oliver@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 29 Jan 2013 21:11:11 +0000 (21:11 +0000)
committeroliver@apple.com <oliver@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 29 Jan 2013 21:11:11 +0000 (21:11 +0000)
https://bugs.webkit.org/show_bug.cgi?id=108212

Reviewed by Mark Hahnenberg.

Add a ContiguousData type that we use to represent contiguous property
storage.  In release builds it is simply a pointer to the correct type,
but in debug builds it also carries the data length and performs bounds
checks.  This means we don't have to add as many manual bounds assertions
when performing operations over contiguous data.

* dfg/DFGOperations.cpp:
* runtime/ArrayStorage.h:
(ArrayStorage):
(JSC::ArrayStorage::vector):
* runtime/Butterfly.h:
(JSC::ContiguousData::ContiguousData):
(ContiguousData):
(JSC::ContiguousData::operator[]):
(JSC::ContiguousData::data):
(JSC::ContiguousData::length):
(JSC):
(JSC::Butterfly::contiguousInt32):
(Butterfly):
(JSC::Butterfly::contiguousDouble):
(JSC::Butterfly::contiguous):
* runtime/JSArray.cpp:
(JSC::JSArray::sortNumericVector):
(ContiguousTypeAccessor):
(JSC::ContiguousTypeAccessor::getAsValue):
(JSC::ContiguousTypeAccessor::setWithValue):
(JSC::ContiguousTypeAccessor::replaceDataReference):
(JSC):
(JSC::JSArray::sortCompactedVector):
(JSC::JSArray::sort):
(JSC::JSArray::fillArgList):
(JSC::JSArray::copyToArguments):
* runtime/JSArray.h:
(JSArray):
* runtime/JSObject.cpp:
(JSC::JSObject::copyButterfly):
(JSC::JSObject::visitButterfly):
(JSC::JSObject::createInitialInt32):
(JSC::JSObject::createInitialDouble):
(JSC::JSObject::createInitialContiguous):
(JSC::JSObject::convertUndecidedToInt32):
(JSC::JSObject::convertUndecidedToDouble):
(JSC::JSObject::convertUndecidedToContiguous):
(JSC::JSObject::convertInt32ToDouble):
(JSC::JSObject::convertInt32ToContiguous):
(JSC::JSObject::genericConvertDoubleToContiguous):
(JSC::JSObject::convertDoubleToContiguous):
(JSC::JSObject::rageConvertDoubleToContiguous):
(JSC::JSObject::ensureInt32Slow):
(JSC::JSObject::ensureDoubleSlow):
(JSC::JSObject::ensureContiguousSlow):
(JSC::JSObject::rageEnsureContiguousSlow):
(JSC::JSObject::ensureLengthSlow):
* runtime/JSObject.h:
(JSC::JSObject::ensureInt32):
(JSC::JSObject::ensureDouble):
(JSC::JSObject::ensureContiguous):
(JSC::JSObject::rageEnsureContiguous):
(JSObject):
(JSC::JSObject::indexingData):
(JSC::JSObject::currentIndexingData):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@141154 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/dfg/DFGOperations.cpp
Source/JavaScriptCore/runtime/ArrayStorage.h
Source/JavaScriptCore/runtime/Butterfly.h
Source/JavaScriptCore/runtime/JSArray.cpp
Source/JavaScriptCore/runtime/JSArray.h
Source/JavaScriptCore/runtime/JSObject.cpp
Source/JavaScriptCore/runtime/JSObject.h

index 0a19be5..989d161 100644 (file)
@@ -1,3 +1,72 @@
+2013-01-29  Oliver Hunt  <oliver@apple.com>
+
+        Force debug builds to do bounds checks on contiguous property storage
+        https://bugs.webkit.org/show_bug.cgi?id=108212
+
+        Reviewed by Mark Hahnenberg.
+
+        Add a ContiguousData type that we use to represent contiguous property
+        storage.  In release builds it is simply a pointer to the correct type,
+        but in debug builds it also carries the data length and performs bounds
+        checks.  This means we don't have to add as many manual bounds assertions
+        when performing operations over contiguous data.
+
+        * dfg/DFGOperations.cpp:
+        * runtime/ArrayStorage.h:
+        (ArrayStorage):
+        (JSC::ArrayStorage::vector):
+        * runtime/Butterfly.h:
+        (JSC::ContiguousData::ContiguousData):
+        (ContiguousData):
+        (JSC::ContiguousData::operator[]):
+        (JSC::ContiguousData::data):
+        (JSC::ContiguousData::length):
+        (JSC):
+        (JSC::Butterfly::contiguousInt32):
+        (Butterfly):
+        (JSC::Butterfly::contiguousDouble):
+        (JSC::Butterfly::contiguous):
+        * runtime/JSArray.cpp:
+        (JSC::JSArray::sortNumericVector):
+        (ContiguousTypeAccessor):
+        (JSC::ContiguousTypeAccessor::getAsValue):
+        (JSC::ContiguousTypeAccessor::setWithValue):
+        (JSC::ContiguousTypeAccessor::replaceDataReference):
+        (JSC):
+        (JSC::JSArray::sortCompactedVector):
+        (JSC::JSArray::sort):
+        (JSC::JSArray::fillArgList):
+        (JSC::JSArray::copyToArguments):
+        * runtime/JSArray.h:
+        (JSArray):
+        * runtime/JSObject.cpp:
+        (JSC::JSObject::copyButterfly):
+        (JSC::JSObject::visitButterfly):
+        (JSC::JSObject::createInitialInt32):
+        (JSC::JSObject::createInitialDouble):
+        (JSC::JSObject::createInitialContiguous):
+        (JSC::JSObject::convertUndecidedToInt32):
+        (JSC::JSObject::convertUndecidedToDouble):
+        (JSC::JSObject::convertUndecidedToContiguous):
+        (JSC::JSObject::convertInt32ToDouble):
+        (JSC::JSObject::convertInt32ToContiguous):
+        (JSC::JSObject::genericConvertDoubleToContiguous):
+        (JSC::JSObject::convertDoubleToContiguous):
+        (JSC::JSObject::rageConvertDoubleToContiguous):
+        (JSC::JSObject::ensureInt32Slow):
+        (JSC::JSObject::ensureDoubleSlow):
+        (JSC::JSObject::ensureContiguousSlow):
+        (JSC::JSObject::rageEnsureContiguousSlow):
+        (JSC::JSObject::ensureLengthSlow):
+        * runtime/JSObject.h:
+        (JSC::JSObject::ensureInt32):
+        (JSC::JSObject::ensureDouble):
+        (JSC::JSObject::ensureContiguous):
+        (JSC::JSObject::rageEnsureContiguous):
+        (JSObject):
+        (JSC::JSObject::indexingData):
+        (JSC::JSObject::currentIndexingData):
+
 2013-01-29  Brent Fulgham  <bfulgham@webkit.org>
 
         [Windows, WinCairo] Unreviewed build fix after r141050
index be0ce25..34bb04f 100644 (file)
@@ -1492,7 +1492,7 @@ char* DFG_OPERATION operationEnsureInt32(ExecState* exec, JSCell* cell)
     if (!cell->isObject())
         return 0;
     
-    return reinterpret_cast<char*>(asObject(cell)->ensureInt32(globalData));
+    return reinterpret_cast<char*>(asObject(cell)->ensureInt32(globalData).data());
 }
 
 char* DFG_OPERATION operationEnsureDouble(ExecState* exec, JSCell* cell)
@@ -1503,7 +1503,7 @@ char* DFG_OPERATION operationEnsureDouble(ExecState* exec, JSCell* cell)
     if (!cell->isObject())
         return 0;
     
-    return reinterpret_cast<char*>(asObject(cell)->ensureDouble(globalData));
+    return reinterpret_cast<char*>(asObject(cell)->ensureDouble(globalData).data());
 }
 
 char* DFG_OPERATION operationEnsureContiguous(ExecState* exec, JSCell* cell)
@@ -1514,7 +1514,7 @@ char* DFG_OPERATION operationEnsureContiguous(ExecState* exec, JSCell* cell)
     if (!cell->isObject())
         return 0;
     
-    return reinterpret_cast<char*>(asObject(cell)->ensureContiguous(globalData));
+    return reinterpret_cast<char*>(asObject(cell)->ensureContiguous(globalData).data());
 }
 
 char* DFG_OPERATION operationRageEnsureContiguous(ExecState* exec, JSCell* cell)
@@ -1525,7 +1525,7 @@ char* DFG_OPERATION operationRageEnsureContiguous(ExecState* exec, JSCell* cell)
     if (!cell->isObject())
         return 0;
     
-    return reinterpret_cast<char*>(asObject(cell)->rageEnsureContiguous(globalData));
+    return reinterpret_cast<char*>(asObject(cell)->rageEnsureContiguous(globalData).data());
 }
 
 char* DFG_OPERATION operationEnsureArrayStorage(ExecState* exec, JSCell* cell)
index ffd84b2..c2a2d8a 100644 (file)
@@ -72,7 +72,9 @@ public:
     {
         return m_sparseMap && m_sparseMap->sparseMode();
     }
-    
+
+    ContiguousJSValues vector() { return ContiguousJSValues(m_vector, vectorLength()); }
+
     WriteBarrier<SparseArrayValueMap> m_sparseMap;
     unsigned m_indexBias;
     unsigned m_numValuesInVector;
index bbbda94..1327732 100644 (file)
@@ -38,6 +38,41 @@ class JSGlobalData;
 class CopyVisitor;
 struct ArrayStorage;
 
+template <typename T> struct ContiguousData {
+    ContiguousData()
+        : m_data(0)
+#if !ASSERT_DISABLED
+        , m_length(0)
+#endif
+    {
+    }
+    ContiguousData(T* data, size_t length)
+        : m_data(data)
+#if !ASSERT_DISABLED
+        , m_length(length)
+#endif
+    {
+        UNUSED_PARAM(length);
+    }
+
+    const T& operator[](size_t index) const { ASSERT(index < m_length); return m_data[index]; }
+    T& operator[](size_t index) { ASSERT(index < m_length); return m_data[index]; }
+
+    T* data() const { return m_data; }
+#if !ASSERT_DISABLED
+    size_t length() const { return m_length; }
+#endif
+
+private:
+    T* m_data;
+#if !ASSERT_DISABLED
+    size_t m_length;
+#endif
+};
+
+typedef ContiguousData<double> ContiguousDoubles;
+typedef ContiguousData<WriteBarrier<Unknown> > ContiguousJSValues;
+
 class Butterfly {
     WTF_MAKE_NONCOPYABLE(Butterfly);
 private:
@@ -88,9 +123,10 @@ public:
     template<typename T>
     T* indexingPayload() { return reinterpret_cast<T*>(this); }
     ArrayStorage* arrayStorage() { return indexingPayload<ArrayStorage>(); }
-    WriteBarrier<Unknown>* contiguousInt32() { return indexingPayload<WriteBarrier<Unknown> >(); }
-    double* contiguousDouble() { return indexingPayload<double>(); }
-    WriteBarrier<Unknown>* contiguous() { return indexingPayload<WriteBarrier<Unknown> >(); }
+    ContiguousJSValues contiguousInt32() { return ContiguousJSValues(indexingPayload<WriteBarrier<Unknown> >(), vectorLength()); }
+
+    ContiguousDoubles contiguousDouble() { return ContiguousDoubles(indexingPayload<double>(), vectorLength()); }
+    ContiguousJSValues contiguous() { return ContiguousJSValues(indexingPayload<WriteBarrier<Unknown> >(), vectorLength()); }
     
     static Butterfly* fromContiguous(WriteBarrier<Unknown>* contiguous)
     {
index 4896ff2..cf32e6b 100644 (file)
@@ -979,7 +979,7 @@ void JSArray::sortNumericVector(ExecState* exec, JSValue compareFunction, CallTy
         lengthNotIncludingUndefined,
         newRelevantLength);
     
-    WriteBarrier<Unknown>* data = indexingData<indexingType>();
+    ContiguousJSValues data = indexingData<indexingType>();
     
     if (indexingType == ArrayWithArrayStorage && arrayStorage()->m_sparseMap.get()) {
         throwOutOfMemoryError(exec);
@@ -1026,8 +1026,8 @@ void JSArray::sortNumericVector(ExecState* exec, JSValue compareFunction, CallTy
         compare = compareNumbersForQSort;
         break;
     }
-    
-    qsort(data, newRelevantLength, sizeof(WriteBarrier<Unknown>), compare);
+    ASSERT(data.length() >= newRelevantLength);
+    qsort(data.data(), newRelevantLength, sizeof(WriteBarrier<Unknown>), compare);
     return;
 }
 
@@ -1061,8 +1061,35 @@ void JSArray::sortNumeric(ExecState* exec, JSValue compareFunction, CallType cal
     }
 }
 
-template<IndexingType indexingType>
-void JSArray::sortCompactedVector(ExecState* exec, void* begin, unsigned relevantLength)
+template <IndexingType> struct ContiguousTypeAccessor {
+    typedef WriteBarrier<Unknown> Type;
+    static JSValue getAsValue(ContiguousData<Type> data, size_t i) { return data[i].get(); }
+    static void setWithValue(JSGlobalData& globalData, JSArray* thisValue, ContiguousData<Type> data, size_t i, JSValue value)
+    {
+        data[i].set(globalData, thisValue, value);
+    }
+    static void replaceDataReference(ContiguousData<Type>* outData, ContiguousJSValues inData)
+    {
+        *outData = inData;
+    }
+};
+
+template <> struct ContiguousTypeAccessor<ArrayWithDouble> {
+    typedef double Type;
+    static JSValue getAsValue(ContiguousData<Type> data, size_t i) { ASSERT(data[i] == data[i]); return JSValue(JSValue::EncodeAsDouble, data[i]); }
+    static void setWithValue(JSGlobalData&, JSArray*, ContiguousData<Type> data, size_t i, JSValue value)
+    {
+        data[i] = value.asNumber();
+    }
+    static NO_RETURN_DUE_TO_CRASH void replaceDataReference(ContiguousData<Type>*, ContiguousJSValues)
+    {
+        RELEASE_ASSERT_WITH_MESSAGE(0, "Inconsistent indexing types during compact array sort.");
+    }
+};
+
+
+template<IndexingType indexingType, typename StorageType>
+void JSArray::sortCompactedVector(ExecState* exec, ContiguousData<StorageType> data, unsigned relevantLength)
 {
     if (!relevantLength)
         return;
@@ -1083,31 +1110,14 @@ void JSArray::sortCompactedVector(ExecState* exec, void* begin, unsigned relevan
     Heap::heap(this)->pushTempSortVector(&values);
         
     bool isSortingPrimitiveValues = true;
-    switch (indexingType) {
-    case ArrayWithInt32:
-        for (size_t i = 0; i < relevantLength; i++) {
-            JSValue value = static_cast<WriteBarrier<Unknown>*>(begin)[i].get();
-            ASSERT(value.isInt32());
-            values[i].first = value;
-        }
-        break;
-        
-    case ArrayWithDouble:
-        for (size_t i = 0; i < relevantLength; i++) {
-            double value = static_cast<double*>(begin)[i];
-            ASSERT(value == value);
-            values[i].first = JSValue(JSValue::EncodeAsDouble, value);
-        }
-        break;
-        
-    default:
-        for (size_t i = 0; i < relevantLength; i++) {
-            JSValue value = static_cast<WriteBarrier<Unknown>*>(begin)[i].get();
-            ASSERT(!value.isUndefined());
-            values[i].first = value;
+
+    for (size_t i = 0; i < relevantLength; i++) {
+        JSValue value = ContiguousTypeAccessor<indexingType>::getAsValue(data, i);
+        ASSERT(indexingType != ArrayWithInt32 || value.isInt32());
+        ASSERT(!value.isUndefined());
+        values[i].first = value;
+        if (indexingType != ArrayWithDouble && indexingType != ArrayWithInt32)
             isSortingPrimitiveValues = isSortingPrimitiveValues && value.isPrimitive();
-        }
-        break;
     }
         
     // FIXME: The following loop continues to call toString on subsequent values even after
@@ -1147,7 +1157,7 @@ void JSArray::sortCompactedVector(ExecState* exec, void* begin, unsigned relevan
     case ArrayWithArrayStorage:
         if (arrayStorage()->vectorLength() < relevantLength) {
             increaseVectorLength(exec->globalData(), relevantLength);
-            begin = arrayStorage()->m_vector;
+            ContiguousTypeAccessor<indexingType>::replaceDataReference(&data, arrayStorage()->vector());
         }
         if (arrayStorage()->length() < relevantLength)
             arrayStorage()->setLength(relevantLength);
@@ -1157,12 +1167,8 @@ void JSArray::sortCompactedVector(ExecState* exec, void* begin, unsigned relevan
         CRASH();
     }
 
-    for (size_t i = 0; i < relevantLength; i++) {
-        if (indexingType == ArrayWithDouble)
-            static_cast<double*>(begin)[i] = values[i].first.asNumber();
-        else
-            static_cast<WriteBarrier<Unknown>*>(begin)[i].set(globalData, this, values[i].first);
-    }
+    for (size_t i = 0; i < relevantLength; i++)
+        ContiguousTypeAccessor<indexingType>::setWithValue(globalData, this, data, i, values[i].first);
     
     Heap::heap(this)->popTempSortVector(&values);
 }
@@ -1217,8 +1223,7 @@ void JSArray::sort(ExecState* exec)
         ArrayStorage* storage = m_butterfly->arrayStorage();
         ASSERT(!storage->m_sparseMap);
         
-        sortCompactedVector<ArrayWithArrayStorage>(
-            exec, storage->m_vector, lengthNotIncludingUndefined);
+        sortCompactedVector<ArrayWithArrayStorage>(exec, storage->vector(), lengthNotIncludingUndefined);
         return;
     }
         
@@ -1467,7 +1472,7 @@ void JSArray::fillArgList(ExecState* exec, MarkedArgumentBuffer& args)
     case ArrayWithInt32:
     case ArrayWithContiguous: {
         vectorEnd = m_butterfly->publicLength();
-        vector = m_butterfly->contiguous();
+        vector = m_butterfly->contiguous().data();
         break;
     }
         
@@ -1528,7 +1533,7 @@ void JSArray::copyToArguments(ExecState* exec, CallFrame* callFrame, uint32_t le
         
     case ArrayWithInt32:
     case ArrayWithContiguous: {
-        vector = m_butterfly->contiguous();
+        vector = m_butterfly->contiguous().data();
         vectorEnd = m_butterfly->publicLength();
         break;
     }
index 68a07f1..5719002 100644 (file)
@@ -161,8 +161,8 @@ private:
     template<IndexingType indexingType>
     void sortNumericVector(ExecState*, JSValue compareFunction, CallType, const CallData&);
         
-    template<IndexingType indexingType>
-    void sortCompactedVector(ExecState*, void* begin, unsigned relevantLength);
+    template<IndexingType indexingType, typename StorageType>
+    void sortCompactedVector(ExecState*, ContiguousData<StorageType>, unsigned relevantLength);
         
     template<IndexingType indexingType>
     void sortVector(ExecState*, JSValue compareFunction, CallType, const CallData&);
index c92a822..78ba279 100644 (file)
@@ -133,8 +133,8 @@ ALWAYS_INLINE void JSObject::copyButterfly(CopyVisitor& visitor, Butterfly* butt
             case ALL_CONTIGUOUS_INDEXING_TYPES:
             case ALL_INT32_INDEXING_TYPES:
             case ALL_DOUBLE_INDEXING_TYPES: {
-                currentTarget = newButterfly->contiguous();
-                currentSource = butterfly->contiguous();
+                currentTarget = newButterfly->contiguous().data();
+                currentSource = butterfly->contiguous().data();
                 RELEASE_ASSERT(newButterfly->publicLength() <= newButterfly->vectorLength());
                 count = newButterfly->vectorLength();
                 break;
@@ -189,7 +189,7 @@ ALWAYS_INLINE void JSObject::visitButterfly(SlotVisitor& visitor, Butterfly* but
     // Mark the array if appropriate.
     switch (structure->indexingType()) {
     case ALL_CONTIGUOUS_INDEXING_TYPES:
-        visitor.appendValues(butterfly->contiguous(), butterfly->publicLength());
+        visitor.appendValues(butterfly->contiguous().data(), butterfly->publicLength());
         break;
     case ALL_ARRAY_STORAGE_INDEXING_TYPES:
         visitor.appendValues(butterfly->arrayStorage()->m_vector, butterfly->arrayStorage()->vectorLength());
@@ -625,7 +625,7 @@ Butterfly* JSObject::createInitialUndecided(JSGlobalData& globalData, unsigned l
     return newButterfly;
 }
 
-WriteBarrier<Unknown>* JSObject::createInitialInt32(JSGlobalData& globalData, unsigned length)
+ContiguousJSValues JSObject::createInitialInt32(JSGlobalData& globalData, unsigned length)
 {
     Butterfly* newButterfly = createInitialIndexedStorage(globalData, length, sizeof(EncodedJSValue));
     Structure* newStructure = Structure::nonPropertyTransition(globalData, structure(), AllocateInt32);
@@ -633,7 +633,7 @@ WriteBarrier<Unknown>* JSObject::createInitialInt32(JSGlobalData& globalData, un
     return newButterfly->contiguousInt32();
 }
 
-double* JSObject::createInitialDouble(JSGlobalData& globalData, unsigned length)
+ContiguousDoubles JSObject::createInitialDouble(JSGlobalData& globalData, unsigned length)
 {
     Butterfly* newButterfly = createInitialIndexedStorage(globalData, length, sizeof(double));
     for (unsigned i = newButterfly->vectorLength(); i--;)
@@ -643,7 +643,7 @@ double* JSObject::createInitialDouble(JSGlobalData& globalData, unsigned length)
     return newButterfly->contiguousDouble();
 }
 
-WriteBarrier<Unknown>* JSObject::createInitialContiguous(JSGlobalData& globalData, unsigned length)
+ContiguousJSValues JSObject::createInitialContiguous(JSGlobalData& globalData, unsigned length)
 {
     Butterfly* newButterfly = createInitialIndexedStorage(globalData, length, sizeof(EncodedJSValue));
     Structure* newStructure = Structure::nonPropertyTransition(globalData, structure(), AllocateContiguous);
@@ -676,14 +676,14 @@ ArrayStorage* JSObject::createInitialArrayStorage(JSGlobalData& globalData)
     return createArrayStorage(globalData, 0, BASE_VECTOR_LEN);
 }
 
-WriteBarrier<Unknown>* JSObject::convertUndecidedToInt32(JSGlobalData& globalData)
+ContiguousJSValues JSObject::convertUndecidedToInt32(JSGlobalData& globalData)
 {
     ASSERT(hasUndecided(structure()->indexingType()));
     setStructure(globalData, Structure::nonPropertyTransition(globalData, structure(), AllocateInt32));
     return m_butterfly->contiguousInt32();
 }
 
-double* JSObject::convertUndecidedToDouble(JSGlobalData& globalData)
+ContiguousDoubles JSObject::convertUndecidedToDouble(JSGlobalData& globalData)
 {
     ASSERT(hasUndecided(structure()->indexingType()));
     
@@ -694,7 +694,7 @@ double* JSObject::convertUndecidedToDouble(JSGlobalData& globalData)
     return m_butterfly->contiguousDouble();
 }
 
-WriteBarrier<Unknown>* JSObject::convertUndecidedToContiguous(JSGlobalData& globalData)
+ContiguousJSValues JSObject::convertUndecidedToContiguous(JSGlobalData& globalData)
 {
     ASSERT(hasUndecided(structure()->indexingType()));
     setStructure(globalData, Structure::nonPropertyTransition(globalData, structure(), AllocateContiguous));
@@ -747,7 +747,7 @@ ArrayStorage* JSObject::convertUndecidedToArrayStorage(JSGlobalData& globalData)
     return convertUndecidedToArrayStorage(globalData, structure()->suggestedArrayStorageTransition());
 }
 
-double* JSObject::convertInt32ToDouble(JSGlobalData& globalData)
+ContiguousDoubles JSObject::convertInt32ToDouble(JSGlobalData& globalData)
 {
     ASSERT(hasInt32(structure()->indexingType()));
     
@@ -767,7 +767,7 @@ double* JSObject::convertInt32ToDouble(JSGlobalData& globalData)
     return m_butterfly->contiguousDouble();
 }
 
-WriteBarrier<Unknown>* JSObject::convertInt32ToContiguous(JSGlobalData& globalData)
+ContiguousJSValues JSObject::convertInt32ToContiguous(JSGlobalData& globalData)
 {
     ASSERT(hasInt32(structure()->indexingType()));
     
@@ -804,7 +804,7 @@ ArrayStorage* JSObject::convertInt32ToArrayStorage(JSGlobalData& globalData)
 }
 
 template<JSObject::DoubleToContiguousMode mode>
-WriteBarrier<Unknown>* JSObject::genericConvertDoubleToContiguous(JSGlobalData& globalData)
+ContiguousJSValues JSObject::genericConvertDoubleToContiguous(JSGlobalData& globalData)
 {
     ASSERT(hasDouble(structure()->indexingType()));
     
@@ -833,12 +833,12 @@ WriteBarrier<Unknown>* JSObject::genericConvertDoubleToContiguous(JSGlobalData&
     return m_butterfly->contiguous();
 }
 
-WriteBarrier<Unknown>* JSObject::convertDoubleToContiguous(JSGlobalData& globalData)
+ContiguousJSValues JSObject::convertDoubleToContiguous(JSGlobalData& globalData)
 {
     return genericConvertDoubleToContiguous<EncodeValueAsDouble>(globalData);
 }
 
-WriteBarrier<Unknown>* JSObject::rageConvertDoubleToContiguous(JSGlobalData& globalData)
+ContiguousJSValues JSObject::rageConvertDoubleToContiguous(JSGlobalData& globalData)
 {
     return genericConvertDoubleToContiguous<RageConvertDoubleToValue>(globalData);
 }
@@ -948,14 +948,14 @@ void JSObject::convertDoubleToContiguousWhilePerformingSetIndex(JSGlobalData& gl
     setIndexQuickly(globalData, index, value);
 }
 
-WriteBarrier<Unknown>* JSObject::ensureInt32Slow(JSGlobalData& globalData)
+ContiguousJSValues JSObject::ensureInt32Slow(JSGlobalData& globalData)
 {
     ASSERT(inherits(&s_info));
     
     switch (structure()->indexingType()) {
     case ALL_BLANK_INDEXING_TYPES:
         if (UNLIKELY(indexingShouldBeSparse() || structure()->needsSlowPutIndexing()))
-            return 0;
+            return ContiguousJSValues();
         return createInitialInt32(globalData, 0);
         
     case ALL_UNDECIDED_INDEXING_TYPES:
@@ -964,22 +964,22 @@ WriteBarrier<Unknown>* JSObject::ensureInt32Slow(JSGlobalData& globalData)
     case ALL_DOUBLE_INDEXING_TYPES:
     case ALL_CONTIGUOUS_INDEXING_TYPES:
     case ALL_ARRAY_STORAGE_INDEXING_TYPES:
-        return 0;
+        return ContiguousJSValues();
         
     default:
         CRASH();
-        return 0;
+        return ContiguousJSValues();
     }
 }
 
-double* JSObject::ensureDoubleSlow(JSGlobalData& globalData)
+ContiguousDoubles JSObject::ensureDoubleSlow(JSGlobalData& globalData)
 {
     ASSERT(inherits(&s_info));
     
     switch (structure()->indexingType()) {
     case ALL_BLANK_INDEXING_TYPES:
         if (UNLIKELY(indexingShouldBeSparse() || structure()->needsSlowPutIndexing()))
-            return 0;
+            return ContiguousDoubles();
         return createInitialDouble(globalData, 0);
         
     case ALL_UNDECIDED_INDEXING_TYPES:
@@ -990,22 +990,22 @@ double* JSObject::ensureDoubleSlow(JSGlobalData& globalData)
         
     case ALL_CONTIGUOUS_INDEXING_TYPES:
     case ALL_ARRAY_STORAGE_INDEXING_TYPES:
-        return 0;
+        return ContiguousDoubles();
         
     default:
         CRASH();
-        return 0;
+        return ContiguousDoubles();
     }
 }
 
-WriteBarrier<Unknown>* JSObject::ensureContiguousSlow(JSGlobalData& globalData, DoubleToContiguousMode mode)
+ContiguousJSValues JSObject::ensureContiguousSlow(JSGlobalData& globalData, DoubleToContiguousMode mode)
 {
     ASSERT(inherits(&s_info));
     
     switch (structure()->indexingType()) {
     case ALL_BLANK_INDEXING_TYPES:
         if (UNLIKELY(indexingShouldBeSparse() || structure()->needsSlowPutIndexing()))
-            return 0;
+            return ContiguousJSValues();
         return createInitialContiguous(globalData, 0);
         
     case ALL_UNDECIDED_INDEXING_TYPES:
@@ -1020,20 +1020,20 @@ WriteBarrier<Unknown>* JSObject::ensureContiguousSlow(JSGlobalData& globalData,
         return convertDoubleToContiguous(globalData);
         
     case ALL_ARRAY_STORAGE_INDEXING_TYPES:
-        return 0;
+        return ContiguousJSValues();
         
     default:
         CRASH();
-        return 0;
+        return ContiguousJSValues();
     }
 }
 
-WriteBarrier<Unknown>* JSObject::ensureContiguousSlow(JSGlobalData& globalData)
+ContiguousJSValues JSObject::ensureContiguousSlow(JSGlobalData& globalData)
 {
     return ensureContiguousSlow(globalData, EncodeValueAsDouble);
 }
 
-WriteBarrier<Unknown>* JSObject::rageEnsureContiguousSlow(JSGlobalData& globalData)
+ContiguousJSValues JSObject::rageEnsureContiguousSlow(JSGlobalData& globalData)
 {
     return ensureContiguousSlow(globalData, RageConvertDoubleToValue);
 }
@@ -2347,7 +2347,7 @@ void JSObject::ensureLengthSlow(JSGlobalData& globalData, unsigned length)
         newVectorLength * sizeof(EncodedJSValue));
     if (hasDouble(structure()->indexingType())) {
         for (unsigned i = oldVectorLength; i < newVectorLength; ++i)
-            m_butterfly->contiguousDouble()[i] = QNaN;
+            m_butterfly->contiguousDouble().data()[i] = QNaN;
     }
     m_butterfly->setVectorLength(newVectorLength);
 }
index 1cb7e85..f460f3c 100644 (file)
@@ -622,7 +622,7 @@ public:
     // indexing should be sparse, we're having a bad time, or because
     // we already have a more general form of storage (double,
     // contiguous, array storage).
-    WriteBarrier<Unknown>* ensureInt32(JSGlobalData& globalData)
+    ContiguousJSValues ensureInt32(JSGlobalData& globalData)
     {
         if (LIKELY(hasInt32(structure()->indexingType())))
             return m_butterfly->contiguousInt32();
@@ -634,7 +634,7 @@ public:
     // indexing should be sparse, we're having a bad time, or because
     // we already have a more general form of storage (contiguous,
     // or array storage).
-    double* ensureDouble(JSGlobalData& globalData)
+    ContiguousDoubles ensureDouble(JSGlobalData& globalData)
     {
         if (LIKELY(hasDouble(structure()->indexingType())))
             return m_butterfly->contiguousDouble();
@@ -644,7 +644,7 @@ public:
         
     // Returns 0 if contiguous storage cannot be created - either because
     // indexing should be sparse or because we're having a bad time.
-    WriteBarrier<Unknown>* ensureContiguous(JSGlobalData& globalData)
+    ContiguousJSValues ensureContiguous(JSGlobalData& globalData)
     {
         if (LIKELY(hasContiguous(structure()->indexingType())))
             return m_butterfly->contiguous();
@@ -655,7 +655,7 @@ public:
     // Same as ensureContiguous(), except that if the indexed storage is in
     // double mode, then it does a rage conversion to contiguous: it
     // attempts to convert each double to an int32.
-    WriteBarrier<Unknown>* rageEnsureContiguous(JSGlobalData& globalData)
+    ContiguousJSValues rageEnsureContiguous(JSGlobalData& globalData)
     {
         if (LIKELY(hasContiguous(structure()->indexingType())))
             return m_butterfly->contiguous();
@@ -735,9 +735,9 @@ protected:
     }
         
     Butterfly* createInitialUndecided(JSGlobalData&, unsigned length);
-    WriteBarrier<Unknown>* createInitialInt32(JSGlobalData&, unsigned length);
-    double* createInitialDouble(JSGlobalData&, unsigned length);
-    WriteBarrier<Unknown>* createInitialContiguous(JSGlobalData&, unsigned length);
+    ContiguousJSValues createInitialInt32(JSGlobalData&, unsigned length);
+    ContiguousDoubles createInitialDouble(JSGlobalData&, unsigned length);
+    ContiguousJSValues createInitialContiguous(JSGlobalData&, unsigned length);
         
     void convertUndecidedForValue(JSGlobalData&, JSValue);
     void convertInt32ForValue(JSGlobalData&, JSValue);
@@ -745,21 +745,21 @@ protected:
     ArrayStorage* createArrayStorage(JSGlobalData&, unsigned length, unsigned vectorLength);
     ArrayStorage* createInitialArrayStorage(JSGlobalData&);
         
-    WriteBarrier<Unknown>* convertUndecidedToInt32(JSGlobalData&);
-    double* convertUndecidedToDouble(JSGlobalData&);
-    WriteBarrier<Unknown>* convertUndecidedToContiguous(JSGlobalData&);
+    ContiguousJSValues convertUndecidedToInt32(JSGlobalData&);
+    ContiguousDoubles convertUndecidedToDouble(JSGlobalData&);
+    ContiguousJSValues convertUndecidedToContiguous(JSGlobalData&);
     ArrayStorage* convertUndecidedToArrayStorage(JSGlobalData&, NonPropertyTransition, unsigned neededLength);
     ArrayStorage* convertUndecidedToArrayStorage(JSGlobalData&, NonPropertyTransition);
     ArrayStorage* convertUndecidedToArrayStorage(JSGlobalData&);
         
-    double* convertInt32ToDouble(JSGlobalData&);
-    WriteBarrier<Unknown>* convertInt32ToContiguous(JSGlobalData&);
+    ContiguousDoubles convertInt32ToDouble(JSGlobalData&);
+    ContiguousJSValues convertInt32ToContiguous(JSGlobalData&);
     ArrayStorage* convertInt32ToArrayStorage(JSGlobalData&, NonPropertyTransition, unsigned neededLength);
     ArrayStorage* convertInt32ToArrayStorage(JSGlobalData&, NonPropertyTransition);
     ArrayStorage* convertInt32ToArrayStorage(JSGlobalData&);
     
-    WriteBarrier<Unknown>* convertDoubleToContiguous(JSGlobalData&);
-    WriteBarrier<Unknown>* rageConvertDoubleToContiguous(JSGlobalData&);
+    ContiguousJSValues convertDoubleToContiguous(JSGlobalData&);
+    ContiguousJSValues rageConvertDoubleToContiguous(JSGlobalData&);
     ArrayStorage* convertDoubleToArrayStorage(JSGlobalData&, NonPropertyTransition, unsigned neededLength);
     ArrayStorage* convertDoubleToArrayStorage(JSGlobalData&, NonPropertyTransition);
     ArrayStorage* convertDoubleToArrayStorage(JSGlobalData&);
@@ -810,7 +810,7 @@ protected:
     // as if it contained JSValues. But it won't always contain JSValues.
     // Make sure you cast this to the appropriate type before using.
     template<IndexingType indexingType>
-    WriteBarrier<Unknown>* indexingData()
+    ContiguousJSValues indexingData()
     {
         switch (indexingType) {
         case ALL_INT32_INDEXING_TYPES:
@@ -819,15 +819,15 @@ protected:
             return m_butterfly->contiguous();
                 
         case ALL_ARRAY_STORAGE_INDEXING_TYPES:
-            return m_butterfly->arrayStorage()->m_vector;
-                
+            return m_butterfly->arrayStorage()->vector();
+
         default:
             CRASH();
-            return 0;
+            return ContiguousJSValues();
         }
     }
 
-    WriteBarrier<Unknown>* currentIndexingData()
+    ContiguousJSValues currentIndexingData()
     {
         switch (structure()->indexingType()) {
         case ALL_INT32_INDEXING_TYPES:
@@ -835,11 +835,11 @@ protected:
             return m_butterfly->contiguous();
 
         case ALL_ARRAY_STORAGE_INDEXING_TYPES:
-            return m_butterfly->arrayStorage()->m_vector;
+            return m_butterfly->arrayStorage()->vector();
 
         default:
             CRASH();
-            return 0;
+            return ContiguousJSValues();
         }
     }
         
@@ -945,16 +945,16 @@ private:
         
     void ensureLengthSlow(JSGlobalData&, unsigned length);
         
-    WriteBarrier<Unknown>* ensureInt32Slow(JSGlobalData&);
-    double* ensureDoubleSlow(JSGlobalData&);
-    WriteBarrier<Unknown>* ensureContiguousSlow(JSGlobalData&);
-    WriteBarrier<Unknown>* rageEnsureContiguousSlow(JSGlobalData&);
+    ContiguousJSValues ensureInt32Slow(JSGlobalData&);
+    ContiguousDoubles ensureDoubleSlow(JSGlobalData&);
+    ContiguousJSValues ensureContiguousSlow(JSGlobalData&);
+    ContiguousJSValues rageEnsureContiguousSlow(JSGlobalData&);
     ArrayStorage* ensureArrayStorageSlow(JSGlobalData&);
     
     enum DoubleToContiguousMode { EncodeValueAsDouble, RageConvertDoubleToValue };
     template<DoubleToContiguousMode mode>
-    WriteBarrier<Unknown>* genericConvertDoubleToContiguous(JSGlobalData&);
-    WriteBarrier<Unknown>* ensureContiguousSlow(JSGlobalData&, DoubleToContiguousMode);
+    ContiguousJSValues genericConvertDoubleToContiguous(JSGlobalData&);
+    ContiguousJSValues ensureContiguousSlow(JSGlobalData&, DoubleToContiguousMode);
     
 protected:
     Butterfly* m_butterfly;