Bug 1264642 - Part 5. Make SerializedStructuredClone{Read,Write}Info use SerializedStructuredCloneBuffer. r=baku
☠☠ backed out by b25d09b7fab5 ☠ ☠
authorKan-Ru Chen <kanru@kanru.info>
Tue, 07 Jun 2016 16:49:43 +0800
changeset 350982 078e5c447f218e78162ae49eafedd925bd9b9275
parent 350981 7c60fc4144fb682ae99c4068464fddf69791834f
child 350983 f0067001c059ff57d6927c6da5a1605f1d29a449
push id6570
push userraliiev@mozilla.com
push dateMon, 14 Nov 2016 12:26:13 +0000
treeherdermozilla-beta@f455459b2ae5 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbaku
bugs1264642
milestone51.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1264642 - Part 5. Make SerializedStructuredClone{Read,Write}Info use SerializedStructuredCloneBuffer. r=baku MozReview-Commit-ID: KUz3E5Sw5W3
dom/indexedDB/ActorsChild.cpp
dom/indexedDB/ActorsParent.cpp
dom/indexedDB/IDBObjectStore.cpp
dom/indexedDB/IndexedDatabase.h
dom/indexedDB/IndexedDatabaseInlines.h
dom/indexedDB/PBackgroundIDBSharedTypes.ipdlh
--- a/dom/indexedDB/ActorsChild.cpp
+++ b/dom/indexedDB/ActorsChild.cpp
@@ -425,18 +425,16 @@ private:
 
   nsresult
   GetResult(JSContext* aCx,
             StructuredCloneReadInfo* aCloneInfo,
             JS::MutableHandle<JS::Value> aResult)
   {
     bool ok = IDBObjectStore::DeserializeValue(aCx, *aCloneInfo, aResult);
 
-    aCloneInfo->mCloneBuffer.clear();
-
     if (NS_WARN_IF(!ok)) {
       return NS_ERROR_DOM_DATA_CLONE_ERR;
     }
 
     return NS_OK;
   }
 
   nsresult
