Merge to XFA: Take adavange of unused bytes at end of CFX strings
authorTom Sepez <tsepez@chromium.org>
Thu, 30 Apr 2015 22:46:34 +0000 (15:46 -0700)
committerTom Sepez <tsepez@chromium.org>
Thu, 30 Apr 2015 22:46:34 +0000 (15:46 -0700)
Original Review URL: https://codereview.chromium.org/1112423003
Original Review URL: https://codereview.chromium.org/1120703003

TBR=thestig@chromium.org

Review URL: https://codereview.chromium.org/1120813003

core/src/fxcrt/fx_basic_bstring.cpp
core/src/fxcrt/fx_basic_wstring.cpp

index 961aebe..2c8f7a7 100644 (file)
@@ -52,13 +52,25 @@ static CFX_StringData* FX_AllocString(int nLen)
     if (nLen == 0 || nLen < 0) {
         return NULL;
     }
+
+    int overhead = sizeof(long) * 3 + 1;  // 3 longs in header plus 1 for NUL.
     pdfium::base::CheckedNumeric<int> nSize = nLen;
-    nSize += sizeof(long) * 3 + 1;
-    CFX_StringData* pData = (CFX_StringData*)FX_Alloc(FX_BYTE, nSize.ValueOrDie());
+    nSize += overhead;
+
+    // Now round to an 8-byte boundary. We'd expect that this is the minimum
+    // granularity of any of the underlying allocators, so there may be cases
+    // where we can save a re-alloc when adding a few characters to a string
+    // by using this otherwise wasted space.
+    nSize += 7;
+    int totalSize = nSize.ValueOrDie() & ~7;
+    int usableSize = totalSize - overhead;
+    FXSYS_assert(usableSize >= nLen);
+
+    CFX_StringData* pData = (CFX_StringData*)FX_Alloc(FX_BYTE, totalSize);
     if (!pData) {
         return NULL;
     }
-    pData->m_nAllocLength = nLen;
+    pData->m_nAllocLength = usableSize;
     pData->m_nDataLength = nLen;
     pData->m_nRefs = 1;
     pData->m_String[nLen] = 0;
index 2ea23e4..42a7ad7 100644 (file)
@@ -9,23 +9,32 @@
 
 static CFX_StringDataW* FX_AllocStringW(int nLen)
 {
+    // TODO(palmer): |nLen| should really be declared as |size_t|, or
+    // at least unsigned.
     if (nLen == 0 || nLen < 0) {
         return NULL;
     }
 
-    pdfium::base::CheckedNumeric<int> iSize = static_cast<int>(sizeof(FX_WCHAR));
-    iSize *= nLen + 1;
-    iSize += sizeof(long) * 3;
+    int overhead = 3 * sizeof(long) + sizeof(FX_WCHAR);  // +WCHAR is for NUL.
+    pdfium::base::CheckedNumeric<int> iSize = nLen;
+    iSize *= sizeof(FX_WCHAR);
+    iSize += overhead;
+
+    // Now round to an 8-byte boundary. We'd expect that this is the minimum
+    // granularity of any of the underlying allocators, so there may be cases
+    // where we can save a re-alloc when adding a few characters to a string
+    // by using this otherwise wasted space.
+    iSize += 7;
+    int totalSize = iSize.ValueOrDie() & ~7;
+    int usableLen = (totalSize - overhead) / sizeof(FX_WCHAR);
+    FXSYS_assert(usableLen >= nLen);
+
     CFX_StringDataW* pData = (CFX_StringDataW*)FX_Alloc(FX_BYTE, iSize.ValueOrDie());
     if (!pData) {
         return NULL;
     }
 
-    // TODO(palmer): |nLen| should really be declared as |size_t|, but for
-    // now I just want to fix the overflow without changing any interfaces.
-    // Declaring |nLen| as |size_t| will also simplify the above code
-    // somewhat.
-    pData->m_nAllocLength = nLen;
+    pData->m_nAllocLength = usableLen;
     pData->m_nDataLength = nLen;
     pData->m_nRefs = 1;
     pData->m_String[nLen] = 0;