Title: [100239] trunk
Revision
100239
Author
dslo...@google.com
Date
2011-11-14 22:14:31 -0800 (Mon, 14 Nov 2011)

Log Message

Source/WebCore: [V8][Chromium]Serialize dense arrays densly
https://bugs.webkit.org/show_bug.cgi?id=72198
This patch ensures that:
- Dense arrays are serialized densly, and not as name-value pairs
- Sparse arrays are allocated as sparse on deserialization.
The criteria to choose whether to serialize densly or sparsely is the size
of a resulting serialized stream.

Reviewed by David Levin.

Test: fast/dom/Window/window-postmessage-arrays.html

* bindings/v8/SerializedScriptValue.cpp:
(WebCore::V8ObjectMap::Writer::writeDenseArray):
(WebCore::V8ObjectMap::Writer::writeGenerateFreshSparseArray):
(WebCore::V8ObjectMap::Writer::writeGenerateFreshDenseArray):
(WebCore::V8ObjectMap::Serializer::writeDenseArray):
(WebCore::V8ObjectMap::Serializer::AbstractObjectState::execDepth):
(WebCore::V8ObjectMap::Serializer::AbstractObjectState::serializeProperties):
(WebCore::V8ObjectMap::Serializer::ObjectState::advance):
(WebCore::V8ObjectMap::Serializer::DenseArrayState::DenseArrayState):
(WebCore::V8ObjectMap::Serializer::DenseArrayState::advance):
(WebCore::V8ObjectMap::Serializer::DenseArrayState::objectDone):
(WebCore::V8ObjectMap::Serializer::SparseArrayState::SparseArrayState):
(WebCore::V8ObjectMap::Serializer::SparseArrayState::advance):
(WebCore::V8ObjectMap::Serializer::serializeDensely):
(WebCore::V8ObjectMap::Serializer::startArrayState):
(WebCore::V8ObjectMap::Serializer::startObjectState):
(WebCore::V8ObjectMap::Serializer::doSerialize):
(WebCore::V8ObjectMap::Reader::read):
(WebCore::V8ObjectMap::Deserializer::newSparseArray):
(WebCore::V8ObjectMap::Deserializer::completeSparseArray):
(WebCore::V8ObjectMap::Deserializer::completeDenseArray):

LayoutTests: [V8][Chromium]Serialize dense arrays densly.
https://bugs.webkit.org/show_bug.cgi?id=72198

Reviewed by David Levin.

* fast/dom/Window/script-tests/postmessage-clone.js:
* fast/dom/Window/window-postmessage-arrays-expected.txt: Added.
* fast/dom/Window/window-postmessage-arrays.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (100238 => 100239)


--- trunk/LayoutTests/ChangeLog	2011-11-15 06:07:16 UTC (rev 100238)
+++ trunk/LayoutTests/ChangeLog	2011-11-15 06:14:31 UTC (rev 100239)
@@ -1,3 +1,14 @@
+2011-11-14  Dmitry Lomov  <dslo...@google.com>
+
+        [V8][Chromium]Serialize dense arrays densly.
+        https://bugs.webkit.org/show_bug.cgi?id=72198
+
+        Reviewed by David Levin.
+
+        * fast/dom/Window/script-tests/postmessage-clone.js:
+        * fast/dom/Window/window-postmessage-arrays-expected.txt: Added.
+        * fast/dom/Window/window-postmessage-arrays.html: Added.
+
 2011-11-14  Peter Kasting  <pkast...@google.com>
 
         [chromium] More rebaselines for r100177 after r100193 did not fully

Modified: trunk/LayoutTests/fast/dom/Window/script-tests/postmessage-clone.js (100238 => 100239)


