<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<!DOCTYPE bugzilla SYSTEM "https://bugs.webkit.org/page.cgi?id=bugzilla.dtd">

<bugzilla version="5.0.4.1"
          urlbase="https://bugs.webkit.org/"
          
          maintainer="admin@webkit.org"
>

    <bug>
          <bug_id>36849</bug_id>
          
          <creation_ts>2010-03-30 13:23:50 -0700</creation_ts>
          <short_desc>Add zero() method to Vector class</short_desc>
          <delta_ts>2011-06-14 12:37:57 -0700</delta_ts>
          <reporter_accessible>1</reporter_accessible>
          <cclist_accessible>1</cclist_accessible>
          <classification_id>1</classification_id>
          <classification>Unclassified</classification>
          <product>WebKit</product>
          <component>Web Template Framework</component>
          <version>528+ (Nightly build)</version>
          <rep_platform>Other</rep_platform>
          <op_sys>OS X 10.5</op_sys>
          <bug_status>RESOLVED</bug_status>
          <resolution>WONTFIX</resolution>
          
          
          <bug_file_loc></bug_file_loc>
          <status_whiteboard></status_whiteboard>
          <keywords></keywords>
          <priority>P2</priority>
          <bug_severity>Normal</bug_severity>
          <target_milestone>---</target_milestone>
          
          
          <everconfirmed>0</everconfirmed>
          <reporter name="Chris Rogers">crogers</reporter>
          <assigned_to name="Nobody">webkit-unassigned</assigned_to>
          <cc>abarth</cc>
    
    <cc>ap</cc>
    
    <cc>cmarrin</cc>
    
    <cc>darin</cc>
    
    <cc>jorlow</cc>
    
    <cc>mjs</cc>
    
    <cc>sam</cc>
          

      

      

      

          <comment_sort_order>oldest_to_newest</comment_sort_order>  
          <long_desc isprivate="0" >
    <commentid>206148</commentid>
    <comment_count>0</comment_count>
    <who name="Chris Rogers">crogers</who>
    <bug_when>2010-03-30 13:23:50 -0700</bug_when>
    <thetext>Add zero() method to Vector class</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>206212</commentid>
    <comment_count>1</comment_count>
      <attachid>52089</attachid>
    <who name="Chris Rogers">crogers</who>
    <bug_when>2010-03-30 15:35:53 -0700</bug_when>
    <thetext>Created attachment 52089
Patch</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>206217</commentid>
    <comment_count>2</comment_count>
    <who name="Chris Rogers">crogers</who>
    <bug_when>2010-03-30 15:40:15 -0700</bug_when>
    <thetext>This patch adds a zero() method to Vector (only for the POD types) which memsets the bytes to all zeroes.  For integer and floating-point values this corresponds to all values of 0 or 0.0.  The reason it&apos;s interesting to have a zero() method when there&apos;s already a fill() method is because zero() can be much more optimized (using memset) rather than using std::fill().</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>206238</commentid>
    <comment_count>3</comment_count>
    <who name="Alexey Proskuryakov">ap</who>
    <bug_when>2010-03-30 16:12:50 -0700</bug_when>
    <thetext>GCC optimizes std::fill() using a memset when possible.

  /**
   *  @brief Fills the range [first,last) with copies of value.
   *  @param  first  A forward iterator.
   *  @param  last   A forward iterator.
   *  @param  value  A reference-to-const of arbitrary type.
   *  @return   Nothing.
   *
   *  This function fills a range with copies of the same value.  For one-byte
   *  types filling contiguous areas of memory, this becomes an inline call to
   *  @c memset.
  */

I think it&apos;s even done at two levels - both as a specialization in STL, and a compiler optimization for those engineers who use explicit loops.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>206257</commentid>
    <comment_count>4</comment_count>
    <who name="Chris Rogers">crogers</who>
    <bug_when>2010-03-30 16:43:14 -0700</bug_when>
    <thetext>Right, but I&apos;m interested in using this for Vector&lt;float&gt; and Vector&lt;double&gt; which won&apos;t have this optimization.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>206443</commentid>
    <comment_count>5</comment_count>
    <who name="Jeremy Orlow">jorlow</who>
    <bug_when>2010-03-31 03:30:41 -0700</bug_when>
    <thetext>I don&apos;t really like the idea of having a method that silently does nothing when it&apos;s not safe.  I actually think having it zero out even non-POD is better than silently doing nothing.