--- a/dom/indexedDB/ActorsParent.cpp
+++ b/dom/indexedDB/ActorsParent.cpp
@@ -14814,38 +14814,38 @@ TransactionBase::VerifyRequestParams(con
 
   RefPtr<FullObjectStoreMetadata> objMetadata =
     GetMetadataForObjectStoreId(aParams.objectStoreId());
   if (NS_WARN_IF(!objMetadata)) {
     ASSERT_UNLESS_FUZZING();
     return false;
   }
 
-  if (NS_WARN_IF(aParams.cloneInfo().data().IsEmpty())) {
+  if (NS_WARN_IF(!aParams.cloneInfo().data().data.Size())) {
     ASSERT_UNLESS_FUZZING();
     return false;
   }
 
   if (objMetadata->mCommonMetadata.autoIncrement() &&
       objMetadata->mCommonMetadata.keyPath().IsValid() &&
       aParams.key().IsUnset()) {
     const SerializedStructuredCloneWriteInfo cloneInfo = aParams.cloneInfo();
 
     if (NS_WARN_IF(!cloneInfo.offsetToKeyProp())) {
       ASSERT_UNLESS_FUZZING();
       return false;
     }
 
-    if (NS_WARN_IF(cloneInfo.data().Length() < sizeof(uint64_t))) {
+    if (NS_WARN_IF(cloneInfo.data().data.Size() < sizeof(uint64_t))) {
       ASSERT_UNLESS_FUZZING();
       return false;
     }
 
     if (NS_WARN_IF(cloneInfo.offsetToKeyProp() >
-                   (cloneInfo.data().Length() - sizeof(uint64_t)))) {
+                   (cloneInfo.data().data.Size() - sizeof(uint64_t)))) {
       ASSERT_UNLESS_FUZZING();
       return false;
     }
   } else if (NS_WARN_IF(aParams.cloneInfo().offsetToKeyProp())) {
     ASSERT_UNLESS_FUZZING();
     return false;
   }
 
@@ -19039,17 +19039,19 @@ DatabaseOperationBase::GetStructuredClon
 
   char* uncompressedBuffer = reinterpret_cast<char*>(uncompressed.Elements());
 
   if (NS_WARN_IF(!snappy::RawUncompress(compressed, compressedLength,
                                         uncompressedBuffer))) {
     return NS_ERROR_FILE_CORRUPTED;
   }
 
-  aInfo->mData.SwapElements(uncompressed);
+  if (!aInfo->mData.WriteBytes(uncompressedBuffer, uncompressed.Length())) {
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
 
   if (!aFileIds.IsVoid()) {
     AutoTArray<int64_t, 10> array;
     nsresult rv = ConvertFileIdsToArray(aFileIds, array);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
 
@@ -25401,16 +25403,25 @@ ObjectStoreAddOrPutRequestOp::DoDatabase
   rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("osid"), osid);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   MOZ_ASSERT(!keyUnset || mMetadata->mCommonMetadata.autoIncrement(),
              "Should have key unless autoIncrement");
 
+  JSStructuredCloneData& data =
+    const_cast<JSStructuredCloneData&>(mParams.cloneInfo().data().data);
+  const char* cloneData;
+  size_t cloneDataSize = data.Size();
+  auto iter = data.Iter();
+  if (NS_WARN_IF(!data.FlattenBytes(iter, &cloneData, cloneDataSize))) {
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
+
   int64_t autoIncrementNum = 0;
 
   if (mMetadata->mCommonMetadata.autoIncrement()) {
     if (keyUnset) {
       autoIncrementNum = mMetadata->mNextAutoIncrementId;
 
       MOZ_ASSERT(autoIncrementNum > 0);
 
@@ -25422,39 +25433,36 @@ ObjectStoreAddOrPutRequestOp::DoDatabase
     } else if (key.IsFloat() &&
                key.ToFloat() >= mMetadata->mNextAutoIncrementId) {
       autoIncrementNum = floor(key.ToFloat());
     }
 
     if (keyUnset && keyPath.IsValid()) {
       const SerializedStructuredCloneWriteInfo& cloneInfo = mParams.cloneInfo();
       MOZ_ASSERT(cloneInfo.offsetToKeyProp());
-      MOZ_ASSERT(cloneInfo.data().Length() > sizeof(uint64_t));
+      MOZ_ASSERT(cloneDataSize > sizeof(uint64_t));
       MOZ_ASSERT(cloneInfo.offsetToKeyProp() <=
-                 (cloneInfo.data().Length() - sizeof(uint64_t)));
+                 (cloneDataSize - sizeof(uint64_t)));
 
       // Special case where someone put an object into an autoIncrement'ing
       // objectStore with no key in its keyPath set. We needed to figure out
       // which row id we would get above before we could set that properly.
-      uint8_t* keyPropPointer =
-        const_cast<uint8_t*>(cloneInfo.data().Elements() +
-                             cloneInfo.offsetToKeyProp());
+      char* keyPropPointer = const_cast<char*>(cloneData + cloneInfo.offsetToKeyProp());
       uint64_t keyPropValue =
         ReinterpretDoubleAsUInt64(static_cast<double>(autoIncrementNum));
 
       LittleEndian::writeUint64(keyPropPointer, keyPropValue);
     }
   }
 
   key.BindToStatement(stmt, NS_LITERAL_CSTRING("key"));
 
   // Compress the bytes before adding into the database.
-  const char* uncompressed =
-    reinterpret_cast<const char*>(mParams.cloneInfo().data().Elements());
-  size_t uncompressedLength = mParams.cloneInfo().data().Length();
+  const char* uncompressed = cloneData;
+  size_t uncompressedLength = cloneDataSize;
 
   // We don't have a smart pointer class that calls free, so we need to
   // manage | compressed | manually.
   {
     size_t compressedLength = snappy::MaxCompressedLength(uncompressedLength);
 
     char* compressed = static_cast<char*>(malloc(compressedLength));
     if (NS_WARN_IF(!compressed)) {
@@ -25776,17 +25784,17 @@ nsresult
 ObjectStoreGetRequestOp::ConvertResponse(
                              uint32_t aIndex,
                              SerializedStructuredCloneReadInfo& aSerializedInfo)
 {
   MOZ_ASSERT(aIndex < mResponse.Length());
 
   StructuredCloneReadInfo& info = mResponse[aIndex];
 
-  info.mData.SwapElements(aSerializedInfo.data());
+  aSerializedInfo.data().data = Move(info.mData);
 
   FallibleTArray<BlobOrMutableFile> blobs;
   nsresult rv = ConvertBlobsToActors(mBackgroundParent,
                                      mDatabase,
                                      info.mFiles,
                                      blobs);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
@@ -26499,17 +26507,17 @@ IndexGetRequestOp::GetResponse(RequestRe
       for (uint32_t count = mResponse.Length(), index = 0;
            index < count;
            index++) {
         StructuredCloneReadInfo& info = mResponse[index];
 
         SerializedStructuredCloneReadInfo& serializedInfo =
           fallibleCloneInfos[index];
 
-        info.mData.SwapElements(serializedInfo.data());
+        serializedInfo.data().data = Move(info.mData);
 
         FallibleTArray<BlobOrMutableFile> blobs;
         nsresult rv = ConvertBlobsToActors(mBackgroundParent,
                                            mDatabase,
                                            info.mFiles,
                                            blobs);
         if (NS_WARN_IF(NS_FAILED(rv))) {
           aResponse = rv;
@@ -26533,17 +26541,17 @@ IndexGetRequestOp::GetResponse(RequestRe
   aResponse = IndexGetResponse();
 
   if (!mResponse.IsEmpty()) {
     StructuredCloneReadInfo& info = mResponse[0];
 
     SerializedStructuredCloneReadInfo& serializedInfo =
       aResponse.get_IndexGetResponse().cloneInfo();
 
-    info.mData.SwapElements(serializedInfo.data());
+    serializedInfo.data().data = Move(info.mData);
 
     FallibleTArray<BlobOrMutableFile> blobs;
     nsresult rv =
       ConvertBlobsToActors(mBackgroundParent,
                            mDatabase,
                            info.mFiles,
                            blobs);
     if (NS_WARN_IF(NS_FAILED(rv))) {
@@ -26847,17 +26855,17 @@ CursorOpBase::PopulateResponseFromStatem
         mResponse = nsTArray<ObjectStoreCursorResponse>();
       } else {
         MOZ_ASSERT(mResponse.type() ==
                      CursorResponse::TArrayOfObjectStoreCursorResponse);
       }
 
       auto& responses = mResponse.get_ArrayOfObjectStoreCursorResponse();
       auto& response = *responses.AppendElement();
-      response.cloneInfo().data().SwapElements(cloneInfo.mData);
+      response.cloneInfo().data().data = Move(cloneInfo.mData);
       response.key() = mCursor->mKey;
 
       mFiles.AppendElement(Move(cloneInfo.mFiles));
       break;
     }
 
     case OpenCursorParams::TObjectStoreOpenKeyCursorParams: {
       MOZ_ASSERT(aInitializeResponse);
@@ -26885,17 +26893,17 @@ CursorOpBase::PopulateResponseFromStatem
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
 
       MOZ_ASSERT(aInitializeResponse);
       mResponse = IndexCursorResponse();
 
       auto& response = mResponse.get_IndexCursorResponse();
-      response.cloneInfo().data().SwapElements(cloneInfo.mData);
+      response.cloneInfo().data().data = Move(cloneInfo.mData);
       response.key() = mCursor->mKey;
       response.sortKey() = mCursor->mSortKey;
       response.objectKey() = mCursor->mObjectKey;
 
       mFiles.AppendElement(Move(cloneInfo.mFiles));
       break;
     }
 
--- a/dom/indexedDB/IDBObjectStore.cpp
+++ b/dom/indexedDB/IDBObjectStore.cpp
@@ -860,25 +860,16 @@ CommonStructuredCloneReadCallback(JSCont
 
     return result;
   }
 
   return StructuredCloneHolder::ReadFullySerializableObjects(aCx, aReader,
                                                              aTag);
 }
 
-// static
-void
-ClearStructuredCloneBuffer(JSAutoStructuredCloneBuffer& aBuffer)
-{
-  if (!aBuffer.empty()) {
-    aBuffer.clear();
-  }
-}
-
 } // namespace
 
 const JSClass IDBObjectStore::sDummyPropJSClass = {
   "IDBObjectStore Dummy",
   0 /* flags */
 };
 
 IDBObjectStore::IDBObjectStore(IDBTransaction* aTransaction,
@@ -1035,101 +1026,84 @@ IDBObjectStore::AppendIndexUpdateInfo(
 
 // static
 void
 IDBObjectStore::ClearCloneReadInfo(StructuredCloneReadInfo& aReadInfo)
 {
   // This is kind of tricky, we only want to release stuff on the main thread,
   // but we can end up being called on other threads if we have already been
   // cleared on the main thread.
-  if (aReadInfo.mCloneBuffer.empty() && !aReadInfo.mFiles.Length()) {
+  if (!aReadInfo.mFiles.Length()) {
     return;
   }
 
-  ClearStructuredCloneBuffer(aReadInfo.mCloneBuffer);
   aReadInfo.mFiles.Clear();
 }
 
 // static
 bool
 IDBObjectStore::DeserializeValue(JSContext* aCx,
                                  StructuredCloneReadInfo& aCloneReadInfo,
                                  JS::MutableHandle<JS::Value> aValue)
 {
   MOZ_ASSERT(aCx);
 
-  if (aCloneReadInfo.mData.IsEmpty()) {
+  if (!aCloneReadInfo.mData.Size()) {
     aValue.setUndefined();
     return true;
   }
 
-  char* data = reinterpret_cast<char*>(aCloneReadInfo.mData.Elements());
-  size_t dataLen = aCloneReadInfo.mData.Length();
-
-  MOZ_ASSERT(!(dataLen % sizeof(uint64_t)));
+  MOZ_ASSERT(!(aCloneReadInfo.mData.Size() % sizeof(uint64_t)));
 
   JSAutoRequest ar(aCx);
 
-  JSStructuredCloneData buf;
-  if (!buf.WriteBytes(data, dataLen)) {
-    return false;
-  }
-
   static const JSStructuredCloneCallbacks callbacks = {
     CommonStructuredCloneReadCallback<ValueDeserializationHelper>,
     nullptr,
     nullptr,
     nullptr,
     nullptr,
     nullptr
   };
 
   // FIXME: Consider to use StructuredCloneHolder here and in other
   //        deserializing methods.
-  if (!JS_ReadStructuredClone(aCx, buf, JS_STRUCTURED_CLONE_VERSION,
+  if (!JS_ReadStructuredClone(aCx, aCloneReadInfo.mData, JS_STRUCTURED_CLONE_VERSION,
                               aValue, &callbacks, &aCloneReadInfo)) {
     return false;
   }
 
   return true;
 }
 
 // static
 bool
 IDBObjectStore::DeserializeIndexValue(JSContext* aCx,
                                       StructuredCloneReadInfo& aCloneReadInfo,
                                       JS::MutableHandle<JS::Value> aValue)
 {
   MOZ_ASSERT(!NS_IsMainThread());
   MOZ_ASSERT(aCx);
 
-  if (aCloneReadInfo.mData.IsEmpty()) {
+  if (!aCloneReadInfo.mData.Size()) {
     aValue.setUndefined();
     return true;
   }
 
-  size_t dataLen = aCloneReadInfo.mData.Length();
-  char* data = reinterpret_cast<char*>(aCloneReadInfo.mData.Elements());
-
-  MOZ_ASSERT(!(dataLen % sizeof(uint64_t)));
+  MOZ_ASSERT(!(aCloneReadInfo.mData.Size() % sizeof(uint64_t)));
 
   JSAutoRequest ar(aCx);
 
-  JSStructuredCloneData buf;
-  if (!buf.WriteBytes(data, dataLen)) {
-    return false;
-  }
-
   static const JSStructuredCloneCallbacks callbacks = {
     CommonStructuredCloneReadCallback<IndexDeserializationHelper>,
     nullptr,
     nullptr
   };
 
-  if (!JS_ReadStructuredClone(aCx, buf, JS_STRUCTURED_CLONE_VERSION,
+  if (!JS_ReadStructuredClone(aCx, aCloneReadInfo.mData, JS_STRUCTURED_CLONE_VERSION,
                               aValue, &callbacks, &aCloneReadInfo)) {
     return false;
   }
 
   return true;
 }
 
 #if !defined(MOZ_B2G)
@@ -1138,44 +1112,35 @@ IDBObjectStore::DeserializeIndexValue(JS
 bool
 IDBObjectStore::DeserializeUpgradeValue(JSContext* aCx,
                                         StructuredCloneReadInfo& aCloneReadInfo,
                                         JS::MutableHandle<JS::Value> aValue)
 {
   MOZ_ASSERT(!NS_IsMainThread());
   MOZ_ASSERT(aCx);
 
-  if (aCloneReadInfo.mData.IsEmpty()) {
+  if (!aCloneReadInfo.mData.Size()) {
     aValue.setUndefined();
     return true;
   }
 
-
-  size_t dataLen = aCloneReadInfo.mData.Length();
-  char* data = reinterpret_cast<char*>(aCloneReadInfo.mData.Elements());
-
-  MOZ_ASSERT(!(dataLen % sizeof(uint64_t)));
+  MOZ_ASSERT(!(aCloneReadInfo.mData.Size() % sizeof(uint64_t)));
 
   JSAutoRequest ar(aCx);
 
-  JSStructuredCloneData buf;
-  if (!buf.WriteBytes(data, dataLen)) {
-    return false;
-  }
-
   static JSStructuredCloneCallbacks callbacks = {
     CommonStructuredCloneReadCallback<UpgradeDeserializationHelper>,
     nullptr,
     nullptr,
     nullptr,
     nullptr,
     nullptr
   };
 
-  if (!JS_ReadStructuredClone(aCx, buf, JS_STRUCTURED_CLONE_VERSION,
+  if (!JS_ReadStructuredClone(aCx, aCloneReadInfo.mData, JS_STRUCTURED_CLONE_VERSION,
                               aValue, &callbacks, &aCloneReadInfo)) {
     return false;
   }
 
   return true;
 }
 
 #endif // MOZ_B2G
@@ -1296,38 +1261,19 @@ IDBObjectStore::AddOrPut(JSContext* aCx,
   StructuredCloneWriteInfo cloneWriteInfo(mTransaction->Database());
   nsTArray<IndexUpdateInfo> updateInfo;
 
   aRv = GetAddInfo(aCx, value, aKey, cloneWriteInfo, key, updateInfo);
   if (aRv.Failed()) {
     return nullptr;
   }
 
-  FallibleTArray<uint8_t> cloneData;
-  size_t size = cloneWriteInfo.mCloneBuffer.data().Size();
-
-  if (NS_WARN_IF(!cloneData.SetLength(size, fallible))) {
-    aRv = NS_ERROR_OUT_OF_MEMORY;
-    return nullptr;
-  }
-
-  const char* buf;
-  auto iter = cloneWriteInfo.mCloneBuffer.data().Iter();
-  cloneWriteInfo.mCloneBuffer.data().FlattenBytes(iter, &buf, size);
-
-  // FIXME Bug XXXXXX Change SerializedStructuredCloneReadInfo and
-  // SerializedStructuredCloneWriteInfo to use JSStructuredCloneData
-  // instead of raw buffer.
-  memcpy(cloneData.Elements(), buf, size);
-
-  cloneWriteInfo.mCloneBuffer.clear();
-
   ObjectStoreAddPutParams commonParams;
   commonParams.objectStoreId() = Id();
-  commonParams.cloneInfo().data().SwapElements(cloneData);
+  commonParams.cloneInfo().data().data = Move(cloneWriteInfo.mCloneBuffer.data());
   commonParams.cloneInfo().offsetToKeyProp() = cloneWriteInfo.mOffsetToKeyProp;
   commonParams.key() = key;
   commonParams.indexUpdateInfos().SwapElements(updateInfo);
 
   // Convert any blobs or mutable files into DatabaseOrMutableFile.
   nsTArray<StructuredCloneWriteInfo::BlobOrMutableFile>& blobOrMutableFiles =
     cloneWriteInfo.mBlobOrMutableFiles;
 
--- a/dom/indexedDB/IndexedDatabase.h
+++ b/dom/indexedDB/IndexedDatabase.h
@@ -40,23 +40,20 @@ struct StructuredCloneFile
 
   // In IndexedDatabaseInlines.h
   inline bool
   operator==(const StructuredCloneFile& aOther) const;
 };
 
 struct StructuredCloneReadInfo
 {
-  nsTArray<uint8_t> mData;
+  JSStructuredCloneData mData;
   nsTArray<StructuredCloneFile> mFiles;
   IDBDatabase* mDatabase;
 
-  // XXX Remove!
-  JSAutoStructuredCloneBuffer mCloneBuffer;
-
   // In IndexedDatabaseInlines.h
   inline
   StructuredCloneReadInfo();
 
   // In IndexedDatabaseInlines.h
   inline
   ~StructuredCloneReadInfo();
 
--- a/dom/indexedDB/IndexedDatabaseInlines.h
+++ b/dom/indexedDB/IndexedDatabaseInlines.h
@@ -49,17 +49,17 @@ StructuredCloneReadInfo::StructuredClone
   : mDatabase(nullptr)
 {
   MOZ_COUNT_CTOR(StructuredCloneReadInfo);
 }
 
 inline
 StructuredCloneReadInfo::StructuredCloneReadInfo(
                              SerializedStructuredCloneReadInfo&& aCloneReadInfo)
-  : mData(Move(aCloneReadInfo.data()))
+  : mData(Move(aCloneReadInfo.data().data))
   , mDatabase(nullptr)
 {
   MOZ_COUNT_CTOR(StructuredCloneReadInfo);
 }
 
 inline
 StructuredCloneReadInfo::~StructuredCloneReadInfo()
 {
@@ -67,17 +67,16 @@ StructuredCloneReadInfo::~StructuredClon
 }
 
 inline StructuredCloneReadInfo&
 StructuredCloneReadInfo::operator=(StructuredCloneReadInfo&& aCloneReadInfo)
 {
   MOZ_ASSERT(&aCloneReadInfo != this);
 
   mData = Move(aCloneReadInfo.mData);
-  mCloneBuffer = Move(aCloneReadInfo.mCloneBuffer);
   mFiles.Clear();
   mFiles.SwapElements(aCloneReadInfo.mFiles);
   mDatabase = aCloneReadInfo.mDatabase;
   aCloneReadInfo.mDatabase = nullptr;
   return *this;
 }
 
 } // namespace indexedDB
--- a/dom/indexedDB/PBackgroundIDBSharedTypes.ipdlh
+++ b/dom/indexedDB/PBackgroundIDBSharedTypes.ipdlh
@@ -25,16 +25,19 @@ using class mozilla::dom::indexedDB::Key
   from "mozilla/dom/indexedDB/Key.h";
 
 using class mozilla::dom::indexedDB::KeyPath
   from "mozilla/dom/indexedDB/KeyPath.h";
 
 using mozilla::dom::quota::PersistenceType
   from "mozilla/dom/quota/PersistenceType.h";
 
+using mozilla::SerializedStructuredCloneBuffer
+  from "ipc/IPCMessageUtils.h";
+
 namespace mozilla {
 namespace dom {
 namespace indexedDB {
 
 struct SerializedKeyRange
 {
   Key lower;
   Key upper;
@@ -52,23 +55,23 @@ union NullableMutableFile
 union BlobOrMutableFile
 {
   PBlob;
   NullableMutableFile;
 };
 
 struct SerializedStructuredCloneReadInfo
 {
-  uint8_t[] data;
+  SerializedStructuredCloneBuffer data;
   BlobOrMutableFile[] blobs;
 };
 
 struct SerializedStructuredCloneWriteInfo
 {
-  uint8_t[] data;
+  SerializedStructuredCloneBuffer data;
   uint64_t offsetToKeyProp;
 };
 
 struct IndexUpdateInfo
 {
   int64_t indexId;
   Key value;
   Key localizedValue;