--- trunk/LayoutTests/fast/dom/Window/script-tests/postmessage-clone.js	2011-11-15 06:07:16 UTC (rev 100238)
+++ trunk/LayoutTests/fast/dom/Window/script-tests/postmessage-clone.js	2011-11-15 06:14:31 UTC (rev 100239)
@@ -97,7 +97,7 @@
         'a[1] = b; ' +
         'return a;'
     ), false, "evalThunk", function(v) {
-        doPassFail(v.length === 3, "length correct"); // undefined
+        doPassFail(v.length === 3 || v.length === 2, "length correct"); // undefined
         doPassFail(v[0] === 0, "index 0 OK"); // mandatory
         doPassFail(v[1].x === 41, "accessor reached"); // mandatory
         doPassFail(v[2] === undefined, "index 2 undefined"); // undefined

Added: trunk/LayoutTests/fast/dom/Window/window-postmessage-arrays-expected.txt (0 => 100239)


--- trunk/LayoutTests/fast/dom/Window/window-postmessage-arrays-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/dom/Window/window-postmessage-arrays-expected.txt	2011-11-15 06:14:31 UTC (rev 100239)
@@ -0,0 +1,30 @@
+PASS: i = 29
+PASS: i = 28
+PASS: i = 27
+PASS: i = 26
+PASS: i = 25
+PASS: i = 24
+PASS: i = 23
+PASS: i = 22
+PASS: i = 21
+PASS: i = 20
+PASS: i = 19
+PASS: i = 18
+PASS: i = 17
+PASS: i = 16
+PASS: i = 15
+PASS: i = 14
+PASS: i = 13
+PASS: i = 12
+PASS: i = 11
+PASS: i = 10
+PASS: i = 9
+PASS: i = 8
+PASS: i = 7
+PASS: i = 6
+PASS: i = 5
+PASS: i = 4
+PASS: i = 3
+PASS: i = 2
+PASS: i = 1
+Done.

Added: trunk/LayoutTests/fast/dom/Window/window-postmessage-arrays.html (0 => 100239)


--- trunk/LayoutTests/fast/dom/Window/window-postmessage-arrays.html	                        (rev 0)
+++ trunk/LayoutTests/fast/dom/Window/window-postmessage-arrays.html	2011-11-15 06:14:31 UTC (rev 100239)
@@ -0,0 +1,62 @@
+<html>
+<head/>
+<body>
+<div id="description"/>
+<div id="console"/>
+<script>
+if (window.layoutTestController) {
+    layoutTestController.dumpAsText();
+    layoutTestController.waitUntilDone();
+}
+
+var console = document.getElementById("console");
+var maxCount = 30;
+
+function recieveMessage(evt) {
+    try {
+      var data = ""
+      if (data.i == 0) {
+          console.innerHTML += "Done."
+          if (window.layoutTestController)
+              layoutTestController.notifyDone();
+      }
+      else {
+          if (data.i < maxCount) {
+              var success = true;
+              for (var j = data.i; j < maxCount; j++) {
+                  success = success && data.a[j] == j;
+                  if (data.a[j] != j) {
+                      console.innerHTML += "Failure: data.i = " + data.i + " j = " + j + " data.a[j] = " + data.a[j] + "<br>";
+                      break;
+                  }
+              }
+              if (data.a.foobar != "FooBar")
+                  success = false;
+              if (data.a.length != maxCount) {
+                  success = false;
+                  console.innerHTML += "FAIL: i = " + data.i + " length = " + data.a.length;
+              }
+              if (success)
+                  console.innerHTML += "PASS: i = " + data.i + "<br>";
+              else
+                  console.innerHTML += "FAIL: i = " + data.i + " array: " + JSON.stringify(data.a) + "<br>";
+          }
+          var a = [];
+          for (var j = data.i - 1; j < maxCount; j++) {
+              a[j] = j;
+          };
+          a.foobar = "FooBar";
+          window.postMessage({i:data.i - 1, a:a}, '*');
+      }
+    } catch (e) {
+        console.innerHTML += "Exception " + e + "<br>";
+        if (window.layoutTestController)
+            layoutTestController.notifyDone();
+    }
+}
+window.addEventListener('message', recieveMessage, false);
+
+window.postMessage({i:maxCount}, '*');
+</script>
+</body>
+</html>

Modified: trunk/Source/WebCore/ChangeLog (100238 => 100239)


--- trunk/Source/WebCore/ChangeLog	2011-11-15 06:07:16 UTC (rev 100238)
+++ trunk/Source/WebCore/ChangeLog	2011-11-15 06:14:31 UTC (rev 100239)
@@ -1,3 +1,39 @@
+2011-11-14  Dmitry Lomov  <dslo...@google.com>
+        
+        [V8][Chromium]Serialize dense arrays densly
+        https://bugs.webkit.org/show_bug.cgi?id=72198
+        This patch ensures that:
+        - Dense arrays are serialized densly, and not as name-value pairs
+        - Sparse arrays are allocated as sparse on deserialization.
+        The criteria to choose whether to serialize densly or sparsely is the size
+        of a resulting serialized stream.
+
+        Reviewed by David Levin.
+
+        Test: fast/dom/Window/window-postmessage-arrays.html
+
+        * bindings/v8/SerializedScriptValue.cpp:
+        (WebCore::V8ObjectMap::Writer::writeDenseArray):
+        (WebCore::V8ObjectMap::Writer::writeGenerateFreshSparseArray):
+        (WebCore::V8ObjectMap::Writer::writeGenerateFreshDenseArray):
+        (WebCore::V8ObjectMap::Serializer::writeDenseArray):
+        (WebCore::V8ObjectMap::Serializer::AbstractObjectState::execDepth):
+        (WebCore::V8ObjectMap::Serializer::AbstractObjectState::serializeProperties):
+        (WebCore::V8ObjectMap::Serializer::ObjectState::advance):
+        (WebCore::V8ObjectMap::Serializer::DenseArrayState::DenseArrayState):
+        (WebCore::V8ObjectMap::Serializer::DenseArrayState::advance):
+        (WebCore::V8ObjectMap::Serializer::DenseArrayState::objectDone):
+        (WebCore::V8ObjectMap::Serializer::SparseArrayState::SparseArrayState):
+        (WebCore::V8ObjectMap::Serializer::SparseArrayState::advance):
+        (WebCore::V8ObjectMap::Serializer::serializeDensely):
+        (WebCore::V8ObjectMap::Serializer::startArrayState):
+        (WebCore::V8ObjectMap::Serializer::startObjectState):
+        (WebCore::V8ObjectMap::Serializer::doSerialize):
+        (WebCore::V8ObjectMap::Reader::read):
+        (WebCore::V8ObjectMap::Deserializer::newSparseArray):
+        (WebCore::V8ObjectMap::Deserializer::completeSparseArray):
+        (WebCore::V8ObjectMap::Deserializer::completeDenseArray):
+
 2011-11-14  Alexandre Elias  <ael...@google.com>
 
         [chromium] Fix scaleDelta zoom-out visibility rect bug

Modified: trunk/Source/WebCore/bindings/v8/SerializedScriptValue.cpp (100238 => 100239)


--- trunk/Source/WebCore/bindings/v8/SerializedScriptValue.cpp	2011-11-15 06:07:16 UTC (rev 100238)
+++ trunk/Source/WebCore/bindings/v8/SerializedScriptValue.cpp	2011-11-15 06:14:31 UTC (rev 100239)
@@ -189,18 +189,19 @@
     FileTag = 'f', // file:RawFile -> File (ref)
     FileListTag = 'l', // length:uint32_t, files:RawFile[length] -> FileList (ref)
     ImageDataTag = '#', // width:uint32_t, height:uint32_t, pixelDataLength:uint32_t, data:byte[pixelDataLength] -> ImageData (ref)
-    ArrayTag = '[', // length:uint32_t -> pops the last array from the open stack;
-                    //                    fills it with the last length elements pushed on the deserialization stack
     ObjectTag = '{', // numProperties:uint32_t -> pops the last object from the open stack;
                      //                           fills it with the last numProperties name,value pairs pushed onto the deserialization stack
     SparseArrayTag = '@', // numProperties:uint32_t, length:uint32_t -> pops the last object from the open stack;
                           //                                            fills it with the last numProperties name,value pairs pushed onto the deserialization stack
+    DenseArrayTag = '$', // numProperties:uint32_t, length:uint32_t -> pops the last object from the open stack;
+                         //                                            fills it with the last length elements and numProperties name,value pairs pushed onto deserialization stack
     RegExpTag = 'R', // pattern:RawString, flags:uint32_t -> RegExp (ref)
     ArrayBufferTag = 'B', // byteLength:uint32_t, data:byte[byteLength] -> ArrayBuffer (ref)
     ArrayBufferViewTag = 'V', // subtag:byte, byteOffset:uint32_t, byteLength:uint32_t -> ArrayBufferView (ref). Consumes an ArrayBuffer from the top of the deserialization stack.
     ObjectReferenceTag = '^', // ref:uint32_t -> reference table[ref]
     GenerateFreshObjectTag = 'o', // -> empty object allocated an object ID and pushed onto the open stack (ref)
-    GenerateFreshArrayTag = 'a', // length:uint32_t -> empty array[length] allocated an object ID and pushed onto the open stack (ref)
+    GenerateFreshSparseArrayTag = 'a', // length:uint32_t -> empty array[length] allocated an object ID and pushed onto the open stack (ref)
+    GenerateFreshDenseArrayTag = 'A', // length:uint32_t -> empty array[length] allocated an object ID and pushed onto the open stack (ref)
     ReferenceCountTag = '?', // refTableSize:uint32_t -> If the reference table is not refTableSize big, fails.
     StringObjectTag = 's', //  string:RawString -> new String(string) (ref)
     NumberObjectTag = 'n', // value:double -> new Number(value) (ref)
@@ -437,12 +438,6 @@
         doWriteUint32(index);
     }
 