Is it possible to add a specialization of fill for doubles and floats when 0.0 is passed in?</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>206610</commentid>
    <comment_count>6</comment_count>
    <who name="Chris Rogers">crogers</who>
    <bug_when>2010-03-31 11:45:05 -0700</bug_when>
    <thetext>Actually, it doesn&apos;t silently do nothing.  I made the method private so it won&apos;t even compile in the cases where it doesn&apos;t make sense and could be dangerous.  For many non-POD type objects, simply initializing to zero would not be a good thing.  For example, OwnPtr would leak.  I suppose it&apos;s possible to specialize the fill() method for 0.0 with float and double (and long double, short, long long, int, etc.), but it seems more concise and precise to be able to call object.zero() rather than object.fill(0.0).</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>206662</commentid>
    <comment_count>7</comment_count>
    <who name="Darin Adler">darin</who>
    <bug_when>2010-03-31 12:49:16 -0700</bug_when>
    <thetext>(In reply to comment #6)
&gt; it seems more concise and precise to be able
&gt; to call object.zero() rather than object.fill(0.0).

More concise, yes.

More precise? No. I believe it&apos;s less precise.

Is there a way to optimize object.fill(0.0) or not?

I suggest we not add this. But I could be convinced otherwise.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>206681</commentid>
    <comment_count>8</comment_count>
    <who name="Chris Rogers">crogers</who>
    <bug_when>2010-03-31 13:15:42 -0700</bug_when>
    <thetext>(In reply to comment #7)
&gt; (In reply to comment #6)
&gt; &gt; it seems more concise and precise to be able
&gt; &gt; to call object.zero() rather than object.fill(0.0).
&gt; 
&gt; More concise, yes.
&gt; 
&gt; More precise? No. I believe it&apos;s less precise.
&gt; 
&gt; Is there a way to optimize object.fill(0.0) or not?
&gt; 
&gt; I suggest we not add this. But I could be convinced otherwise.

OK, maybe not more precise :)

But one point I was trying to make is that the current patch addresses all of the potential interesting cases where I could see this being useful (char, unsigned char, short, float, double, long double, long long, etc.).    I&apos;m not sure how to get the same behavior other than creating a specialization of fill() for each of  these types separately which seems somewhat cumbersome.  Maybe there&apos;s a shortcut to avoid this - any suggestions?</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>206696</commentid>
    <comment_count>9</comment_count>
    <who name="Chris Marrin">cmarrin</who>
    <bug_when>2010-03-31 13:37:06 -0700</bug_when>
    <thetext>Do we really need this method in the Vector class? It may be a bit more concise, but it seems like overkill. I don&apos;t think it will improve performance in any significant way, and I don&apos;t thing &apos;zero()&apos; is any more clear than &apos;fill(0)&apos;. It seems like it just unnecessarily adds to the size of the API of this function.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>206733</commentid>
    <comment_count>10</comment_count>
    <who name="Sam Weinig">sam</who>
    <bug_when>2010-03-31 14:47:15 -0700</bug_when>
    <thetext>What about something like either of these.



namespace WTF {

template &lt;bool canZero, typename T&gt;
struct ZeroFiller;

template&lt;typename T&gt;
struct ZeroFiller&lt;true, T&gt; {
    static void zero(T* begin, T* end)
    {
        memset(begin, 0, reinterpret_cast&lt;char*&gt;(end) - reinterpret_cast&lt;char*&gt;(begin));
    }
};

template&lt;typename T&gt;
void zeroFill(T* begin, T* end)
{
    ZeroFiller::zero&lt;IsPod&lt;T&gt;::value, T&gt;(first, last)
}

} // namespace WTF


or


namespace WTF {

template&lt;typename T&gt;
void zeroFill(T* begin, T* end)
{
    COMPILE_ASSERT(IsPod&lt;T&gt;);
    memset(begin, 0, reinterpret_cast&lt;char*&gt;(end) - reinterpret_cast&lt;char*&gt;(begin));
}

} // namespace WTF</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>206744</commentid>
    <comment_count>11</comment_count>
    <who name="Chris Rogers">crogers</who>
    <bug_when>2010-03-31 14:59:31 -0700</bug_when>
    <thetext>(In reply to comment #9)
&gt; Do we really need this method in the Vector class? It may be a bit more
&gt; concise, but it seems like overkill. I don&apos;t think it will improve performance
&gt; in any significant way, and I don&apos;t thing &apos;zero()&apos; is any more clear than
&gt; &apos;fill(0)&apos;. It seems like it just unnecessarily adds to the size of the API of
&gt; this function.

For many applications the performance benefit may be fairly small, but for audio it makes sense.  When I worked on the CoreAudio team we were pressured very hard to make these types of optimizations, unroll loops, write SIMD code (altivec, SSE), etc.

The &quot;footprint&quot; of having a zero() method doesn&apos;t seem that heavy to me.  But if people really don&apos;t like to have the method in the Vector class, then I could certainly write helper functions which use memset() - something like:

void zero(Vector&lt;float&gt;);
void zero(Vector&lt;double&gt;);

These could be defined in Vector.h, somewhere else in wtf, or directly in my audio directory.

The reason I made this patch is because people didn&apos;t like the idea of me sub-classing Vector in order to implement a zero() method (in addition to some other things) in this bug:

https://bugs.webkit.org/show_bug.cgi?id=34452

Adam Barth suggested I could implement this in Vector (using traits).  The other approaches (subclassing or helper functions) are also fine with me.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>206745</commentid>
    <comment_count>12</comment_count>
    <who name="Chris Rogers">crogers</who>
    <bug_when>2010-03-31 15:02:08 -0700</bug_when>
    <thetext>(In reply to comment #10)
&gt; What about something like either of these.
&gt; 
&gt; 
&gt; 
&gt; namespace WTF {
&gt; 
&gt; template &lt;bool canZero, typename T&gt;
&gt; struct ZeroFiller;
&gt; 
&gt; template&lt;typename T&gt;
&gt; struct ZeroFiller&lt;true, T&gt; {
&gt;     static void zero(T* begin, T* end)
&gt;     {
&gt;         memset(begin, 0, reinterpret_cast&lt;char*&gt;(end) -
&gt; reinterpret_cast&lt;char*&gt;(begin));
&gt;     }
&gt; };
&gt; 
&gt; template&lt;typename T&gt;
&gt; void zeroFill(T* begin, T* end)
&gt; {
&gt;     ZeroFiller::zero&lt;IsPod&lt;T&gt;::value, T&gt;(first, last)
&gt; }
&gt; 
&gt; } // namespace WTF
&gt; 
&gt; 
&gt; or
&gt; 
&gt; 
&gt; namespace WTF {
&gt; 
&gt; template&lt;typename T&gt;
&gt; void zeroFill(T* begin, T* end)
&gt; {
&gt;     COMPILE_ASSERT(IsPod&lt;T&gt;);
&gt;     memset(begin, 0, reinterpret_cast&lt;char*&gt;(end) -
&gt; reinterpret_cast&lt;char*&gt;(begin));
&gt; }
&gt; 
&gt; } // namespace WTF

Sam, thanks that looks pretty good.  Which file do you think this code belongs in?</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>206748</commentid>
    <comment_count>13</comment_count>
    <who name="Sam Weinig">sam</who>
    <bug_when>2010-03-31 15:04:47 -0700</bug_when>
    <thetext>&gt; Sam, thanks that looks pretty good.  Which file do you think this code belongs
&gt; in?

I think StdLibExtras.h would be good.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>206751</commentid>
    <comment_count>14</comment_count>
    <who name="Chris Rogers">crogers</who>
    <bug_when>2010-03-31 15:11:35 -0700</bug_when>
    <thetext>(In reply to comment #13)
&gt; &gt; Sam, thanks that looks pretty good.  Which file do you think this code belongs
&gt; &gt; in?
&gt; 
&gt; I think StdLibExtras.h would be good.

Sounds good - if nobody objects I&apos;d like to take Sam&apos;s suggestion and just to round things out also add the following function:

template&lt;typename T&gt;
void zeroFill(Vector&lt;T&gt; v)
{
    zeroFill(v.begin(). v.end());
}</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>206752</commentid>
    <comment_count>15</comment_count>
    <who name="Chris Rogers">crogers</who>
    <bug_when>2010-03-31 15:12:39 -0700</bug_when>
    <thetext>Sorry I meant to pass by reference...

template&lt;typename T&gt;
void zeroFill(Vector&lt;T&gt;&amp; v)
{
    zeroFill(v.begin(). v.end());
}</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>206988</commentid>
    <comment_count>16</comment_count>
    <who name="Maciej Stachowiak">mjs</who>
    <bug_when>2010-03-31 23:45:57 -0700</bug_when>
    <thetext>(In reply to comment #10)
&gt; What about something like either of these.
&gt; 
&gt; 
&gt; 
&gt; namespace WTF {
&gt; 
&gt; template &lt;bool canZero, typename T&gt;
&gt; struct ZeroFiller;
&gt; 
&gt; template&lt;typename T&gt;
&gt; struct ZeroFiller&lt;true, T&gt; {
&gt;     static void zero(T* begin, T* end)
&gt;     {
&gt;         memset(begin, 0, reinterpret_cast&lt;char*&gt;(end) -
&gt; reinterpret_cast&lt;char*&gt;(begin));
&gt;     }
&gt; };
&gt; 
&gt; template&lt;typename T&gt;
&gt; void zeroFill(T* begin, T* end)
&gt; {
&gt;     ZeroFiller::zero&lt;IsPod&lt;T&gt;::value, T&gt;(first, last)
&gt; }
&gt; 
&gt; } // namespace WTF

1) How about implementing the non-POD version with a loop that just assigns 0? That will still fail at compile time if the type pointed to is one where you can&apos;t assign 0.

2) Is there any evidence that zeroFill() would measurably improve performance over fill(0)?

Regards,
Maciej</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>206993</commentid>
    <comment_count>17</comment_count>
    <who name="Maciej Stachowiak">mjs</who>
    <bug_when>2010-03-31 23:48:25 -0700</bug_when>
    <thetext>(In reply to comment #14)
&gt; (In reply to comment #13)
&gt; &gt; &gt; Sam, thanks that looks pretty good.  Which file do you think this code belongs
&gt; &gt; &gt; in?
&gt; &gt; 
&gt; &gt; I think StdLibExtras.h would be good.
&gt; 
&gt; Sounds good - if nobody objects I&apos;d like to take Sam&apos;s suggestion and just to
&gt; round things out also add the following function:
&gt; 
&gt; template&lt;typename T&gt;
&gt; void zeroFill(Vector&lt;T&gt; v)
&gt; {
&gt;     zeroFill(v.begin(). v.end());
&gt; }

Not sure that small bit of abstraction is much of a win. It also depends on the fact that the Vector iterator is a raw pointer, which isn&apos;t guaranteed. v.data() and v.data() + v.size() would be more robust ways to get the endpoints as pointers.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>206994</commentid>
    <comment_count>18</comment_count>
      <attachid>52089</attachid>
    <who name="Maciej Stachowiak">mjs</who>
    <bug_when>2010-03-31 23:49:04 -0700</bug_when>
    <thetext>Comment on attachment 52089
Patch

r- because we seem to have rough consensus that the zero() method is not the right approach (though we are still discussing what ways of doing it would be better).</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>207263</commentid>
    <comment_count>19</comment_count>
    <who name="Chris Marrin">cmarrin</who>
    <bug_when>2010-04-01 11:17:05 -0700</bug_when>
    <thetext>It looks like std::fill() only uses a memset() optimization for 1 byte types. So I understand the need for an optimization. But can&apos;t this be done by optimizing Vector::fill() to use memset for any pod type being set to 0?</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>207328</commentid>
    <comment_count>20</comment_count>
    <who name="Chris Rogers">crogers</who>
    <bug_when>2010-04-01 12:51:12 -0700</bug_when>
    <thetext>(In reply to comment #19)
&gt; It looks like std::fill() only uses a memset() optimization for 1 byte types.
&gt; So I understand the need for an optimization. But can&apos;t this be done by
&gt; optimizing Vector::fill() to use memset for any pod type being set to 0?

It clearly can be done in a brute-force way (template specializations for each one), but I&apos;m not sure of an elegant solution there but will look closer at it since I suspect there is one.  Otherwise, I&apos;m happy with Sam&apos;s solution.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>207330</commentid>
    <comment_count>21</comment_count>
    <who name="Chris Rogers">crogers</who>
    <bug_when>2010-04-01 12:55:45 -0700</bug_when>
    <thetext>(In reply to comment #17)
&gt; (In reply to comment #14)
&gt; &gt; (In reply to comment #13)
&gt; &gt; &gt; &gt; Sam, thanks that looks pretty good.  Which file do you think this code belongs
&gt; &gt; &gt; &gt; in?
&gt; &gt; &gt; 
&gt; &gt; &gt; I think StdLibExtras.h would be good.
&gt; &gt; 
&gt; &gt; Sounds good - if nobody objects I&apos;d like to take Sam&apos;s suggestion and just to
&gt; &gt; round things out also add the following function:
&gt; &gt; 
&gt; &gt; template&lt;typename T&gt;
&gt; &gt; void zeroFill(Vector&lt;T&gt; v)
&gt; &gt; {
&gt; &gt;     zeroFill(v.begin(). v.end());
&gt; &gt; }
&gt; 
&gt; Not sure that small bit of abstraction is much of a win. It also depends on the
&gt; fact that the Vector iterator is a raw pointer, which isn&apos;t guaranteed.
&gt; v.data() and v.data() + v.size() would be more robust ways to get the endpoints
&gt; as pointers.

OK, v.data() sounds good.  At least in my use cases, and I suspect the majority of cases, zeroFill() would be called to clear the whole vector which is what prompted me to create the shortcut method which seems more concise.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>207409</commentid>
    <comment_count>22</comment_count>
    <who name="Chris Rogers">crogers</who>
    <bug_when>2010-04-01 14:33:33 -0700</bug_when>
    <thetext>&gt; 
&gt; 2) Is there any evidence that zeroFill() would measurably improve performance
&gt; over fill(0)?
&gt; 
&gt; Regards,
&gt; Maciej

memset() is definitely quite a bit faster than a straight zero-filling loop.  It&apos;s tremendously optimized and its source code is quite interesting to read.

I created a quick benchmark to test my zero() method vs. fill():

    // Make sure memset() code is &quot;hot&quot; (so we&apos;re not measuring paging activity)
    float temp[2048];
    memset(temp, 0, sizeof(float) * 2048);

    printf(&quot;            n       fill()     memset()   speed improvement\n&quot;);
    
    for (unsigned i = 0; i &lt; 24; ++i) {
        const int k = 1UL &lt;&lt; i;
        const int n = k * 128;
        Vector&lt;float&gt; v1(n);
        Vector&lt;float&gt; v2(n);
        v1.fill(1.0);
        v2.fill(1.0);
        PerformanceTimer timer1(&quot;fill  &quot;); // PerformanceTimer internally uses UpTime(), but could use mach_absolute_time()
        PerformanceTimer timer2(&quot;memset&quot;);
        timer1.Start();
        v1.fill(0.0);
        timer1.Stop(); // print elapsed time

        timer2.Start();
        v2.zero();
        timer2.Stop();
        
        // times in usec
        double time1 = timer1.GetElapsedTime();
        double time2 = timer2.GetElapsedTime();
        double speedUp = time1 / time2;
        printf(&quot;%14d %10.3f %10.3f %10.3f\n&quot;, n, time1, time2, speedUp);
    }


Here are the results run on the latest 8-core Xeon desktop Mac (laptops and ARM chips would be somewhat slower):

            n       fill()     memset()   speed improvement
           128      0.291      0.223      1.305
           256      0.411      0.191      2.152
           512      0.712      0.218      3.266
          1024      0.902      0.194      4.649
          2048      1.760      0.329      5.350
          4096      3.299      0.691      4.774
          8192      6.531      1.397      4.675
         16384     13.029      2.825      4.612
         32768     26.016      6.163      4.221
         65536     56.320     16.795      3.353
        131072    107.894     33.843      3.188
        262144    207.663     65.043      3.193
        524288    415.301    131.098      3.168
       1048576    841.864    549.443      1.532
       2097152   1721.820   1280.595      1.345
       4194304   3377.447   2427.105      1.392
       8388608   6726.940   4902.623      1.372
      16777216  13458.201   9882.302      1.362
      33554432  26849.611  19685.213      1.364
      67108864  53677.435  39297.878      1.366
     134217728 107947.327  79122.879      1.364</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>420659</commentid>
    <comment_count>23</comment_count>
    <who name="Chris Rogers">crogers</who>
    <bug_when>2011-06-14 12:37:57 -0700</bug_when>
    <thetext>Changing to won&apos;t fix there exist alternatives for WebGL and Web Audio such as:
ArrayBufferView::zeroRangeImpl()</thetext>
  </long_desc>
      
          <attachment
              isobsolete="0"
              ispatch="1"
              isprivate="0"
          >
            <attachid>52089</attachid>
            <date>2010-03-30 15:35:53 -0700</date>
            <delta_ts>2010-06-11 10:41:15 -0700</delta_ts>
            <desc>Patch</desc>
            <filename>bug-36849-20100330153551.patch</filename>
            <type>text/plain</type>
            <size>4139</size>
            <attacher name="Chris Rogers">crogers</attacher>
            
              <data encoding="base64">ZGlmZiAtLWdpdCBhL0phdmFTY3JpcHRDb3JlL0NoYW5nZUxvZyBiL0phdmFTY3JpcHRDb3JlL0No
YW5nZUxvZwppbmRleCAzZmQ2ZmU5Li5jNWUzMmIxIDEwMDY0NAotLS0gYS9KYXZhU2NyaXB0Q29y
ZS9DaGFuZ2VMb2cKKysrIGIvSmF2YVNjcmlwdENvcmUvQ2hhbmdlTG9nCkBAIC0xLDMgKzEsMTcg
QEAKKzIwMTAtMDMtMzAgIENocmlzIFJvZ2VycyAgPGNyb2dlcnNAZ29vZ2xlLmNvbT4KKworICAg
ICAgICBSZXZpZXdlZCBieSBOT0JPRFkgKE9PUFMhKS4KKworICAgICAgICBBZGQgemVybygpIG1l
dGhvZCB0byBWZWN0b3IgY2xhc3MKKyAgICAgICAgaHR0cHM6Ly9idWdzLndlYmtpdC5vcmcvc2hv
d19idWcuY2dpP2lkPTM2ODQ5CisKKyAgICAgICAgKiB3dGYvVmVjdG9yLmg6CisgICAgICAgIChX
VEY6Oik6CisgICAgICAgIChXVEY6OlZlY3RvclR5cGVPcGVyYXRpb25zOjp6ZXJvKToKKyAgICAg
ICAgKFdURjo6VmVjdG9yOjp6ZXJvKToKKyAgICAgICAgKiB3dGYvVmVjdG9yVHJhaXRzLmg6Cisg
ICAgICAgIChXVEY6Oik6CisKIDIwMTAtMDMtMjkgIFBhdHJpY2sgR2Fuc3RlcmVyICA8cGFyb2dh
QHBhcm9nYS5jb20+CiAKICAgICAgICAgUmV2aWV3ZWQgYnkgRGFyaW4gQWRsZXIuCmRpZmYgLS1n
aXQgYS9KYXZhU2NyaXB0Q29yZS93dGYvVmVjdG9yLmggYi9KYXZhU2NyaXB0Q29yZS93dGYvVmVj
dG9yLmgKaW5kZXggNmY1NWU1My4uYzg4Y2QyZiAxMDA2NDQKLS0tIGEvSmF2YVNjcmlwdENvcmUv
d3RmL1ZlY3Rvci5oCisrKyBiL0phdmFTY3JpcHRDb3JlL3d0Zi9WZWN0b3IuaApAQCAtMTE4LDYg
KzExOCwyNSBAQCBuYW1lc3BhY2UgV1RGIHsKICAgICAgICAgfQogICAgIH07CiAKKyAgICB0ZW1w
bGF0ZSA8Ym9vbCBjYW5aZXJvLCB0eXBlbmFtZSBUPgorICAgIHN0cnVjdCBWZWN0b3JaZXJvZXI7
CisKKyAgICB0ZW1wbGF0ZTx0eXBlbmFtZSBUPgorICAgIHN0cnVjdCBWZWN0b3JaZXJvZXI8ZmFs
c2UsIFQ+IHsKKyAgICBwcml2YXRlOgorICAgICAgICBzdGF0aWMgdm9pZCB6ZXJvKFQqIGJlZ2lu
LCBUKiBlbmQpCisgICAgICAgIHsKKyAgICAgICAgfQorICAgIH07CisKKyAgICB0ZW1wbGF0ZTx0
eXBlbmFtZSBUPgorICAgIHN0cnVjdCBWZWN0b3JaZXJvZXI8dHJ1ZSwgVD4geworICAgICAgICBz
dGF0aWMgdm9pZCB6ZXJvKFQqIGJlZ2luLCBUKiBlbmQpCisgICAgICAgIHsKKyAgICAgICAgICAg
IG1lbXNldChiZWdpbiwgMCwgcmVpbnRlcnByZXRfY2FzdDxjaGFyKj4oZW5kKSAtIHJlaW50ZXJw
cmV0X2Nhc3Q8Y2hhcio+KGJlZ2luKSk7CisgICAgICAgIH0KKyAgICB9OworCiAgICAgdGVtcGxh
dGUgPGJvb2wgY2FuTW92ZVdpdGhNZW1jcHksIHR5cGVuYW1lIFQ+CiAgICAgc3RydWN0IFZlY3Rv
ck1vdmVyOwogCkBAIC0yNDksNiArMjY4LDExIEBAIG5hbWVzcGFjZSBXVEYgewogICAgICAgICAg
ICAgVmVjdG9ySW5pdGlhbGl6ZXI8VmVjdG9yVHJhaXRzPFQ+OjpuZWVkc0luaXRpYWxpemF0aW9u
LCBWZWN0b3JUcmFpdHM8VD46OmNhbkluaXRpYWxpemVXaXRoTWVtc2V0LCBUPjo6aW5pdGlhbGl6
ZShiZWdpbiwgZW5kKTsKICAgICAgICAgfQogCisgICAgICAgIHN0YXRpYyB2b2lkIHplcm8oVCog
YmVnaW4sIFQqIGVuZCkKKyAgICAgICAgeworICAgICAgICAgICAgVmVjdG9yWmVyb2VyPFZlY3Rv
clRyYWl0czxUPjo6Y2FuWmVybywgVD46Onplcm8oYmVnaW4sIGVuZCk7CisgICAgICAgIH0KKwog
ICAgICAgICBzdGF0aWMgdm9pZCBtb3ZlKGNvbnN0IFQqIHNyYywgY29uc3QgVCogc3JjRW5kLCBU
KiBkc3QpCiAgICAgICAgIHsKICAgICAgICAgICAgIFZlY3Rvck1vdmVyPFZlY3RvclRyYWl0czxU
Pjo6Y2FuTW92ZVdpdGhNZW1jcHksIFQ+Ojptb3ZlKHNyYywgc3JjRW5kLCBkc3QpOwpAQCAtNjAy
LDYgKzYyNiw3IEBAIG5hbWVzcGFjZSBXVEYgewogCiAgICAgICAgIHZvaWQgZmlsbChjb25zdCBU
Jiwgc2l6ZV90KTsKICAgICAgICAgdm9pZCBmaWxsKGNvbnN0IFQmIHZhbCkgeyBmaWxsKHZhbCwg
c2l6ZSgpKTsgfQorICAgICAgICB2b2lkIHplcm8oKSB7IFR5cGVPcGVyYXRpb25zOjp6ZXJvKGJl
Z2luKCksIGVuZCgpKTsgfQogCiAgICAgICAgIHRlbXBsYXRlPHR5cGVuYW1lIEl0ZXJhdG9yPiB2
b2lkIGFwcGVuZFJhbmdlKEl0ZXJhdG9yIHN0YXJ0LCBJdGVyYXRvciBlbmQpOwogCmRpZmYgLS1n
aXQgYS9KYXZhU2NyaXB0Q29yZS93dGYvVmVjdG9yVHJhaXRzLmggYi9KYXZhU2NyaXB0Q29yZS93
dGYvVmVjdG9yVHJhaXRzLmgKaW5kZXggM2YzM2IyOS4uOWNjODZmOCAxMDA2NDQKLS0tIGEvSmF2
YVNjcmlwdENvcmUvd3RmL1ZlY3RvclRyYWl0cy5oCisrKyBiL0phdmFTY3JpcHRDb3JlL3d0Zi9W
ZWN0b3JUcmFpdHMuaApAQCAtMzksNiArMzksNyBAQCBuYW1lc3BhY2UgV1RGIHsKICAgICB7CiAg
ICAgICAgIHN0YXRpYyBjb25zdCBib29sIG5lZWRzRGVzdHJ1Y3Rpb24gPSB0cnVlOwogICAgICAg
ICBzdGF0aWMgY29uc3QgYm9vbCBuZWVkc0luaXRpYWxpemF0aW9uID0gdHJ1ZTsKKyAgICAgICAg
c3RhdGljIGNvbnN0IGJvb2wgY2FuWmVybyA9IGZhbHNlOwogICAgICAgICBzdGF0aWMgY29uc3Qg
Ym9vbCBjYW5Jbml0aWFsaXplV2l0aE1lbXNldCA9IGZhbHNlOwogICAgICAgICBzdGF0aWMgY29u
c3QgYm9vbCBjYW5Nb3ZlV2l0aE1lbWNweSA9IGZhbHNlOwogICAgICAgICBzdGF0aWMgY29uc3Qg
Ym9vbCBjYW5Db3B5V2l0aE1lbWNweSA9IGZhbHNlOwpAQCAtNTEsNiArNTIsNyBAQCBuYW1lc3Bh
Y2UgV1RGIHsKICAgICB7CiAgICAgICAgIHN0YXRpYyBjb25zdCBib29sIG5lZWRzRGVzdHJ1Y3Rp
b24gPSBmYWxzZTsKICAgICAgICAgc3RhdGljIGNvbnN0IGJvb2wgbmVlZHNJbml0aWFsaXphdGlv
biA9IGZhbHNlOworICAgICAgICBzdGF0aWMgY29uc3QgYm9vbCBjYW5aZXJvID0gdHJ1ZTsKICAg
ICAgICAgc3RhdGljIGNvbnN0IGJvb2wgY2FuSW5pdGlhbGl6ZVdpdGhNZW1zZXQgPSBmYWxzZTsK
ICAgICAgICAgc3RhdGljIGNvbnN0IGJvb2wgY2FuTW92ZVdpdGhNZW1jcHkgPSB0cnVlOwogICAg
ICAgICBzdGF0aWMgY29uc3QgYm9vbCBjYW5Db3B5V2l0aE1lbWNweSA9IHRydWU7CkBAIC02NSw2
ICs2Nyw3IEBAIG5hbWVzcGFjZSBXVEYgewogICAgIHsKICAgICAgICAgc3RhdGljIGNvbnN0IGJv
b2wgbmVlZHNEZXN0cnVjdGlvbiA9IHRydWU7CiAgICAgICAgIHN0YXRpYyBjb25zdCBib29sIG5l
ZWRzSW5pdGlhbGl6YXRpb24gPSB0cnVlOworICAgICAgICBzdGF0aWMgY29uc3QgYm9vbCBjYW5a
ZXJvID0gZmFsc2U7CiAgICAgICAgIHN0YXRpYyBjb25zdCBib29sIGNhbkluaXRpYWxpemVXaXRo
TWVtc2V0ID0gdHJ1ZTsKICAgICAgICAgc3RhdGljIGNvbnN0IGJvb2wgY2FuTW92ZVdpdGhNZW1j
cHkgPSB0cnVlOwogICAgICAgICBzdGF0aWMgY29uc3QgYm9vbCBjYW5Db3B5V2l0aE1lbWNweSA9
IGZhbHNlOwpAQCAtODgsNiArOTEsNyBAQCBuYW1lc3BhY2UgV1RGIHsKIAogICAgICAgICBzdGF0
aWMgY29uc3QgYm9vbCBuZWVkc0Rlc3RydWN0aW9uID0gRmlyc3RUcmFpdHM6Om5lZWRzRGVzdHJ1
Y3Rpb24gfHwgU2Vjb25kVHJhaXRzOjpuZWVkc0Rlc3RydWN0aW9uOwogICAgICAgICBzdGF0aWMg
Y29uc3QgYm9vbCBuZWVkc0luaXRpYWxpemF0aW9uID0gRmlyc3RUcmFpdHM6Om5lZWRzSW5pdGlh
bGl6YXRpb24gfHwgU2Vjb25kVHJhaXRzOjpuZWVkc0luaXRpYWxpemF0aW9uOworICAgICAgICBz
dGF0aWMgY29uc3QgYm9vbCBjYW5aZXJvID0gRmlyc3RUcmFpdHM6OmNhblplcm8gJiYgU2Vjb25k
VHJhaXRzOjpjYW5aZXJvOwogICAgICAgICBzdGF0aWMgY29uc3QgYm9vbCBjYW5Jbml0aWFsaXpl
V2l0aE1lbXNldCA9IEZpcnN0VHJhaXRzOjpjYW5Jbml0aWFsaXplV2l0aE1lbXNldCAmJiBTZWNv
bmRUcmFpdHM6OmNhbkluaXRpYWxpemVXaXRoTWVtc2V0OwogICAgICAgICBzdGF0aWMgY29uc3Qg
Ym9vbCBjYW5Nb3ZlV2l0aE1lbWNweSA9IEZpcnN0VHJhaXRzOjpjYW5Nb3ZlV2l0aE1lbWNweSAm
JiBTZWNvbmRUcmFpdHM6OmNhbk1vdmVXaXRoTWVtY3B5OwogICAgICAgICBzdGF0aWMgY29uc3Qg
Ym9vbCBjYW5Db3B5V2l0aE1lbWNweSA9IEZpcnN0VHJhaXRzOjpjYW5Db3B5V2l0aE1lbWNweSAm
JiBTZWNvbmRUcmFpdHM6OmNhbkNvcHlXaXRoTWVtY3B5Owo=
</data>
<flag name="review"
          id="35478"
          type_id="1"
          status="-"
          setter="mjs"
    />
          </attachment>
      

    </bug>

</bugzilla>