<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[173224] trunk/Source/bmalloc</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/173224">173224</a></dd>
<dt>Author</dt> <dd>ggaren@apple.com</dd>
<dt>Date</dt> <dd>2014-09-03 14:00:33 -0700 (Wed, 03 Sep 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>bmalloc crashes on the EWS bots (due to bad large object allocation)
https://bugs.webkit.org/show_bug.cgi?id=136469

Reviewed by Andreas Kling.

It's possible to convince bmalloc to perform a bad large object allocation,
through these steps:

(1) Insert object A into freelist F0.

(2) Split, merge and split again A's neighbors such that object B is
inserted into freelist F0, with boundary tag and size equal to object A,
but pointer not completely equal to object A. Put object B at the head of F0.

(3) Allocate some other object from F0, swapping its position in the
freelist with object B, such that object A is now ahead of object B.

--&gt; Now, the next allocation for size A/B will allocate object A, which
has a slightly wrong idea about where the object actually begins.
Immediately, you'll corrupt a little memory, and over time, you'll also
corrupt boundary tag metadata.

The solution is to store the begin pointer in the boundary tag. Luckily,
this doesn't make the tag any bigger, and it's not a noticeable slowdown
on MallocBench.

* bmalloc/Algorithm.h:
(bmalloc::rightShift):
* bmalloc/BeginTag.h:
(bmalloc::BeginTag::isInFreeList): This is the bug fix. Make sure to
validate the start pointer when popping off the free list. Through a
very uncommon set of steps, it is possible to have an item in the free
list that is valid by all accounts except for its start pointer.

* bmalloc/BoundaryTag.h:
(bmalloc::BoundaryTag::compactBegin):
(bmalloc::BoundaryTag::setRange):
(bmalloc::BoundaryTag::setSize): Deleted. Record a compact version of the
start pointer. We don't need the whole pointer -- just the offset, in
largeAlignment increments, into the relevant boundary tag bucket.

* bmalloc/BoundaryTagInlines.h:
(bmalloc::validateNext):
(bmalloc::BoundaryTag::init):
(bmalloc::BoundaryTag::mergeLarge):
(bmalloc::BoundaryTag::splitLarge):
* bmalloc/SegregatedFreeList.cpp:
(bmalloc::SegregatedFreeList::insert):
(bmalloc::SegregatedFreeList::takeGreedy):
(bmalloc::SegregatedFreeList::take): Provide the whole range instead of
the size when establishing a boundary tag, as required by the new
interface.

* bmalloc/Sizes.h:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourcebmallocChangeLog">trunk/Source/bmalloc/ChangeLog</a></li>
<li><a href="#trunkSourcebmallocbmallocAlgorithmh">trunk/Source/bmalloc/bmalloc/Algorithm.h</a></li>
<li><a href="#trunkSourcebmallocbmallocBeginTagh">trunk/Source/bmalloc/bmalloc/BeginTag.h</a></li>
<li><a href="#trunkSourcebmallocbmallocBoundaryTagh">trunk/Source/bmalloc/bmalloc/BoundaryTag.h</a></li>
<li><a href="#trunkSourcebmallocbmallocBoundaryTagInlinesh">trunk/Source/bmalloc/bmalloc/BoundaryTagInlines.h</a></li>
<li><a href="#trunkSourcebmallocbmallocSegregatedFreeListcpp">trunk/Source/bmalloc/bmalloc/SegregatedFreeList.cpp</a></li>
<li><a href="#trunkSourcebmallocbmallocSizesh">trunk/Source/bmalloc/bmalloc/Sizes.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourcebmallocChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/bmalloc/ChangeLog (173223 => 173224)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/bmalloc/ChangeLog        2014-09-03 20:59:58 UTC (rev 173223)
+++ trunk/Source/bmalloc/ChangeLog        2014-09-03 21:00:33 UTC (rev 173224)
</span><span class="lines">@@ -1,3 +1,60 @@
</span><ins>+2014-09-02  Geoffrey Garen  &lt;ggaren@apple.com&gt;
+
+        bmalloc crashes on the EWS bots (due to bad large object allocation)
+        https://bugs.webkit.org/show_bug.cgi?id=136469
+
+        Reviewed by Andreas Kling.
+
+        It's possible to convince bmalloc to perform a bad large object allocation,
+        through these steps:
+
+        (1) Insert object A into freelist F0.
+
+        (2) Split, merge and split again A's neighbors such that object B is
+        inserted into freelist F0, with boundary tag and size equal to object A,
+        but pointer not completely equal to object A. Put object B at the head of F0.
+
+        (3) Allocate some other object from F0, swapping its position in the
+        freelist with object B, such that object A is now ahead of object B.
+
+        --&gt; Now, the next allocation for size A/B will allocate object A, which
+        has a slightly wrong idea about where the object actually begins.
+        Immediately, you'll corrupt a little memory, and over time, you'll also
+        corrupt boundary tag metadata.
+
+        The solution is to store the begin pointer in the boundary tag. Luckily,
+        this doesn't make the tag any bigger, and it's not a noticeable slowdown
+        on MallocBench.
+
+        * bmalloc/Algorithm.h:
+        (bmalloc::rightShift):
+        * bmalloc/BeginTag.h:
+        (bmalloc::BeginTag::isInFreeList): This is the bug fix. Make sure to
+        validate the start pointer when popping off the free list. Through a
+        very uncommon set of steps, it is possible to have an item in the free
+        list that is valid by all accounts except for its start pointer.
+
+        * bmalloc/BoundaryTag.h:
+        (bmalloc::BoundaryTag::compactBegin):
+        (bmalloc::BoundaryTag::setRange):
+        (bmalloc::BoundaryTag::setSize): Deleted. Record a compact version of the
+        start pointer. We don't need the whole pointer -- just the offset, in
+        largeAlignment increments, into the relevant boundary tag bucket.
+
+        * bmalloc/BoundaryTagInlines.h:
+        (bmalloc::validateNext):
+        (bmalloc::BoundaryTag::init):
+        (bmalloc::BoundaryTag::mergeLarge):
+        (bmalloc::BoundaryTag::splitLarge):
+        * bmalloc/SegregatedFreeList.cpp:
+        (bmalloc::SegregatedFreeList::insert):
+        (bmalloc::SegregatedFreeList::takeGreedy):
+        (bmalloc::SegregatedFreeList::take): Provide the whole range instead of
+        the size when establishing a boundary tag, as required by the new
+        interface.
+
+        * bmalloc/Sizes.h:
+
</ins><span class="cx"> 2014-08-14  Geoffrey Garen  &lt;ggaren@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Fixed a bmalloc crash seen on the EWS bot
</span></span></pre></div>
<a id="trunkSourcebmallocbmallocAlgorithmh"></a>
<div class="modfile"><h4>Modified: trunk/Source/bmalloc/bmalloc/Algorithm.h (173223 => 173224)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/bmalloc/bmalloc/Algorithm.h        2014-09-03 20:59:58 UTC (rev 173223)
+++ trunk/Source/bmalloc/bmalloc/Algorithm.h        2014-09-03 21:00:33 UTC (rev 173224)
</span><span class="lines">@@ -46,12 +46,17 @@
</span><span class="cx"> {
</span><span class="cx">     return a &lt; b ? a : b;
</span><span class="cx"> }
</span><del>-    
</del><ins>+
</ins><span class="cx"> template&lt;typename T&gt; inline constexpr T mask(T value, uintptr_t mask)
</span><span class="cx"> {
</span><span class="cx">     return reinterpret_cast&lt;T&gt;(reinterpret_cast&lt;uintptr_t&gt;(value) &amp; mask);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+template&lt;typename T&gt; inline constexpr T rightShift(T value, uintptr_t shift)
+{
+    return reinterpret_cast&lt;T&gt;(reinterpret_cast&lt;uintptr_t&gt;(value) &gt;&gt; shift);
+}
+
</ins><span class="cx"> template&lt;typename T&gt; inline constexpr bool test(T value, uintptr_t mask)
</span><span class="cx"> {
</span><span class="cx">     return !!(reinterpret_cast&lt;uintptr_t&gt;(value) &amp; mask);
</span></span></pre></div>
<a id="trunkSourcebmallocbmallocBeginTagh"></a>
<div class="modfile"><h4>Modified: trunk/Source/bmalloc/bmalloc/BeginTag.h (173223 => 173224)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/bmalloc/bmalloc/BeginTag.h        2014-09-03 20:59:58 UTC (rev 173223)
+++ trunk/Source/bmalloc/bmalloc/BeginTag.h        2014-09-03 21:00:33 UTC (rev 173224)
</span><span class="lines">@@ -32,12 +32,12 @@
</span><span class="cx"> 
</span><span class="cx"> class BeginTag : public BoundaryTag {
</span><span class="cx"> public:
</span><del>-    bool isInFreeList(size_t);
</del><ins>+    bool isInFreeList(const Range&amp;);
</ins><span class="cx"> };
</span><span class="cx"> 
</span><del>-inline bool BeginTag::isInFreeList(size_t size)
</del><ins>+inline bool BeginTag::isInFreeList(const Range&amp; range)
</ins><span class="cx"> {
</span><del>-    return isFree() &amp;&amp; !isEnd() &amp;&amp; this-&gt;size() == size;
</del><ins>+    return isFree() &amp;&amp; !isEnd() &amp;&amp; this-&gt;size() == range.size() &amp;&amp; this-&gt;compactBegin() == compactBegin(range);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> } // namespace bmalloc
</span></span></pre></div>
<a id="trunkSourcebmallocbmallocBoundaryTagh"></a>
<div class="modfile"><h4>Modified: trunk/Source/bmalloc/bmalloc/BoundaryTag.h (173223 => 173224)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/bmalloc/bmalloc/BoundaryTag.h        2014-09-03 20:59:58 UTC (rev 173223)
+++ trunk/Source/bmalloc/bmalloc/BoundaryTag.h        2014-09-03 21:00:33 UTC (rev 173224)
</span><span class="lines">@@ -27,6 +27,7 @@
</span><span class="cx"> #define BoundaryTag_h
</span><span class="cx"> 
</span><span class="cx"> #include &quot;BAssert.h&quot;
</span><ins>+#include &quot;Range.h&quot;
</ins><span class="cx"> #include &quot;Sizes.h&quot;
</span><span class="cx"> 
</span><span class="cx"> namespace bmalloc {
</span><span class="lines">@@ -41,6 +42,7 @@
</span><span class="cx">     static Range init(LargeChunk*);
</span><span class="cx">     static Range deallocate(void*);
</span><span class="cx">     static void allocate(size_t, Range&amp;, Range&amp; leftover, bool&amp; hasPhysicalPages);
</span><ins>+    static unsigned compactBegin(const Range&amp;);
</ins><span class="cx"> 
</span><span class="cx">     bool isXLarge() { return m_size == xLargeMarker; }
</span><span class="cx">     void setXLarge() { m_size = xLargeMarker; }
</span><span class="lines">@@ -58,17 +60,21 @@
</span><span class="cx">     void clear() { memset(this, 0, sizeof(*this)); }
</span><span class="cx">     
</span><span class="cx">     size_t size() { return m_size; }
</span><del>-    void setSize(size_t);
</del><ins>+    unsigned compactBegin() { return m_compactBegin; }
+
+    void setRange(const Range&amp;);
</ins><span class="cx">     
</span><span class="cx">     EndTag* prev();
</span><span class="cx">     BeginTag* next();
</span><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     static const size_t flagBits = 3;
</span><del>-    static const size_t sizeBits = bitCount&lt;unsigned&gt;() - flagBits;
</del><ins>+    static const size_t compactBeginBits = 5;
+    static const size_t sizeBits = bitCount&lt;unsigned&gt;() - flagBits - compactBeginBits;
</ins><span class="cx">     static const size_t xLargeMarker = 1; // This size is unused because our minimum object size is greater than it.
</span><span class="cx"> 
</span><span class="cx">     static_assert(largeMin &gt; xLargeMarker, &quot;largeMin must provide enough umbrella to fit xLargeMarker.&quot;);
</span><ins>+    static_assert((1 &lt;&lt; compactBeginBits) - 1 &gt;= largeMin / largeAlignment, &quot;compactBegin must be encodable in a BoundaryTag.&quot;);
</ins><span class="cx">     static_assert((1 &lt;&lt; sizeBits) - 1 &gt;= largeMax, &quot;largeMax must be encodable in a BoundaryTag.&quot;);
</span><span class="cx"> 
</span><span class="cx">     static void splitLarge(BeginTag*, size_t size, EndTag*&amp; endTag, Range&amp;, Range&amp; leftover);
</span><span class="lines">@@ -79,13 +85,23 @@
</span><span class="cx">     bool m_isFree: 1;
</span><span class="cx">     bool m_isEnd: 1;
</span><span class="cx">     bool m_hasPhysicalPages: 1;
</span><ins>+    unsigned m_compactBegin: compactBeginBits;
</ins><span class="cx">     unsigned m_size: sizeBits;
</span><span class="cx"> };
</span><span class="cx"> 
</span><del>-inline void BoundaryTag::setSize(size_t size)
</del><ins>+inline unsigned BoundaryTag::compactBegin(const Range&amp; range)
</ins><span class="cx"> {
</span><del>-    m_size = static_cast&lt;unsigned&gt;(size);
-    BASSERT(this-&gt;size() == size);
</del><ins>+    return static_cast&lt;unsigned&gt;(
+        reinterpret_cast&lt;uintptr_t&gt;(
+            rightShift(
+                mask(range.begin(), largeMin - 1), largeAlignmentShift)));
+}
+
+inline void BoundaryTag::setRange(const Range&amp; range)
+{
+    m_compactBegin = compactBegin(range);
+    m_size = static_cast&lt;unsigned&gt;(range.size());
+    BASSERT(this-&gt;size() == range.size());
</ins><span class="cx">     BASSERT(!isXLarge());
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourcebmallocbmallocBoundaryTagInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/bmalloc/bmalloc/BoundaryTagInlines.h (173223 => 173224)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/bmalloc/bmalloc/BoundaryTagInlines.h        2014-09-03 20:59:58 UTC (rev 173223)
+++ trunk/Source/bmalloc/bmalloc/BoundaryTagInlines.h        2014-09-03 21:00:33 UTC (rev 173224)
</span><span class="lines">@@ -64,7 +64,7 @@
</span><span class="cx"> 
</span><span class="cx"> static inline void validateNext(BeginTag* next, const Range&amp; range)
</span><span class="cx"> {
</span><del>-    if (next-&gt;size() == largeMin &amp;&amp; !next-&gt;isFree()) // Right sentinel tag.
</del><ins>+    if (next-&gt;size() == largeMin &amp;&amp; !next-&gt;compactBegin() &amp;&amp; !next-&gt;isFree()) // Right sentinel tag.
</ins><span class="cx">         return;
</span><span class="cx"> 
</span><span class="cx">     void* nextObject = range.end();
</span><span class="lines">@@ -84,7 +84,7 @@
</span><span class="cx">     Range range(chunk-&gt;begin(), chunk-&gt;end() - chunk-&gt;begin());
</span><span class="cx"> 
</span><span class="cx">     BeginTag* beginTag = LargeChunk::beginTag(range.begin());
</span><del>-    beginTag-&gt;setSize(range.size());
</del><ins>+    beginTag-&gt;setRange(range);
</ins><span class="cx">     beginTag-&gt;setFree(true);
</span><span class="cx">     beginTag-&gt;setHasPhysicalPages(false);
</span><span class="cx"> 
</span><span class="lines">@@ -97,12 +97,12 @@
</span><span class="cx">     
</span><span class="cx">     EndTag* leftSentinel = beginTag-&gt;prev();
</span><span class="cx">     BASSERT(leftSentinel &gt;= static_cast&lt;void*&gt;(chunk));
</span><del>-    leftSentinel-&gt;setSize(largeMin);
</del><ins>+    leftSentinel-&gt;setRange(Range(nullptr, largeMin));
</ins><span class="cx">     leftSentinel-&gt;setFree(false);
</span><span class="cx"> 
</span><span class="cx">     BeginTag* rightSentinel = endTag-&gt;next();
</span><span class="cx">     BASSERT(rightSentinel &lt; static_cast&lt;void*&gt;(range.begin()));
</span><del>-    rightSentinel-&gt;setSize(largeMin);
</del><ins>+    rightSentinel-&gt;setRange(Range(nullptr, largeMin));
</ins><span class="cx">     rightSentinel-&gt;setFree(false);
</span><span class="cx">     
</span><span class="cx">     return range;
</span><span class="lines">@@ -150,7 +150,7 @@
</span><span class="cx">     if (next-&gt;isFree())
</span><span class="cx">         mergeLargeRight(endTag, next, range, hasPhysicalPages);
</span><span class="cx"> 
</span><del>-    beginTag-&gt;setSize(range.size());
</del><ins>+    beginTag-&gt;setRange(range);
</ins><span class="cx">     beginTag-&gt;setFree(true);
</span><span class="cx">     beginTag-&gt;setHasPhysicalPages(hasPhysicalPages);
</span><span class="cx"> 
</span><span class="lines">@@ -175,25 +175,26 @@
</span><span class="cx"> 
</span><span class="cx"> INLINE void BoundaryTag::splitLarge(BeginTag* beginTag, size_t size, EndTag*&amp; endTag, Range&amp; range, Range&amp; leftover)
</span><span class="cx"> {
</span><del>-    beginTag-&gt;setSize(size);
</del><ins>+    leftover = Range(range.begin() + size, range.size() - size);
+    range = Range(range.begin(), size);
</ins><span class="cx"> 
</span><ins>+    beginTag-&gt;setRange(range);
+
</ins><span class="cx">     EndTag* splitEndTag = LargeChunk::endTag(range.begin(), size);
</span><span class="cx">     if (splitEndTag != static_cast&lt;BoundaryTag*&gt;(beginTag))
</span><span class="cx">         *splitEndTag = *beginTag;
</span><span class="cx"> 
</span><del>-    leftover = Range(range.begin() + size, range.size() - size);
</del><span class="cx">     BASSERT(leftover.size() &gt;= largeMin);
</span><span class="cx">     BeginTag* leftoverBeginTag = LargeChunk::beginTag(leftover.begin());
</span><span class="cx">     *leftoverBeginTag = *beginTag;
</span><del>-    leftoverBeginTag-&gt;setSize(leftover.size());
</del><ins>+    leftoverBeginTag-&gt;setRange(leftover);
</ins><span class="cx"> 
</span><span class="cx">     if (leftoverBeginTag != static_cast&lt;BoundaryTag*&gt;(endTag))
</span><span class="cx">         *endTag = *leftoverBeginTag;
</span><span class="cx"> 
</span><del>-    validate(beginTag-&gt;prev(), Range(range.begin(), size), leftoverBeginTag);
</del><ins>+    validate(beginTag-&gt;prev(), range, leftoverBeginTag);
</ins><span class="cx">     validate(leftoverBeginTag-&gt;prev(), leftover, endTag-&gt;next());
</span><span class="cx"> 
</span><del>-    range = Range(range.begin(), size);
</del><span class="cx">     endTag = splitEndTag;
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourcebmallocbmallocSegregatedFreeListcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/bmalloc/bmalloc/SegregatedFreeList.cpp (173223 => 173224)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/bmalloc/bmalloc/SegregatedFreeList.cpp        2014-09-03 20:59:58 UTC (rev 173223)
+++ trunk/Source/bmalloc/bmalloc/SegregatedFreeList.cpp        2014-09-03 21:00:33 UTC (rev 173224)
</span><span class="lines">@@ -39,7 +39,7 @@
</span><span class="cx"> {
</span><span class="cx"> IF_DEBUG(
</span><span class="cx">     BeginTag* beginTag = LargeChunk::beginTag(range.begin());
</span><del>-    BASSERT(beginTag-&gt;isInFreeList(range.size()));
</del><ins>+    BASSERT(beginTag-&gt;isInFreeList(range));
</ins><span class="cx"> )
</span><span class="cx"> 
</span><span class="cx">     auto&amp; list = select(range.size());
</span><span class="lines">@@ -66,7 +66,7 @@
</span><span class="cx">         // We don't eagerly remove items when we merge and/or split ranges,
</span><span class="cx">         // so we need to validate each free list entry before using it.
</span><span class="cx">         BeginTag* beginTag = LargeChunk::beginTag(range.begin());
</span><del>-        if (!beginTag-&gt;isInFreeList(range.size())) {
</del><ins>+        if (!beginTag-&gt;isInFreeList(range)) {
</ins><span class="cx">             list.pop(i);
</span><span class="cx">             continue;
</span><span class="cx">         }
</span><span class="lines">@@ -114,7 +114,7 @@
</span><span class="cx">         // We don't eagerly remove items when we merge and/or split ranges, so
</span><span class="cx">         // we need to validate each free list entry before using it.
</span><span class="cx">         BeginTag* beginTag = LargeChunk::beginTag(range.begin());
</span><del>-        if (!beginTag-&gt;isInFreeList(range.size())) {
</del><ins>+        if (!beginTag-&gt;isInFreeList(range)) {
</ins><span class="cx">             list.pop(i);
</span><span class="cx">             continue;
</span><span class="cx">         }
</span></span></pre></div>
<a id="trunkSourcebmallocbmallocSizesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/bmalloc/bmalloc/Sizes.h (173223 => 173224)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/bmalloc/bmalloc/Sizes.h        2014-09-03 20:59:58 UTC (rev 173223)
+++ trunk/Source/bmalloc/bmalloc/Sizes.h        2014-09-03 21:00:33 UTC (rev 173224)
</span><span class="lines">@@ -68,6 +68,8 @@
</span><span class="cx">     static const size_t largeChunkMask = ~(largeChunkSize - 1ul);
</span><span class="cx"> 
</span><span class="cx">     static const size_t largeAlignment = 64;
</span><ins>+    static const size_t largeAlignmentShift = 6;
+    static_assert(1 &lt;&lt; largeAlignmentShift == largeAlignment, &quot;largeAlignmentShift be log2(largeAlignment).&quot;);
</ins><span class="cx">     static const size_t largeMax = largeChunkSize * 99 / 100; // Plenty of room for metadata.
</span><span class="cx">     static const size_t largeMin = 1024;
</span><span class="cx"> 
</span></span></pre>
</div>
</div>

</body>
</html>