-    void writeArray(uint32_t length)
-    {
-        append(ArrayTag);
-        doWriteUint32(length);
-    }
-
     void writeObjectReference(uint32_t reference)
     {
         append(ObjectReferenceTag);
@@ -462,6 +457,13 @@
         doWriteUint32(length);
     }
 
+    void writeDenseArray(uint32_t numProperties, uint32_t length)
+    {
+        append(DenseArrayTag);
+        doWriteUint32(numProperties);
+        doWriteUint32(length);
+    }
+
     Vector<BufferValueType>& data()
     {
         fillHole();
@@ -479,12 +481,19 @@
         append(GenerateFreshObjectTag);
     }
 
-    void writeGenerateFreshArray(uint32_t length)
+    void writeGenerateFreshSparseArray(uint32_t length)
     {
-        append(GenerateFreshArrayTag);
+        append(GenerateFreshSparseArrayTag);
         doWriteUint32(length);
     }
 
+    void writeGenerateFreshDenseArray(uint32_t length)
+    {
+        append(GenerateFreshDenseArrayTag);
+        doWriteUint32(length);
+    }
+
+
 private:
     void doWriteArrayBuffer(const ArrayBuffer& arrayBuffer)
     {
@@ -622,12 +631,6 @@
         return handleError(JSFailure, state);
     }
 
