Replace JSArray destructor with finalizer
authormhahnenberg@apple.com <mhahnenberg@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 1 Feb 2012 22:15:45 +0000 (22:15 +0000)
committermhahnenberg@apple.com <mhahnenberg@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 1 Feb 2012 22:15:45 +0000 (22:15 +0000)
https://bugs.webkit.org/show_bug.cgi?id=77488

Reviewed by Geoffrey Garen.

Source/JavaScriptCore:

* JavaScriptCore.exp:
* runtime/JSArray.cpp:
(JSC::JSArray::finalize): Added finalizer.
(JSC::JSArray::allocateSparseMap): Factored out code for allocating new sparse maps.
(JSC):
(JSC::JSArray::deallocateSparseMap): Factored out code for deallocating sparse maps.
(JSC::JSArray::enterDictionaryMode): Renamed enterSparseMode to enterDictionaryMode
because the old name was confusing because we could have a sparse array that never
called enterSparseMode.
(JSC::JSArray::defineOwnNumericProperty):
(JSC::JSArray::setLengthWritable):
(JSC::JSArray::putByIndexBeyondVectorLength):
(JSC::JSArray::setLength):
(JSC::JSArray::pop):
(JSC::JSArray::sort):
(JSC::JSArray::compactForSorting):
* runtime/JSArray.h:
(JSArray):

LayoutTests:

* fast/js/script-tests/sparse-array.js: Added code to test oscillation between
sparse and dense arrays.
* fast/js/sparse-array-expected.txt:

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

LayoutTests/ChangeLog
LayoutTests/fast/js/script-tests/sparse-array.js
LayoutTests/fast/js/sparse-array-expected.txt
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/JavaScriptCore.exp
Source/JavaScriptCore/runtime/JSArray.cpp
Source/JavaScriptCore/runtime/JSArray.h

index f594b5a..6a6ed1f 100644 (file)
@@ -1,3 +1,14 @@
+2012-02-01  Mark Hahnenberg  <mhahnenberg@apple.com>
+
+        Replace JSArray destructor with finalizer
+        https://bugs.webkit.org/show_bug.cgi?id=77488
+
+        Reviewed by Geoffrey Garen.
+
+        * fast/js/script-tests/sparse-array.js: Added code to test oscillation between 
+        sparse and dense arrays.
+        * fast/js/sparse-array-expected.txt:
+
 2012-02-01  Elliot Poger  <epoger@google.com>
 
         rebaseline box-shadow-clipped-slices
index 5f5e348..944087e 100644 (file)
@@ -15,5 +15,13 @@ shouldBe('array[0]', 'NaN');
 shouldBe('array[49999]', 'undefined');
 shouldBe('array[50000]', '100');
 shouldBe('array[50001]', 'undefined');
+// This tests oscillation between being sparse and dense.
+delete array[50000];
+array.length = 5;
+array[50000] = 100;
+shouldBe('array[0]', 'NaN');
+shouldBe('array[49999]', 'undefined');
+shouldBe('array[50000]', '100');
+shouldBe('array[50001]', 'undefined');
 
 debug('');
index e6a24aa..d115c82 100644 (file)
@@ -11,6 +11,10 @@ PASS array[0] is NaN
 PASS array[49999] is undefined
 PASS array[50000] is 100
 PASS array[50001] is undefined
+PASS array[0] is NaN
+PASS array[49999] is undefined
+PASS array[50000] is 100
+PASS array[50001] is undefined
 
 PASS successfullyParsed is true
 
index d26388d..4b89a05 100644 (file)
@@ -1,3 +1,29 @@
+2012-02-01  Mark Hahnenberg  <mhahnenberg@apple.com>
+
+        Replace JSArray destructor with finalizer
+        https://bugs.webkit.org/show_bug.cgi?id=77488
+
+        Reviewed by Geoffrey Garen.
+
+        * JavaScriptCore.exp:
+        * runtime/JSArray.cpp:
+        (JSC::JSArray::finalize): Added finalizer.
+        (JSC::JSArray::allocateSparseMap): Factored out code for allocating new sparse maps.
+        (JSC):
+        (JSC::JSArray::deallocateSparseMap): Factored out code for deallocating sparse maps.
+        (JSC::JSArray::enterDictionaryMode): Renamed enterSparseMode to enterDictionaryMode 
+        because the old name was confusing because we could have a sparse array that never 
+        called enterSparseMode.
+        (JSC::JSArray::defineOwnNumericProperty):
+        (JSC::JSArray::setLengthWritable):
+        (JSC::JSArray::putByIndexBeyondVectorLength):
+        (JSC::JSArray::setLength):
+        (JSC::JSArray::pop):
+        (JSC::JSArray::sort):
+        (JSC::JSArray::compactForSorting):
+        * runtime/JSArray.h:
+        (JSArray):
+
 2012-02-01  Andy Wingo  <wingo@igalia.com>
 
         Refactor identifier resolution in BytecodeGenerator
