Changeset 100239 in webkit
- Timestamp:
- Nov 14, 2011, 10:14:31 PM (15 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 4 edited
-
LayoutTests/ChangeLog (modified) (1 diff)
-
LayoutTests/fast/dom/Window/script-tests/postmessage-clone.js (modified) (1 diff)
-
LayoutTests/fast/dom/Window/window-postmessage-arrays-expected.txt (added)
-
LayoutTests/fast/dom/Window/window-postmessage-arrays.html (added)
-
Source/WebCore/ChangeLog (modified) (1 diff)
-
Source/WebCore/bindings/v8/SerializedScriptValue.cpp (modified) (23 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r100238 r100239 1 2011-11-14 Dmitry Lomov <dslomov@google.com> 2 3 [V8][Chromium]Serialize dense arrays densly. 4 https://bugs.webkit.org/show_bug.cgi?id=72198 5 6 Reviewed by David Levin. 7 8 * fast/dom/Window/script-tests/postmessage-clone.js: 9 * fast/dom/Window/window-postmessage-arrays-expected.txt: Added. 10 * fast/dom/Window/window-postmessage-arrays.html: Added. 11 1 12 2011-11-14 Peter Kasting <pkasting@google.com> 2 13 -
trunk/LayoutTests/fast/dom/Window/script-tests/postmessage-clone.js
r91959 r100239 98 98 'return a;' 99 99 ), false, "evalThunk", function(v) { 100 doPassFail(v.length === 3 , "length correct"); // undefined100 doPassFail(v.length === 3 || v.length === 2, "length correct"); // undefined 101 101 doPassFail(v[0] === 0, "index 0 OK"); // mandatory 102 102 doPassFail(v[1].x === 41, "accessor reached"); // mandatory -
trunk/Source/WebCore/ChangeLog
r100235 r100239 1 2011-11-14 Dmitry Lomov <dslomov@google.com> 2 3 [V8][Chromium]Serialize dense arrays densly 4 https://bugs.webkit.org/show_bug.cgi?id=72198 5 This patch ensures that: 6 - Dense arrays are serialized densly, and not as name-value pairs 7 - Sparse arrays are allocated as sparse on deserialization. 8 The criteria to choose whether to serialize densly or sparsely is the size 9 of a resulting serialized stream. 10 11 Reviewed by David Levin. 12 13 Test: fast/dom/Window/window-postmessage-arrays.html 14 15 * bindings/v8/SerializedScriptValue.cpp: 16 (WebCore::V8ObjectMap::Writer::writeDenseArray): 17 (WebCore::V8ObjectMap::Writer::writeGenerateFreshSparseArray): 18 (WebCore::V8ObjectMap::Writer::writeGenerateFreshDenseArray): 19 (WebCore::V8ObjectMap::Serializer::writeDenseArray): 20 (WebCore::V8ObjectMap::Serializer::AbstractObjectState::execDepth): 21 (WebCore::V8ObjectMap::Serializer::AbstractObjectState::serializeProperties): 22 (WebCore::V8ObjectMap::Serializer::ObjectState::advance): 23 (WebCore::V8ObjectMap::Serializer::DenseArrayState::DenseArrayState): 24 (WebCore::V8ObjectMap::Serializer::DenseArrayState::advance): 25 (WebCore::V8ObjectMap::Serializer::DenseArrayState::objectDone): 26 (WebCore::V8ObjectMap::Serializer::SparseArrayState::SparseArrayState): 27 (WebCore::V8ObjectMap::Serializer::SparseArrayState::advance): 28 (WebCore::V8ObjectMap::Serializer::serializeDensely): 29 (WebCore::V8ObjectMap::Serializer::startArrayState): 30 (WebCore::V8ObjectMap::Serializer::startObjectState): 31 (WebCore::V8ObjectMap::Serializer::doSerialize): 32 (WebCore::V8ObjectMap::Reader::read): 33 (WebCore::V8ObjectMap::Deserializer::newSparseArray): 34 (WebCore::V8ObjectMap::Deserializer::completeSparseArray): 35 (WebCore::V8ObjectMap::Deserializer::completeDenseArray): 36 1 37 2011-11-14 Alexandre Elias <aelias@google.com> 2 38 -
trunk/Source/WebCore/bindings/v8/SerializedScriptValue.cpp
r99229 r100239 190 190 FileListTag = 'l', // length:uint32_t, files:RawFile[length] -> FileList (ref) 191 191 ImageDataTag = '#', // width:uint32_t, height:uint32_t, pixelDataLength:uint32_t, data:byte[pixelDataLength] -> ImageData (ref) 192 ArrayTag = '[', // length:uint32_t -> pops the last array from the open stack;193 // fills it with the last length elements pushed on the deserialization stack194 192 ObjectTag = '{', // numProperties:uint32_t -> pops the last object from the open stack; 195 193 // fills it with the last numProperties name,value pairs pushed onto the deserialization stack 196 194 SparseArrayTag = '@', // numProperties:uint32_t, length:uint32_t -> pops the last object from the open stack; 197 195 // fills it with the last numProperties name,value pairs pushed onto the deserialization stack 196 DenseArrayTag = '$', // numProperties:uint32_t, length:uint32_t -> pops the last object from the open stack; 197 // fills it with the last length elements and numProperties name,value pairs pushed onto deserialization stack 198 198 RegExpTag = 'R', // pattern:RawString, flags:uint32_t -> RegExp (ref) 199 199 ArrayBufferTag = 'B', // byteLength:uint32_t, data:byte[byteLength] -> ArrayBuffer (ref) … … 201 201 ObjectReferenceTag = '^', // ref:uint32_t -> reference table[ref] 202 202 GenerateFreshObjectTag = 'o', // -> empty object allocated an object ID and pushed onto the open stack (ref) 203 GenerateFreshArrayTag = 'a', // length:uint32_t -> empty array[length] allocated an object ID and pushed onto the open stack (ref) 203 GenerateFreshSparseArrayTag = 'a', // length:uint32_t -> empty array[length] allocated an object ID and pushed onto the open stack (ref) 204 GenerateFreshDenseArrayTag = 'A', // length:uint32_t -> empty array[length] allocated an object ID and pushed onto the open stack (ref) 204 205 ReferenceCountTag = '?', // refTableSize:uint32_t -> If the reference table is not refTableSize big, fails. 205 206 StringObjectTag = 's', // string:RawString -> new String(string) (ref) … … 438 439 } 439 440 440 void writeArray(uint32_t length)441 {442 append(ArrayTag);443 doWriteUint32(length);444 }445 446 441 void writeObjectReference(uint32_t reference) 447 442 { … … 463 458 } 464 459 460 void writeDenseArray(uint32_t numProperties, uint32_t length) 461 { 462 append(DenseArrayTag); 463 doWriteUint32(numProperties); 464 doWriteUint32(length); 465 } 466 465 467 Vector<BufferValueType>& data() 466 468 { … … 480 482 } 481 483 482 void writeGenerateFresh Array(uint32_t length)483 { 484 append(GenerateFresh ArrayTag);484 void writeGenerateFreshSparseArray(uint32_t length) 485 { 486 append(GenerateFreshSparseArrayTag); 485 487 doWriteUint32(length); 486 488 } 489 490 void writeGenerateFreshDenseArray(uint32_t length) 491 { 492 append(GenerateFreshDenseArrayTag); 493 doWriteUint32(length); 494 } 495 487 496 488 497 private: … … 623 632 } 624 633 625 StateBase* writeArray(uint32_t length, StateBase* state)626 {627 m_writer.writeArray(length);628 return pop(state);629 }630 631 634 StateBase* writeObject(uint32_t numProperties, StateBase* state) 632 635 { … … 640 643 return pop(state); 641 644 } 645 646 StateBase* writeDenseArray(uint32_t numProperties, uint32_t length, StateBase* state) 647 { 648 m_writer.writeDenseArray(numProperties, length); 649 return pop(state); 650 } 651 642 652 643 653 private: … … 700 710 } 701 711 }; 702 703 #if 0704 // Currently unused, see comment in newArrayState.705 class ArrayState : public State<v8::Array> {706 public:707 ArrayState(v8::Handle<v8::Array> array, StateBase* next)708 : State<v8::Array>(array, next)709 , m_index(-1)710 {711 }712 713 virtual StateBase* advance(Serializer& serializer)714 {715 ++m_index;716 for (; m_index < composite()->Length(); ++m_index) {717 v8::Handle<v8::Value> value = composite()->Get(m_index);718 if (StateBase* newState = serializer.checkException(this))719 return newState;720 if (StateBase* newState = serializer.doSerialize(value, this))721 return newState;722 }723 return serializer.writeArray(composite()->Length(), this);724 }725 726 private:727 unsigned m_index;728 };729 #endif730 712 731 713 class AbstractObjectState : public State<v8::Object> { … … 740 722 } 741 723 742 virtual StateBase* advance(Serializer& serializer) 724 virtual uint32_t execDepth() const { return m_isSerializingAccessor ? 1 : 0; } 725 726 protected: 727 virtual StateBase* objectDone(unsigned numProperties, Serializer&) = 0; 728 729 StateBase* serializeProperties(bool ignoreIndexed, Serializer& serializer) 743 730 { 744 731 m_isSerializingAccessor = false; 745 if (!m_index) {746 m_propertyNames = composite()->GetPropertyNames();747 if (StateBase* newState = serializer.checkException(this))748 return newState;749 if (m_propertyNames.IsEmpty())750 return serializer.reportFailure(this);751 }752 732 while (m_index < m_propertyNames->Length()) { 753 733 bool isAccessor = false; … … 767 747 if (StateBase* newState = serializer.checkException(this)) 768 748 return newState; 769 if (hasStringProperty || hasIndexedProperty)749 if (hasStringProperty || (hasIndexedProperty && !ignoreIndexed)) 770 750 m_propertyName = propertyName; 771 751 else { … … 800 780 } 801 781 802 virtual uint32_t execDepth() const { return m_isSerializingAccessor ? 1 : 0; } 803 804 protected: 805 virtual StateBase* objectDone(unsigned numProperties, Serializer&) = 0; 782 v8::Local<v8::Array> m_propertyNames; 806 783 807 784 private: 808 v8::Local<v8::Array> m_propertyNames;809 785 v8::Local<v8::Value> m_propertyName; 810 786 unsigned m_index; … … 823 799 } 824 800 801 virtual StateBase* advance(Serializer& serializer) 802 { 803 if (m_propertyNames.IsEmpty()) { 804 m_propertyNames = composite()->GetPropertyNames(); 805 if (StateBase* newState = serializer.checkException(this)) 806 return newState; 807 if (m_propertyNames.IsEmpty()) 808 return serializer.reportFailure(this); 809 } 810 return serializeProperties(false, serializer); 811 } 812 825 813 protected: 826 814 virtual StateBase* objectDone(unsigned numProperties, Serializer& serializer) … … 830 818 }; 831 819 820 class DenseArrayState : public AbstractObjectState { 821 public: 822 DenseArrayState(v8::Handle<v8::Array> array, v8::Handle<v8::Array> propertyNames, StateBase* next) 823 : AbstractObjectState(array, next) 824 , m_arrayIndex(0) 825 , m_arrayLength(array->Length()) 826 { 827 m_propertyNames = v8::Local<v8::Array>::New(propertyNames); 828 } 829 830 virtual StateBase* advance(Serializer& serializer) 831 { 832 while (m_arrayIndex < m_arrayLength) { 833 v8::Handle<v8::Value> value = composite().As<v8::Array>()->Get(m_arrayIndex); 834 m_arrayIndex++; 835 if (StateBase* newState = serializer.checkException(this)) 836 return newState; 837 if (StateBase* newState = serializer.doSerialize(value, this)) 838 return newState; 839 } 840 return serializeProperties(true, serializer); 841 } 842 843 protected: 844 virtual StateBase* objectDone(unsigned numProperties, Serializer& serializer) 845 { 846 return serializer.writeDenseArray(numProperties, m_arrayLength, this); 847 } 848 849 private: 850 uint32_t m_arrayIndex; 851 uint32_t m_arrayLength; 852 }; 853 832 854 class SparseArrayState : public AbstractObjectState { 833 855 public: 834 SparseArrayState(v8::Handle<v8::Array> array, StateBase* next)856 SparseArrayState(v8::Handle<v8::Array> array, v8::Handle<v8::Array> propertyNames, StateBase* next) 835 857 : AbstractObjectState(array, next) 836 858 { 859 m_propertyNames = v8::Local<v8::Array>::New(propertyNames); 860 } 861 862 virtual StateBase* advance(Serializer& serializer) 863 { 864 return serializeProperties(false, serializer); 837 865 } 838 866 … … 995 1023 } 996 1024 997 static StateBase* newArrayState(v8::Handle<v8::Array> array, StateBase* next) 998 { 999 // FIXME: use plain Array state when we can quickly check that 1000 // an array is not sparse and has only indexed properties. 1001 return new SparseArrayState(array, next); 1002 } 1003 1004 static StateBase* newObjectState(v8::Handle<v8::Object> object, StateBase* next) 1005 { 1025 static bool shouldSerializeDensely(uint32_t length, uint32_t propertyCount) 1026 { 1027 // Let K be the cost of serializing all property values that are there 1028 // Cost of serializing sparsely: 5*propertyCount + K (5 bytes per uint32_t key) 1029 // Cost of serializing densely: K + 1*(length - propertyCount) (1 byte for all properties that are not there) 1030 // so densely is better than sparsly whenever 6*propertyCount > length 1031 return 6 * propertyCount >= length; 1032 } 1033 1034 StateBase* startArrayState(v8::Handle<v8::Array> array, StateBase* next) 1035 { 1036 v8::Handle<v8::Array> propertyNames = array->GetPropertyNames(); 1037 if (StateBase* newState = checkException(next)) 1038 return newState; 1039 uint32_t length = array->Length(); 1040 1041 if (shouldSerializeDensely(length, propertyNames->Length())) { 1042 m_writer.writeGenerateFreshDenseArray(length); 1043 return push(new DenseArrayState(array, propertyNames, next)); 1044 } 1045 1046 m_writer.writeGenerateFreshSparseArray(length); 1047 return push(new SparseArrayState(array, propertyNames, next)); 1048 } 1049 1050 StateBase* startObjectState(v8::Handle<v8::Object> object, StateBase* next) 1051 { 1052 m_writer.writeGenerateFreshObject(); 1006 1053 // FIXME: check not a wrapper 1007 return new ObjectState(object, next);1054 return push(new ObjectState(object, next)); 1008 1055 } 1009 1056 … … 1083 1130 writeBooleanObject(value); 1084 1131 else if (value->IsArray()) { 1085 m_writer.writeGenerateFreshArray(value.As<v8::Array>()->Length()); 1086 return push(newArrayState(value.As<v8::Array>(), next)); 1132 return startArrayState(value.As<v8::Array>(), next); 1087 1133 } else if (V8File::HasInstance(value)) 1088 1134 writeFile(value); … … 1100 1146 if (isHostObject(jsObject) || jsObject->IsCallable() || value->IsNativeError()) 1101 1147 return handleError(DataCloneError, next); 1102 m_writer.writeGenerateFreshObject(); 1103 return push(newObjectState(jsObject, next)); 1148 return startObjectState(jsObject, next); 1104 1149 } else 1105 1150 return handleError(DataCloneError, next); … … 1118 1163 virtual bool tryGetObjectFromObjectReference(uint32_t reference, v8::Handle<v8::Value>*) = 0; 1119 1164 virtual bool tryGetTransferredMessagePort(uint32_t index, v8::Handle<v8::Value>*) = 0; 1120 virtual bool newArray(uint32_t length) = 0; 1165 virtual bool newSparseArray(uint32_t length) = 0; 1166 virtual bool newDenseArray(uint32_t length) = 0; 1121 1167 virtual bool newObject() = 0; 1122 virtual bool completeArray(uint32_t length, v8::Handle<v8::Value>*) = 0;1123 1168 virtual bool completeObject(uint32_t numProperties, v8::Handle<v8::Value>*) = 0; 1124 1169 virtual bool completeSparseArray(uint32_t numProperties, uint32_t length, v8::Handle<v8::Value>*) = 0; 1170 virtual bool completeDenseArray(uint32_t numProperties, uint32_t length, v8::Handle<v8::Value>*) = 0; 1125 1171 }; 1126 1172 … … 1235 1281 break; 1236 1282 1237 case ArrayTag: {1238 uint32_t length;1239 if (!doReadUint32(&length))1240 return false;1241 if (!creator.completeArray(length, value))1242 return false;1243 break;1244 }1245 1283 case RegExpTag: 1246 1284 if (!readRegExp(value)) … … 1267 1305 break; 1268 1306 } 1307 case DenseArrayTag: { 1308 uint32_t numProperties; 1309 uint32_t length; 1310 if (!doReadUint32(&numProperties)) 1311 return false; 1312 if (!doReadUint32(&length)) 1313 return false; 1314 if (!creator.completeDenseArray(numProperties, length, value)) 1315 return false; 1316 break; 1317 } 1269 1318 case ArrayBufferViewTag: { 1270 1319 if (m_version <= 0) … … 1290 1339 return true; 1291 1340 } 1292 case GenerateFresh ArrayTag: {1341 case GenerateFreshSparseArrayTag: { 1293 1342 if (m_version <= 0) 1294 1343 return false; … … 1296 1345 if (!doReadUint32(&length)) 1297 1346 return false; 1298 if (!creator.newArray(length)) 1347 if (!creator.newSparseArray(length)) 1348 return false; 1349 return true; 1350 } 1351 case GenerateFreshDenseArrayTag: { 1352 if (m_version <= 0) 1353 return false; 1354 uint32_t length; 1355 if (!doReadUint32(&length)) 1356 return false; 1357 if (!creator.newDenseArray(length)) 1299 1358 return false; 1300 1359 return true; … … 1708 1767 } 1709 1768 1710 virtual bool newArray(uint32_t length) 1769 virtual bool newSparseArray(uint32_t) 1770 { 1771 v8::Local<v8::Array> array = v8::Array::New(0); 1772 openComposite(array); 1773 return true; 1774 } 1775 1776 virtual bool newDenseArray(uint32_t length) 1711 1777 { 1712 1778 v8::Local<v8::Array> array = v8::Array::New(length); 1713 if (array.IsEmpty())1714 return false;1715 1779 openComposite(array); 1716 1780 return true; … … 1782 1846 array = composite.As<v8::Array>(); 1783 1847 } else 1784 array = v8::Array::New( length);1848 array = v8::Array::New(); 1785 1849 if (array.IsEmpty()) 1786 1850 return false; 1787 1851 return initializeObject(array, numProperties, value); 1852 } 1853 1854 virtual bool completeDenseArray(uint32_t numProperties, uint32_t length, v8::Handle<v8::Value>* value) 1855 { 1856 v8::Local<v8::Array> array; 1857 if (m_version > 0) { 1858 v8::Local<v8::Value> composite; 1859 if (!closeComposite(&composite)) 1860 return false; 1861 array = composite.As<v8::Array>(); 1862 } 1863 if (array.IsEmpty()) 1864 return false; 1865 if (!initializeObject(array, numProperties, value)) 1866 return false; 1867 if (length > stackDepth()) 1868 return false; 1869 for (unsigned i = 0, stackPos = stackDepth() - length; i < length; i++, stackPos++) { 1870 v8::Local<v8::Value> elem = element(stackPos); 1871 if (!elem->IsUndefined()) 1872 array->Set(i, elem); 1873 } 1874 pop(length); 1875 return true; 1788 1876 } 1789 1877
Note:
See TracChangeset
for help on using the changeset viewer.