totalPhysicalSize calculation when splitting a range must account for double rounding...
authorsbarati@apple.com <sbarati@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 3 Apr 2018 20:41:26 +0000 (20:41 +0000)
committersbarati@apple.com <sbarati@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 3 Apr 2018 20:41:26 +0000 (20:41 +0000)
https://bugs.webkit.org/show_bug.cgi?id=184275

Reviewed by Mark Lam.

The rounding error could happen when we split a range where the
range's total physical size equals the range's total size. The
rounding may cause the left size to lose a byte, and the right
size to gain a byte. This caused the right side to be a byte
large than its size.

* bmalloc/LargeRange.h:
(bmalloc::LargeRange::LargeRange):
(bmalloc::LargeRange::split const):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@230222 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/bmalloc/ChangeLog
Source/bmalloc/bmalloc/LargeRange.h

index 79ac3e7..7a245f2 100644 (file)
@@ -1,3 +1,20 @@
+2018-04-03  Saam Barati  <sbarati@apple.com>
+
+        totalPhysicalSize calculation when splitting a range must account for double rounding effects
+        https://bugs.webkit.org/show_bug.cgi?id=184275
+
+        Reviewed by Mark Lam.
+
+        The rounding error could happen when we split a range where the
+        range's total physical size equals the range's total size. The
+        rounding may cause the left size to lose a byte, and the right
+        size to gain a byte. This caused the right side to be a byte
+        large than its size.
+
+        * bmalloc/LargeRange.h:
+        (bmalloc::LargeRange::LargeRange):
+        (bmalloc::LargeRange::split const):
+
 2018-04-02  Saam Barati  <sbarati@apple.com>
 
         bmalloc should compute its own estimate of its footprint
index 2b81c25..879c84f 100644 (file)
@@ -45,7 +45,7 @@ public:
         , m_startPhysicalSize(startPhysicalSize)
         , m_totalPhysicalSize(totalPhysicalSize)
     {
-        BASSERT(size() >= this->totalPhysicalSize());
+        BASSERT(this->size() >= this->totalPhysicalSize());
         BASSERT(this->totalPhysicalSize() >= this->startPhysicalSize());
     }
 
@@ -131,8 +131,14 @@ inline std::pair<LargeRange, LargeRange> LargeRange::split(size_t leftSize) cons
 
     double ratio = static_cast<double>(leftSize) / static_cast<double>(this->size());
     size_t leftTotalPhysicalSize = static_cast<size_t>(ratio * totalPhysicalSize());
+    BASSERT(leftTotalPhysicalSize <= leftSize);
     leftTotalPhysicalSize = std::max(startPhysicalSize(), leftTotalPhysicalSize);
     size_t rightTotalPhysicalSize = totalPhysicalSize() - leftTotalPhysicalSize;
+    if (rightTotalPhysicalSize > rightSize) { // This may happen because of rounding.
+        leftTotalPhysicalSize += rightTotalPhysicalSize - rightSize;
+        BASSERT(leftTotalPhysicalSize <= leftSize);
+        rightTotalPhysicalSize = rightSize;
+    }
 
     LargeRange left(begin(), leftSize, startPhysicalSize(), leftTotalPhysicalSize);
     LargeRange right(left.end(), rightSize, 0, rightTotalPhysicalSize);