index 2f7b315..7266c4e 100644 (file)
@@ -288,10 +288,8 @@ __ZN3JSC7JSArray17defineOwnPropertyEPNS_8JSObjectEPNS_9ExecStateERKNS_10Identifi
 __ZN3JSC7JSArray25getOwnPropertySlotByIndexEPNS_6JSCellEPNS_9ExecStateEjRNS_12PropertySlotE
 __ZN3JSC7JSArray30tryFinishCreationUninitializedERNS_12JSGlobalDataEj
 __ZN3JSC7JSArray6s_infoE
-__ZN3JSC7JSArray7destroyEPNS_6JSCellE
 __ZN3JSC7JSArrayC1ERNS_12JSGlobalDataEPNS_9StructureE
 __ZN3JSC7JSArrayC2ERNS_12JSGlobalDataEPNS_9StructureE
-__ZN3JSC7JSArrayD2Ev
 __ZN3JSC7JSValue13isValidCalleeEv
 __ZN3JSC7Options17numberOfGCMarkersE
 __ZN3JSC7Options24opaqueRootMergeThresholdE
index 2afb6a0..c84fb5b 100644 (file)
@@ -200,16 +200,12 @@ JSArray* JSArray::tryFinishCreationUninitialized(JSGlobalData& globalData, unsig
     return this;
 }
 
-JSArray::~JSArray()
+// This function can be called multiple times on the same object.
+void JSArray::finalize(JSCell* cell)
 {
-    ASSERT(jsCast<JSArray*>(this));
-    checkConsistency(DestructorConsistencyCheck);
-    delete m_sparseValueMap;
-}
-
-void JSArray::destroy(JSCell* cell)
-{
-    jsCast<JSArray*>(cell)->JSArray::~JSArray();
+    JSArray* thisObject = jsCast<JSArray*>(cell);
+    thisObject->checkConsistency(DestructorConsistencyCheck);
+    thisObject->deallocateSparseMap();
 }
 
 inline std::pair<SparseArrayValueMap::iterator, bool> SparseArrayValueMap::add(JSArray* array, unsigned i)
@@ -309,13 +305,27 @@ inline void SparseArrayValueMap::visitChildren(SlotVisitor& visitor)
         visitor.append(&it->second);
 }
 
-void JSArray::enterSparseMode(JSGlobalData& globalData)
+void JSArray::allocateSparseMap(JSGlobalData& globalData)
+{
+    m_sparseValueMap = new SparseArrayValueMap;
+    globalData.heap.addFinalizer(this, finalize);
+}
+
+void JSArray::deallocateSparseMap()
+{
+    delete m_sparseValueMap;
+    m_sparseValueMap = 0;
+}
+
+void JSArray::enterDictionaryMode(JSGlobalData& globalData)
 {
     ArrayStorage* storage = m_storage;
     SparseArrayValueMap* map = m_sparseValueMap;
 
-    if (!map)
-        map = m_sparseValueMap = new SparseArrayValueMap;
+    if (!map) {
+        allocateSparseMap(globalData);
+        map = m_sparseValueMap;
+    }
 
     if (map->sparseMode())
         return;
@@ -404,7 +414,7 @@ bool JSArray::defineOwnNumericProperty(ExecState* exec, unsigned index, Property
             return true;
         }
 
-        enterSparseMode(exec->globalData());
+        enterDictionaryMode(exec->globalData());
     }
 
     SparseArrayValueMap* map = m_sparseValueMap;