-    StateBase* writeArray(uint32_t length, StateBase* state)
-    {
-        m_writer.writeArray(length);
-        return pop(state);
-    }
-
     StateBase* writeObject(uint32_t numProperties, StateBase* state)
     {
         m_writer.writeObject(numProperties);
@@ -640,6 +643,13 @@
         return pop(state);
     }
 
+    StateBase* writeDenseArray(uint32_t numProperties, uint32_t length, StateBase* state)
+    {
+        m_writer.writeDenseArray(numProperties, length);
+        return pop(state);
+    }
+
+
 private:
     class StateBase {
         WTF_MAKE_NONCOPYABLE(StateBase);
@@ -700,34 +710,6 @@
         }
     };
 
-#if 0
-    // Currently unused, see comment in newArrayState.
-    class ArrayState : public State<v8::Array> {
-    public:
-        ArrayState(v8::Handle<v8::Array> array, StateBase* next)
-            : State<v8::Array>(array, next)
-            , m_index(-1)
-        {
-        }
-
-        virtual StateBase* advance(Serializer& serializer)
-        {
-            ++m_index;
-            for (; m_index < composite()->Length(); ++m_index) {
-                v8::Handle<v8::Value> value = composite()->Get(m_index);
-                if (StateBase* newState = serializer.checkException(this))
-                    return newState;
-                if (StateBase* newState = serializer.doSerialize(value, this))
-                    return newState;
-            }
-            return serializer.writeArray(composite()->Length(), this);
-        }
-
-    private:
-        unsigned m_index;
-    };
-#endif
-
     class AbstractObjectState : public State<v8::Object> {
     public:
         AbstractObjectState(v8::Handle<v8::Object> object, StateBase* next)
@@ -739,16 +721,14 @@
         {
         }
 
-        virtual StateBase* advance(Serializer& serializer)
+        virtual uint32_t execDepth() const { return m_isSerializingAccessor ? 1 : 0; }
+
+    protected:
+        virtual StateBase* objectDone(unsigned numProperties, Serializer&) = 0;
+
+        StateBase* serializeProperties(bool ignoreIndexed, Serializer& serializer) 
         {
             m_isSerializingAccessor = false;
-            if (!m_index) {
-                m_propertyNames = composite()->GetPropertyNames();
-                if (StateBase* newState = serializer.checkException(this))
-                    return newState;
-                if (m_propertyNames.IsEmpty())
-                    return serializer.reportFailure(this);
-            }
             while (m_index < m_propertyNames->Length()) {
                 bool isAccessor = false;
                 if (!m_nameDone) {
@@ -766,7 +746,7 @@
                     isAccessor = hasStringProperty && composite()->HasRealNamedCallbackProperty(propertyName.As<v8::String>());
                     if (StateBase* newState = serializer.checkException(this))
                         return newState;
-                    if (hasStringProperty || hasIndexedProperty)
+                    if (hasStringProperty || (hasIndexedProperty && !ignoreIndexed))
                         m_propertyName = propertyName;
                     else {
                         ++m_index;
@@ -799,13 +779,9 @@
             return objectDone(m_numSerializedProperties, serializer);
         }
 
-        virtual uint32_t execDepth() const { return m_isSerializingAccessor ? 1 : 0; }
+        v8::Local<v8::Array> m_propertyNames;
 
-    protected:
-        virtual StateBase* objectDone(unsigned numProperties, Serializer&) = 0;
-
     private:
-        v8::Local<v8::Array> m_propertyNames;
         v8::Local<v8::Value> m_propertyName;
         unsigned m_index;
         unsigned m_numSerializedProperties;
@@ -822,6 +798,18 @@
         {
         }
 
+        virtual StateBase* advance(Serializer& serializer)
+        {
+            if (m_propertyNames.IsEmpty()) {
+                m_propertyNames = composite()->GetPropertyNames();
+                if (StateBase* newState = serializer.checkException(this))
+                    return newState;
+                if (m_propertyNames.IsEmpty())
+                    return serializer.reportFailure(this);
+            }
+            return serializeProperties(false, serializer);
+        }
+
     protected:
         virtual StateBase* objectDone(unsigned numProperties, Serializer& serializer)
         {
@@ -829,13 +817,53 @@
         }
     };
 
+    class DenseArrayState : public AbstractObjectState {
+    public:
+        DenseArrayState(v8::Handle<v8::Array> array, v8::Handle<v8::Array> propertyNames, StateBase* next)
+            : AbstractObjectState(array, next)
+            , m_arrayIndex(0)
+            , m_arrayLength(array->Length())
+        {
+            m_propertyNames = v8::Local<v8::Array>::New(propertyNames);
+        }
+
+        virtual StateBase* advance(Serializer& serializer)
+        {
+            while (m_arrayIndex < m_arrayLength) {
+                v8::Handle<v8::Value> value = composite().As<v8::Array>()->Get(m_arrayIndex);
+                m_arrayIndex++;
+                if (StateBase* newState = serializer.checkException(this))
+                    return newState;
+                if (StateBase* newState = serializer.doSerialize(value, this))
+                    return newState;
+            }
+            return serializeProperties(true, serializer);
+        }
+
+    protected:
+        virtual StateBase* objectDone(unsigned numProperties, Serializer& serializer)
+        {
+            return serializer.writeDenseArray(numProperties, m_arrayLength, this);
+        }
+
+    private:
+        uint32_t m_arrayIndex;
+        uint32_t m_arrayLength;
+    };
+
     class SparseArrayState : public AbstractObjectState {
     public:
-        SparseArrayState(v8::Handle<v8::Array> array, StateBase* next)
+        SparseArrayState(v8::Handle<v8::Array> array, v8::Handle<v8::Array> propertyNames, StateBase* next)
             : AbstractObjectState(array, next)
         {
+            m_propertyNames = v8::Local<v8::Array>::New(propertyNames);
         }
 
+        virtual StateBase* advance(Serializer& serializer) 
+        {
+            return serializeProperties(false, serializer);
+        }
+
     protected:
         virtual StateBase* objectDone(unsigned numProperties, Serializer& serializer)
         {
@@ -994,17 +1022,36 @@
         m_writer.writeArrayBuffer(*arrayBuffer);
     }
 
-    static StateBase* newArrayState(v8::Handle<v8::Array> array, StateBase* next)
+    static bool shouldSerializeDensely(uint32_t length, uint32_t propertyCount) 
     {
-        // FIXME: use plain Array state when we can quickly check that
-        // an array is not sparse and has only indexed properties.
-        return new SparseArrayState(array, next);
+        // Let K be the cost of serializing all property values that are there
+        // Cost of serializing sparsely: 5*propertyCount + K (5 bytes per uint32_t key)
+        // Cost of serializing densely: K + 1*(length - propertyCount) (1 byte for all properties that are not there)
+        // so densely is better than sparsly whenever 6*propertyCount > length
+        return 6 * propertyCount >= length;
     }
 
-    static StateBase* newObjectState(v8::Handle<v8::Object> object, StateBase* next)
+    StateBase* startArrayState(v8::Handle<v8::Array> array, StateBase* next)
     {
+        v8::Handle<v8::Array> propertyNames = array->GetPropertyNames();
+        if (StateBase* newState = checkException(next))
+            return newState;
+        uint32_t length = array->Length();
+
+        if (shouldSerializeDensely(length, propertyNames->Length())) {
+            m_writer.writeGenerateFreshDenseArray(length);
+            return push(new DenseArrayState(array, propertyNames, next));
+        }
+
+        m_writer.writeGenerateFreshSparseArray(length);
+        return push(new SparseArrayState(array, propertyNames, next));
+    }
+
+    StateBase* startObjectState(v8::Handle<v8::Object> object, StateBase* next)
+    {
+        m_writer.writeGenerateFreshObject();
         // FIXME: check not a wrapper
-        return new ObjectState(object, next);
+        return push(new ObjectState(object, next));
     }
 
     // Marks object as having been visited by the serializer and assigns it a unique object reference ID.
@@ -1082,8 +1129,7 @@
         else if (value->IsBooleanObject())
             writeBooleanObject(value);
         else if (value->IsArray()) {
-            m_writer.writeGenerateFreshArray(value.As<v8::Array>()->Length());
-            return push(newArrayState(value.As<v8::Array>(), next));
+            return startArrayState(value.As<v8::Array>(), next);
         } else if (V8File::HasInstance(value))
             writeFile(value);
         else if (V8Blob::HasInstance(value))
@@ -1099,8 +1145,7 @@
         else if (value->IsObject()) {
             if (isHostObject(jsObject) || jsObject->IsCallable() || value->IsNativeError())
                 return handleError(DataCloneError, next);
-            m_writer.writeGenerateFreshObject();
-            return push(newObjectState(jsObject, next));
+            return startObjectState(jsObject, next);
         } else
             return handleError(DataCloneError, next);
     }
@@ -1117,11 +1162,12 @@
     virtual void pushObjectReference(const v8::Handle<v8::Value>&) = 0;
     virtual bool tryGetObjectFromObjectReference(uint32_t reference, v8::Handle<v8::Value>*) = 0;
     virtual bool tryGetTransferredMessagePort(uint32_t index, v8::Handle<v8::Value>*) = 0;
-    virtual bool newArray(uint32_t length) = 0;
+    virtual bool newSparseArray(uint32_t length) = 0;
+    virtual bool newDenseArray(uint32_t length) = 0;
     virtual bool newObject() = 0;
-    virtual bool completeArray(uint32_t length, v8::Handle<v8::Value>*) = 0;
     virtual bool completeObject(uint32_t numProperties, v8::Handle<v8::Value>*) = 0;
     virtual bool completeSparseArray(uint32_t numProperties, uint32_t length, v8::Handle<v8::Value>*) = 0;
+    virtual bool completeDenseArray(uint32_t numProperties, uint32_t length, v8::Handle<v8::Value>*) = 0;
 };
 
 // Reader is responsible for deserializing primitive types and
@@ -1234,14 +1280,6 @@
             creator.pushObjectReference(*value);
             break;
 
-        case ArrayTag: {
-            uint32_t length;
-            if (!doReadUint32(&length))
-                return false;
-            if (!creator.completeArray(length, value))
-                return false;
-            break;
-        }
         case RegExpTag:
             if (!readRegExp(value))
                 return false;
@@ -1266,6 +1304,17 @@
                 return false;
             break;
         }
+        case DenseArrayTag: {
+            uint32_t numProperties;
+            uint32_t length;
+            if (!doReadUint32(&numProperties))
+                return false;
+            if (!doReadUint32(&length))
+                return false;
+            if (!creator.completeDenseArray(numProperties, length, value))
+                return false;
+            break;
+        }
         case ArrayBufferViewTag: {
             if (m_version <= 0)
                 return false;
@@ -1289,16 +1338,26 @@
                 return false;
             return true;
         }
-        case GenerateFreshArrayTag: {
+        case GenerateFreshSparseArrayTag: {
             if (m_version <= 0)
                 return false;
             uint32_t length;
             if (!doReadUint32(&length))
                 return false;
-            if (!creator.newArray(length))
+            if (!creator.newSparseArray(length))
                 return false;
             return true;
         }
+        case GenerateFreshDenseArrayTag: {
+            if (m_version <= 0)
+                return false;
+            uint32_t length;
+            if (!doReadUint32(&length))
+                return false;
+            if (!creator.newDenseArray(length))
+                return false;
+            return true;
+        }
         case MessagePortTag: {
             if (m_version <= 0)
                 return false;
@@ -1707,11 +1766,16 @@
         return result;
     }
 
-    virtual bool newArray(uint32_t length)
+    virtual bool newSparseArray(uint32_t)
     {
+        v8::Local<v8::Array> array = v8::Array::New(0);
+        openComposite(array);
+        return true;
+    }
+
+    virtual bool newDenseArray(uint32_t length)
+    {
         v8::Local<v8::Array> array = v8::Array::New(length);
-        if (array.IsEmpty())
-            return false;
         openComposite(array);
         return true;
     }
@@ -1781,12 +1845,36 @@
                 return false;
             array = composite.As<v8::Array>();
         } else
-            array = v8::Array::New(length);
+            array = v8::Array::New();
         if (array.IsEmpty())
             return false;
         return initializeObject(array, numProperties, value);
     }
 
+    virtual bool completeDenseArray(uint32_t numProperties, uint32_t length, v8::Handle<v8::Value>* value)
+    {
+        v8::Local<v8::Array> array;
+        if (m_version > 0) {
+            v8::Local<v8::Value> composite;
+            if (!closeComposite(&composite))
+                return false;
+            array = composite.As<v8::Array>();
+        }
+        if (array.IsEmpty())
+            return false;
+        if (!initializeObject(array, numProperties, value))
+            return false;
+        if (length > stackDepth())
+            return false;
+        for (unsigned i = 0, stackPos = stackDepth() - length; i < length; i++, stackPos++) {
+            v8::Local<v8::Value> elem = element(stackPos);
+            if (!elem->IsUndefined())
+                array->Set(i, elem);
+        }
+        pop(length);
+        return true;
+    }
+
     virtual void pushObjectReference(const v8::Handle<v8::Value>& object)
     {
         m_objectPool.append(object);
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to