author | Nathan Froyd <froydnj@mozilla.com> |
Tue, 04 Nov 2014 08:57:25 -0500 | |
changeset 214026 | 13d940a1c8a0953678ea05359d89ffbe22be7edd |
parent 214025 | 5e6d8b6023e32f464ac8595969531f40b5113c05 |
child 214027 | 08cef10b6076c64ecbdc7b725ca4b1090185a6b7 |
push id | 27771 |
push user | ryanvm@gmail.com |
push date | Wed, 05 Nov 2014 19:04:24 +0000 |
treeherder | mozilla-central@305b4fecce99 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | bent |
bugs | 1088043 |
milestone | 36.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
|
--- a/ipc/glue/IPCMessageUtils.h +++ b/ipc/glue/IPCMessageUtils.h @@ -6,21 +6,23 @@ #ifndef __IPC_GLUE_IPCMESSAGEUTILS_H__ #define __IPC_GLUE_IPCMESSAGEUTILS_H__ #include "base/process_util.h" #include "chrome/common/ipc_message_utils.h" #include "mozilla/ArrayUtils.h" +#include "mozilla/DebugOnly.h" #include "mozilla/TimeStamp.h" #ifdef XP_WIN #include "mozilla/TimeStamp_windows.h" #endif #include "mozilla/TypedEnum.h" +#include "mozilla/TypeTraits.h" #include "mozilla/IntegerTypeTraits.h" #include <stdint.h> #include "nsID.h" #include "nsMemory.h" #include "nsString.h" #include "nsTArray.h" @@ -459,38 +461,100 @@ struct ParamTraits<nsLiteralString> : Pa typedef nsLiteralString paramType; }; template <typename E> struct ParamTraits<FallibleTArray<E> > { typedef FallibleTArray<E> paramType; + // We write arrays of integer or floating-point data using a single pickling + // call, rather than writing each element individually. We deliberately do + // not use mozilla::IsPod here because it is perfectly reasonable to have + // a data structure T for which IsPod<T>::value is true, yet also have a + // ParamTraits<T> specialization. + static const bool sUseWriteBytes = (mozilla::IsIntegral<E>::value || + mozilla::IsFloatingPoint<E>::value); + + // Compute the byte length for |aNumElements| of type E. If that length + // would overflow an int, return false. Otherwise, return true and place + // the byte length in |aTotalLength|. + // + // Pickle's ReadBytes/WriteBytes interface takes lengths in ints, hence this + // dance. + static bool ByteLengthIsValid(size_t aNumElements, int* aTotalLength) { + static_assert(sizeof(int) == sizeof(int32_t), "int is an unexpected size!"); + + // nsTArray only handles sizes up to INT32_MAX. + if (aNumElements > size_t(INT32_MAX)) { + return false; + } + + int64_t numBytes = static_cast<int64_t>(aNumElements) * sizeof(E); + if (numBytes > int64_t(INT32_MAX)) { + return false; + } + + *aTotalLength = static_cast<int>(numBytes); + return true; + } + static void Write(Message* aMsg, const paramType& aParam) { uint32_t length = aParam.Length(); WriteParam(aMsg, length); - for (uint32_t index = 0; index < length; index++) { - WriteParam(aMsg, aParam[index]); + + if (sUseWriteBytes) { + int pickledLength = 0; + mozilla::DebugOnly<bool> valid = ByteLengthIsValid(length, &pickledLength); + MOZ_ASSERT(valid); + aMsg->WriteBytes(aParam.Elements(), pickledLength); + } else { + for (uint32_t index = 0; index < length; index++) { + WriteParam(aMsg, aParam[index]); + } } } static bool Read(const Message* aMsg, void** aIter, paramType* aResult) { uint32_t length; if (!ReadParam(aMsg, aIter, &length)) { return false; } - aResult->SetCapacity(length); - for (uint32_t index = 0; index < length; index++) { - E* element = aResult->AppendElement(); - if (!(element && ReadParam(aMsg, aIter, element))) { + if (sUseWriteBytes) { + int pickledLength = 0; + if (!ByteLengthIsValid(length, &pickledLength)) { + return false; + } + + const char* outdata; + if (!aMsg->ReadBytes(aIter, &outdata, pickledLength)) { + return false; + } + + E* elements = aResult->AppendElements(length); + if (!elements) { return false; } + + memcpy(elements, outdata, pickledLength); + } else { + if (!aResult->SetCapacity(length)) { + return false; + } + + for (uint32_t index = 0; index < length; index++) { + E* element = aResult->AppendElement(); + MOZ_ASSERT(element); + if (!ReadParam(aMsg, aIter, element)) { + return false; + } + } } return true; } static void Log(const paramType& aParam, std::wstring* aLog) { for (uint32_t index = 0; index < aParam.Length(); index++) {