@@ -514,7 +524,7 @@ void JSArray::setLengthWritable(ExecState* exec, bool writable)
     if (!isLengthWritable() || writable)
         return;
 
-    enterSparseMode(exec->globalData());
+    enterDictionaryMode(exec->globalData());
 
     SparseArrayValueMap* map = m_sparseValueMap;
     ASSERT(map);
@@ -787,8 +797,8 @@ NEVER_INLINE void JSArray::putByIndexBeyondVectorLength(ExecState* exec, unsigne
             return;
         }
         // We don't want to, or can't use a vector to hold this property - allocate a sparse map & add the value.
-        map = new SparseArrayValueMap;
-        m_sparseValueMap = map;
+        allocateSparseMap(exec->globalData());
+        map = m_sparseValueMap;
         map->put(exec, this, i, value);
         return;
     }
@@ -822,8 +832,7 @@ NEVER_INLINE void JSArray::putByIndexBeyondVectorLength(ExecState* exec, unsigne
     SparseArrayValueMap::const_iterator end = map->end();
     for (SparseArrayValueMap::const_iterator it = map->begin(); it != end; ++it)
         vector[it->first].set(globalData, this, it->second.getNonSparseMode());
-    delete map;
-    m_sparseValueMap = 0;
+    deallocateSparseMap();
 
     // Store the new property into the vector.
     WriteBarrier<Unknown>& valueSlot = vector[i];
@@ -1134,10 +1143,8 @@ bool JSArray::setLength(ExecState* exec, unsigned newLength, bool throwException
             } else {
                 for (unsigned i = 0; i < keys.size(); ++i)
                     map->remove(keys[i]);
-                if (map->isEmpty()) {
-                    delete map;
-                    m_sparseValueMap = 0;
-                }
+                if (map->isEmpty())
+                    deallocateSparseMap();
             }
         }
     }
@@ -1202,10 +1209,8 @@ JSValue JSArray::pop(ExecState* exec)
                 }
                 
                 map->remove(it);
-                if (map->isEmpty() && !map->sparseMode()) {
-                    delete map;
-                    m_sparseValueMap = 0;
-                }
+                if (map->isEmpty() && !map->sparseMode())
+                    deallocateSparseMap();
             }
         }
     }
@@ -1640,8 +1645,7 @@ void JSArray::sort(ExecState* exec, JSValue compareFunction, CallType callType,
             ++numDefined;
         }
 
-        delete map;
-        m_sparseValueMap = 0;
+        deallocateSparseMap();
     }
 
     ASSERT(tree.abstractor().m_nodes.size() >= numDefined);
@@ -1753,8 +1757,7 @@ unsigned JSArray::compactForSorting(JSGlobalData& globalData)
         for (SparseArrayValueMap::const_iterator it = map->begin(); it != end; ++it)
             storage->m_vector[numDefined++].setWithoutWriteBarrier(it->second.getNonSparseMode());
 
-        delete map;
-        m_sparseValueMap = 0;
+        deallocateSparseMap();
     }
 
     for (unsigned i = numDefined; i < newUsedVectorLength; ++i)
index 5e47977..a3354c6 100644 (file)
@@ -133,8 +133,7 @@ namespace JSC {
     public:
         typedef JSNonFinalObject Base;
 
-        JS_EXPORT_PRIVATE ~JSArray();
-        JS_EXPORT_PRIVATE static void destroy(JSCell*);
+        static void finalize(JSCell*);
 
         static JSArray* create(JSGlobalData& globalData, Structure* structure, unsigned initialLength = 0)
         {
@@ -275,7 +274,9 @@ namespace JSC {
         void setLengthWritable(ExecState*, bool writable);
         void putDescriptor(ExecState*, SparseArrayEntry*, PropertyDescriptor&, PropertyDescriptor& old);
         bool defineOwnNumericProperty(ExecState*, unsigned, PropertyDescriptor&, bool throwException);
-        void enterSparseMode(JSGlobalData&);
+        void enterDictionaryMode(JSGlobalData&);
+        void allocateSparseMap(JSGlobalData&);
+        void deallocateSparseMap();
 
         bool getOwnPropertySlotSlowCase(ExecState*, unsigned propertyName, PropertySlot&);
         void putByIndexBeyondVectorLength(ExecState*, unsigned propertyName, JSValue);